hadean-godot/Scripts/Building.gd

207 lines
7.1 KiB
GDScript
Raw Normal View History

2025-10-10 03:01:08 -04:00
@tool
extends TileTransform
class_name Building
var triangle_points = PackedVector2Array([
Vector2(0, -20) * 0.85 + Vector2.DOWN * 3,
Vector2(-20, 15) * 0.85 + Vector2.DOWN * 3,
Vector2(20, 15) * 0.85 + Vector2.DOWN * 3,
Vector2(0, -20) * 0.85 + Vector2.DOWN * 3,
])
var history: Array[BuildingData] = []
var data: BuildingData = null
func attempt_upgrade(new_data: BuildingData) -> bool:
var old_data = data
for resource_requirement in new_data.resource_requirements:
var resource = resource_requirement.resource
var required = resource_requirement.amount
var current = ResourceController.get_resource_value(resource)
if current < required:
return false
for field_requirement in new_data.field_requirements:
if !field_requirement.is_satisfied_at_position(self.grid, self.tile_pos):
return false
for resource_requirement in new_data.resource_requirements:
var resource = resource_requirement.resource
var required = resource_requirement.amount
ResourceController.consume_resource(resource, required)
grid.unregister_building(self)
for storage in data.resource_stockpiles:
ResourceController.remove_storage(storage)
data = new_data
grid.register_building(self)
for storage in data.resource_stockpiles:
ResourceController.add_storage(storage)
queue_redraw()
history.push_front(old_data)
return true
func attempt_upgrades() -> bool:
if randf() > 0.1: return false
for upgrade_path in data.upgrade_paths:
if attempt_upgrade(upgrade_path):
return true
return false
func _init(_tile_pos: Vector2i, _size: Vector2i, building_data: BuildingData):
self.data = building_data
self.tile_pos = _tile_pos
self.size = _size
func _ready():
super._ready()
grid.register_building(self)
for storage in data.resource_stockpiles:
ResourceController.add_storage(storage)
ResourceController.upgrade.connect(_upgrade_downgrade)
ResourceController.produce.connect(_resource_produce)
ResourceController.consume.connect(_resource_consume)
func _downgrade_or_die():
while history.size() > 0:
var downgrade_data = history.pop_front()
if attempt_upgrade(downgrade_data):
history.pop_front()
return
queue_free()
func _upgrade_downgrade():
attempt_upgrades()
if death_timer >= max_death:
_downgrade_or_die()
var death_timer = 0
var max_death = 5
func _resource_produce():
for resource_data in data.resource_prouction:
ResourceController.add_resource(resource_data.resource, resource_data.amount)
func _resource_consume():
var good_cycle = true
for resource_data in data.resource_consumption:
good_cycle = good_cycle and ResourceController.consume_resource(
resource_data.resource,
resource_data.amount
)
# i know it says resource consumption but this is also where we make sure
# our fields still make sense, okay?
for field_requirement in data.field_requirements:
if !field_requirement.is_satisfied_at_position(self.grid, self.tile_pos):
good_cycle = false
#var field_value = grid.get_field_value_at(field_requirement.field, tile_pos)
#if field_requirement.enforce_min and field_value < field_requirement.minimum:
#good_cycle = false
#if field_requirement.enforce_max and field_value > field_requirement.maximum:
#good_cycle = false
if !good_cycle:
death_timer += 1
queue_redraw()
elif death_timer != 0:
death_timer = 0
queue_redraw()
func _draw():
seed(get_instance_id())
match data.style:
BuildingData.RenderStyle.RandomBuilding: _draw_building()
BuildingData.RenderStyle.Full: _render_full()
BuildingData.RenderStyle.Outline: _render_outline()
BuildingData.RenderStyle.Triangle: _render_triangle()
BuildingData.RenderStyle.Circles: _render_circles()
if death_timer > 0: _draw_death_timer_overlay()
func _exit_tree():
grid.unregister_building(self)
for storage in data.resource_stockpiles:
ResourceController.remove_storage(storage)
ResourceController.upgrade.disconnect(_upgrade_downgrade)
ResourceController.produce.disconnect(_resource_produce)
ResourceController.consume.disconnect(_resource_consume)
func randf_norm():
return (randf() + randf() + randf() + randf() + randf()) / 5.0
func random_box_within(bounds: Rect2, min_size: float = 0.2, max_size: float = 0.6) -> Rect2:
var size = bounds.size * Vector2(
randf_norm() * (max_size - min_size) + min_size,
randf_norm() * (max_size - min_size) + min_size
)
var position = (bounds.size - size) * Vector2(randf(), randf())
return Rect2(bounds.position + position, size)
func _get_render_bounds() -> Rect2:
var dimensions = self.size * (self.grid.cell_size if self.grid != null else 100)
return Rect2(dimensions / -2.0, dimensions)
func _draw_building():
var render_bounds = _get_render_bounds()
var bottom_box = random_box_within(render_bounds, 0.2, 0.6)
#draw_rect(_get_render_bounds(), data.color.darkened(0.5), true)
draw_rect(bottom_box, self.data.color, true)
#draw_rect(render_bounds, self.data.color, false, 2)
_draw_rect_inset(render_bounds, data.color, 4)
func _render_full():
draw_rect(_get_render_bounds(), data.color, true)
func _render_outline():
var bounds = _get_render_bounds().grow(-8)
var left = bounds.grow_side(SIDE_RIGHT, -(bounds.size.y - 4))
var right = bounds.grow_side(SIDE_LEFT, -(bounds.size.y - 4))
var top = bounds.grow_side(SIDE_BOTTOM, -(bounds.size.y - 4))
var bottom = bounds.grow_side(SIDE_TOP, -(bounds.size.y - 4))
draw_dashed_line(bounds.position, bounds.position + Vector2.RIGHT * bounds.size.x, data.color, 4, 6)
draw_dashed_line(bounds.position, bounds.position + Vector2.DOWN * bounds.size.y, data.color, 4, 6)
draw_dashed_line(bounds.position + bounds.size, bounds.position + bounds.size + Vector2.LEFT * bounds.size.x, data.color, 4, 6)
draw_dashed_line(bounds.position + bounds.size, bounds.position + bounds.size + Vector2.UP * bounds.size.y, data.color, 4, 6)
func _render_triangle():
draw_colored_polygon(triangle_points, data.color)
func _render_circles():
var bounds = _get_render_bounds()
for idx in range(3):
var radius = min(bounds.size.x, bounds.size.y) / 4.0 * randf_norm()
var inner_bounds = bounds.grow(-radius)
var point = inner_bounds.position \
+ Vector2(randf(), randf()) * inner_bounds.size
draw_circle(point, radius, data.color, true, -1, true)
func _draw_rect_inset(rect: Rect2, color: Color, width: float):
var left = rect.grow_side(SIDE_RIGHT, -(rect.size.y - width))
var right = rect.grow_side(SIDE_LEFT, -(rect.size.y - width))
var top = rect.grow_side(SIDE_BOTTOM, -(rect.size.y - width))
var bottom = rect.grow_side(SIDE_TOP, -(rect.size.y - width))
draw_rect(left, color, true)
draw_rect(right, color, true)
draw_rect(top, color, true)
draw_rect(bottom, color, true)
func _draw_death_timer_overlay():
var bounds = _get_render_bounds()
var font_size = 18
var color = Color.GOLDENROD if death_timer < max_death * 0.8 else Color("ee6464")
var outline_color = Color.BLACK if death_timer < max_death * 0.8 else Color.BLACK
draw_colored_polygon(triangle_points, color)
draw_polyline(triangle_points, outline_color, 3.0, true)
draw_polyline(triangle_points, color, 1.0, true)
var height = ThemeDB.fallback_font.get_height(font_size)
draw_string(
ThemeDB.fallback_font,
Vector2.LEFT * 5.0 + Vector2.DOWN * 11.5,
"!",
HORIZONTAL_ALIGNMENT_CENTER,
10.5,
font_size,
outline_color
)