class_name CardPicker extends CenterContainer #fixme INI is probably redundant. enum { INI, CARDS, CARDS_SELECTED, TRANSITION, POSTS, POSTS_SELECTED, DONE } @export var current_scene_id : Scenes.id = Scenes.id.NONE var _input_locked: bool = true var selection_state := INI: set(state): print_debug("Setting picker state to %s" % ["INI","CARDS","CARDS_SELECTED","TRANSITION","POSTS","POSTS_SELECTED","DONE"][state]) selection_state = state _input_locked = !(state == CARDS or state == POSTS) if state == CARDS_SELECTED: var tween: Tween = get_tree().create_tween() tween.tween_property($thought_prompt, "modulate", Color(1, 1, 1, 0), 0.5) elif state == DONE: reset() var anim_players:Array[AnimationPlayer] = [] var curr_selection_id: int = -1: set(new_id): if selection_state == CARDS or selection_state == POSTS: if not curr_selection_id == -1: options[curr_selection_id].highlighted = false if new_id > options.size() -1: curr_selection_id = 0 elif new_id < 0: curr_selection_id = options.size() - 1 else: curr_selection_id = new_id options[curr_selection_id].highlighted = true else: curr_selection_id = new_id var output:Array = [] var options:Array = [] signal cards_picked(cardnames: Array[String]) # Called when the node enters the scene tree for the first time. func _ready() -> void: if current_scene_id != Scenes.id.NONE: pick_cards(current_scene_id, false) func reset(): card_anim_skipped = false output = [] options = [] anim_players = [] var card_controls: Array[Node] = $cards.get_children() for control in card_controls: options.append(control.get_child(1)) anim_players.append(control.get_child(0)) curr_selection_id = 0 for player in anim_players: player.play("reveal") func fill_card_slots(id: int): var new_cards : Array[Card] = HardCards.get_cards_by_scene_id(id) for i in range(new_cards.size()): $cards.get_child(i).remove_child($cards.get_child(i).get_child(1)) var new_card:Card = new_cards[i] $cards.get_child(i).add_child(new_card) new_card.owner = self new_card.connect("mouse_entered", Callable(self, "get_highlight")) options.append(new_card) anim_players.append($cards.get_child(i).get_child(0)) func fill_post_slots(): var sticky_notes: Array[StickyNote] = [] for card: Card in output: sticky_notes.append_array(HardCards.get_children_of(card.card_id)) for note:StickyNote in sticky_notes: note.current_handle = self sticky_notes.shuffle() options = [] for ancor in $sticky_notes.get_children(): ancor.remove_child(ancor.get_child(1)) for i in range(sticky_notes.size()): options.append(sticky_notes[i]) $sticky_notes.get_child(i).add_child(options[i], false) options[i].owner = self var picked_player: AnimationPlayer var random_player: AnimationPlayer var on_cooldown: bool = false var card_anim_skipped:bool = false func _input(event): if not _input_locked: if not on_cooldown: # Navigation: keyboard arrows, gamepad D-pad, and analog stick if event.is_action_pressed("ui_up") or event.is_action_pressed("ui_left") or event.is_action_pressed("ui_focus_next"): curr_selection_id -= 1 on_cooldown = true get_tree().create_timer(0.15).timeout.connect(func(): on_cooldown = false, CONNECT_ONE_SHOT) elif event.is_action_pressed("ui_down") or event.is_action_pressed("ui_right") or event.is_action_pressed("ui_focus_prev"): curr_selection_id += 1 on_cooldown = true get_tree().create_timer(0.15).timeout.connect(func(): on_cooldown = false, CONNECT_ONE_SHOT) # Selection: Enter/Space on keyboard, A button (Joy 0) on gamepad, or left click if event.is_action_pressed("ui_accept") or event.is_action_pressed("collect_memento_ui"): pick(curr_selection_id) elif event.is_action_pressed("skip"): $Meaning.stop() if selection_state == CARDS_SELECTED: picked_player.play("skip_pick", .1) random_player.play("skip_shuffle", .1) for player in anim_players: player.advance(10.0) transition() card_anim_skipped = true show_posts() elif selection_state == POSTS_SELECTED: for player:AnimationPlayer in anim_players + [picked_player, random_player]: player.play("ini") # I do not know, why process_frame won't work here, but this is workaround seems to prevent the notes from flashing the next selection. await(get_tree().create_timer(0.1).timeout) transition() elif selection_state == TRANSITION: show_posts() func pick(id: int) -> void: print_debug("%s picked card %s at id %d" % [name, options[id].text, id]) if id == -1: curr_selection_id = 0 return if selection_state == CARDS: selection_state = CARDS_SELECTED elif selection_state == POSTS: selection_state = POSTS_SELECTED anim_players[id].play("pick") picked_player = anim_players[id] var yield_to := anim_players[id].animation_finished output.append(options[id]) options.remove_at(id) anim_players.remove_at(id) var parent_id:StringName if selection_state == POSTS_SELECTED: parent_id = output[-1].parent_id var i:int = 0 for option:StickyNote in options: if option.parent_id == parent_id: options.erase(option) anim_players[i].play("unshuffle") anim_players.remove_at(i) print_debug("Removed StickyNote %s from options pool" % HardCards.get_obscure_name(option.name)) i += 1 var winning_id print_debug("Randomly selected card %s" % HardCards.get_obscure_name(options[1].name)) if not (current_scene_id == Scenes.id.YOUTH_JUI_JUTSU and selection_state == CARDS_SELECTED): randomize() # investigate if this fixes error on line 197 winning_id = randi() % options.size() - ( 1 if selection_state == POSTS_SELECTED else 0) else: winning_id = 1 if id == 0 else 0 if Steamworks.has_initialized: Steam.setAchievement("FIGHT_BACK") Steam.storeStats() output.append(options.pop_at(winning_id)) random_player = anim_players[winning_id] anim_players.pop_at(winning_id).play("shuffle") for anim in anim_players: anim.play("unshuffle") await yield_to if not card_anim_skipped: transition() func transition(): if selection_state == CARDS_SELECTED: selection_state = TRANSITION options = [] anim_players = [] for control in $sticky_notes.get_children(): options.append(control.get_child(1)) anim_players.append(control.get_child(0)) control.get_child(0).play("post") curr_selection_id = -1 fill_post_slots() await anim_players[0].animation_finished if selection_state != POSTS: show_posts() elif selection_state == POSTS_SELECTED: var out_str:Array[StringName] = [] for card in output: out_str.append(card.text if card.text != "" else "c_void") cards_picked.emit(out_str) selection_state = DONE func show_posts(): for player:AnimationPlayer in anim_players: player.play("RESET") selection_state = POSTS func handle_hover(new_highlight): if not _input_locked: curr_selection_id = options.find(new_highlight) func handle_mouse_button(button_event: InputEventMouseButton, new_selection: Node): if not _input_locked: if button_event.button_index == MOUSE_BUTTON_LEFT and button_event.pressed and not button_event.is_echo(): pick(options.find(new_selection)) func pick_cards(id: Scenes.id, repeat: bool): current_scene_id = id print_debug("Reached actor %s in sequence %s. Is%s repeating." % [name, Scenes.id.keys()[id], " not" if repeat else ""]) if not repeat: hide() Input.mouse_mode = Input.MOUSE_MODE_VISIBLE fill_card_slots(id) reset() show() selection_state = CARDS if id == Scenes.id.YOUTH_DRAVEN and not repeat: $Meaning.play() State.room.scene_player.play("intro") await cards_picked hide() await get_tree().process_frame State.room.save_room()