clockwork-city/prefabs/citizen.gd
duncgibbs a9352d337d
Some checks failed
linting & formatting / build (push) Failing after 24s
way too many changes; multiplayer version, like, 0.6 or 0.7
2026-04-20 13:03:39 -05:00

207 lines
5.7 KiB
GDScript

class_name Citizen extends CharacterBody2D
enum Status { NONE, DRUNK, ARMED, CAFFEINATED }
const DRUNK_ICON = preload("uid://28x2e52skdt1")
const COFFEE_ICON = preload("uid://0644a3psplk8")
const ARMED_ICON = preload("uid://cn8biugbtcns5")
var direction: Board.Direction:
set(new_direction):
direction = new_direction
if direction == Board.Direction.NONE:
idle()
else:
walk()
var paused: bool:
set(value):
paused = value
if paused:
animated_sprite.pause()
else:
animated_sprite.play()
var speed: float = 50
var current_tile_coords: Vector2i
var direction_queue: Array[Board.Direction] = []
var money: int = 0
var money_label_tween: Tween
var tiles_visited: Dictionary[Tile, int] = {}
var buildings_visited: Dictionary[Building, int] = {}
var _statuses: Array[Status] = []
@onready var animated_sprite: AnimatedSprite2D = %AnimatedSprite
@onready var sprite_collision: CollisionShape2D = %SpriteCollision
@onready var tile_area: Area2D = %TileArea
@onready var money_label: Label = %MoneyLabel
@onready var status_container: Container = %StatusContainer
func _ready() -> void:
Globals.board_game.citizen_count += 1
func pause() -> void:
paused = true
func unpause() -> void:
paused = false
func add_status(status: Status) -> void:
_statuses.push_back(status)
match status:
Status.DRUNK:
status_container.add_child(DRUNK_ICON.instantiate())
Status.CAFFEINATED:
status_container.add_child(COFFEE_ICON.instantiate())
Status.ARMED:
status_container.add_child(ARMED_ICON.instantiate())
func remove_status(status: Status) -> void:
var status_idx := _statuses.find(status)
_statuses.remove_at(status_idx)
status_container.get_child(status_idx).free()
func get_status_count(status: Status) -> int:
return _statuses.count(status)
func remove_all_statuses(status: Status) -> void:
while _statuses.has(status):
remove_status(status)
func play_money_animation() -> void:
if is_instance_valid(money_label_tween):
money_label_tween.kill()
var starting_position = sprite_collision.position - (money_label.size / 2)
money_label_tween = create_tween()
(
money_label_tween
. tween_property(money_label, "position", starting_position - Vector2(0, 25), 0.75)
. from(starting_position)
)
(
money_label_tween
. parallel()
. tween_property(money_label, "modulate", Color(1, 1, 1, 0), 0.75)
. from(Color(1, 1, 1, 1))
)
func set_offset(offset: Vector2) -> void:
animated_sprite.position = offset
sprite_collision.position = offset
status_container.position = offset + Vector2(5, -5)
func _physics_process(delta: float) -> void:
if paused:
return
var motion: Vector2
match direction:
Board.Direction.UP:
#position = position.move_toward(position + Vector2.UP, speed * delta)
motion = Vector2.UP * speed * delta
Board.Direction.DOWN:
#position = position.move_toward(position + Vector2.DOWN, speed * delta)
motion = Vector2.DOWN * speed * delta
Board.Direction.RIGHT:
#position = position.move_toward(position + Vector2.RIGHT, speed * delta)
motion = Vector2.RIGHT * speed * delta
Board.Direction.LEFT:
#position = position.move_toward(position + Vector2.LEFT, speed * delta)
motion = Vector2.LEFT * speed * delta
move_and_collide(motion)
func idle() -> void:
Globals.board_game.citizen_count -= 1
animated_sprite.play("idle")
func walk() -> void:
match direction:
Board.Direction.UP:
animated_sprite.play("walk_up")
Board.Direction.DOWN:
animated_sprite.play("walk_down")
Board.Direction.LEFT:
animated_sprite.flip_h = true
animated_sprite.play("walk_right")
Board.Direction.RIGHT:
animated_sprite.flip_h = false
animated_sprite.play("walk_right")
#func check_for_wall() -> void:
#var tile_walls = board.wall_map.get_cell_scene(current_tile_coords).walls
#if tile_walls.has(direction):
#direction = Board.get_next_direction(direction)
#check_for_wall()
func check_for_turn(tile: Tile) -> void:
if tile is Turn:
if _statuses.has(Status.DRUNK):
remove_status(Status.DRUNK)
else:
direction = tile.direction
func check_for_building() -> void:
if Globals.board_game.board.buildings.has(
current_tile_coords + Board.get_direction_vector(direction)
):
var building = Globals.board_game.board.buildings[
current_tile_coords + Board.get_direction_vector(direction)
]
if !building.can_citizen_enter(current_tile_coords, direction):
direction = Board.get_next_direction(direction)
check_for_building()
func handle_tile_area_exited(_area: Area2D):
if is_queued_for_deletion():
return
current_tile_coords = Globals.board_game.board.tile_map.local_to_map(tile_area.global_position)
if (
!Globals.board_game.board.tiles.has(current_tile_coords)
and !Globals.board_game.board.buildings.has(current_tile_coords)
):
if direction != Board.Direction.NONE:
direction = Board.Direction.NONE
return
if !direction_queue.is_empty():
direction = direction_queue.pop_front()
elif Globals.board_game.board.buildings.has(current_tile_coords):
var building = Globals.board_game.board.buildings[current_tile_coords]
if !buildings_visited.has(building):
buildings_visited.set(building, 0)
buildings_visited[building] += 1
building.activate(self)
direction_queue = building.get_direction_queue(self)
direction = direction_queue.pop_front()
elif Globals.board_game.board.tiles.has(current_tile_coords):
var tile = Globals.board_game.board.tiles[current_tile_coords]
if !tiles_visited.has(tile):
tiles_visited.set(tile, 0)
tiles_visited[tile as Tile] += 1
check_for_building()
check_for_turn(tile)
if (
buildings_visited.values().any(func(v: int): return v > 3)
or tiles_visited.values().any(func(v: int): return v > 3)
):
direction = Board.Direction.NONE
func handle_post_turn_actions() -> void:
queue_free()