@tool extends Node class_name GameManager @export_category("Complete rosters") @export var character_roster: Array[CharacterResource] @export var face_mask_roster: Array[MaskResource] @export var mouth_mask_roster: Array[MaskResource] @export_category("References") @export var character: Character @export var guest_list: List @export var mask_list: List @export_category("Tables") @export var tables: Array[Table] @export_category("Predetermined levels") @export_group("Level 1") @export var lvl1_guest_1: MaskedChara @export var lvl1_guest_2: MaskedChara @export_group("Level 2") @export var lvl2_guest_1: MaskedChara @export var lvl2_guest_2: MaskedChara @export_group("Level 3") @export var lvl3_guest_1: MaskedChara @export var lvl3_guest_2: MaskedChara @export var lvl3_guest_3: MaskedChara @export_category("Random levels") @export var current_level: Levels = Levels.LVL1 @export var max_number_guests: int = 9 @export var no_mask_probability: float = 0.2 @export var dual_mask_probability: float = 0.2 @export_tool_button("Create chara roster") var create_roster_action = create_new_roster signal ring_bell_noise signal victory_noise signal defeat_noise var current_chara_roster: Array[MaskedChara] enum GameState { READY, GUEST_REVIEW, FINISHED } enum Levels { LVL1, LVL2, LVL3, RANDOM } var current_game_state = GameState.READY var first_guest = true var current_guest: MaskedChara var selected_seat: Seat var roster_size: int = 2 @onready var camera_2d: Camera2D = $"../Camera2D" @onready var ring_bell: Sprite2D = $"../RingBell" @onready var bell_anim_player: AnimationPlayer = $"../RingBell/AnimationPlayer" func create_new_roster() -> void: current_chara_roster = [] var roster_for_this_round = character_roster.duplicate() var max_number_of_people = min(roster_size, character_roster.size(), max_number_guests) for i in range(max_number_of_people): # Pick unique characters for the roster var random_index = randi_range(0, roster_for_this_round.size() - 1) var chara: CharacterResource = roster_for_this_round.pop_at(random_index) var mouth_mask: MaskResource var eyes_mask: MaskResource var no_masked = randf() <= no_mask_probability if (no_masked): current_chara_roster.append(MaskedChara.new(chara, eyes_mask, mouth_mask)) continue var should_pick_eye_mask = randi_range(0, 1) == 1 var dual_masked = randf() <= dual_mask_probability if (should_pick_eye_mask): eyes_mask = face_mask_roster.pick_random() if dual_masked: mouth_mask = mouth_mask_roster.pick_random() else: mouth_mask = mouth_mask_roster.pick_random() if dual_masked: eyes_mask = face_mask_roster.pick_random() var masked_chara = MaskedChara.new(chara, eyes_mask, mouth_mask) current_chara_roster.append(masked_chara) func review_next_guest(): # See previous guest out if not first_guest: character.go_out() var timer = get_tree().create_timer(2) await timer.timeout # Check if we have more guests, if not we go to the ending current_guest = current_chara_roster.pop_front() if current_guest == null: current_game_state = GameState.FINISHED compute_ending() return # Process next guest character.chara_resource = current_guest.character character.mask_eyes.mask_resource = current_guest.face_mask character.mask_mouth.mask_resource = current_guest.mouth_mask first_guest = false character.come_in() func compute_ending(): var camera_tween = get_tree().create_tween() camera_tween.set_ease(Tween.EASE_IN_OUT) camera_tween.set_trans(Tween.TRANS_CUBIC) camera_tween.tween_property(camera_2d, "position", Vector2(2720.0, 0), 1.0) camera_tween.tween_callback(ending_tween_cb) func ending_tween_cb(): var final_score = 0.0 var table1_score = tables[0].compute_score() var table2_score = tables[1].compute_score() var table3_score = tables[2].compute_score() final_score = table1_score + table2_score + table3_score print("Final score: %s" % final_score) var is_defeat = table1_score < 0 or table2_score < 0 or table3_score < 0 if is_defeat: defeat_noise.emit() else: victory_noise.emit() await get_tree().create_timer(5).timeout var camera_tween = get_tree().create_tween() camera_tween.set_ease(Tween.EASE_IN_OUT) camera_tween.set_trans(Tween.TRANS_CUBIC) camera_tween.tween_property(camera_2d, "position", Vector2.ZERO, 1.0) # Progress levels current_game_state = GameState.READY ring_bell.visible = true bell_anim_player.play("idle") if is_defeat: return if current_level == Levels.LVL1: current_level = Levels.LVL2 elif current_level == Levels.LVL2: current_level = Levels.LVL3 else: roster_size += 1 current_level = Levels.RANDOM func _ready() -> void: character.visible = false func _on_ready_bell_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void: if event is InputEventMouseButton and event.is_pressed(): ring_bell_noise.emit() if current_game_state == GameState.READY: on_ready_bell_pressed() func on_ready_bell_pressed() -> void: if(current_game_state != GameState.READY): return for table in tables: table.initialize() if current_level == Levels.LVL1: current_chara_roster = [lvl1_guest_1, lvl1_guest_2] elif current_level == Levels.LVL2: current_chara_roster = [lvl2_guest_1, lvl2_guest_2] elif current_level == Levels.LVL3: current_chara_roster = [lvl3_guest_1, lvl3_guest_2, lvl3_guest_3] else: create_new_roster() var all_chara_in_current_roster: Array[CharacterResource] = [] var all_masks_in_current_roster: Array[MaskResource] = [] for masked_chara in current_chara_roster: all_chara_in_current_roster.append(masked_chara.character) if masked_chara.face_mask != null: all_masks_in_current_roster.append(masked_chara.face_mask) if masked_chara.mouth_mask != null: all_masks_in_current_roster.append(masked_chara.mouth_mask) mask_list.set_list(all_masks_in_current_roster) guest_list.set_list(all_chara_in_current_roster) current_game_state = GameState.GUEST_REVIEW bell_anim_player.stop() ring_bell.visible = false first_guest = true review_next_guest() func on_seat_clicked(seat: Seat) -> void: if current_guest == null and not current_game_state == GameState.GUEST_REVIEW: return selected_seat = seat var camera_tween = get_tree().create_tween() camera_tween.set_ease(Tween.EASE_IN_OUT) camera_tween.set_trans(Tween.TRANS_CUBIC) camera_tween.tween_property(camera_2d, "position", Vector2.ZERO, 1.0) camera_tween.tween_callback(camera_tween_cb) func camera_tween_cb() -> void: selected_seat.set_guest(current_guest) review_next_guest()