Pre-submission

This commit is contained in:
Kienan Stewart 2023-10-01 16:56:55 -04:00
parent 929e3028eb
commit 0d07037de1
92 changed files with 2370 additions and 1 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
.import
*.import
build/

67
HexGrid.gd Normal file
View File

@ -0,0 +1,67 @@
extends Node2D
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
var rings = 4
var storage = []
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func init_storage(rings: int):
self.rings = rings
self.storage = []
# Not the smallest size, but will make a "square" buffer and some
# indices will never be accessed by get_item()
var size = (rings * 2) - 1
size *= size
self.storage.resize(size)
func _get_index(q: int, r: int):
# Using axial coordinates q and r are bounded from -(rings-1) to (rings-1)
assert(_is_valid_q_r(q, r))
# To map to storage, we "push" the values up by (rings-1) so there are
# never any negative indices. Once there, we can use q, r as row, column
# addresses
var q_mod = q + (self.rings - 1)
var r_mod = r + (self.rings - 1)
var row_size = (self.rings * 2) - 1
var index = (q_mod * row_size) + r_mod
assert(index < self.storage.size())
return index
func _is_valid_q_r(q: int, r: int):
return abs(q) < self.rings and abs(r) < self.rings
func get_item(q: int, r: int):
var index = self._get_index(q, r)
return self.storage[index]
func set_item(q: int, r: int, item):
var index = _get_index(q, r)
self.storage[index] = item
func tag_edge_nodes(direction: Vector2, group: String):
var edges = []
for item in self.storage:
if item == null:
continue
var loc = item.pf_location
var adjacent_spot = loc + direction
#print("Testing location: ", loc)
if not self._is_valid_q_r(adjacent_spot.x, adjacent_spot.y):
edges.append(loc)
continue
var neighbour = self.get_item(adjacent_spot.x, adjacent_spot.y)
if neighbour == null:
edges.append(loc)
for e in edges:
var item = self.get_item(e.x, e.y)
item.add_to_group(group)
func get_neighbours(q, r):
return []

46
Menu.gd Normal file
View File

@ -0,0 +1,46 @@
extends PopupPanel
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass
func _on_Continue_pressed():
self.set_visible(false)
func _on_Quit_pressed():
get_tree().quit()
func _on_Help_pressed():
self.set_visible(false)
# Brittle, refers to the layout in "Game" scenetree
get_node("../Help").set_visible(true)
func _on_Restart_pressed():
get_tree().get_root().get_node("/root/Game").reset()
self.set_visible(false)
func _on_scores_updated(scores):
var total = 0
var max_score = 0
for x in scores:
total += x
max_score = max(max_score, x)
get_node("VBoxContainer/Score").set_bbcode("[center]Score: %d[/center]" % total)
var s = ""
for x in range(scores.size()):
s += "Year %d: %d\n" % [x, scores[x]]
print(s)
get_node("VBoxContainer/ScoreByYear").set_bbcode(s)

View File

@ -0,0 +1,20 @@
# LD54 : Da 'lil Patch
You only have a small space. Can you keep it cultivated and producing well as
the years go on?
## Tools
* Debian Linux
* Godot 3.5 (gdscript)
* Art: GIMP, mypaint, inkscape, krita
* Sound: Audacity
## External Assets
* Font: Bitstream Vera Mono Nerd
## Licenses
* Assets (excluding font): CC-BY-SA-4.0
* Source code: GPLv3

BIN
assets/Burn.wav Normal file

Binary file not shown.

BIN
assets/Cull.wav Normal file

Binary file not shown.

BIN
assets/Fertilize.wav Normal file

Binary file not shown.

BIN
assets/Plant.wav Normal file

Binary file not shown.

BIN
assets/Query.wav Normal file

Binary file not shown.

BIN
assets/Rock.wav Normal file

Binary file not shown.

BIN
assets/Tweet.wav Normal file

Binary file not shown.

BIN
assets/apple fruit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
assets/apple icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
assets/apple plant.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
assets/apple tree.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

BIN
assets/bean icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
assets/bean plant.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
assets/bg.kra Normal file

Binary file not shown.

BIN
assets/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 KiB

BIN
assets/clover flower.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
assets/clover icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
assets/clover plant.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
assets/corn fruit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
assets/corn ripe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
assets/hex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

58
assets/hex.svg Normal file
View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg135"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="hex.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="2.9897026"
inkscape:cx="198.34749"
inkscape:cy="216.74397"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="32"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs132" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="star"
style="fill:none;stroke:#000000;stroke-width:0.352999;stroke-linejoin:bevel;paint-order:markers fill stroke"
id="path576"
inkscape:flatsided="true"
sodipodi:sides="6"
sodipodi:cx="47.286068"
sodipodi:cy="53.504932"
sodipodi:r1="22.602188"
sodipodi:r2="19.574068"
sodipodi:arg1="0.52369612"
sodipodi:arg2="1.0472949"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 66.859037,64.807932 47.283868,76.10712 27.710899,64.804121 l 0.0022,-22.602188 19.575169,-11.299189 19.572969,11.303 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/icon burn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
assets/icon corn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
assets/icon cull.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
assets/icon fertilize.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
assets/icon plant.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
assets/icon query.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
assets/icon remove rock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
assets/plant.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
assets/rocky 1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/rocky 2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
assets/rocky 3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
assets/screenshots/tile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/seeds.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/small arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
assets/soil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/sound-.wav Normal file

Binary file not shown.

BIN
assets/sprouts.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
assets/strong weed icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
assets/sun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/tiles.xcf Normal file

Binary file not shown.

BIN
assets/weed icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
assets/weed plant.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

176
export_presets.cfg Normal file
View File

@ -0,0 +1,176 @@
[preset.0]
name="Linux/X11"
platform="Linux/X11"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="build/linux-x86_64/dalilpatch.x86_64"
script_export_mode=1
script_encryption_key=""
[preset.0.options]
custom_template/debug=""
custom_template/release=""
binary_format/64_bits=true
binary_format/embed_pck=false
texture_format/bptc=false
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
texture_format/no_bptc_fallbacks=true
[preset.1]
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="build/win11-x64_64/dalilpatch.x86_64.exe"
script_export_mode=1
script_encryption_key=""
[preset.1.options]
custom_template/debug=""
custom_template/release=""
binary_format/64_bits=true
binary_format/embed_pck=false
texture_format/bptc=false
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
texture_format/no_bptc_fallbacks=true
codesign/enable=false
codesign/identity_type=0
codesign/identity=""
codesign/password=""
codesign/timestamp=true
codesign/timestamp_server_url=""
codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PoolStringArray( )
application/modify_resources=true
application/icon=""
application/file_version=""
application/product_version=""
application/company_name=""
application/product_name=""
application/file_description=""
application/copyright=""
application/trademarks=""
[preset.2]
name="HTML5"
platform="HTML5"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="build/web/dalilpatch.x86_64.exe.html"
script_export_mode=1
script_encryption_key=""
[preset.2.options]
custom_template/debug=""
custom_template/release=""
variant/export_type=0
vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false
html/export_icon=true
html/custom_html_shell=""
html/head_include=""
html/canvas_resize_policy=2
html/focus_canvas_on_start=true
html/experimental_virtual_keyboard=false
progressive_web_app/enabled=false
progressive_web_app/offline_page=""
progressive_web_app/display=1
progressive_web_app/orientation=0
progressive_web_app/icon_144x144=""
progressive_web_app/icon_180x180=""
progressive_web_app/icon_512x512=""
progressive_web_app/background_color=Color( 0, 0, 0, 1 )
[preset.3]
name="Mac OSX"
platform="Mac OSX"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="build/osx/dalilpatch.x86_64.exe.html.zip"
script_export_mode=1
script_encryption_key=""
[preset.3.options]
custom_template/debug=""
custom_template/release=""
application/name=""
application/info="Made with Godot Engine"
application/icon=""
application/identifier=""
application/signature=""
application/app_category="Games"
application/short_version="1.0"
application/version="1.0"
application/copyright=""
display/high_res=false
privacy/microphone_usage_description=""
privacy/camera_usage_description=""
privacy/location_usage_description=""
privacy/address_book_usage_description=""
privacy/calendar_usage_description=""
privacy/photos_library_usage_description=""
privacy/desktop_folder_usage_description=""
privacy/documents_folder_usage_description=""
privacy/downloads_folder_usage_description=""
privacy/network_volumes_usage_description=""
privacy/removable_volumes_usage_description=""
codesign/enable=true
codesign/identity=""
codesign/timestamp=true
codesign/hardened_runtime=true
codesign/replace_existing_signature=true
codesign/entitlements/custom_file=""
codesign/entitlements/allow_jit_code_execution=false
codesign/entitlements/allow_unsigned_executable_memory=false
codesign/entitlements/allow_dyld_environment_variables=false
codesign/entitlements/disable_library_validation=false
codesign/entitlements/audio_input=false
codesign/entitlements/camera=false
codesign/entitlements/location=false
codesign/entitlements/address_book=false
codesign/entitlements/calendars=false
codesign/entitlements/photos_library=false
codesign/entitlements/apple_events=false
codesign/entitlements/debugging=false
codesign/entitlements/app_sandbox/enabled=false
codesign/entitlements/app_sandbox/network_server=false
codesign/entitlements/app_sandbox/network_client=false
codesign/entitlements/app_sandbox/device_usb=false
codesign/entitlements/app_sandbox/device_bluetooth=false
codesign/entitlements/app_sandbox/files_downloads=0
codesign/entitlements/app_sandbox/files_pictures=0
codesign/entitlements/app_sandbox/files_music=0
codesign/entitlements/app_sandbox/files_movies=0
codesign/custom_options=PoolStringArray( )
notarization/enable=false
notarization/apple_id_name=""
notarization/apple_id_password=""
notarization/apple_team_id=""
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false

View File

@ -11,12 +11,53 @@ config_version=4
[application]
config/name="Ld 54"
config/description="Get the most out of the small bit of land that you can call yours"
run/main_scene="res://src/Game.tscn"
boot_splash/show_image=false
config/icon="res://icon.png"
[gui]
common/drop_mouse_on_gui_input_disabled=true
[input]
ui_help={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":true,"control":false,"meta":false,"command":false,"pressed":false,"scancode":47,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
ui_plant={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
ui_query={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
ui_cull={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
ui_burn={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":70,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
ui_removerock={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":71,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
ui_fertilize={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":72,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
[physics]
common/enable_pause_aware_picking=true

435
src/Game.gd Normal file
View File

@ -0,0 +1,435 @@
extends Node
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
signal day_time_changed(old, new)
signal season_changed(old, new)
signal year_changed(old, new)
signal action_points_changed(old, new)
signal scores_updated(new)
enum SEASON {SPRING, SUMMER_1, SUMMER_2, FALL}
const season_text = ["Spring", "Early Summer", "Late Summer", "Autumn"]
const season_light_mod = [1.0, 1.1, 1.2, 1.0]
enum TIME {DAWN, MORNING, AFTERNOON, DUSK}
const time_text = ["Dawn", "Morning", "Afternoon", "Dusk"]
const time_light_strength = [20, 60, 80, 10]
const time_light_from = [
# q-r space
Vector2(-1, 0),
Vector2(0, -1),
Vector2(1, -1),
Vector2(1, 0)
]
const time_light_to = [
# q-r space
Vector2(1, 0),
Vector2(0, 1),
Vector2(-1, 1),
Vector2(-1, 0)
]
const StructureSpot = preload("Spot.tscn")
const Soil = preload("Soil.tscn")
const Plant = preload("Plant.tscn")
const HexGrid = preload("HexGrid.tscn")
const FadingText = preload("res://src/ui/FadingText.tscn")
const hex_scale = 1.5
const hex_size = 32 * hex_scale
const hex_width = hex_size * sqrt(3)
const hex_height = 2 * hex_size
var year = 0
var scores = []
var current_season = SEASON.SPRING
var current_time = TIME.DAWN
var grid = null
var action_points = 3
var current_action = "plant"
var last_action = "plant"
var current_plant = "corn"
var current_ap = 3
var current_hex = null
var hex_click_start = null
var stage_timer = 0.0
var stage_time = 2.0
var plant_types = {
"corn": preload("res://src/plants/Corn.tscn").instance(),
"bean": preload("res://src/plants/Bean.tscn").instance(),
"apple": preload("res://src/plants/Apple.tscn").instance(),
"clover": preload("res://src/plants/Clover.tscn").instance(),
"weed": preload("res://src/plants/Weed.tscn").instance(),
"strong_weed": preload("res://src/plants/StrongWeed.tscn").instance(),
}
func sun_strength(time, season):
return round(self.time_light_strength[time] * self.season_light_mod[season])
func update_action_points(value):
emit_signal("action_points_changed", self.action_points, self.action_points + value)
self.action_points += value
func reset():
get_tree().call_group("runtime", "queue_free")
self.year = 0
self.scores = [0]
self.action_points = 3
self.update_action_points(0)
self.current_season = SEASON.SPRING
self.current_time = TIME.DAWN
self.current_ap = 3
self.current_hex = null
if self.current_action == "pass_time":
self.current_action = self.last_action
get_node("Ui/Right/VBoxContainer2/ActionMenu").unlock()
self.hex_click_start = null
self.stage_timer = -1.0
self.grid = null
print("Reset")
self.init_playfield()
func init_playfield():
var grid = HexGrid.instance()
grid.add_to_group("runtime")
grid.init_storage(4)
var center = get_viewport().get_visible_rect().size / 2
var hex_offset = Vector2(
0, # ((4*2)-1) * hex_width / 2,
((4*2)-1) * hex_height / 2
)
hex_offset.x += center.x
# print(str(center))
var soil = 0
var spot = 0
for q in range(-3, 4):
for r in range(-3, 4):
var s = -q-r
# We don't want some parts of the rhombus on the playfield
if abs((q + r)) >= 4:
continue
var x = null
var pos = Vector2(0, 0)
if abs(q) < 3 and abs(r) < 3 and abs(s) < 3:
# On the inside make Soil
x = Soil.instance()
soil += 1
else:
# disable structure spots for the moment
continue
# On the outer ring, make a structure spot, except on the
# bottom half
if r >= 0:
continue
x = StructureSpot.instance()
spot += 1
x.add_to_group("runtime")
x.set_location(Vector2(q, r))
grid.set_item(q, r, x)
# print("Created at ", q, ",", r, ": ", x)
# Set position
pos.y = hex_offset.y + (r * hex_height * 0.75)
pos.x = hex_offset.x + (q * hex_width) + (r * (hex_size-5))
#print(str(q), ",", str(r), " ", str(pos))
x.set_position(pos)
x.connect("mouse_entered", self, "_on_HexHover", [x, true])
x.connect("mouse_exited", self, "_on_HexHover", [x, false])
x.connect("input_event", self, "_on_HexInputEvent", [x])
add_child(x)
for t in range(self.time_light_from.size()):
grid.tag_edge_nodes(self.time_light_from[t], "edge_time_%d" % t)
#print("Created %d soil and %d spot tiles" % [soil, spot])
self.grid = grid
add_child(grid)
# Called when the node enters the scene tree for the first time.
func _ready():
find_node("PlantMenu").set_plants(self.plant_types)
get_node("Ui/Right/VBoxContainer2/ActionMenu").connect("action_changed", self, "_on_action_changed")
self.connect("action_points_changed", get_node("Ui/Right/VBoxContainer2/ActionMenu"), "_on_action_points_changed")
get_node("Ui/Left/VBoxContainer/PlantMenu").connect("plant_type_changed", self, "_on_plant_type_changed")
self.connect("action_points_changed", self, "_on_action_points_changed")
self.connect("day_time_changed", get_node("Sun"), "_on_day_time_changed")
self.connect("day_time_changed", self, "_on_day_time_changed")
self.connect("season_changed", self, "_on_season_changed")
self.connect("year_changed", self, "_on_year_changed")
self.connect("scores_updated", get_node("Ui/Menu"), "_on_scores_updated")
self.reset()
randomize()
func advance_year():
emit_signal("year_changed", self.year, self.year + 1)
self.year += 1
self.scores.append(0)
emit_signal("scores_updated", self.scores)
func advance_season():
var t = self.current_season + 1
var advance_year = false
if t > SEASON.FALL:
t = SEASON.SPRING
advance_year = true
# Do events for the end of the current season
var banner = FadingText.instance()
banner.set_text(self.season_text[t])
banner.set_scale(Vector2(3.0, 3.0))
banner.life_cur = 4.0
var center = get_viewport().get_visible_rect().size / 2
# Do this to remove some of the visual line splitting
var size = banner.get_text_size() * banner.get_scale()
#print("Banner text size: ", size)
#print("Banner size: ", banner.get_size())
banner.set_size(Vector2(size.x, size.y))
size = banner.get_text_size() * banner.get_scale()
banner.set_position(Vector2(center.x - size.x/2.0, 30 - min(10, size.y/2.0)))
#print("Banner position: ", banner.get_position())
add_child(banner)
# Plants consume the nutrients and health of soil + Plant effects
#for soil in get_tree().get_nodes_in_group("soil"):
# soil.nourish_plants_and_run_plant_effects(self.current_season, t, self.grid)
get_tree().call_group("soil", "nourish_plants_and_run_plant_effects", self.current_season, t, self.grid)
# Add action points
self.update_action_points(2)
if advance_year:
for soil in get_tree().get_nodes_in_group("soil"):
if soil.stored != null:
var plant_score = soil.stored.get_score()
self.scores[self.year] += plant_score
if plant_score > 0:
var f = FadingText.instance()
f.set_text("%+d points" % plant_score)
f.set_position(Vector2(32, 32))
f.set_modulate(Color(0.9, 0.1, 0.9))
soil.add_child(f)
soil.end_of_year(self.grid)
self.advance_year()
self.set_season(t)
# Any events at the start of the new season
func set_season(season: int):
emit_signal("season_changed", self.current_season, season)
self.current_season = season
func advance_time():
var t = self.current_time + 1
var advance_season = false
print("Advancing time to ", t)
if t > TIME.DUSK:
t = TIME.DAWN
advance_season = true
# Do the things that have to be done for the old time
# Show where light is coming from
var group = "edge_time_%d" % self.current_time
var sun = self.sun_strength(self.current_time, self.current_season)
for node in get_tree().get_nodes_in_group(group):
node.display_arrow(self.time_light_from[self.current_time],
self.hex_height, self.hex_width, self.hex_size)
# Calculate the light that reaches all the tiles
var first = node
var second = null
var light = sun
var last_tallest = 0
while first != null:
first.apply_light(light)
last_tallest = max(last_tallest, first.get_height())
var loc = first.pf_location + self.time_light_to[self.current_time]
if self.grid._is_valid_q_r(loc.x, loc.y):
second = self.grid.get_item(loc.x, loc.y)
if second != null:
if last_tallest > second.get_height():
light = 0
else:
light = sun
last_tallest = max(last_tallest, second.get_height())
first = second
second = null
# Run growth on tiles
# For tiles that have no plants, weed maybe
if advance_season:
self.advance_season()
self.set_time(t)
# Any events at the start of the new time
func set_time(period: int):
emit_signal("day_time_changed", self.current_time, period)
self.current_time = period
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
if self.current_action == "pass_time":
if self.stage_timer > 0.0:
self.stage_timer -= delta
else:
self.advance_time()
if self.current_time != TIME.DAWN:
self.stage_timer = self.stage_time
else:
self.current_action = self.last_action
self.update_current_hex_action_possibility()
# Some other things...
get_node("Ui/Right/VBoxContainer2/ActionMenu").unlock()
func _unhandled_input(event):
if Input.is_action_pressed("ui_cancel"):
get_node("Ui/Menu").popup_centered()
if Input.is_action_pressed("ui_help"):
var help = get_node("Ui/Help")
if help.is_visible():
help.set_visible(false)
else:
help.popup_centered()
var action_menu = get_node("Ui/Right/VBoxContainer2/ActionMenu")
if Input.is_action_pressed("ui_plant"):
action_menu.find_node("Plant").set_pressed(true)
if Input.is_action_pressed("ui_query"):
action_menu.find_node("Query").set_pressed(true)
if Input.is_action_pressed("ui_cull"):
action_menu.find_node("Cull").set_pressed(true)
if Input.is_action_pressed("ui_burn"):
action_menu.find_node("Burn").set_pressed(true)
if Input.is_action_pressed("ui_removerock"):
action_menu.find_node("RemoveRock").set_pressed(true)
if Input.is_action_pressed("ui_fertilize"):
action_menu.find_node("Fertilize").set_pressed(true)
func _on_Help_pressed():
get_node("Ui/Help").popup_centered()
func _on_MenuButton_pressed():
get_node("Ui/Menu").popup_centered()
func _on_HexHover(hex, inside):
#print("Hex ", hex, " at ", hex.pf_location)
if inside:
self.current_hex = hex
hex.start_tooltip_timer()
hex.get_node("Border").set_modulate(Color(0.0, 1.0, 0.0))
self.update_current_hex_action_possibility()
else:
self.current_hex = null
hex.update_tooltip("")
hex.hide_tooltip()
hex.get_node("Border").set_modulate(Color(1.0, 1.0, 1.0))
self.update_current_hex_action_possibility()
func update_current_hex_action_possibility():
if self.current_hex == null:
# Reset mouse pointer
Input.set_default_cursor_shape(Input.CURSOR_ARROW)
return
# Need to check if current action be done on the hex
# Show user why not
var action_compat = self.current_hex.can_do_action(self.current_action)
var applicable = action_compat[0]
var possible = action_compat[1]
var reason = action_compat[2]
var cost = action_compat[3]
if cost > self.action_points:
possible = false
reason = "Too few action points. Have %d, need %d" % [self.action_points, cost]
if applicable:
if not possible:
Input.set_default_cursor_shape(Input.CURSOR_FORBIDDEN)
self.current_hex.get_node("Border").set_modulate(Color(1.0, 0.0, 0.0))
self.current_hex.update_tooltip(reason)
else:
Input.set_default_cursor_shape(Input.CURSOR_CAN_DROP)
else:
self.current_hex.get_node("Border").set_modulate(Color(0.25, 0.25, 0.25))
func _on_HexInputEvent(viewport, event, shape, hex):
if event is InputEventMouseButton:
if event.button_index == BUTTON_LEFT:
if event.pressed:
self.hex_click_start = hex
else:
if self.hex_click_start == hex:
self.do_action(hex, self.current_action)
else:
self.hex_click_start = null
func do_action(hex, action):
# Recheck if action is possible on hex
var action_compat = hex.can_do_action(action)
var cost = action_compat[3]
if not action_compat[0] or not action_compat[1]:
return
if cost > self.action_points:
return
print(action, " on ", hex)
if action == "query":
get_node("Ui/Right/VBoxContainer2/Details/Panel").set_text(hex.query_details())
get_node("AudioQuery").play()
elif action == "plant":
print(self.current_plant)
hex.do_action(action,
{"plant": self.plant_types[self.current_plant].duplicate()})
get_node("AudioPlant").play()
elif action == "cull":
var r = hex.do_action(action, null)
if r != null and r > 0:
self.scores[self.current_year] += r
print("Got %+d from culling plant", r)
emit_signal("scores_updated", self.scores)
get_node("AudioCull").play()
elif action == "burn":
hex.do_action(action, null)
get_node("AudioBurn").play()
elif action == "removerock":
hex.do_action(action, null)
get_node("AudioRemoveRock").play()
elif action == "fertilize":
hex.do_action(action, null)
get_node("AudioFertilize").play()
else:
print("UNKNOWN ACTION ", action)
if (cost > 0):
var f = FadingText.instance()
f.set_text("%+d AP" % -cost)
f.set_position(Vector2(32, 0))
f.move_towards = Vector2(64, -32)
f.set_modulate(Color(0.9, 0.1, 0.1))
hex.add_child(f)
self.update_action_points(-cost)
func _on_action_changed(action):
self.last_action = self.current_action
self.current_action = action
self.update_current_hex_action_possibility()
if action == "pass_time":
self.advance_time()
self.stage_timer = self.stage_time
func _on_day_time_changed(old, new):
get_node("Ui/Left/VBoxContainer/TimeLabel").set_text("Time: %s" % self.time_text[new])
# Show a banner of the stage
var banner = FadingText.instance()
banner.set_text(self.time_text[old])
banner.set_scale(Vector2(2.0, 2.0))
var center = get_viewport().get_visible_rect().size / 2
var size = banner.get_text_size()
banner.set_position(Vector2(center.x - size.x/2.0, center.y*2.0 - 20 - size.y/2.0))
add_child(banner)
if new == TIME.DAWN:
get_node("AudioDawn").play()
func _on_season_changed(old, new):
get_node("Ui/Left/VBoxContainer/SeasonLabel").set_text("Season: %s" % self.season_text[new])
func _on_year_changed(old, new):
get_node("Ui/Left/VBoxContainer/YearLabel").set_text("Year: %d" % self.year)
func _on_action_points_changed(old, new):
self.update_current_hex_action_possibility()
func _on_plant_type_changed(value):
self.current_plant = value

171
src/Game.tscn Normal file
View File

@ -0,0 +1,171 @@
[gd_scene load_steps=15 format=2]
[ext_resource path="res://src/Game.gd" type="Script" id=1]
[ext_resource path="res://src/Menu.tscn" type="PackedScene" id=2]
[ext_resource path="res://src/Help.tscn" type="PackedScene" id=3]
[ext_resource path="res://src/Sun.tscn" type="PackedScene" id=4]
[ext_resource path="res://src/ui/PlantMenu.tscn" type="PackedScene" id=5]
[ext_resource path="res://src/ui/ActionMenu.tscn" type="PackedScene" id=6]
[ext_resource path="res://assets/bg.png" type="Texture" id=7]
[ext_resource path="res://assets/Tweet.wav" type="AudioStream" id=8]
[ext_resource path="res://assets/Plant.wav" type="AudioStream" id=9]
[ext_resource path="res://assets/Rock.wav" type="AudioStream" id=10]
[ext_resource path="res://assets/Query.wav" type="AudioStream" id=11]
[ext_resource path="res://assets/Cull.wav" type="AudioStream" id=12]
[ext_resource path="res://assets/Fertilize.wav" type="AudioStream" id=13]
[ext_resource path="res://assets/Burn.wav" type="AudioStream" id=14]
[node name="Game" type="Node2D"]
script = ExtResource( 1 )
[node name="Ui" type="Control" parent="."]
margin_right = 40.0
margin_bottom = 40.0
[node name="Menu" parent="Ui" instance=ExtResource( 2 )]
[node name="Help" parent="Ui" instance=ExtResource( 3 )]
[node name="Left" type="Panel" parent="Ui"]
margin_right = 160.0
margin_bottom = 600.0
size_flags_horizontal = 0
size_flags_vertical = 0
[node name="VBoxContainer" type="VBoxContainer" parent="Ui/Left"]
margin_right = 40.0
margin_bottom = 40.0
[node name="TimeLabel" type="Button" parent="Ui/Left/VBoxContainer"]
margin_right = 160.0
margin_bottom = 20.0
hint_tooltip = "When you \"Let Time Pass\", the day goes through Dawn, Morning, Afternoon, and Dusk.
Each part of the day shines light from a different direction on to your field. The sun is strongest in the Afternoon.
Tall items block the passage of sunlight to those behind."
focus_mode = 0
shortcut_in_tooltip = false
enabled_focus_mode = 0
text = "Time: Dawn"
flat = true
[node name="SeasonLabel" type="Button" parent="Ui/Left/VBoxContainer"]
margin_top = 24.0
margin_right = 160.0
margin_bottom = 44.0
hint_tooltip = "Each Dawn is the start of a new season.
Each new season gives you more Action Points (AP).
At the end of the Autumn season, all the plants are automatically harvested.
Unless a perennial survives winter, it will also be removed."
shortcut_in_tooltip = false
text = "Season: Spring"
flat = true
[node name="YearLabel" type="Button" parent="Ui/Left/VBoxContainer"]
margin_top = 48.0
margin_right = 160.0
margin_bottom = 68.0
hint_tooltip = "The in-game year"
shortcut_in_tooltip = false
text = "Year: 0"
flat = true
[node name="PlantMenu" parent="Ui/Left/VBoxContainer" instance=ExtResource( 5 )]
margin_top = 72.0
margin_right = 160.0
margin_bottom = 395.0
[node name="Right" type="Panel" parent="Ui"]
margin_left = 864.0
margin_right = 1024.0
margin_bottom = 600.0
__meta__ = {
"_edit_group_": true
}
[node name="VBoxContainer2" type="VBoxContainer" parent="Ui/Right"]
margin_right = 40.0
margin_bottom = 40.0
[node name="HBoxContainer" type="HBoxContainer" parent="Ui/Right/VBoxContainer2"]
margin_right = 160.0
margin_bottom = 20.0
rect_min_size = Vector2( 160, 0 )
size_flags_horizontal = 3
size_flags_vertical = 3
alignment = 1
[node name="Help" type="Button" parent="Ui/Right/VBoxContainer2/HBoxContainer"]
margin_left = 33.0
margin_right = 75.0
margin_bottom = 20.0
hint_tooltip = "Help"
text = "Help"
icon_align = 1
expand_icon = true
[node name="MenuButton" type="Button" parent="Ui/Right/VBoxContainer2/HBoxContainer"]
margin_left = 79.0
margin_right = 127.0
margin_bottom = 20.0
hint_tooltip = "Menu"
text = "Menu"
align = 0
icon_align = 1
expand_icon = true
[node name="ActionMenu" parent="Ui/Right/VBoxContainer2" instance=ExtResource( 6 )]
margin_bottom = 285.0
[node name="Details" type="VBoxContainer" parent="Ui/Right/VBoxContainer2"]
margin_top = 289.0
margin_right = 160.0
margin_bottom = 322.0
[node name="Label" type="Label" parent="Ui/Right/VBoxContainer2/Details"]
margin_right = 160.0
margin_bottom = 14.0
text = "Details"
align = 1
valign = 1
autowrap = true
uppercase = true
[node name="Panel" type="RichTextLabel" parent="Ui/Right/VBoxContainer2/Details"]
margin_top = 18.0
margin_right = 160.0
margin_bottom = 33.0
bbcode_enabled = true
fit_content_height = true
[node name="Sun" parent="." instance=ExtResource( 4 )]
position = Vector2( 226, 335 )
[node name="Background" type="Sprite" parent="."]
z_index = -2
z_as_relative = false
texture = ExtResource( 7 )
centered = false
[node name="AudioDawn" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 8 )
[node name="AudioPlant" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 9 )
[node name="AudioQuery" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 11 )
[node name="AudioCull" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 12 )
[node name="AudioRemoveRock" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 10 )
[node name="AudioBurn" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 14 )
[node name="AudioFertilize" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 13 )
[connection signal="pressed" from="Ui/Right/VBoxContainer2/HBoxContainer/Help" to="." method="_on_Help_pressed"]
[connection signal="pressed" from="Ui/Right/VBoxContainer2/HBoxContainer/MenuButton" to="." method="_on_MenuButton_pressed"]

16
src/Help.gd Normal file
View File

@ -0,0 +1,16 @@
extends PopupPanel
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

87
src/Help.tscn Normal file
View File

@ -0,0 +1,87 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://src/Help.gd" type="Script" id=1]
[ext_resource path="res://assets/Bitstream Vera Sans Mono Bold Nerd Font Complete.ttf" type="DynamicFontData" id=2]
[ext_resource path="res://assets/screenshots/tile.png" type="Texture" id=3]
[ext_resource path="res://assets/screenshots/light.png" type="Texture" id=4]
[sub_resource type="DynamicFont" id=1]
size = 40
outline_size = 1
font_data = ExtResource( 2 )
[node name="Help" type="PopupPanel"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 72.0
margin_right = 72.0
script = ExtResource( 1 )
[node name="HBoxContainer" type="VBoxContainer" parent="."]
margin_right = 40.0
margin_bottom = 40.0
[node name="Label" type="Label" parent="HBoxContainer"]
margin_right = 965.0
margin_bottom = 48.0
size_flags_horizontal = 3
custom_colors/font_color = Color( 0.996078, 1, 0.258824, 1 )
custom_colors/font_outline_modulate = Color( 1, 0, 0.972549, 1 )
custom_fonts/font = SubResource( 1 )
text = "Da 'Lil Patch"
align = 1
[node name="VBoxContainer" type="HBoxContainer" parent="HBoxContainer"]
margin_top = 52.0
margin_right = 965.0
margin_bottom = 508.0
[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer/VBoxContainer"]
margin_right = 965.0
margin_bottom = 456.0
[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/VBoxContainer/HBoxContainer"]
margin_right = 160.0
margin_bottom = 456.0
rect_min_size = Vector2( 160, 0 )
[node name="Sprite" type="Sprite" parent="HBoxContainer/VBoxContainer/HBoxContainer/VBoxContainer"]
position = Vector2( 84, 63 )
texture = ExtResource( 3 )
[node name="Sprite2" type="Sprite" parent="HBoxContainer/VBoxContainer/HBoxContainer/VBoxContainer"]
position = Vector2( 78, 223 )
scale = Vector2( 0.623711, 0.617424 )
texture = ExtResource( 4 )
[node name="Label2" type="Label" parent="HBoxContainer/VBoxContainer/HBoxContainer"]
margin_left = 164.0
margin_right = 965.0
margin_bottom = 456.0
text = "In \"Da 'Lil Patch\", the goal is to make the best use of the small plot of land you have.
Choose plants from the left-hand side menu, and select which actions you want to do from the right-hand side menu.
1. The first thing you will want to do is place some seeds down.
2. Click pass time to see how the plants get sunlight and grow
At the end of each \"Autumn\" plants are harvested and give you score based on how ripe they are. Some plants, like Weeds
and Clover, don't give any points. Some plants can take a long time to bear fruit.
Each plant changes the soil it's own, and potentially affects the tiles around it it.
The sunlight comes from four (4) different directions each time you click on \"Pass Time\": left, top-left, top-right, and right.
The strength of the sunlight varies with the time of day and the current season. As each growth tick happens, you'll see \"+X\"
over the plants in green for how much growth they received.
Some tiles also turn dark, to show that they haven't received any sunlight. When there is a plant in the tile that's taller than
the adjacent tiles in the sunlight's path, it will shade the next tiles until a taller plant is encountered.
As each season passes, the plants consume nutrients and health from the soil. Most soil also accumulates rocks as the
harvests happen. Eventually there might be big boulders on some of the tiles! Each season also gives you some more Action
Points, which can be used to Cull (remove) plants early, Burn plants off the land, Remove Rocks, or Fertilize a tile. Each action
has a different cost and effect explained by the tooltips.
You can check the scores for the years that have passed in the menu by clicking on the Menu button or hitting Escape.
You can press escape to close this pane, and Shift+Slash to show it again."

106
src/Hex.gd Normal file
View File

@ -0,0 +1,106 @@
extends Node2D
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
var pf_location = Vector2(-1, -1)
var stored = null
var tooltip_timer = -1.0
var last_light_received = 0
var last_light_timer = 0.0
var last_light_timer_max = 2.0
var arrow_sprite_life_max = 2.0
var arrow_sprite_life = 0.0
var arrow_sprite = preload("res://assets/small arrow.png")
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func _process(delta):
if tooltip_timer != -1.0:
if tooltip_timer >= 0.0:
tooltip_timer -= delta
if tooltip_timer <= 0.0 and not get_node("Tooltip").is_visible():
get_node("Tooltip").set_visible(true)
if self.arrow_sprite_life > 0.0:
self.arrow_sprite_life -= delta
if self.arrow_sprite_life <= 0.0:
get_node("Arrow").queue_free()
if self.last_light_timer >= 0.0:
self.last_light_timer -= delta
if self.last_light_timer <= 0.0:
get_node("Light").set_visible(false)
if get_node("Sprite") != null:
get_node("Sprite").set_modulate(self.get_default_modulate())
func start_tooltip_timer():
self.tooltip_timer = 0.5
func hide_tooltip():
get_node("Tooltip").set_visible(false)
self.tooltip_timer = -1.0
func set_location(x: Vector2):
self.pf_location = x
self.update_tooltip("")
func update_tooltip(tooltip):
if tooltip:
tooltip += "\n"
tooltip += "Location: " + str(pf_location.x) + "," + str(pf_location.y)
get_node("Tooltip").set_text(tooltip)
func query_details():
return "Location: " + str(pf_location.x) + "," + str(pf_location.y)
func can_do_action(action):
if action == "query":
return [true, true, "", 0]
else:
return [false, false, "Action not applicable: " + action, 0]
func do_action(action, args):
pass
func get_height():
if self.stored == null:
return 0;
return self.stored.height
func display_arrow(direction: Vector2, height, width, size):
var s = Sprite.new()
s.set_texture(self.arrow_sprite)
s.set_name("Arrow")
self.arrow_sprite_life = self.arrow_sprite_life_max
var pos = Vector2(
(direction.x * height * 0.75) + (direction.y * width * 0.6),
(direction.y * size * 1.25)
)
s.set_position(pos)
var angle = PI * float(-direction.x) * 0.5
angle += PI * float(direction.y) * 0.33
if direction.y != 0 and direction.x == 0:
angle += PI
s.rotate(angle)
add_child(s)
func apply_light(value):
# print("[%s] Received light: %s" % [self, value])
self.last_light_received = value
get_node("Light").set_text(str(self.last_light_received))
get_node("Light").set_visible(true)
self.last_light_timer = self.last_light_timer_max
if get_node("Sprite") != null and value <= 0:
get_node("Sprite").set_modulate(Color(0, 0, 0, 0.50))
func get_neighbours(grid, include_storage = false):
var r = []
var neighbours = grid.get_neighbours(self.pf_location.x, self.pf_location.y)
if include_storage:
return neighbours
func get_default_modulate():
return Color(1.0, 1.0, 1.0, 1.0)

42
src/Hex.tscn Normal file
View File

@ -0,0 +1,42 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://assets/hex.png" type="Texture" id=1]
[ext_resource path="res://src/Hex.gd" type="Script" id=2]
[node name="Hex" type="Area2D"]
script = ExtResource( 2 )
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."]
polygon = PoolVector2Array( 34, -21, 0, -41, -37, -19, -37, 22, -1, 42, 34, 22 )
[node name="Border" type="Sprite" parent="."]
scale = Vector2( 1.5, 1.5 )
texture = ExtResource( 1 )
[node name="Tooltip" type="RichTextLabel" parent="."]
visible = false
margin_left = -39.0
margin_top = 5.0
margin_right = 101.0
margin_bottom = 51.0
text = "Lorem Ipsum"
fit_content_height = true
[node name="Light" type="RichTextLabel" parent="."]
visible = false
margin_left = -38.0
margin_top = -21.0
margin_right = 2.0
margin_bottom = 19.0
text = "0"
fit_content_height = true
[node name="Growth" type="RichTextLabel" parent="."]
visible = false
margin_left = 29.0
margin_top = -20.0
margin_right = 69.0
margin_bottom = 20.0
mouse_filter = 2
text = "0"
fit_content_height = true

6
src/HexGrid.tscn Normal file
View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://HexGrid.gd" type="Script" id=1]
[node name="HexGrid" type="Node2D"]
script = ExtResource( 1 )

83
src/Menu.tscn Normal file
View File

@ -0,0 +1,83 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://Menu.gd" type="Script" id=1]
[ext_resource path="res://assets/Bitstream Vera Sans Mono Bold Nerd Font Complete.ttf" type="DynamicFontData" id=2]
[sub_resource type="DynamicFont" id=1]
size = 40
outline_size = 1
font_data = ExtResource( 2 )
[node name="Menu" type="PopupPanel"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_right = -484.0
margin_bottom = -354.0
size_flags_horizontal = 0
size_flags_vertical = 0
script = ExtResource( 1 )
[node name="VBoxContainer" type="VBoxContainer" parent="."]
margin_left = 4.0
margin_top = 4.0
margin_right = 536.0
margin_bottom = 242.0
[node name="Label" type="Label" parent="VBoxContainer"]
margin_right = 532.0
margin_bottom = 48.0
size_flags_horizontal = 3
custom_colors/font_color = Color( 0.996078, 1, 0.258824, 1 )
custom_colors/font_outline_modulate = Color( 1, 0, 0.972549, 1 )
custom_fonts/font = SubResource( 1 )
text = "Da 'Lil Patch"
align = 1
[node name="Score" type="RichTextLabel" parent="VBoxContainer"]
margin_top = 52.0
margin_right = 532.0
margin_bottom = 67.0
bbcode_enabled = true
bbcode_text = "[center]Score: 0[/center]"
text = "Score: 0"
fit_content_height = true
[node name="ScoreByYear" type="RichTextLabel" parent="VBoxContainer"]
margin_top = 71.0
margin_right = 532.0
margin_bottom = 86.0
bbcode_enabled = true
fit_content_height = true
[node name="Continue" type="Button" parent="VBoxContainer"]
margin_top = 90.0
margin_right = 532.0
margin_bottom = 124.0
size_flags_vertical = 3
text = "Continue"
[node name="Restart" type="Button" parent="VBoxContainer"]
margin_top = 128.0
margin_right = 532.0
margin_bottom = 162.0
size_flags_vertical = 3
text = "Restart"
[node name="Help" type="Button" parent="VBoxContainer"]
margin_top = 166.0
margin_right = 532.0
margin_bottom = 200.0
size_flags_vertical = 3
text = "Help"
[node name="Quit" type="Button" parent="VBoxContainer"]
margin_top = 204.0
margin_right = 532.0
margin_bottom = 238.0
size_flags_vertical = 3
text = "Quit"
[connection signal="pressed" from="VBoxContainer/Continue" to="." method="_on_Continue_pressed"]
[connection signal="pressed" from="VBoxContainer/Restart" to="." method="_on_Restart_pressed"]
[connection signal="pressed" from="VBoxContainer/Help" to="." method="_on_Help_pressed"]
[connection signal="pressed" from="VBoxContainer/Quit" to="." method="_on_Quit_pressed"]

150
src/Plant.gd Normal file
View File

@ -0,0 +1,150 @@
extends Node2D
const FadingText = preload("res://src/ui/FadingText.tscn")
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
enum STAGE {SEED, SPROUT, GROWTH, FRUIT, RIPE}
const default_sprites = [
preload("res://assets/seeds.png"),
preload("res://assets/sprouts.png"),
preload("res://assets/plant.png"),
preload("res://assets/plant.png"),
preload("res://assets/plant.png"),
preload("res://assets/plant.png")
]
var sprites = []
var icon = preload("res://assets/hex.png")
var icon_tooltip = "Plaaaant me"
var description = "A plant"
# run time
var growth = 0
var height = 0
# per-type stats
# each stat contributes to growth during each section of the day
# there are 4 sections to the day, and 4 growing periods
var light_range = [15, 85] # below x too shady, above y too sunny
var growth_mod_by_light = [2, 10, -1] # shady, ok, sunny
var rockiness_range = [5, 50]
var growth_mod_by_rockiness = [-1, 10, -5]
var nutrient_range = [10, 100]
var growth_mod_by_nutrition = [0, 10, 15]
var soil_health_range = [25, 75]
var growth_mod_by_soil_health = [0, 5, 10]
var base_score = 100
var score_mod_by_growth = [0.0, 0.0, 0.0, 0.1, 1.2, 1.5]
var growth_thresholds = [100, 175, 250, 300, 400] # for each stage above
var heights = [0, 0, 1, 1, 1, 1]
var plantable = true
var survives_winter = false
var season_rockiness_mod = 0
var season_nutrient_mod = -10
var season_health_mod = -5
var harvest_nutrient_mod = 5
var harvest_health_mod = 5
var harvest_rockiness_mod = 5
# @TODO adjacency effects
static func find_by_range_area(value, ranges, mods):
var v = 0
for x in ranges:
if value > x:
v += 1
continue
break
if v >= mods.size():
v = mods.size()-1
return mods[v]
# Called when the node enters the scene tree for the first time.
func _ready():
get_node("Sprite").set_texture(self.sprites[self.get_stage()])
func get_description():
var s = "%s\n\n" % self.description
s += "Base score: %d\nScore mods by growth stage: %s\n\n" % [self.base_score, self.score_mod_by_growth]
s += "At the end of each season\n\tRockiness: %d\n\tSoil health: %d\n\tSoil nutrients: %d\n\n" %[self.season_rockiness_mod, self.season_health_mod, self.season_nutrient_mod]
s += "When harvested:\n\tRockiness: %d\n\tSoil health: %d\n\tSoil nutrients: %d\n" %[self.harvest_rockiness_mod, self.harvest_health_mod, self.harvest_nutrient_mod]
return s
func _init():
self.sprites.resize(self.default_sprites.size())
for x in range(self.default_sprites.size()):
if self.sprites[x] == null:
self.sprites[x] = self.default_sprites[x]
func query_details():
var stage = self.get_stage()
var next = "N/A"
if stage < self.growth_thresholds.size():
next = str(self.growth_thresholds[stage])
var s = "Growth: %d\nHeight: %d\nNext stage at: %s\n\n" % [self.growth, self.height, next]
return s
func get_stage():
var stage = 0
for x in self.growth_thresholds:
if self.growth >= x:
stage += 1
else:
break
return stage
func get_icon_tooltip():
return self.icon_tooltip
func apply_light(light, soil):
var growth_light = self.find_by_range_area(light, self.light_range, self.growth_mod_by_light)
var growth_rockiness = self.find_by_range_area(soil.rockiness, self.rockiness_range, self.growth_mod_by_rockiness)
var growth_health = self.find_by_range_area(soil.misc_health, self.soil_health_range, self.growth_mod_by_soil_health)
var growth_nutrients = self.find_by_range_area(soil.nutrients, self.nutrient_range, self.growth_mod_by_nutrition)
var growth = growth_light + growth_rockiness + growth_health + growth_nutrients
#print("Grew %d = %d + %d + %d + %d" %[growth, growth_light, growth_rockiness, growth_health, growth_nutrients])
self.grow(growth)
func grow(value):
var index = self.get_stage()
if index >= self.heights.size():
index = self.heights.size() - 1
self.growth += value
self.height = self.heights[index]
get_node("Height").set_text(str(self.height))
get_node("Sprite").set_texture(self.sprites[index])
var t = FadingText.instance()
t.set_position(Vector2(32, -24))
t.move_towards = Vector2(50, -60)
t.set_text("%+d🌱🌱" % value)
t.set_modulate(Color(0.1, 0.85, 0.1))
t.set_scale(Vector2(1.5, 1.5))
add_child(t)
func get_score():
var mod = self.find_by_range_area(self.growth, self.growth_thresholds, self.score_mod_by_growth)
var score = int(round(float(self.base_score) * mod))
return score
func use_nutrients_and_run_plant_effects(soil, old_season, new_season, grid):
print("plant use nitrients ", self)
soil.update_stat("rockiness", self.season_rockiness_mod)
soil.update_stat("nutrients", self.season_nutrient_mod)
soil.update_stat("health", self.season_health_mod)
func end_of_year(soil, grid):
soil.update_stat("nutrients", self.harvest_nutrient_mod)
soil.update_stat("health", self.harvest_health_mod)
if not self.survives_winter:
soil.update_stat("rockiness", self.harvest_rockiness_mod)
self.queue_free()
soil.stored = null
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

19
src/Plant.tscn Normal file
View File

@ -0,0 +1,19 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://src/Plant.gd" type="Script" id=1]
[node name="Plant" type="Node2D"]
script = ExtResource( 1 )
[node name="Sprite" type="Sprite" parent="."]
scale = Vector2( 1.5, 1.5 )
[node name="Height" type="RichTextLabel" parent="."]
margin_left = -4.0
margin_top = 26.0
margin_right = 36.0
margin_bottom = 66.0
hint_tooltip = "Height"
mouse_filter = 1
text = "0"
fit_content_height = true

160
src/Soil.gd Normal file
View File

@ -0,0 +1,160 @@
extends "res://src/Hex.gd"
const Plant = preload("res://src/Plant.tscn")
signal soil_stat_changed(name, old, new)
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
var weed_rockiness_range = [20, 60]
var weed_probability_from_rockiness = [0.05, 0.1, 0.15]
var weed_health_range = [25, 50, 75]
var weed_probability_from_health = [0.2, 0.15, 0.1, 0.05]
var weed_nutrient_range = [33, 66]
var weed_probability_from_nutrient = [0.1, 0.2, 0.3]
var strong_weed_probability = 0.5
var rockiness = 0
var nutrients = 50
var misc_health = 50 # pH, moisture, aeration
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
static func find_by_range_area(value, ranges, mods):
var v = 0
for x in ranges:
if value > x:
v += 1
continue
break
if v >= mods.size():
v = mods.size()-1
return mods[v]
func can_do_action(action):
if action == "plant":
return [true, self.stored == null, "", 0]
elif action == "cull":
return [true, self.stored != null, "You can only cull on soil tiles that have plants", 1]
elif action == "burn":
return [true, self.stored != null, "You can only burn soil tiles that have plants", 2]
elif action == "removerock":
return [true, self.rockiness >= 20, "You can only remove rocks on soil that have rocks >= 20", 3]
elif action == "fertilize":
return [true, true, "", 4]
return .can_do_action(action)
func query_details():
var details = "Rockiness: %d\nNutrients %d\nHealth %d\n\nPlant: %s\n" % [self.rockiness, self.nutrients, self.misc_health, str(self.stored)]
if self.stored != null and self.stored:
details += self.stored.query_details()
details += "Soil gains rockiness and loses nutrients and health over time based on which plants are sown.\n\n"
details += "If there are no plants, there's a chance that weeds grow.\n\n"
details += .query_details()
return details
func do_action(action, args):
if action == "cull":
assert(self.stored != null)
var plant = self.stored
self.stored = null
var score = plant.get_score()
self.update_stat("rockiness", plant.harvest_rockiness_mod)
# @TODO do plant removal effects
plant.queue_free()
return score
elif action == "plant":
self.stored = args["plant"]
add_child(self.stored)
self.stored.add_to_group("runtime")
elif action == "burn":
assert(self.stored != null)
var plant = self.stored
self.stored = null
self.update_stat("nutrients", 15)
self.update_stat("health", -5)
plant.queue_free()
elif action == "removerock":
self.update_stat("rockiness", -self.rockiness)
elif action == "fertilize":
self.update_stat("nutrients", 50)
self.update_stat("health", 50)
func apply_light(value):
.apply_light(value)
if self.stored != null:
self.stored.apply_light(value, self)
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass
func nourish_plants_and_run_plant_effects(old_season, new_season, grid):
print("soil nourish")
if self.stored:
self.stored.use_nutrients_and_run_plant_effects(self, old_season, new_season, grid)
else:
# Increase the health of the soil slightly from not being used
self.update_stat("misc_health", 2)
# Chance of generating a weed
var p_weed = 0.0
p_weed += find_by_range_area(self.rockiness, self.weed_rockiness_range, self.weed_probability_from_rockiness)
p_weed += find_by_range_area(self.nutrients, self.weed_nutrient_range, self.weed_probability_from_nutrient)
p_weed += find_by_range_area(self.misc_health, self.weed_health_range, self.weed_probability_from_health)
if randf() <= p_weed:
var weed_name = "weed"
if randf() > self.strong_weed_probability:
weed_name = "strong_weed"
var game = get_tree().current_scene
self.do_action("plant", {"plant": game.plant_types[weed_name].duplicate()})
func end_of_year(grid):
if self.stored:
self.stored.end_of_year(self, grid)
#
func update_stat(name, value):
var old
var new
if name == "rockiness":
old = self.rockiness
new = self.rockiness + value
new = min(100, max(0, new))
self.rockiness = new
var rock_sprite = null
if self.rockiness >= 75:
rock_sprite = load("res://assets/rocky 3.png")
elif self.rockiness >= 50:
rock_sprite = load("res://assets/rocky 2.png")
elif self.rockiness >= 20:
rock_sprite = load("res://assets/rocky 1.png")
if rock_sprite != null:
get_node("Rocks").set_texture(rock_sprite)
get_node("Rocks").set_visible(rock_sprite != null)
elif name == "health":
old = self.misc_health
new = self.misc_health + value
new = min(100, max(0, new))
self.misc_health = new
elif name == "nutrients":
old = self.nutrients
new = self.nutrients + value
new = min(100, max(0, new))
self.nutrients = new
else:
print("Unknown stat: %s" % name)
return
if old != new:
emit_signal("soil_stat_changed", name, old, new)
func get_default_modulate():
if self.misc_health >= 75:
return Color("#b27308")
elif self.misc_health >= 50:
return Color("#da8d09")
elif self.misc_health >= 25:
return Color("#c49911")
return Color("#faaf2f")

16
src/Soil.tscn Normal file
View File

@ -0,0 +1,16 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://src/Soil.gd" type="Script" id=1]
[ext_resource path="res://src/Hex.tscn" type="PackedScene" id=2]
[ext_resource path="res://assets/soil.png" type="Texture" id=3]
[node name="Soil" groups=["soil"] instance=ExtResource( 2 )]
script = ExtResource( 1 )
[node name="Rocks" type="Sprite" parent="." index="2"]
[node name="Sprite" type="Sprite" parent="." index="3"]
modulate = Color( 0.909804, 0.588235, 0.0352941, 1 )
scale = Vector2( 1.5, 1.5 )
z_index = -1
texture = ExtResource( 3 )

22
src/Spot.gd Normal file
View File

@ -0,0 +1,22 @@
extends "res://src/Hex.gd"
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
func _ready():
#get_node("Border").set_modulate(Color(1.0, 0.0, 0.0))
pass # Replace with function body.
func query_details():
var details = "Structure spots are tiles in which various objects may be built.\n\n"
details += "Object: %s\n\n" % self.stored
details += .query_details()
return details
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

7
src/Spot.tscn Normal file
View File

@ -0,0 +1,7 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/Hex.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/Spot.gd" type="Script" id=2]
[node name="Spot" groups=["spot"] instance=ExtResource( 1 )]
script = ExtResource( 2 )

25
src/Sun.gd Normal file
View File

@ -0,0 +1,25 @@
extends Node2D
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
var goal = 0.0
var goals = [0.0, 0.35, 0.75, 1.0]
var speed = 0.3
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func _on_day_time_changed(old, new):
#print("Sun time: ", new)
self.goal = goals[new]
func _process(delta):
if abs(self.goal - get_node("Path2D/PathFollow2D").get_unit_offset()) > 0.1:
var offset = get_node("Path2D/PathFollow2D").get_unit_offset()
offset += self.speed * delta
if offset >= self.goal:
offset = self.goal
get_node("Path2D/PathFollow2D").set_unit_offset(offset)

26
src/Sun.tscn Normal file
View File

@ -0,0 +1,26 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://assets/sun.png" type="Texture" id=1]
[ext_resource path="res://src/Sun.gd" type="Script" id=2]
[sub_resource type="Curve2D" id=1]
_data = {
"points": PoolVector2Array( -0.840896, -10.0908, 0.840896, 10.0908, -3, -11, 0, 0, 0, 0, 9, -74, 0, 0, 0, 0, 27, -132, 0, 0, 0, 0, 45, -164, 0, 0, 0, 0, 71, -199, 0, 0, 0, 0, 100, -222, 0, 0, 0, 0, 136, -236, 0, 0, 0, 0, 172, -247, 0, 0, 0, 0, 208, -257, 0, 0, 0, 0, 243, -265, 0, 0, 0, 0, 272, -266, 0, 0, 0, 0, 317, -265, 0, 0, 0, 0, 355, -259, 0, 0, 0, 0, 389, -251, 0, 0, 0, 0, 429, -238, 0, 0, 0, 0, 455, -224, 0, 0, 0, 0, 478, -206, 0, 0, 0, 0, 506, -184, 0, 0, 0, 0, 543, -146, 0, 0, 0, 0, 559, -119, 0, 0, 0, 0, 568, -97, 0, 0, 0, 0, 579, -63, 0, 0, 0, 0, 584, -17, 0, 0, 0, 0, 589, 78 )
}
[node name="Sun" type="Node2D"]
script = ExtResource( 2 )
[node name="Path2D" type="Path2D" parent="."]
curve = SubResource( 1 )
[node name="PathFollow2D" type="PathFollow2D" parent="Path2D"]
position = Vector2( -3, -11 )
rotation = -1.3641
rotate = false
lookahead = 128.411
[node name="Sprite" type="Sprite" parent="Path2D/PathFollow2D"]
rotation = -0.244346
scale = Vector2( 2, 2 )
texture = ExtResource( 1 )

35
src/plants/Apple.gd Normal file
View File

@ -0,0 +1,35 @@
extends "res://src/Plant.gd"
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
func _init():
self.icon = preload("res://assets/apple icon.png")
self.icon_tooltip = "A slow growing tree that survives over winter"
self.description = "Delicious, but you have to plan ahead"
self.light_range = [25, 75]
self.season_nutrient_mod = -1
self.season_health_mod = -1
self.harvest_nutrient_mod = 0
self.harvest_health_mod = 0
self.base_score = 300
self.sprites[2] = preload("res://assets/apple plant.png")
self.sprites[3] = preload("res://assets/apple plant.png")
self.sprites[4] = preload("res://assets/apple tree.png")
self.sprites[5] = preload("res://assets/apple fruit.png")
self.heights = [0, 1, 2, 3, 4, 5]
self.score_mod_by_growth = [0.0, 0.0, 0.0, 0.0, 2, 3]
self.growth_thresholds = [200, 400, 600, 800, 1000]
self.survives_winter = true
self.harvest_rockiness_mod = 100
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

7
src/plants/Apple.tscn Normal file
View File

@ -0,0 +1,7 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/Plant.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/plants/Apple.gd" type="Script" id=2]
[node name="Apple" instance=ExtResource( 1 )]
script = ExtResource( 2 )

30
src/plants/Bean.gd Normal file
View File

@ -0,0 +1,30 @@
extends "res://src/Plant.gd"
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
func _init():
self.icon = preload("res://assets/bean icon.png")
self.icon_tooltip = "Beans help replenish nutrients of neighbouring tiles"
self.description = "A staple that is good at replenishing soil nutrients"
self.light_range = [15, 75]
self.base_score = 75
self.season_nutrient_mod = -5
self.harvest_nutrient_mod = 50
self.harvest_health_mod = 0
self.sprites[3] = preload("res://assets/bean plant.png")
self.sprites[4] = preload("res://assets/bean plant.png")
self.sprites[5] = preload("res://assets/bean plant.png")
self.heights = [0, 1, 2, 2, 2, 3]
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

7
src/plants/Bean.tscn Normal file
View File

@ -0,0 +1,7 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/Plant.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/plants/Bean.gd" type="Script" id=2]
[node name="Bean" instance=ExtResource( 1 )]
script = ExtResource( 2 )

31
src/plants/Clover.gd Normal file
View File

@ -0,0 +1,31 @@
extends "res://src/Plant.gd"
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
func _init():
self.icon = preload("res://assets/clover icon.png")
self.icon_tooltip = "Clover helps replenish the health of the soil on the tile"
self.description = "Good for the soil, and bees like it too"
self.light_range = [10, 90]
self.season_nutrient_mod = -1
self.season_health_mod = 5
self.harvest_health_mod = 10
self.harvest_rockiness_mod = 0
self.base_score = 0
self.sprites[2] = preload("res://assets/clover plant.png")
self.sprites[3] = preload("res://assets/clover plant.png")
self.sprites[4] = preload("res://assets/clover flower.png")
self.sprites[5] = preload("res://assets/clover flower.png")
self.heights = [0, 1, 1, 1, 1, 1]
self.growth_thresholds = [25, 50, 75, 100, 110, 125]
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

7
src/plants/Clover.tscn Normal file
View File

@ -0,0 +1,7 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/Plant.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/plants/Clover.gd" type="Script" id=2]
[node name="Clover" instance=ExtResource( 1 )]
script = ExtResource( 2 )

23
src/plants/Corn.gd Normal file
View File

@ -0,0 +1,23 @@
extends "res://src/Plant.gd"
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
func _init():
self.icon = preload("res://assets/icon corn.png")
self.icon_tooltip = "Corn needs lots of nutrients and light, but can be very productive"
self.description = "A staple crop that grows well in sun"
self.light_range = [25, 98]
self.sprites[3] = preload("res://assets/corn fruit.png")
self.sprites[4] = preload("res://assets/corn ripe.png")
self.sprites[5] = preload("res://assets/corn ripe.png")
self.heights = [0, 1, 2, 3, 3, 3]
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

7
src/plants/Corn.tscn Normal file
View File

@ -0,0 +1,7 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/Plant.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/plants/Corn.gd" type="Script" id=2]
[node name="Corn" instance=ExtResource( 1 )]
script = ExtResource( 2 )

31
src/plants/StrongWeed.gd Normal file
View File

@ -0,0 +1,31 @@
extends "res://src/Plant.gd"
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# grows tall and saps the nutrients from adjoining soil
func _init():
self.light_range = [5, 95]
self.base_score = 0
self.harvest_rockiness_mod = 25
self.season_nutrient_mod = -10
self.growth_thresholds = [75, 100, 140, 175, 20000]
self.heights = [0, 1, 2, 3, 3, 3]
self.survives_winter = true
self.plantable = false
self.icon = preload("res://assets/strong weed icon.png")
self.sprites[3] = preload("res://assets/strong weed plant.png")
self.sprites[4] = preload("res://assets/strong weed plant.png")
self.sprites[5] = preload("res://assets/strong weed plant.png")
self.description = "Ouch, prickly!"
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

View File

@ -0,0 +1,7 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/Plant.tscn" type="PackedScene" id=1]
[ext_resource path="res://src/plants/StrongWeed.gd" type="Script" id=2]
[node name="StrongWeed" instance=ExtResource( 1 )]
script = ExtResource( 2 )

33
src/plants/Weed.gd Normal file
View File

@ -0,0 +1,33 @@
extends "res://src/Plant.gd"
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Grows fast, but short and it's tough roots drag rocks up when removed
func _init():
self.light_range = [20, 80]
self.base_score = 0
self.harvest_rockiness_mod = 15
self.season_nutrient_mod = -15
self.growth_thresholds = [50, 75, 100, 125, 150]
self.heights = [0, 1, 1, 1, 2, 2]
self.plantable = false
self.icon = preload("res://assets/weed icon.png")
self.sprites[3] = preload("res://assets/weed plant.png")
self.sprites[4] = preload("res://assets/weed plant.png")
self.sprites[5] = preload("res://assets/weed plant.png")
self.description = "It noms nutrients and its roots pull up lots of rocks"
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func use_nutrients_and_run_plant_effects(soil, old_season, new_season, grid):
# For each soil neighbour, use it's nutrients
.use_nutrients_and_run_plant_effects(soil, old_season, new_season, grid)
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

7
src/plants/Weed.tscn Normal file
View File

@ -0,0 +1,7 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/plants/Weed.gd" type="Script" id=1]
[ext_resource path="res://src/Plant.tscn" type="PackedScene" id=2]
[node name="Weed" instance=ExtResource( 2 )]
script = ExtResource( 1 )

13
src/plants/test.tscn Normal file
View File

@ -0,0 +1,13 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://test.gd" type="Script" id=1]
[node name="Area2D" type="Area2D"]
position = Vector2( -4, -2 )
script = ExtResource( 1 )
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."]
position = Vector2( 14, 14 )
polygon = PoolVector2Array( 9, -10, -8, -10, -9, 2, 0, 0, 0, 0, 0, 0, 0, 0 )
[connection signal="mouse_entered" from="." to="." method="_on_Area2D_mouse_entered"]

55
src/ui/ActionMenu.gd Normal file
View File

@ -0,0 +1,55 @@
extends VBoxContainer
const FadingText = preload("res://src/ui/FadingText.tscn")
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
signal action_changed(new_value)
# Called when the node enters the scene tree for the first time.
func _ready():
for c in get_node("Grid").get_children():
c.connect("toggled", self, "_on_ActionButton_toggled", [c.get_name().to_lower()])
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass
func _on_ActionButton_toggled(pressed, action_name):
var another_pressed = false
for child in get_node("Grid").get_children():
if child.get_name().to_lower() != action_name:
if child.is_pressed():
another_pressed = true
child.set_pressed(false)
break;
if not another_pressed and not pressed:
for child in get_node("Grid").get_children():
if child.get_name().to_lower() == action_name:
child.set_pressed(true)
return
if pressed:
emit_signal("action_changed", action_name)
func _on_PassTime_pressed():
get_node("PassTime").set_disabled(true)
for c in get_node("Grid").get_children():
c.set_disabled(true)
emit_signal("action_changed", "pass_time")
func unlock():
get_node("PassTime").set_disabled(false)
for c in get_node("Grid").get_children():
c.set_disabled(false)
func _on_action_points_changed(old, new):
get_node("ActionPoints").set_text("Action Points: %d" % new)
if new > old:
var f = FadingText.instance()
f.set_text("%+d AP" % (new - old))
f.set_modulate(Color(0.0, 0.9, 0.1))
add_child(f)

102
src/ui/ActionMenu.tscn Normal file
View File

@ -0,0 +1,102 @@
[gd_scene load_steps=8 format=2]
[ext_resource path="res://assets/icon plant.png" type="Texture" id=1]
[ext_resource path="res://assets/icon cull.png" type="Texture" id=2]
[ext_resource path="res://src/ui/ActionMenu.gd" type="Script" id=3]
[ext_resource path="res://assets/icon query.png" type="Texture" id=4]
[ext_resource path="res://assets/icon remove rock.png" type="Texture" id=5]
[ext_resource path="res://assets/icon burn.png" type="Texture" id=6]
[ext_resource path="res://assets/icon fertilize.png" type="Texture" id=7]
[node name="ActionMenu" type="VBoxContainer"]
margin_top = 24.0
margin_right = 160.0
margin_bottom = 87.0
script = ExtResource( 3 )
[node name="ActionPoints" type="RichTextLabel" parent="."]
margin_right = 160.0
margin_bottom = 15.0
text = "Action Points: 3"
fit_content_height = true
[node name="Grid" type="GridContainer" parent="."]
margin_top = 19.0
margin_right = 160.0
margin_bottom = 237.0
columns = 2
[node name="Plant" type="Button" parent="Grid"]
margin_right = 76.0
margin_bottom = 70.0
hint_tooltip = "Plant (a)
Cost: 0 AP
Select a plant from the plant menu on the left, and click a soil tile to plant seeds there."
toggle_mode = true
shortcut_in_tooltip = false
pressed = true
icon = ExtResource( 1 )
icon_align = 1
[node name="Query" type="Button" parent="Grid"]
margin_left = 80.0
margin_right = 156.0
margin_bottom = 70.0
hint_tooltip = "Query (s)
Click on a tile to show more detail information"
toggle_mode = true
icon = ExtResource( 4 )
[node name="Cull" type="Button" parent="Grid"]
margin_top = 74.0
margin_right = 76.0
margin_bottom = 144.0
hint_tooltip = "Cull / Harvest (d)
Cost: 1 AP
Select a tile to remove any of the plants on it."
toggle_mode = true
icon = ExtResource( 2 )
icon_align = 1
[node name="Burn" type="Button" parent="Grid"]
margin_left = 80.0
margin_top = 74.0
margin_right = 156.0
margin_bottom = 144.0
hint_tooltip = "Burn (f)
Cost: 2 AP
Select a tile to remove any of the plants on it with fire. Doing so does not increase rockiness, and adds nutrients but reduces soil health."
toggle_mode = true
icon = ExtResource( 6 )
icon_align = 1
[node name="RemoveRock" type="Button" parent="Grid"]
margin_top = 148.0
margin_right = 76.0
margin_bottom = 218.0
hint_tooltip = "Remove Rock (g)
Cost: 3 AP
Select a tile to a reduce it's rockiness to 0"
toggle_mode = true
icon = ExtResource( 5 )
icon_align = 1
[node name="Fertilize" type="Button" parent="Grid"]
margin_left = 80.0
margin_top = 148.0
margin_right = 156.0
margin_bottom = 218.0
hint_tooltip = "Fertilize (h)
Cost: 4 AP
Greatly increase the nutirents and health of soil"
toggle_mode = true
icon = ExtResource( 7 )
icon_align = 1
[node name="PassTime" type="Button" parent="."]
margin_top = 241.0
margin_right = 160.0
margin_bottom = 261.0
text = "Let time pass"
[connection signal="pressed" from="PassTime" to="." method="_on_PassTime_pressed"]

44
src/ui/FadingText.gd Normal file
View File

@ -0,0 +1,44 @@
extends RichTextLabel
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
var life_max = 1.5
var life_cur = life_max
var autostart = true
var started = false
var move_towards = false
var move_speed = 10
func get_text_size():
var f = self.get_theme_default_font()
return f.get_string_size(self.get_text())
# Called when the node enters the scene tree for the first time.
func _ready():
if self.autostart:
self.started = true
print(self.get_position())
func _process(delta):
if not started:
return
self.life_cur -= delta
if self.life_cur <= 0.0:
self.set_visible(false)
self.started = false
self.queue_free()
else:
var m = self.get_modulate()
var a = self.life_cur / self.life_max
m = Color(m.r, m.g, m.b, a)
self.set_modulate(m)
if self.move_towards is Vector2:
var new_pos = self.get_position().move_toward(self.move_towards, delta * self.move_speed)
self.set_position(new_pos)
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

18
src/ui/FadingText.tscn Normal file
View File

@ -0,0 +1,18 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/ui/FadingText.gd" type="Script" id=1]
[ext_resource path="res://src/ui/ThemeWithFontOutline.tres" type="Theme" id=2]
[node name="FadingText" type="RichTextLabel"]
margin_bottom = 75.0
grow_horizontal = 2
grow_vertical = 2
rect_min_size = Vector2( 100, 100 )
rect_clip_content = false
mouse_filter = 2
size_flags_horizontal = 3
theme = ExtResource( 2 )
bbcode_enabled = true
fit_content_height = true
scroll_active = false
script = ExtResource( 1 )

9
src/ui/FontOutline.tres Normal file
View File

@ -0,0 +1,9 @@
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://assets/Bitstream Vera Sans Mono Bold Nerd Font Complete.ttf" type="DynamicFontData" id=1]
[resource]
size = 18
outline_size = 1
outline_color = Color( 0, 0, 0, 1 )
font_data = ExtResource( 1 )

63
src/ui/PlantMenu.gd Normal file
View File

@ -0,0 +1,63 @@
extends VBoxContainer
signal plant_type_changed(name)
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func set_plants(plant_types):
var i = 1
for x in plant_types:
if not plant_types[x].plantable and false:
continue
var button = Button.new()
#button.set_normal_texture(plant_types[x].icon)
button.set_button_icon(plant_types[x].icon)
button.set_toggle_mode(true)
if i <= 10:
var short = ShortCut.new()
var ip = InputEventKey.new()
ip.set_scancode(KEY_0 + (i % 10))
short.set_shortcut(ip)
button.set_shortcut(short)
button.connect("toggled", self, "_on_plant_icon_toggled", [button, x])
get_node("Plants").add_child(button)
button.set_tooltip(plant_types[x].get_icon_tooltip())
# Drag and drop
if i == 1:
self._on_plant_icon_toggled(true, button, x)
i += 1
func _on_plant_icon_toggled(pressed, button, plant_type_name):
var another_pressed = false
for child in get_node("Plants").get_children():
if child != button:
if child.is_pressed():
another_pressed = true
break;
if not another_pressed and not pressed:
button.set_pressed(true)
return
if pressed:
for child in get_node("Plants").get_children():
if child == button:
continue
child.set_pressed(false)
else:
get_node("Details").set_bbcode("")
if (pressed):
var game = get_tree().current_scene
if game.plant_types[plant_type_name] != null:
get_node("Details").set_bbcode("%s\n\n%s" %[plant_type_name.capitalize(), game.plant_types[plant_type_name].get_description()])
emit_signal("plant_type_changed", plant_type_name)
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

34
src/ui/PlantMenu.tscn Normal file
View File

@ -0,0 +1,34 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://src/ui/PlantMenu.gd" type="Script" id=1]
[node name="VBoxContainer" type="VBoxContainer"]
margin_bottom = 23.0
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource( 1 )
[node name="RichTextLabel" type="RichTextLabel" parent="."]
margin_right = 160.0
margin_bottom = 15.0
bbcode_enabled = true
bbcode_text = "[center]Plants[/center]"
text = "Plants"
fit_content_height = true
[node name="Plants" type="GridContainer" parent="."]
margin_top = 19.0
margin_right = 160.0
margin_bottom = 19.0
columns = 2
[node name="Details" type="RichTextLabel" parent="."]
margin_top = 23.0
margin_right = 160.0
margin_bottom = 323.0
rect_min_size = Vector2( 160, 300 )
size_flags_horizontal = 3
size_flags_vertical = 3
bbcode_enabled = true
bbcode_text = "Lorem Ipsum"
text = "Lorem Ipsum"

View File

@ -0,0 +1,6 @@
[gd_resource type="Theme" load_steps=2 format=2]
[ext_resource path="res://src/ui/FontOutline.tres" type="DynamicFont" id=1]
[resource]
default_font = ExtResource( 1 )

20
test.gd Normal file
View File

@ -0,0 +1,20 @@
extends Area2D
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass
func _on_Area2D_mouse_entered():
print("IN!")