class_name Citizen extends CharacterBody2D enum Status { NONE, DRUNK, ARMED, CAFFEINATED, PACKAGED } const DRUNK_ICON = preload("uid://28x2e52skdt1") const COFFEE_ICON = preload("uid://0644a3psplk8") const ARMED_ICON = preload("uid://cn8biugbtcns5") const PACKAGE_ICON = preload("uid://drhv16h2tgoju") 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 package_distance: int = 0 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 money = Globals.board_game.current_board_state.citizens_starting_money 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()) Status.PACKAGED: status_container.add_child(PACKAGE_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_adjacent_building() -> void: for adj in [Vector2i.UP, Vector2i.RIGHT, Vector2i.DOWN, Vector2i.LEFT]: var building = Globals.board_game.board.buildings.get(current_tile_coords + adj) if building is SoupKitchen: building.activate(self) 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 get_status_count(Citizen.Status.PACKAGED) > 0: package_distance += 1 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) if !direction_queue.is_empty(): 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_adjacent_building() 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()