From 6c032642a6418d6f264216f865cc7dcf1ca8454d Mon Sep 17 00:00:00 2001 From: Nathan Lovato Date: Mon, 13 Apr 2020 19:17:15 -0600 Subject: [PATCH] Format code with gdformat --- godot/addons/rect_extents_gizmo/plugin.gd | 55 ++++---- godot/assets/shaders/TransitionColor.gd | 8 +- godot/src/combat/CombatAction.gd | 14 +- godot/src/combat/CombatArena.gd | 44 ++++--- godot/src/combat/Hit.gd | 3 +- godot/src/combat/Rewards.gd | 34 +++-- godot/src/combat/animation/BattlerAnim.gd | 4 +- godot/src/combat/battlers/Battler.gd | 31 +++-- godot/src/combat/battlers/BattlerSkin.gd | 37 +++--- godot/src/combat/battlers/BattlerTemplate.gd | 30 ++--- godot/src/combat/battlers/Drops.gd | 3 +- godot/src/combat/battlers/Formation.gd | 4 +- godot/src/combat/battlers/actions/Attack.gd | 1 + .../combat/battlers/actions/BattlerActions.gd | 4 +- .../combat/battlers/actions/SkillAction.gd | 11 +- godot/src/combat/battlers/ai/BattlerAI.gd | 9 +- godot/src/combat/battlers/ai/PlayerInput.gd | 10 +- godot/src/combat/battlers/ai/RandomAI.gd | 16 ++- .../combat/battlers/skills/LearnedSkill.gd | 4 +- godot/src/combat/battlers/skills/Skill.gd | 12 +- .../combat/battlers/stats/CharacterStats.gd | 64 ++++++---- .../src/combat/battlers/stats/GrowthStats.gd | 60 +++++---- godot/src/combat/battlers/stats/Status.gd | 18 ++- godot/src/combat/interface/CombatInterface.gd | 17 ++- godot/src/combat/interface/OldSchoolUI.gd | 3 +- godot/src/combat/interface/PopupLabel.gd | 15 ++- .../src/combat/interface/PopupLabelBuilder.gd | 15 ++- godot/src/combat/interface/SelectArrow.gd | 56 ++++---- .../interface/bars/BattlerBarsBuilder.gd | 9 +- godot/src/combat/interface/bars/StatBar.gd | 20 ++- .../combat/interface/bars/ValueBarLabel.gd | 3 +- .../combat/interface/bars/lifebar/LifeBar.gd | 5 +- .../combat/interface/bars/manabar/ManaBar.gd | 5 +- .../interface/circular_menu/CircularButton.gd | 19 +-- .../interface/circular_menu/CircularMenu.gd | 120 ++++++++++++++---- .../combat/interface/circular_menu/Tooltip.gd | 11 +- .../interface/turn_order/CombatPortrait.gd | 26 ++-- .../combat/interface/turn_order/TurnOrder.gd | 21 +-- godot/src/combat/turn_queue/TurnQueue.gd | 26 ++-- godot/src/dialogue/DialogueDatabase.gd | 8 +- godot/src/dialogue/DialoguePlayer.gd | 13 +- godot/src/dialogue/characters/Character.gd | 6 +- godot/src/interface/Interface.gd | 4 + godot/src/interface/TopLevelUi.gd | 1 + godot/src/interface/debug/DebugInterface.gd | 6 +- .../interface/game_over/GameOverInterface.gd | 45 ++++--- godot/src/interface/gui/GUI.gd | 42 ++++-- godot/src/interface/gui/QuestJournal.gd | 62 ++++++--- godot/src/interface/gui/boss/BossLifebar.gd | 7 +- godot/src/interface/gui/player/PlayerGUI.gd | 2 + .../interface/gui/player/life_bar/Lifebar.gd | 3 + .../gui/player/life_bar/TextureProgress.gd | 19 ++- godot/src/interface/items/ItemButton.gd | 8 +- godot/src/interface/items/ItemGrid.gd | 4 +- godot/src/interface/items/ItemsList.gd | 18 ++- godot/src/interface/menus/Menu.gd | 18 ++- godot/src/items/ConsumableItem.gd | 5 +- godot/src/items/Equipment.gd | 13 +- godot/src/items/Item.gd | 8 +- godot/src/main/Game.gd | 22 +++- godot/src/main/MusicPlayer.gd | 2 + godot/src/main/save/GameSaver.gd | 24 ++-- godot/src/main/save/SaveGame.gd | 4 +- godot/src/main/utils/RectExtents.gd | 22 ++-- godot/src/map/DialogueBox.gd | 25 ++-- godot/src/map/LocalMap.gd | 6 +- godot/src/map/grid/GameBoard.gd | 28 ++-- godot/src/map/grid/Pathfinder.gd | 22 ++-- godot/src/map/grid/PawnContainer.gd | 21 +-- godot/src/map/grid/SpawningPoint.gd | 3 +- godot/src/map/pawns/Pawn.gd | 2 +- godot/src/map/pawns/PawnActor.gd | 24 +++- godot/src/map/pawns/PawnAnim.gd | 4 + godot/src/map/pawns/PawnFollower.gd | 4 +- godot/src/map/pawns/PawnInteractive.gd | 39 +++--- godot/src/map/pawns/PawnLeader.gd | 28 ++-- .../map/pawns/actions/CompleteQuestAction.gd | 7 +- godot/src/map/pawns/actions/DialogueAction.gd | 6 +- .../src/map/pawns/actions/GiveQuestAction.gd | 9 +- godot/src/map/pawns/actions/MapAction.gd | 7 +- .../map/pawns/actions/StartCombatAction.gd | 3 +- godot/src/party/Inventory.gd | 13 +- godot/src/party/Party.gd | 6 +- godot/src/party/PartyMember.gd | 35 +++-- godot/src/quest/Quest.gd | 33 +++-- godot/src/quest/QuestBubble.gd | 15 ++- godot/src/quest/QuestContainer.gd | 4 +- godot/src/quest/QuestItemReward.gd | 4 +- godot/src/quest/QuestSystem.gd | 22 +++- .../objectives/QuestInteractObjective.gd | 9 +- godot/src/quest/objectives/QuestObjective.gd | 4 +- .../quest/objectives/QuestSlayObjective.gd | 12 +- 92 files changed, 1009 insertions(+), 599 deletions(-) diff --git a/godot/addons/rect_extents_gizmo/plugin.gd b/godot/addons/rect_extents_gizmo/plugin.gd index 20e8707..3f455d0 100644 --- a/godot/addons/rect_extents_gizmo/plugin.gd +++ b/godot/addons/rect_extents_gizmo/plugin.gd @@ -4,37 +4,31 @@ tool extends EditorPlugin -enum Anchors { - TOP_LEFT, - TOP_RIGHT, - BOTTOM_LEFT, - BOTTOM_RIGHT -} +enum Anchors { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT } # Stores the currently edited rect_extents node # null if no RectExtents node is selected and active -var rect_extents : RectExtents +var rect_extents: RectExtents # List of all anchors drawn over the RectExtents node # Each anchor has the form { position: Vector2, rect: Rect2 } -var anchors : Array +var anchors: Array # Get and stores the anchor the user is dragging from the anchors array above -var dragged_anchor : Dictionary = {} +var dragged_anchor: Dictionary = {} # Stores the RectExtents' state when the user starts dragging an anchor # we need this info to safely add undo/redo support when the drag operation ends -var rect_drag_start : Dictionary = { - 'size': Vector2(), - 'offset': Vector2() -} +var rect_drag_start: Dictionary = {'size': Vector2(), 'offset': Vector2()} -const CIRCLE_RADIUS : float = 6.0 -const STROKE_RADIUS : float = 2.0 +const CIRCLE_RADIUS: float = 6.0 +const STROKE_RADIUS: float = 2.0 const STROKE_COLOR = Color("#f50956") const FILL_COLOR = Color("#ffffff") + func edit(object: Object) -> void: print("edit %s" % object.get_path()) rect_extents = object + func make_visible(visible: bool) -> void: # Called when the editor is requested to become visible. if not rect_extents: @@ -43,33 +37,35 @@ func make_visible(visible: bool) -> void: rect_extents = null update_overlays() + func handles(object: Object) -> bool: # Required to use forward_canvas_draw_... below return object is RectExtents + func forward_canvas_draw_over_viewport(overlay: Control) -> void: # Calculate the 4 anchor positions and bounding rectangles # from the selected RectExtents node and draw them as circles # over the viewport if not rect_extents or not rect_extents.is_inside_tree(): return - + var pos = rect_extents.position var offset = rect_extents.offset - var half_size : Vector2 = rect_extents.size / 2.0 - var edit_anchors : = { + var half_size: Vector2 = rect_extents.size / 2.0 + var edit_anchors := { Anchors.TOP_LEFT: pos - half_size + offset, Anchors.TOP_RIGHT: pos + Vector2(half_size.x, -1.0 * half_size.y) + offset, Anchors.BOTTOM_LEFT: pos + Vector2(-1.0 * half_size.x, half_size.y) + offset, Anchors.BOTTOM_RIGHT: pos + half_size + offset, } - var transform_viewport : = rect_extents.get_viewport_transform() - var transform_global : = rect_extents.get_canvas_transform() + var transform_viewport := rect_extents.get_viewport_transform() + var transform_global := rect_extents.get_canvas_transform() anchors = [] - var anchor_size : Vector2 = Vector2(CIRCLE_RADIUS * 2.0, CIRCLE_RADIUS * 2.0) + var anchor_size: Vector2 = Vector2(CIRCLE_RADIUS * 2.0, CIRCLE_RADIUS * 2.0) for coord in edit_anchors.values(): - var anchor_center : Vector2 = transform_viewport * (transform_global * coord) + var anchor_center: Vector2 = transform_viewport * (transform_global * coord) var new_anchor = { 'position': anchor_center, 'rect': Rect2(anchor_center - anchor_size / 2.0, anchor_size), @@ -77,11 +73,13 @@ func forward_canvas_draw_over_viewport(overlay: Control) -> void: draw_anchor(new_anchor, overlay) anchors.append(new_anchor) -func draw_anchor(anchor : Dictionary, overlay : Control) -> void: + +func draw_anchor(anchor: Dictionary, overlay: Control) -> void: var pos = anchor['position'] overlay.draw_circle(pos, CIRCLE_RADIUS + STROKE_RADIUS, STROKE_COLOR) overlay.draw_circle(pos, CIRCLE_RADIUS, FILL_COLOR) + func drag_to(event_position: Vector2) -> void: if not dragged_anchor: return @@ -89,11 +87,12 @@ func drag_to(event_position: Vector2) -> void: var viewport_transform_inv := rect_extents.get_viewport().get_global_canvas_transform().affine_inverse() var viewport_position: Vector2 = viewport_transform_inv.xform(event_position) var transform_inv := rect_extents.get_global_transform().affine_inverse() - var target_position : Vector2 = transform_inv.xform(viewport_position.round()) + var target_position: Vector2 = transform_inv.xform(viewport_position.round()) # Update the rectangle's size. Only resizes uniformly around the center for now var target_size = (target_position - rect_extents.offset).abs() * 2.0 rect_extents.size = target_size + func forward_canvas_gui_input(event: InputEvent) -> bool: if not rect_extents or not rect_extents.visible: return false @@ -116,13 +115,13 @@ func forward_canvas_gui_input(event: InputEvent) -> bool: dragged_anchor = {} var undo := get_undo_redo() undo.create_action("Move anchor") - + undo.add_do_property(rect_extents, "size", rect_extents.size) undo.add_undo_property(rect_extents, "size", rect_drag_start['size']) - + undo.add_do_property(rect_extents, "offset", rect_extents.offset) undo.add_undo_property(rect_extents, "offset", rect_drag_start['offset']) - + undo.commit_action() return true if not dragged_anchor: @@ -135,6 +134,6 @@ func forward_canvas_gui_input(event: InputEvent) -> bool: # Cancelling with ui_cancel if event.is_action_pressed("ui_cancel"): dragged_anchor = {} - + return true return false diff --git a/godot/assets/shaders/TransitionColor.gd b/godot/assets/shaders/TransitionColor.gd index e43cbc5..4669623 100644 --- a/godot/assets/shaders/TransitionColor.gd +++ b/godot/assets/shaders/TransitionColor.gd @@ -3,21 +3,25 @@ extends ColorRect onready var anim_player = $AnimationPlayer -export(float, 0.0, 1.0) var transition : float = 0.0 setget set_transition -export(float, 0.0, 1.0) var smoothness : float = 0.0 setget set_smoothness +export (float, 0.0, 1.0) var transition: float = 0.0 setget set_transition +export (float, 0.0, 1.0) var smoothness: float = 0.0 setget set_smoothness + func set_transition(value): transition = value material.set('shader_param/cutoff', 1.0 - value) + func set_smoothness(value): smoothness = value material.set('shader_param/smooth_size', value) + func fade_to_color(): anim_player.play("to_color") yield(anim_player, "animation_finished") + func fade_from_color(): anim_player.play("to_transparent") yield(anim_player, "animation_finished") diff --git a/godot/src/combat/CombatAction.gd b/godot/src/combat/CombatAction.gd index b8acd6f..5529c57 100644 --- a/godot/src/combat/CombatAction.gd +++ b/godot/src/combat/CombatAction.gd @@ -7,22 +7,26 @@ var initialized = false # Since Actions can be instanced by code (ie skills) these # actions doesn't have an owner, that's why we get the owner # from it's parent (BattlerActions.gd) -onready var actor : Battler = get_parent().get_owner() +onready var actor: Battler = get_parent().get_owner() -export(Texture) var icon = load("res://assets/sprites/icons/slash.png") -export(String) var description : String = "Base combat action" +export (Texture) var icon = load("res://assets/sprites/icons/slash.png") +export (String) var description: String = "Base combat action" -func initialize(battler : Battler) -> void: + +func initialize(battler: Battler) -> void: actor = battler initialized = true -func execute(targets : Array): + +func execute(targets: Array): assert(initialized) print("%s missing overwrite of the execute method" % name) return false + func return_to_start_position(): yield(actor.skin.return_to_start(), "completed") + func can_use() -> bool: return true diff --git a/godot/src/combat/CombatArena.gd b/godot/src/combat/CombatArena.gd index 0a55007..6ff0ebd 100644 --- a/godot/src/combat/CombatArena.gd +++ b/godot/src/combat/CombatArena.gd @@ -4,13 +4,13 @@ class_name CombatArena const BattlerNode = preload("res://src/combat/battlers/Battler.tscn") -onready var turn_queue : TurnQueue = $TurnQueue +onready var turn_queue: TurnQueue = $TurnQueue onready var interface = $CombatInterface onready var rewards = $Rewards -var active : bool = false -var party : Array = [] -var initial_formation : Formation +var active: bool = false +var party: Array = [] +var initial_formation: Formation # TODO: Refactor and clean up this script # sent when the battler is starting to end (before battle_completed) @@ -21,24 +21,27 @@ signal battle_completed signal victory signal game_over -func initialize(formation : Formation, party : Array): + +func initialize(formation: Formation, party: Array): initial_formation = formation ready_field(formation, party) - + # reparent the enemy battlers into the turn queue var battlers = turn_queue.get_battlers() for battler in battlers: battler.initialize() - + interface.initialize(self, turn_queue, battlers) rewards.initialize(battlers) turn_queue.initialize() - + + func battle_start(): yield(play_intro(), "completed") active = true play_turn() + func play_intro(): for battler in turn_queue.get_party(): battler.appear() @@ -47,21 +50,22 @@ func play_intro(): battler.appear() yield(get_tree().create_timer(0.5), "timeout") -func ready_field(formation : Formation, party_members : Array): + +func ready_field(formation: Formation, party_members: Array): # use a formation as a factory for the scene's content # @param formation - the combat template of what the player will be fighting # @param party_members - list of active party battlers that will go to combat for enemy_template in formation.get_children(): - var enemy : Battler = enemy_template.duplicate() + var enemy: Battler = enemy_template.duplicate() turn_queue.add_child(enemy) - enemy.stats.reset() # ensure the enemy starts with full health and mana - + enemy.stats.reset() # ensure the enemy starts with full health and mana + var party_spawn_positions = $SpawnPositions/Party for i in len(party_members): # TODO move this into a battler factory and pass already copied info into the scene var party_member = party_members[i] var spawn_point = party_spawn_positions.get_child(i) - var battler : Battler = party_member.get_battler_copy() + var battler: Battler = party_member.get_battler_copy() battler.position = spawn_point.position battler.name = party_member.name battler.set_meta("party_member", party_member) @@ -72,6 +76,7 @@ func ready_field(formation : Formation, party_members : Array): # safely attach the interface to the AI in case player input is needed battler.ai.set("interface", interface) + func battle_end(): emit_signal("battle_ends") active = false @@ -85,17 +90,18 @@ func battle_end(): else: emit_signal("game_over") + func play_turn(): - var battler : Battler = get_active_battler() - var targets : Array - var action : CombatAction + var battler: Battler = get_active_battler() + var targets: Array + var action: CombatAction while not battler.is_able_to_play(): turn_queue.skip_turn() battler = get_active_battler() battler.selected = true - var opponents : Array = get_targets() + var opponents: Array = get_targets() if not opponents: battle_end() return @@ -103,15 +109,17 @@ func play_turn(): action = yield(battler.ai.choose_action(battler, opponents), "completed") targets = yield(battler.ai.choose_target(battler, action, opponents), "completed") battler.selected = false - + if targets != []: yield(turn_queue.play_turn(action, targets), "completed") if active: play_turn() + func get_active_battler() -> Battler: return turn_queue.active_battler + func get_targets() -> Array: if get_active_battler().party_member: return turn_queue.get_monsters() diff --git a/godot/src/combat/Hit.gd b/godot/src/combat/Hit.gd index b90203f..3ad66e2 100644 --- a/godot/src/combat/Hit.gd +++ b/godot/src/combat/Hit.gd @@ -5,5 +5,6 @@ class_name Hit var damage = 0 # var effect : StatusEffect = StatusEffect.new() -func _init(strength : int, additional_damage : int = 0) -> void: + +func _init(strength: int, additional_damage: int = 0) -> void: damage = strength + additional_damage diff --git a/godot/src/combat/Rewards.gd b/godot/src/combat/Rewards.gd index a8f1bb0..d4b2099 100644 --- a/godot/src/combat/Rewards.gd +++ b/godot/src/combat/Rewards.gd @@ -1,10 +1,11 @@ extends Node -var experience_earned : int = 0 -var party : Array = [] -var rewards : Array = [] +var experience_earned: int = 0 +var party: Array = [] +var rewards: Array = [] -func initialize(battlers : Array): + +func initialize(battlers: Array): # We rely on signals to only add experience of enemies that have been defeated. # This allows us to support enemies running away and not receiving exp for them, # as well as allowing the party to run away and only earn partial exp @@ -17,30 +18,33 @@ func initialize(battlers : Array): battler.stats.connect("health_depleted", self, "_add_reward", [battler]) else: party.append(battler) - -func _add_reward(battler : Battler): + + +func _add_reward(battler: Battler): # Appends dictionaries with the form { 'item': Item.tres, 'amount': amount } of dropped items to the drops array. experience_earned += battler.drops.experience for drop in battler.drops.get_drops(): if drop.chance - randf() > drop.chance: continue - var amount : int = 1 if drop.max_amount == 1 else round(rand_range(drop.min_amount, drop.max_amount)) - rewards.append({ - 'item': drop.item, - 'amount': amount - }) + var amount: int = ( + 1 + if drop.max_amount == 1 + else round(rand_range(drop.min_amount, drop.max_amount)) + ) + rewards.append({'item': drop.item, 'amount': amount}) + # TODO: party shouldn't be Battlers but the actual party func _reward_to_battlers() -> Array: # Rewards the surviving party members with experience points - + # # @returns Array of Battlers who have leveled up var survived = [] for member in party: if not member.stats.is_alive: continue survived.append(member) - + var exp_per_survivor = int(ceil(float(experience_earned) / float(len(survived)))) var leveled_up = [] # TODO: restore experience gain @@ -53,6 +57,7 @@ func _reward_to_battlers() -> Array: # leveled_up.append(member) return leveled_up + func on_battle_completed(): # On victory be sure to grant the battlers their earned exp # and show the interface @@ -67,7 +72,8 @@ func on_battle_completed(): $Panel/Label.text = "Found %s %s(s)" % [drop.amount, drop.item.name] yield(get_tree().create_timer(2.0), "timeout") $Panel.visible = false - + + func on_flee(): # End combat condition when the party flees experience_earned /= 2 diff --git a/godot/src/combat/animation/BattlerAnim.gd b/godot/src/combat/animation/BattlerAnim.gd index 01220a6..ffe855a 100644 --- a/godot/src/combat/animation/BattlerAnim.gd +++ b/godot/src/combat/animation/BattlerAnim.gd @@ -3,12 +3,14 @@ extends Position2D class_name BattlerAnim onready var anim = $AnimationPlayer -onready var extents : RectExtents = $RectExtents +onready var extents: RectExtents = $RectExtents + func play_stagger(): anim.play("take_damage") yield(anim, "animation_finished") + func play_death(): anim.play("death") yield(anim, "animation_finished") diff --git a/godot/src/combat/battlers/Battler.gd b/godot/src/combat/battlers/Battler.gd index 0936d42..39d1d63 100644 --- a/godot/src/combat/battlers/Battler.gd +++ b/godot/src/combat/battlers/Battler.gd @@ -7,64 +7,73 @@ class_name Battler signal died(battler) -export var TARGET_OFFSET_DISTANCE : float = 120.0 +export var TARGET_OFFSET_DISTANCE: float = 120.0 -export var stats : Resource -onready var drops : = $Drops +export var stats: Resource +onready var drops := $Drops onready var skin = $Skin onready var actions = $Actions onready var bars = $Bars onready var skills = $Skills onready var ai = $AI -var target_global_position : Vector2 +var target_global_position: Vector2 -var selected : bool = false setget set_selected -var selectable : bool = false setget set_selectable -var display_name : String +var selected: bool = false setget set_selected +var selectable: bool = false setget set_selectable +var display_name: String export var party_member = false -export var turn_order_icon : Texture +export var turn_order_icon: Texture + func _ready() -> void: - var direction : Vector2 = Vector2(-1.0, 0.0) if party_member else Vector2(1.0, 0.0) + var direction: Vector2 = Vector2(-1.0, 0.0) if party_member else Vector2(1.0, 0.0) target_global_position = $TargetAnchor.global_position + direction * TARGET_OFFSET_DISTANCE selectable = true - + + func initialize(): skin.initialize() actions.initialize(skills.get_children()) stats = stats.copy() stats.connect("health_depleted", self, "_on_health_depleted") + func is_able_to_play() -> bool: # Returns true if the battler can perform an action return stats.health > 0 + func set_selected(value): selected = value skin.blink = value + func set_selectable(value): selectable = value if not selectable: set_selected(false) + func take_damage(hit): stats.take_damage(hit) # prevent playing both stagger and death animation if health <= 0 if stats.health > 0: skin.play_stagger() + func _on_health_depleted(): selectable = false yield(skin.play_death(), "completed") emit_signal("died", self) + func appear(): var offset_direction = 1.0 if party_member else -1.0 skin.position.x += TARGET_OFFSET_DISTANCE * offset_direction skin.appear() -func has_point(point : Vector2): + +func has_point(point: Vector2): return skin.battler_anim.extents.has_point(point) diff --git a/godot/src/combat/battlers/BattlerSkin.gd b/godot/src/combat/battlers/BattlerSkin.gd index d60ce52..b81cb8e 100644 --- a/godot/src/combat/battlers/BattlerSkin.gd +++ b/godot/src/combat/battlers/BattlerSkin.gd @@ -1,24 +1,27 @@ extends Position2D -export var TURN_START_MOVE_DISTANCE : float = 40.0 -export var TWEEN_DURATION : float = 0.3 +export var TURN_START_MOVE_DISTANCE: float = 40.0 +export var TWEEN_DURATION: float = 0.3 onready var tween = $Tween onready var anim = $AnimationPlayer -var battler_anim : BattlerAnim -onready var position_start : Vector2 +var battler_anim: BattlerAnim +onready var position_start: Vector2 + +var blink: bool = false setget set_blink -var blink : bool = false setget set_blink func _ready(): hide() + func initialize(): for child in get_children(): if child is BattlerAnim: battler_anim = child break + func move_forward(): var direction = Vector2(-1.0, 0.0) if owner.party_member else Vector2(1.0, 0.0) tween.interpolate_property( @@ -28,11 +31,13 @@ func move_forward(): position_start + TURN_START_MOVE_DISTANCE * direction, TWEEN_DURATION, Tween.TRANS_QUAD, - Tween.EASE_OUT) + Tween.EASE_OUT + ) tween.start() yield(tween, "tween_completed") -func move_to(target : Battler): + +func move_to(target: Battler): tween.interpolate_property( self, 'global_position', @@ -40,22 +45,20 @@ func move_to(target : Battler): target.target_global_position, TWEEN_DURATION, Tween.TRANS_QUAD, - Tween.EASE_OUT) + Tween.EASE_OUT + ) tween.start() yield(tween, "tween_completed") + func return_to_start(): tween.interpolate_property( - self, - 'position', - position, - position_start, - TWEEN_DURATION, - Tween.TRANS_QUAD, - Tween.EASE_OUT) + self, 'position', position, position_start, TWEEN_DURATION, Tween.TRANS_QUAD, Tween.EASE_OUT + ) tween.start() yield(tween, "tween_completed") + func set_blink(value): blink = value if blink: @@ -63,14 +66,18 @@ func set_blink(value): else: anim.play("idle") + func play_stagger(): battler_anim.play_stagger() + func play_death(): yield(battler_anim.play_death(), "completed") + func appear(): anim.play("appear") + func get_extents() -> RectExtents: return battler_anim.extents diff --git a/godot/src/combat/battlers/BattlerTemplate.gd b/godot/src/combat/battlers/BattlerTemplate.gd index c6c0671..39fde46 100644 --- a/godot/src/combat/battlers/BattlerTemplate.gd +++ b/godot/src/combat/battlers/BattlerTemplate.gd @@ -2,21 +2,21 @@ extends Resource class_name BattlerTemplate -export var anim : PackedScene -export var stats : Resource -export var skills : Array +export var anim: PackedScene +export var stats: Resource +export var skills: Array # For drops, we're currently using an Array of dictionaries # Example: - # { - # 'item': Sword.tres, - # 'min_amount': 1, - # 'max_amount': 1, - # 'chance': 0.5 - # }, { - # 'item': Potion.tres, - # 'min_amount': 3, - # 'max_amount': 20, - # 'chance': 0.25 - # }, -export var drops : Array \ No newline at end of file +# { +# 'item': Sword.tres, +# 'min_amount': 1, +# 'max_amount': 1, +# 'chance': 0.5 +# }, { +# 'item': Potion.tres, +# 'min_amount': 3, +# 'max_amount': 20, +# 'chance': 0.25 +# }, +export var drops: Array diff --git a/godot/src/combat/battlers/Drops.gd b/godot/src/combat/battlers/Drops.gd index e5aa497..02588fd 100644 --- a/godot/src/combat/battlers/Drops.gd +++ b/godot/src/combat/battlers/Drops.gd @@ -3,7 +3,8 @@ extends Node class_name Drops -export var experience : int = 0 +export var experience: int = 0 + func get_drops() -> Array: return get_children() diff --git a/godot/src/combat/battlers/Formation.gd b/godot/src/combat/battlers/Formation.gd index 0f7e7ec..ddb57b3 100644 --- a/godot/src/combat/battlers/Formation.gd +++ b/godot/src/combat/battlers/Formation.gd @@ -1,5 +1,5 @@ extends Node class_name Formation -export(PackedScene) var platform_template -export(Texture) var background_image +export (PackedScene) var platform_template +export (Texture) var background_image diff --git a/godot/src/combat/battlers/actions/Attack.gd b/godot/src/combat/battlers/actions/Attack.gd index d637d1a..fd88d9c 100644 --- a/godot/src/combat/battlers/actions/Attack.gd +++ b/godot/src/combat/battlers/actions/Attack.gd @@ -1,5 +1,6 @@ extends CombatAction + func execute(targets): assert(initialized) if actor.party_member and not targets: diff --git a/godot/src/combat/battlers/actions/BattlerActions.gd b/godot/src/combat/battlers/actions/BattlerActions.gd index cd7393a..bedfad2 100644 --- a/godot/src/combat/battlers/actions/BattlerActions.gd +++ b/godot/src/combat/battlers/actions/BattlerActions.gd @@ -2,11 +2,13 @@ extends Node const skill_action_scene = preload("res://src/combat/battlers/actions/SkillAction.tscn") -func initialize(skills : Array) -> void: + +func initialize(skills: Array) -> void: for skill in skills: var new_skill = skill_action_scene.instance() new_skill.skill = skill add_child(new_skill) + func get_actions(): return get_children() diff --git a/godot/src/combat/battlers/actions/SkillAction.gd b/godot/src/combat/battlers/actions/SkillAction.gd index 6d3e1f4..6d5c960 100644 --- a/godot/src/combat/battlers/actions/SkillAction.gd +++ b/godot/src/combat/battlers/actions/SkillAction.gd @@ -2,33 +2,36 @@ extends CombatAction class_name SkillAction -var skill : Skill = null +var skill: Skill = null + func _ready() -> void: name = skill.name icon = skill.icon randomize() + func execute(targets): assert(initialized) if actor.party_member and not targets: return false - + # Use skill on all targets actor.stats.mana -= skill.mana_cost randomize() if randf() < skill.success_chance: - var hit = Hit.new(actor.stats.strength, skill.base_damage) + var hit = Hit.new(actor.stats.strength, skill.base_damage) for target in targets: target.take_damage(hit) else: skill.emit_signal("missed", "Miss!") pass - + yield(actor.get_tree().create_timer(1.0), "timeout") yield(return_to_start_position(), "completed") return true + func can_use() -> bool: return actor.stats.mana >= skill.mana_cost diff --git a/godot/src/combat/battlers/ai/BattlerAI.gd b/godot/src/combat/battlers/ai/BattlerAI.gd index 87fbe29..d9c6ca8 100644 --- a/godot/src/combat/battlers/ai/BattlerAI.gd +++ b/godot/src/combat/battlers/ai/BattlerAI.gd @@ -2,12 +2,13 @@ extends Node class_name BattlerAI -func choose_action(actor : Battler, battlers : Array = []): + +func choose_action(actor: Battler, battlers: Array = []): # Select an action to perform in combat # Can be based on state of the actor pass - -func choose_target(actor : Battler, action : CombatAction, battlers : Array = []): + + +func choose_target(actor: Battler, action: CombatAction, battlers: Array = []): # Chooses a target to perform an action on pass - \ No newline at end of file diff --git a/godot/src/combat/battlers/ai/PlayerInput.gd b/godot/src/combat/battlers/ai/PlayerInput.gd index 5540c58..620d23e 100644 --- a/godot/src/combat/battlers/ai/PlayerInput.gd +++ b/godot/src/combat/battlers/ai/PlayerInput.gd @@ -1,14 +1,16 @@ extends BattlerAI -var interface : Node +var interface: Node -func choose_action(actor : Battler, battlers : Array = []): + +func choose_action(actor: Battler, battlers: Array = []): # Select an action to perform in combat # Can be based on state of the actor interface.open_actions_menu(actor) return yield(interface, "action_selected") - -func choose_target(actor : Battler, action : CombatAction, battlers : Array = []): + + +func choose_target(actor: Battler, action: CombatAction, battlers: Array = []): # Chooses a target to perform an action on interface.select_targets(battlers) return yield(interface, "targets_selected") diff --git a/godot/src/combat/battlers/ai/RandomAI.gd b/godot/src/combat/battlers/ai/RandomAI.gd index 815e67e..51db44d 100644 --- a/godot/src/combat/battlers/ai/RandomAI.gd +++ b/godot/src/combat/battlers/ai/RandomAI.gd @@ -2,23 +2,25 @@ extends BattlerAI const DEFAULT_CHANCE = 0.75 -func choose_action(actor : Battler, battlers : Array = []): + +func choose_action(actor: Battler, battlers: Array = []): # For now, we just choose the first action on a battler # we use yield even though determining an action is instantaneous # because the combat arena expects this to be an async function yield(get_tree(), "idle_frame") return actor.actions.get_child(0) - -func choose_target(actor : Battler, action : CombatAction, battlers : Array = []): + + +func choose_target(actor: Battler, action: CombatAction, battlers: Array = []): # Chooses a target to perform an action on yield(get_tree(), "idle_frame") var this_chance = randi() % 100 var target_min_health = battlers[randi() % len(battlers)] - + if this_chance > DEFAULT_CHANCE: return [target_min_health] - - var min_health = target_min_health.stats.health + + var min_health = target_min_health.stats.health for target in battlers: # don't attack battlers on your team if actor.party_member == target.party_member: @@ -26,5 +28,5 @@ func choose_target(actor : Battler, action : CombatAction, battlers : Array = [] if target.stats.health < min_health: target_min_health = target - + return [target_min_health] diff --git a/godot/src/combat/battlers/skills/LearnedSkill.gd b/godot/src/combat/battlers/skills/LearnedSkill.gd index f47921b..ba161ee 100644 --- a/godot/src/combat/battlers/skills/LearnedSkill.gd +++ b/godot/src/combat/battlers/skills/LearnedSkill.gd @@ -1,5 +1,5 @@ extends Node class_name LearnedSkill -export var skill : Resource -export var level : int = 1 +export var skill: Resource +export var level: int = 1 diff --git a/godot/src/combat/battlers/skills/Skill.gd b/godot/src/combat/battlers/skills/Skill.gd index 471bdd7..e5ef40a 100644 --- a/godot/src/combat/battlers/skills/Skill.gd +++ b/godot/src/combat/battlers/skills/Skill.gd @@ -4,10 +4,10 @@ class_name Skill signal missed(text) -export var name : String = "Skill" -export var description : String = "" -export var icon : Texture = load("res://icon.png") +export var name: String = "Skill" +export var description: String = "" +export var icon: Texture = load("res://icon.png") -export var mana_cost : int -export var base_damage : int -export(float, 0.0, 1.0) var success_chance : float +export var mana_cost: int +export var base_damage: int +export (float, 0.0, 1.0) var success_chance: float diff --git a/godot/src/combat/battlers/stats/CharacterStats.gd b/godot/src/combat/battlers/stats/CharacterStats.gd index a6ed1ef..4267cc0 100644 --- a/godot/src/combat/battlers/stats/CharacterStats.gd +++ b/godot/src/combat/battlers/stats/CharacterStats.gd @@ -6,26 +6,28 @@ extends Resource class_name CharacterStats signal health_changed(new_health, old_health) -signal health_depleted() +signal health_depleted signal mana_changed(new_mana, old_mana) -signal mana_depleted() +signal mana_depleted var modifiers = {} -var health : int -var mana : int setget set_mana -export var max_health : int = 1 setget set_max_health, _get_max_health -export var max_mana : int = 0 setget set_max_mana, _get_max_mana -export var strength : int = 1 setget ,_get_strength -export var defense : int = 1 setget ,_get_defense -export var speed : int = 1 setget ,_get_speed -var is_alive : bool setget ,_is_alive -var level : int - +var health: int +var mana: int setget set_mana +export var max_health: int = 1 setget set_max_health, _get_max_health +export var max_mana: int = 0 setget set_max_mana, _get_max_mana +export var strength: int = 1 setget , _get_strength +export var defense: int = 1 setget , _get_defense +export var speed: int = 1 setget , _get_speed +var is_alive: bool setget , _is_alive +var level: int + + func reset(): health = self.max_health mana = self.max_mana - + + func copy() -> CharacterStats: # Perform a more accurate duplication, as normally Resource duplication # does not retain any changes, instead duplicating from what's registered @@ -35,7 +37,8 @@ func copy() -> CharacterStats: copy.mana = mana return copy -func take_damage(hit : Hit): + +func take_damage(hit: Hit): var old_health = health health -= hit.damage health = max(0, health) @@ -43,51 +46,64 @@ func take_damage(hit : Hit): if health == 0: emit_signal("health_depleted") -func heal(amount : int): + +func heal(amount: int): var old_health = health health = min(health + amount, max_health) emit_signal("health_changed", health, old_health) -func set_mana(value : int): + +func set_mana(value: int): var old_mana = mana mana = max(0, value) emit_signal("mana_changed", mana, old_mana) if mana == 0: emit_signal("mana_depleted") - -func set_max_health(value : int): + + +func set_max_health(value: int): if value == null: return max_health = max(1, value) -func set_max_mana(value : int): + +func set_max_mana(value: int): if value == null: return max_mana = max(0, value) -func add_modifier(id : int, modifier): + +func add_modifier(id: int, modifier): modifiers[id] = modifier -func remove_modifier(id : int): + +func remove_modifier(id: int): modifiers.erase(id) - + + func _is_alive() -> bool: return health >= 0 + func _get_max_health() -> int: return max_health + func _get_max_mana() -> int: return max_mana + func _get_strength() -> int: return strength - + + func _get_defense() -> int: return defense - + + func _get_speed() -> int: return speed + func _get_level() -> int: return level diff --git a/godot/src/combat/battlers/stats/GrowthStats.gd b/godot/src/combat/battlers/stats/GrowthStats.gd index a9fe7d4..3ea4330 100644 --- a/godot/src/combat/battlers/stats/GrowthStats.gd +++ b/godot/src/combat/battlers/stats/GrowthStats.gd @@ -1,17 +1,18 @@ extends Resource class_name GrowthStats -export var level_lookup : Array = [] -export var max_health_curve : Curve -export var max_mana_curve : Curve -export var strength_curve : Curve -export var defense_curve : Curve -export var speed_curve : Curve - -func create_stats(experience : int) -> CharacterStats: +export var level_lookup: Array = [] +export var max_health_curve: Curve +export var max_mana_curve: Curve +export var strength_curve: Curve +export var defense_curve: Curve +export var speed_curve: Curve + + +func create_stats(experience: int) -> CharacterStats: # Creates and returns a CharacterStats Resource with stats # calculated based on the character's experience - var stats : = CharacterStats.new() + var stats := CharacterStats.new() stats.level = get_level(experience) stats.max_health = _get_max_health(experience) stats.max_mana = _get_max_mana(experience) @@ -21,42 +22,49 @@ func create_stats(experience : int) -> CharacterStats: stats.reset() # give stats full hp and mana on level up return stats -func get_level(value : int) -> int: - var max_level : int = len(level_lookup) + +func get_level(value: int) -> int: + var max_level: int = len(level_lookup) assert(max_level > 0) - var level : int = 0 - while level + 1 < max_level && value > level_lookup[level+1]: + var level: int = 0 + while level + 1 < max_level && value > level_lookup[level + 1]: level += 1 return level -func _get_interpolated_level(value : int = 0) -> float: + +func _get_interpolated_level(value: int = 0) -> float: # Calculate level, which updates all stats var max_level = len(level_lookup) assert(max_level > 0) - var level : int = get_level(value) + var level: int = get_level(value) return float(level) / float(max_level) - -func _get_max_health(experience : int)-> int: + + +func _get_max_health(experience: int) -> int: assert(max_health_curve != null) - var level : float = _get_interpolated_level(experience) + var level: float = _get_interpolated_level(experience) return int(max_health_curve.interpolate_baked(level)) -func _get_max_mana(experience : int)-> int: + +func _get_max_mana(experience: int) -> int: assert(max_mana_curve != null) - var level : float = _get_interpolated_level(experience) + var level: float = _get_interpolated_level(experience) return int(max_mana_curve.interpolate_baked(level)) -func _get_strength(experience : int)-> int: + +func _get_strength(experience: int) -> int: assert(strength_curve != null) - var level : float = _get_interpolated_level(experience) + var level: float = _get_interpolated_level(experience) return int(strength_curve.interpolate_baked(level)) -func _get_defense(experience : int)-> int: + +func _get_defense(experience: int) -> int: assert(defense_curve != null) - var level : float = _get_interpolated_level(experience) + var level: float = _get_interpolated_level(experience) return int(defense_curve.interpolate_baked(level)) -func _get_speed(experience : int)-> int: + +func _get_speed(experience: int) -> int: assert(speed_curve != null) - var level : float = _get_interpolated_level(experience) + var level: float = _get_interpolated_level(experience) return int(speed_curve.interpolate_baked(level)) diff --git a/godot/src/combat/battlers/stats/Status.gd b/godot/src/combat/battlers/stats/Status.gd index 240b7b6..1f11a4e 100644 --- a/godot/src/combat/battlers/stats/Status.gd +++ b/godot/src/combat/battlers/stats/Status.gd @@ -8,8 +8,10 @@ var statuses_active = {} # Example status const POISON = { 'name': "Poison", - 'effect': { - 'periodic_damage': { + 'effect': + { + 'periodic_damage': + { 'cycles': 5, 'stat': 'health', 'damage': 1, @@ -18,22 +20,18 @@ const POISON = { } const INVINCIBLE = { 'name': "Invincible", - 'effect': { - 'stat_modifier': { - 'add': { - 'defense': 1000, - 'magic_defense': 1000 - } - } - } + 'effect': {'stat_modifier': {'add': {'defense': 1000, 'magic_defense': 1000}}} } + func add(id, status): statuses_active[id] = status + func remove(id): statuses_active.erase(id) + func as_string(): var string = "" for status in statuses_active.values(): diff --git a/godot/src/combat/interface/CombatInterface.gd b/godot/src/combat/interface/CombatInterface.gd index 28c839e..122d923 100644 --- a/godot/src/combat/interface/CombatInterface.gd +++ b/godot/src/combat/interface/CombatInterface.gd @@ -10,26 +10,29 @@ onready var popup = $PopUpHandler onready var select_arrow = $SelectArrow onready var turn_order = $TurnOrder -export var buttons_offset : Vector2 = Vector2(-75.0, 0.0) +export var buttons_offset: Vector2 = Vector2(-75.0, 0.0) -func initialize(combat_arena : CombatArena, turn_queue : TurnQueue, battlers : Array): + +func initialize(combat_arena: CombatArena, turn_queue: TurnQueue, battlers: Array): turn_order.initialize(combat_arena, turn_queue) lifebar_builder.initialize(battlers) popup.initialize(battlers) remove_child(select_arrow) -func open_actions_menu(battler : Battler) -> void: + +func open_actions_menu(battler: Battler) -> void: var menu = CircularMenu.instance() add_child(menu) - var extents : RectExtents = battler.skin.get_extents() + var extents: RectExtents = battler.skin.get_extents() menu.rect_position = battler.global_position - Vector2(0.0, extents.size.y) + buttons_offset menu.initialize(battler) menu.open() - var selected_action : CombatAction = yield(menu, "action_selected") + var selected_action: CombatAction = yield(menu, "action_selected") emit_signal("action_selected", selected_action) -func select_targets(selectable_battlers : Array) -> void: + +func select_targets(selectable_battlers: Array) -> void: add_child(select_arrow) - var targets : Array = yield(select_arrow.select_targets(selectable_battlers), "completed") + var targets: Array = yield(select_arrow.select_targets(selectable_battlers), "completed") emit_signal("targets_selected", targets) remove_child(select_arrow) diff --git a/godot/src/combat/interface/OldSchoolUI.gd b/godot/src/combat/interface/OldSchoolUI.gd index 8e4a6c0..5d249df 100644 --- a/godot/src/combat/interface/OldSchoolUI.gd +++ b/godot/src/combat/interface/OldSchoolUI.gd @@ -2,7 +2,8 @@ extends Control onready var monster_info = $Row/MonstersPanel/Column -func initialize(battlers : Array): + +func initialize(battlers: Array): for b in battlers: var battler = b as Battler if battler.party_member: diff --git a/godot/src/combat/interface/PopupLabel.gd b/godot/src/combat/interface/PopupLabel.gd index 98a7785..6e0b2bf 100644 --- a/godot/src/combat/interface/PopupLabel.gd +++ b/godot/src/combat/interface/PopupLabel.gd @@ -1,18 +1,19 @@ extends Control -onready var anim_player : AnimationPlayer = $AnimationPlayer -onready var label : Label = $Label +onready var anim_player: AnimationPlayer = $AnimationPlayer +onready var label: Label = $Label -export var offset : = Vector2(0.0, -40.0) +export var offset := Vector2(0.0, -40.0) -func start(battler : Battler, type : String, message : String) -> void: + +func start(battler: Battler, type: String, message: String) -> void: # Initializes the node and starts its animation # @type: either health, mana, missed. Determines the animation the label will use assert(type in ['missed', 'mana', 'health']) - var extents : RectExtents = battler.skin.get_extents() + var extents: RectExtents = battler.skin.get_extents() label.text = message - - var animation_name : = "" + + var animation_name := "" if type == "missed": offset *= 2 animation_name = type diff --git a/godot/src/combat/interface/PopupLabelBuilder.gd b/godot/src/combat/interface/PopupLabelBuilder.gd index 44edda2..717c96b 100644 --- a/godot/src/combat/interface/PopupLabelBuilder.gd +++ b/godot/src/combat/interface/PopupLabelBuilder.gd @@ -1,22 +1,25 @@ extends Control -const PopupLabel : = preload("PopupLabel.tscn") +const PopupLabel := preload("PopupLabel.tscn") -func initialize(battlers : Array) -> void: + +func initialize(battlers: Array) -> void: for battler in battlers: battler.stats.connect("health_changed", self, "spawn_label_number", [battler, "health"]) battler.stats.connect("mana_changed", self, "spawn_label_number", [battler, "mana"]) for skill in battler.skills.get_children(): skill.connect("missed", self, "spawn_label", [battler, "missed"]) -func spawn_label_number(new_value : int, old_value : int, battler : Battler, type : String) -> void: + +func spawn_label_number(new_value: int, old_value: int, battler: Battler, type: String) -> void: # Spawns a damage or a mana cost animated label # Converts a difference to a string and delegates to spawn_label - var message : = str(new_value - old_value) + var message := str(new_value - old_value) spawn_label(message, battler, type) -func spawn_label(message : String, battler : Battler, type : String) -> void: + +func spawn_label(message: String, battler: Battler, type: String) -> void: # Spawns an animated PopupLabel - var l : = PopupLabel.instance() + var l := PopupLabel.instance() add_child(l) l.start(battler, type, message) diff --git a/godot/src/combat/interface/SelectArrow.gd b/godot/src/combat/interface/SelectArrow.gd index 6b3c3d1..2b4c210 100644 --- a/godot/src/combat/interface/SelectArrow.gd +++ b/godot/src/combat/interface/SelectArrow.gd @@ -5,17 +5,18 @@ signal target_selected(battler) onready var anim_player = $Sprite/AnimationPlayer onready var tween = $Tween -export var MOVE_DURATION : float = 0.1 +export var MOVE_DURATION: float = 0.1 const DIRECTION_UP = Vector2(0.0, -1.0) const DIRECTION_LEFT = Vector2(-1.0, 0.0) const DIRECTION_RIGHT = Vector2(1.0, 0.0) const DIRECTION_DOWN = Vector2(0.0, 1.0) -var targets : Array -var target_active : Battler +var targets: Array +var target_active: Battler -func select_targets(battlers : Array) -> Array: + +func select_targets(battlers: Array) -> Array: # Currently the arrow only allows you to select one target # Returns an array containing the target visible = true @@ -25,24 +26,27 @@ func select_targets(battlers : Array) -> Array: rect_global_position = target_active.target_global_position anim_player.play("wiggle") grab_focus() - var selected_target : Battler = yield(self, "target_selected") + var selected_target: Battler = yield(self, "target_selected") hide() targets = [] if not selected_target: return [] return [selected_target] -func move_to(battler : Battler): + +func move_to(battler: Battler): tween.interpolate_property( self, - 'rect_global_position', + 'rect_global_position', rect_global_position, battler.target_global_position, MOVE_DURATION, Tween.TRANS_CUBIC, - Tween.EASE_OUT) + Tween.EASE_OUT + ) tween.start() + # Mouse and touch controls func _input(event: InputEvent) -> void: if not event is InputEventMouseButton: @@ -60,18 +64,19 @@ func _input(event: InputEvent) -> void: accept_event() return + func _gui_input(event): - if !visible: + if ! visible: return - + if event.is_action_pressed("ui_accept"): emit_signal("target_selected", target_active) accept_event() elif event.is_action_pressed("ui_cancel"): emit_signal("target_selected", null) accept_event() - - var new_target : Battler = null + + var new_target: Battler = null if event.is_action_pressed("ui_left"): new_target = find_closest_target(DIRECTION_LEFT) accept_event() @@ -89,19 +94,20 @@ func _gui_input(event): target_active = new_target move_to(target_active) -func find_closest_target(direction : Vector2) -> Battler: + +func find_closest_target(direction: Vector2) -> Battler: # Returns the closest target in the given direction # Use DIRECTION_* constants if targets.size() == 1: return targets[0] - var selected_target : Battler = null - var distance_to_selected : float = 100000.0 + var selected_target: Battler = null + var distance_to_selected: float = 100000.0 # Filter battlers to prioritize those in the given direction - var priority_battlers : Array = [] - var other_battlers : Array = [] + var priority_battlers: Array = [] + var other_battlers: Array = [] for battler in targets: - var to_battler : Vector2 = battler.global_position - target_active.global_position + var to_battler: Vector2 = battler.global_position - target_active.global_position if to_battler.length() < 1.0: continue var abs_angle_to_battler = abs(direction.angle_to(to_battler)) @@ -111,22 +117,22 @@ func find_closest_target(direction : Vector2) -> Battler: priority_battlers.append(battler) else: other_battlers.append(battler) - + # Select in a cone for battler in priority_battlers: - var distance : float = battler.global_position.distance_to(target_active.global_position) + var distance: float = battler.global_position.distance_to(target_active.global_position) selected_target = battler distance_to_selected = distance if selected_target: return selected_target - + # If no battlers in the narrow cone, # select by lowest distance along the direction vector's axis - var axis : String = 'x' if direction in [DIRECTION_LEFT, DIRECTION_RIGHT] else 'y' - var compare_direction : float = direction.x if axis == 'x' else direction.y + var axis: String = 'x' if direction in [DIRECTION_LEFT, DIRECTION_RIGHT] else 'y' + var compare_direction: float = direction.x if axis == 'x' else direction.y for battler in other_battlers: - var to_battler : Vector2 = battler.global_position - target_active.global_position - var distance : float = abs(to_battler.x) if axis == 'x' else abs(to_battler.y) + var to_battler: Vector2 = battler.global_position - target_active.global_position + var distance: float = abs(to_battler.x) if axis == 'x' else abs(to_battler.y) if distance < distance_to_selected: selected_target = battler distance_to_selected = distance diff --git a/godot/src/combat/interface/bars/BattlerBarsBuilder.gd b/godot/src/combat/interface/bars/BattlerBarsBuilder.gd index fd1b27c..6efb82d 100644 --- a/godot/src/combat/interface/bars/BattlerBarsBuilder.gd +++ b/godot/src/combat/interface/bars/BattlerBarsBuilder.gd @@ -3,18 +3,21 @@ extends Node var HookableLifebar = preload("res://src/combat/interface/bars/lifebar/HookableLifeBar.tscn") var HookableManaBar = preload("res://src/combat/interface/bars/manabar/HookableManaBar.tscn") -func initialize(battlers : Array) -> void: + +func initialize(battlers: Array) -> void: for battler in battlers: create_lifebar(battler) if battler.stats.max_mana > 0: create_manabar(battler) -func create_lifebar(battler : Battler) -> void: + +func create_lifebar(battler: Battler) -> void: var lifebar = HookableLifebar.instance() battler.bars.add_child(lifebar) lifebar.initialize(battler) -func create_manabar(battler : Battler) -> void: + +func create_manabar(battler: Battler) -> void: var manabar = HookableManaBar.instance() battler.bars.add_child(manabar) manabar.initialize(battler) diff --git a/godot/src/combat/interface/bars/StatBar.gd b/godot/src/combat/interface/bars/StatBar.gd index d26fa7f..97635d1 100644 --- a/godot/src/combat/interface/bars/StatBar.gd +++ b/godot/src/combat/interface/bars/StatBar.gd @@ -4,21 +4,24 @@ class_name StatBar onready var bar = $Column/TextureProgress onready var label = $Column/LifeLabel -var max_value : int = 0 setget set_max_value -var value : int = 0 setget set_value +var max_value: int = 0 setget set_max_value +var value: int = 0 setget set_value + +export var LABEL_ABOVE: bool +export var HIDE_ON_DEPLETED: bool -export var LABEL_ABOVE : bool -export var HIDE_ON_DEPLETED : bool func _ready() -> void: if LABEL_ABOVE: label.raise() + func set_max_value(new_value) -> void: max_value = new_value bar.max_value = new_value label.display(value, new_value) + func set_value(new_value) -> void: value = new_value bar.value = new_value @@ -26,15 +29,18 @@ func set_value(new_value) -> void: if HIDE_ON_DEPLETED and value == 0: hide() -func initialize(battler : Battler) -> void: + +func initialize(battler: Battler) -> void: _connect_value_signals(battler) -func _connect_value_signals(battler : Battler) -> void: + +func _connect_value_signals(battler: Battler) -> void: print("Signals not connected in: " + name) + func _on_value_changed(new_value, old_value) -> void: self.value = new_value - + func _on_value_depleted() -> void: if HIDE_ON_DEPLETED: diff --git a/godot/src/combat/interface/bars/ValueBarLabel.gd b/godot/src/combat/interface/bars/ValueBarLabel.gd index 1f4c5cd..44d727b 100644 --- a/godot/src/combat/interface/bars/ValueBarLabel.gd +++ b/godot/src/combat/interface/bars/ValueBarLabel.gd @@ -1,4 +1,5 @@ extends Label -func display(value : int, max_value : int): + +func display(value: int, max_value: int): text = "%s/%s" % [value, max_value] diff --git a/godot/src/combat/interface/bars/lifebar/LifeBar.gd b/godot/src/combat/interface/bars/lifebar/LifeBar.gd index 8e1d652..9510387 100644 --- a/godot/src/combat/interface/bars/lifebar/LifeBar.gd +++ b/godot/src/combat/interface/bars/lifebar/LifeBar.gd @@ -3,10 +3,11 @@ extends "res://src/combat/interface/bars/StatBar.gd" class_name LifeBar -func _connect_value_signals(battler : Battler) -> void: + +func _connect_value_signals(battler: Battler) -> void: var battler_stats = battler.stats battler_stats.connect("health_changed", self, "_on_value_changed") battler_stats.connect("health_depleted", self, "_on_value_depleted") - + self.max_value = battler_stats.max_health self.value = battler_stats.health diff --git a/godot/src/combat/interface/bars/manabar/ManaBar.gd b/godot/src/combat/interface/bars/manabar/ManaBar.gd index 9489180..c3d2a28 100644 --- a/godot/src/combat/interface/bars/manabar/ManaBar.gd +++ b/godot/src/combat/interface/bars/manabar/ManaBar.gd @@ -3,10 +3,11 @@ extends "res://src/combat/interface/bars/StatBar.gd" class_name ManaBar -func _connect_value_signals(battler : Battler) -> void: + +func _connect_value_signals(battler: Battler) -> void: var battler_stats = battler.stats battler_stats.connect("mana_changed", self, "_on_value_changed") battler_stats.connect("mana_depleted", self, "_on_value_depleted") - + self.max_value = battler_stats.max_mana self.value = battler_stats.mana diff --git a/godot/src/combat/interface/circular_menu/CircularButton.gd b/godot/src/combat/interface/circular_menu/CircularButton.gd index 43792ab..4049f94 100644 --- a/godot/src/combat/interface/circular_menu/CircularButton.gd +++ b/godot/src/combat/interface/circular_menu/CircularButton.gd @@ -2,16 +2,17 @@ # Reacts to mouse hover and focus events extends Button -onready var animation_player : = $AnimationPlayer as AnimationPlayer -onready var tooltip : = $Tooltip as Control -onready var button_icon : = $Background/Icon as TextureRect +onready var animation_player := $AnimationPlayer as AnimationPlayer +onready var tooltip := $Tooltip as Control +onready var button_icon := $Background/Icon as TextureRect -var mouse_over : bool -var active : bool -var target_position : Vector2 -var unfocused_scale : Vector2 +var mouse_over: bool +var active: bool +var target_position: Vector2 +var unfocused_scale: Vector2 -func initialize(action : CombatAction, target_position : Vector2) -> void: + +func initialize(action: CombatAction, target_position: Vector2) -> void: # Places the Button on the screen, where the appear tween animation should end # Disables the button if the action isn't usable, for example # if the battler doesn't have enough mana @@ -30,6 +31,7 @@ func initialize(action : CombatAction, target_position : Vector2) -> void: connect('focus_entered', self, 'enter_focus') connect('focus_exited', self, 'exit_focus') + func enter_focus(): raise() tooltip.show() @@ -37,6 +39,7 @@ func enter_focus(): yield(animation_player, "animation_finished") animation_player.play('active') + func exit_focus(): tooltip.hide() animation_player.play('deactivate') diff --git a/godot/src/combat/interface/circular_menu/CircularMenu.gd b/godot/src/combat/interface/circular_menu/CircularMenu.gd index af8e80a..3900bf0 100644 --- a/godot/src/combat/interface/circular_menu/CircularMenu.gd +++ b/godot/src/combat/interface/circular_menu/CircularMenu.gd @@ -2,22 +2,23 @@ extends Control signal action_selected(action) -onready var tween : = $Tween as Tween -onready var buttons : = $Buttons as Control +onready var tween := $Tween as Tween +onready var buttons := $Buttons as Control -enum Directions { LEFT = -1, RIGHT = 1} -enum Layout { CENTERED = 0, CLOCKWISE = 1, COUNTER_CLOCKWISE = -1} +enum Directions { LEFT = -1, RIGHT = 1 } +enum Layout { CENTERED = 0, CLOCKWISE = 1, COUNTER_CLOCKWISE = -1 } -const CircularButton : = preload("CircularButton.tscn") +const CircularButton := preload("CircularButton.tscn") -export(Layout) var layout : int = Layout.CENTERED -export(float, 0.0, 300.0) var radius : float = 190 setget set_radius -export(float, 0, 1.0) var spacing : float = 0.2 setget set_spacing -export(float, -1.0, 1.0) var offset : float = -0.1 setget set_offset -export(float, 0.01, 0.1) var animation_offset : float = 0.08 -export(float, 0.1, 0.5) var animation_duration : float = 0.2 +export (Layout) var layout: int = Layout.CENTERED +export (float, 0.0, 300.0) var radius: float = 190 setget set_radius +export (float, 0, 1.0) var spacing: float = 0.2 setget set_spacing +export (float, -1.0, 1.0) var offset: float = -0.1 setget set_offset +export (float, 0.01, 0.1) var animation_offset: float = 0.08 +export (float, 0.1, 0.5) var animation_duration: float = 0.2 -func initialize(actor : Battler) -> void: + +func initialize(actor: Battler) -> void: # Creates a circular menu from a battler's actions var actions = actor.actions.get_actions() for action in actions: @@ -27,32 +28,89 @@ func initialize(actor : Battler) -> void: button.initialize(action, target_position) button.connect("pressed", self, "_on_CircularButton_pressed", [action]) + func open() -> void: # Plays the open animation on every circular button, with a short time offset # Gives focus to the first button show() for button_index in buttons.get_child_count(): var button = buttons.get_child(button_index) - tween.interpolate_property(button, "rect_scale", Vector2(), button.unfocused_scale, animation_duration, Tween.TRANS_QUART, Tween.EASE_IN, animation_offset * button_index) - tween.interpolate_property(button, "rect_position", Vector2(), button.target_position, animation_duration, Tween.TRANS_QUART, Tween.EASE_IN, animation_offset * button_index) - tween.interpolate_property(button, "modulate", Color('#00ffffff'), Color('#ffffffff'), animation_duration, Tween.TRANS_QUART, Tween.EASE_OUT, animation_offset * button_index) + tween.interpolate_property( + button, + "rect_scale", + Vector2(), + button.unfocused_scale, + animation_duration, + Tween.TRANS_QUART, + Tween.EASE_IN, + animation_offset * button_index + ) + tween.interpolate_property( + button, + "rect_position", + Vector2(), + button.target_position, + animation_duration, + Tween.TRANS_QUART, + Tween.EASE_IN, + animation_offset * button_index + ) + tween.interpolate_property( + button, + "modulate", + Color('#00ffffff'), + Color('#ffffffff'), + animation_duration, + Tween.TRANS_QUART, + Tween.EASE_OUT, + animation_offset * button_index + ) tween.start() yield(tween, "tween_completed") buttons.get_child(0).grab_focus() + func close() -> void: # Play the close animation on every circular button, with a short time offset # Frees the node at the end of the animation for button_index in buttons.get_child_count(): var button = buttons.get_child(button_index) button.animation_player.stop() - tween.interpolate_property(button, "rect_scale", button.rect_scale, Vector2(), animation_duration, Tween.TRANS_QUART, Tween.EASE_OUT, animation_offset * button_index) - tween.interpolate_property(button, "rect_position", button.rect_position, Vector2(), animation_duration, Tween.TRANS_QUART, Tween.EASE_OUT, animation_offset * button_index) - tween.interpolate_property(button, "modulate", Color('#ffffffff'), Color('#00ffffff'), animation_duration, Tween.TRANS_QUART, Tween.EASE_OUT, animation_offset * button_index) + tween.interpolate_property( + button, + "rect_scale", + button.rect_scale, + Vector2(), + animation_duration, + Tween.TRANS_QUART, + Tween.EASE_OUT, + animation_offset * button_index + ) + tween.interpolate_property( + button, + "rect_position", + button.rect_position, + Vector2(), + animation_duration, + Tween.TRANS_QUART, + Tween.EASE_OUT, + animation_offset * button_index + ) + tween.interpolate_property( + button, + "modulate", + Color('#ffffffff'), + Color('#00ffffff'), + animation_duration, + Tween.TRANS_QUART, + Tween.EASE_OUT, + animation_offset * button_index + ) tween.start() yield(tween, "tween_completed") queue_free() + func cancel_animation() -> void: tween.stop_all() for button_index in buttons.get_child_count(): @@ -62,8 +120,9 @@ func cancel_animation() -> void: var first_button = buttons.get_child(0) first_button.grab_focus() + func _unhandled_input(event: InputEvent) -> void: - var direction : = 0 + var direction := 0 if event.is_action_pressed("ui_right") or event.is_action_pressed("ui_focus_next"): direction = Directions.RIGHT if event.is_action_pressed("ui_left") or event.is_action_pressed("ui_focus_prev"): @@ -73,32 +132,38 @@ func _unhandled_input(event: InputEvent) -> void: return accept_event() - var in_focus : Button = get_focus_owner() + var in_focus: Button = get_focus_owner() # if not in_focus.get_parent() == buttons: # in_focus = buttons.get_child(0) # return if tween.is_active(): cancel_animation() - var next_button_index = (in_focus.get_index() + direction + buttons.get_child_count()) % buttons.get_child_count() + var next_button_index = ( + (in_focus.get_index() + direction + buttons.get_child_count()) + % buttons.get_child_count() + ) buttons.get_child(next_button_index).grab_focus() + func _on_CircularButton_pressed(action): yield(close(), "completed") emit_signal("action_selected", action) + func _update() -> void: if not is_inside_tree(): return for button in buttons.get_children(): button.rect_position = _calculate_position(button, buttons.get_child_count()) -func _calculate_position(button, buttons_count : int) -> Vector2: + +func _calculate_position(button, buttons_count: int) -> Vector2: # Returns the button's position relative to the menu # The calculation is different if the menu is centered over the character, # built clockwise, or counter-clockwise var spacing_angle = spacing * PI var start_offset_angle = offset * PI - var button_position : Vector2 + var button_position: Vector2 if layout == Layout.CENTERED: var centering_offset = spacing_angle / 2.0 * (buttons_count - 1) var angle = spacing_angle * button.get_index() - centering_offset + start_offset_angle @@ -108,14 +173,17 @@ func _calculate_position(button, buttons_count : int) -> Vector2: button_position = Vector2(0, -radius).rotated(angle) return button_position -func set_radius(new_value : float) -> void: + +func set_radius(new_value: float) -> void: radius = new_value _update() -func set_spacing(new_value : float) -> void: + +func set_spacing(new_value: float) -> void: spacing = new_value _update() -func set_offset(new_value : float) -> void: + +func set_offset(new_value: float) -> void: offset = new_value _update() diff --git a/godot/src/combat/interface/circular_menu/Tooltip.gd b/godot/src/combat/interface/circular_menu/Tooltip.gd index 83b79fd..8318770 100644 --- a/godot/src/combat/interface/circular_menu/Tooltip.gd +++ b/godot/src/combat/interface/circular_menu/Tooltip.gd @@ -2,13 +2,15 @@ extends Control onready var label = get_node("Background/Label") onready var background = get_node("Background") -export var tooltip_margin : int = 25 +export var tooltip_margin: int = 25 -func initialize(button : Control, action : CombatAction) -> void: + +func initialize(button: Control, action: CombatAction) -> void: label.text = action.name label.connect('draw', self, '_resize_background') update_position(button) + func _resize_background() -> void: # Updates the horizontal size of the background image according to the label's size # Called after Godot re-drew the label @@ -16,10 +18,11 @@ func _resize_background() -> void: background.rect_size.x = label.rect_size.x + tooltip_margin label.disconnect('draw', self, '_resize_background') -func update_position(button : Control) -> void: + +func update_position(button: Control) -> void: var button_center = button.rect_position + button.rect_size / 2.0 var polar_angle = -cartesian2polar(button_center.x, button_center.y).y - var new_pos : = rect_position + var new_pos := rect_position if polar_angle < 0.0: new_pos.y = abs(rect_position.y) + button.rect_size.y if -PI / 2.0 < polar_angle and polar_angle < PI / 2.0: diff --git a/godot/src/combat/interface/turn_order/CombatPortrait.gd b/godot/src/combat/interface/turn_order/CombatPortrait.gd index 06cc22a..b4e71d4 100644 --- a/godot/src/combat/interface/turn_order/CombatPortrait.gd +++ b/godot/src/combat/interface/turn_order/CombatPortrait.gd @@ -2,12 +2,13 @@ extends Control class_name CombatPortrait -onready var battler : Battler -onready var tween : Tween = $Tween -onready var animation_player : AnimationPlayer = $AnimationPlayer -onready var icon : TextureRect = $Background/Icon +onready var battler: Battler +onready var tween: Tween = $Tween +onready var animation_player: AnimationPlayer = $AnimationPlayer +onready var icon: TextureRect = $Background/Icon -func initialize(battler : Battler, play_animation : bool = true) -> void: + +func initialize(battler: Battler, play_animation: bool = true) -> void: battler.stats.connect('health_depleted', self, '_on_health_depleted') self.battler = battler @@ -20,37 +21,42 @@ func initialize(battler : Battler, play_animation : bool = true) -> void: if play_animation: reduce() + func reduce() -> void: # Used as the initialization animation. animation_player.play('reduce') + func highlight() -> void: # Highlight the portrait. # Used when the battler becomes active. animation_player.play('highlight') + func wait() -> void: # Remove the portrait highlight. # Used when the battler switch from the active to the waiting state. animation_player.play('wait') + func disable() -> void: # Disable (grey-out) the portrait. # Used when the battler won't be playing anymore (dead, petrified, etc.). animation_player.play('disable') + func _appear(alpha): # Tween the modulation alpha to make the portrait appear. - var from : Color = modulate - var to : Color = modulate - + var from: Color = modulate + var to: Color = modulate + to.a = alpha - tween.interpolate_property(self, 'modulate', from, to, 0.3, - Tween.TRANS_LINEAR, Tween.EASE_OUT) + tween.interpolate_property(self, 'modulate', from, to, 0.3, Tween.TRANS_LINEAR, Tween.EASE_OUT) tween.start() + func _on_health_depleted(): disable() diff --git a/godot/src/combat/interface/turn_order/TurnOrder.gd b/godot/src/combat/interface/turn_order/TurnOrder.gd index 1b72b0a..893f031 100644 --- a/godot/src/combat/interface/turn_order/TurnOrder.gd +++ b/godot/src/combat/interface/turn_order/TurnOrder.gd @@ -1,31 +1,34 @@ extends Control -onready var last_active_battler : Battler +onready var last_active_battler: Battler onready var portraits = $CombatPortraits var CombatPortrait = preload("res://src/combat/interface/turn_order/CombatPortrait.tscn") -func initialize(combat_arena : CombatArena, turn_queue : TurnQueue): + +func initialize(combat_arena: CombatArena, turn_queue: TurnQueue): combat_arena.connect('battle_ends', self, '_on_battle_ends') turn_queue.connect('queue_changed', self, '_on_queue_changed') -func rebuild(battlers : Array, active_battler : Battler) -> void: + +func rebuild(battlers: Array, active_battler: Battler) -> void: # Creates the turn order interface. - + # For each battler, both PC and NPC, create its interactive portrait and add # it to the portraits list. for portrait in portraits.get_children(): portrait.queue_free() for battler in battlers: - var new_portrait : CombatPortrait = CombatPortrait.instance() + var new_portrait: CombatPortrait = CombatPortrait.instance() var play_animation = false if battler == active_battler else true portraits.add_child(new_portrait) new_portrait.initialize(battler, play_animation) -func next(playing_battler : Battler) -> void: + +func next(playing_battler: Battler) -> void: # Switch to the next battler. - + # Deactivate the previous portrait and highlight the next one. for portrait in portraits.get_children(): if portrait.battler == playing_battler: @@ -36,7 +39,8 @@ func next(playing_battler : Battler) -> void: last_active_battler = playing_battler -func _on_queue_changed(battlers : Array, active_battler : Battler) -> void: + +func _on_queue_changed(battlers: Array, active_battler: Battler) -> void: # Update the turn order interface according to the battlers state. # Only rebuild the interface if the number of battler has changed. if battlers.size() != portraits.get_child_count(): @@ -47,6 +51,7 @@ func _on_queue_changed(battlers : Array, active_battler : Battler) -> void: if active_battler.is_able_to_play(): next(active_battler) + func _on_battle_ends(): # When the battle is starting to end, free the turn order interface. queue_free() diff --git a/godot/src/combat/turn_queue/TurnQueue.gd b/godot/src/combat/turn_queue/TurnQueue.gd index 635f17e..d05321e 100644 --- a/godot/src/combat/turn_queue/TurnQueue.gd +++ b/godot/src/combat/turn_queue/TurnQueue.gd @@ -4,8 +4,9 @@ class_name TurnQueue signal queue_changed -onready var active_battler : Battler -var last_action_canceled : bool = false +onready var active_battler: Battler +var last_action_canceled: bool = false + func initialize(): var battlers = get_battlers() @@ -15,7 +16,8 @@ func initialize(): active_battler = get_child(0) emit_signal('queue_changed', get_battlers(), active_battler) -func play_turn(action : CombatAction, targets : Array): + +func play_turn(action: CombatAction, targets: Array): if not last_action_canceled: yield(active_battler.skin.move_forward(), "completed") action.initialize(active_battler) @@ -26,36 +28,44 @@ func play_turn(action : CombatAction, targets : Array): last_action_canceled = false _next_battler() + func skip_turn(): _next_battler() + func _next_battler(): - var next_battler_index : int = (active_battler.get_index() + 1) % get_child_count() + var next_battler_index: int = (active_battler.get_index() + 1) % get_child_count() active_battler = get_child(next_battler_index) emit_signal('queue_changed', get_battlers(), active_battler) -static func sort_battlers(a : Battler, b : Battler) -> bool: + +static func sort_battlers(a: Battler, b: Battler) -> bool: return a.stats.speed > b.stats.speed + func get_party(): return _get_targets(true) + func get_monsters(): return _get_targets(false) -func _get_targets(in_party : bool = false) -> Array: - var targets : Array = [] + +func _get_targets(in_party: bool = false) -> Array: + var targets: Array = [] for child in get_children(): if child.party_member == in_party && child.stats.health > 0: targets.append(child) return targets + func get_battlers(): return get_children() + func print_queue(): # Prints the Battlers' and their speed in the turn order - var string : String + var string: String for battler in get_children(): string += battler.name + "(%s)" % battler.stats.speed + " " print(string) diff --git a/godot/src/dialogue/DialogueDatabase.gd b/godot/src/dialogue/DialogueDatabase.gd index dbf88fb..fc1b16c 100644 --- a/godot/src/dialogue/DialogueDatabase.gd +++ b/godot/src/dialogue/DialogueDatabase.gd @@ -1,7 +1,8 @@ extends Node const SOURCE_DIRECTORY = "res://src/dialogue/characters/" -var characters : Dictionary +var characters: Dictionary + func _ready() -> void: var dir = Directory.new() @@ -9,7 +10,7 @@ func _ready() -> void: if not dir.open(SOURCE_DIRECTORY) == OK: print("Could not read directory %s" % SOURCE_DIRECTORY) dir.list_dir_begin() - var file_name : String + var file_name: String while true: file_name = dir.get_next() if file_name == "": @@ -18,7 +19,8 @@ func _ready() -> void: continue characters[file_name.get_basename()] = load(SOURCE_DIRECTORY.plus_file(file_name)) -func get_texture(character_name : String, expression : String = "neutral") -> Texture: + +func get_texture(character_name: String, expression: String = "neutral") -> Texture: # Returns the Texture corresponding to a character's name and expression name assert(character_name in characters) assert(expression in characters[character_name].expressions) diff --git a/godot/src/dialogue/DialoguePlayer.gd b/godot/src/dialogue/DialoguePlayer.gd index f0526a6..bf07c8f 100644 --- a/godot/src/dialogue/DialoguePlayer.gd +++ b/godot/src/dialogue/DialoguePlayer.gd @@ -5,12 +5,13 @@ class_name DialoguePlayer signal started signal finished -var title : String = "" -var text : String = "" -var expression : String +var title: String = "" +var text: String = "" +var expression: String + +var _conversation: Array +var _index_current: int = 0 -var _conversation : Array -var _index_current : int = 0 func start(dialogue_dict): # Takes a dictionary of conversation data returned by Dialogue.load() @@ -20,11 +21,13 @@ func start(dialogue_dict): _index_current = 0 _update() + func next(): _index_current += 1 assert(_index_current <= _conversation.size()) _update() + func _update(): text = _conversation[_index_current].text title = _conversation[_index_current].name diff --git a/godot/src/dialogue/characters/Character.gd b/godot/src/dialogue/characters/Character.gd index 57f9d8d..dc69809 100644 --- a/godot/src/dialogue/characters/Character.gd +++ b/godot/src/dialogue/characters/Character.gd @@ -1,5 +1,5 @@ extends Resource -export var display_name : String -export(String, MULTILINE) var backstory : String -export var expressions : Dictionary +export var display_name: String +export (String, MULTILINE) var backstory: String +export var expressions: Dictionary diff --git a/godot/src/interface/Interface.gd b/godot/src/interface/Interface.gd index 6f4c0fa..0efec3d 100644 --- a/godot/src/interface/Interface.gd +++ b/godot/src/interface/Interface.gd @@ -2,14 +2,17 @@ extends CanvasLayer onready var shop_menu = $ShopMenu + func _ready(): shop_menu.connect('closed', self, 'remove_child', [shop_menu]) remove_child(shop_menu) + func initialize(player): $PlayerGUI.initialize(player.get_health_node(), player.get_purse()) $PauseMenu.initialize(player) + func _on_Level_loaded(level): var tree = get_tree() for seller in tree.get_nodes_in_group('seller'): @@ -19,6 +22,7 @@ func _on_Level_loaded(level): var spawners = tree.get_nodes_in_group('monster_spawner') $LifebarsBuilder.initialize(monsters, spawners) + func shop_open(seller_shop, buyer): add_child(shop_menu) shop_menu.open(seller_shop, buyer) diff --git a/godot/src/interface/TopLevelUi.gd b/godot/src/interface/TopLevelUi.gd index d489249..4ef4821 100644 --- a/godot/src/interface/TopLevelUi.gd +++ b/godot/src/interface/TopLevelUi.gd @@ -1,5 +1,6 @@ tool extends Control + func _ready(): set_as_toplevel(true) diff --git a/godot/src/interface/debug/DebugInterface.gd b/godot/src/interface/debug/DebugInterface.gd index 1056933..595ceac 100644 --- a/godot/src/interface/debug/DebugInterface.gd +++ b/godot/src/interface/debug/DebugInterface.gd @@ -1,10 +1,12 @@ extends Control -onready var spin_box : SpinBox = $Column/HBoxContainer/SpinBox -onready var game_saver : Node = $GameSaver +onready var spin_box: SpinBox = $Column/HBoxContainer/SpinBox +onready var game_saver: Node = $GameSaver + func _on_SaveButton_pressed() -> void: game_saver.save(spin_box.value) + func _on_LoadButton_pressed() -> void: game_saver.load(spin_box.value) diff --git a/godot/src/interface/game_over/GameOverInterface.gd b/godot/src/interface/game_over/GameOverInterface.gd index 46ee624..b962f48 100644 --- a/godot/src/interface/game_over/GameOverInterface.gd +++ b/godot/src/interface/game_over/GameOverInterface.gd @@ -1,28 +1,28 @@ extends CanvasLayer class_name GameOverInterface -signal restart_requested() +signal restart_requested -onready var panel : = $Panel as Panel -onready var tween : = $Tween as Tween -onready var selection_arrow : = $Panel/SelectionArrow as Control -onready var message_label : = $Panel/VBoxContainer/Message as Label -onready var try_again_button : = $Panel/VBoxContainer/Options/TryAgain as Button -onready var options : = $Panel/VBoxContainer/Options +onready var panel := $Panel as Panel +onready var tween := $Tween as Tween +onready var selection_arrow := $Panel/SelectionArrow as Control +onready var message_label := $Panel/VBoxContainer/Message as Label +onready var try_again_button := $Panel/VBoxContainer/Options/TryAgain as Button +onready var options := $Panel/VBoxContainer/Options enum Reason { PARTY_DEFEATED } -const MESSAGES = { - 'party_defeated': 'Your party was defeated!' -} +const MESSAGES = {'party_defeated': 'Your party was defeated!'} var buttons = [] -var selected_button_index : = 0 +var selected_button_index := 0 + func _ready() -> void: buttons = options.get_children() _move_arrow() + func _unhandled_input(event) -> void: if not panel.visible: return @@ -35,36 +35,43 @@ func _unhandled_input(event) -> void: elif event.is_action_pressed("ui_accept"): buttons[selected_button_index].emit_signal("pressed") + func _move_arrow() -> void: var move_to = _get_arrow_position(selected_button_index) - tween.interpolate_property(selection_arrow, - "rect_global_position", - selection_arrow.rect_global_position, - move_to, - 0.1, - Tween.TRANS_QUART, + tween.interpolate_property( + selection_arrow, + "rect_global_position", + selection_arrow.rect_global_position, + move_to, + 0.1, + Tween.TRANS_QUART, Tween.EASE_OUT ) tween.start() + func display(reason) -> void: match reason: Reason.PARTY_DEFEATED: message_label.text = MESSAGES['party_defeated'] panel.show() + func hide() -> void: panel.hide() + func _on_Exit_pressed() -> void: get_tree().quit() + func _on_TryAgain_pressed(): emit_signal("restart_requested") + func _on_Load_pressed(): print("IMPLEMENT LOAD GAME FUNCTIONALITY") -func _get_arrow_position(button_index : int = 0) -> Vector2: + +func _get_arrow_position(button_index: int = 0) -> Vector2: return buttons[button_index].get_global_rect().position - \ No newline at end of file diff --git a/godot/src/interface/gui/GUI.gd b/godot/src/interface/gui/GUI.gd index 993c561..27d03a3 100644 --- a/godot/src/interface/gui/GUI.gd +++ b/godot/src/interface/gui/GUI.gd @@ -1,48 +1,62 @@ extends CanvasLayer class_name GUI -onready var tween : = $Tween -onready var container : = $Container -onready var quest_journal : = $Container/QuestJournal -onready var quest_button : = $Container/QuestButton -onready var animation_player : = $Container/AnimationPlayer +onready var tween := $Tween +onready var container := $Container +onready var quest_journal := $Container/QuestJournal +onready var quest_button := $Container/QuestButton +onready var animation_player := $Container/AnimationPlayer + func _ready() -> void: quest_journal.connect("updated", self, "_wiggle_element", [quest_button]) + func _wiggle_element(element) -> void: var wiggles = 6 var offset = Vector2(15, 0) var last_position = element.rect_position for i in range(wiggles): - var direction = 1 if i % 2 == 0 else - 1 - tween.interpolate_property(element, + var direction := 1 + if (i % 2) == 0: + direction = -1 + + tween.interpolate_property( + element, "rect_position", last_position, element.rect_position + offset * direction, 0.05, - Tween.TRANS_BOUNCE, + Tween.TRANS_BOUNCE, Tween.EASE_IN, - i * 0.05) + i * 0.05 + ) last_position = element.rect_position + offset * direction - tween.interpolate_property(element, + tween.interpolate_property( + element, "rect_position", last_position, element.rect_position, 0.05, - Tween.TRANS_BOUNCE, + Tween.TRANS_BOUNCE, Tween.EASE_IN, - wiggles * 0.05) - tween.start() + wiggles * 0.05 + ) + tween.start() + func _on_QuestButton_pressed(): - animation_player.play("slide_out_quest_journal" if quest_journal.active else "slide_in_quest_journal") + animation_player.play( + "slide_out_quest_journal" if quest_journal.active else "slide_in_quest_journal" + ) quest_journal.active = not quest_journal.active if not quest_journal.active: quest_button.release_focus() + func hide() -> void: container.hide() + func show() -> void: container.show() diff --git a/godot/src/interface/gui/QuestJournal.gd b/godot/src/interface/gui/QuestJournal.gd index 6f24ba6..0efb4bf 100644 --- a/godot/src/interface/gui/QuestJournal.gd +++ b/godot/src/interface/gui/QuestJournal.gd @@ -1,18 +1,19 @@ extends Control class_name QuestJournal -signal updated() +signal updated -onready var tree : = $Column/Tree +onready var tree := $Column/Tree -export var active_icon : Texture -export var inactive_icon : Texture -export var completed_icon : Texture -export var objective_completed : Texture -export var objective_uncompleted : Texture +export var active_icon: Texture +export var inactive_icon: Texture +export var completed_icon: Texture +export var objective_completed: Texture +export var objective_uncompleted: Texture + +var tree_root: TreeItem +var active := false -var tree_root : TreeItem -var active : = false func _ready() -> void: for quest in QuestSystem.get_available_quests(): @@ -22,7 +23,8 @@ func _ready() -> void: tree.set_hide_root(true) tree_root = tree.create_item() -func _on_quest_started(quest : Quest) -> void: + +func _on_quest_started(quest: Quest) -> void: var quest_root = _add_tree_item(tree_root, quest.title, active_icon, quest) _add_tree_item(quest_root, quest.description) for reward_text in quest.get_rewards_as_text(): @@ -31,13 +33,22 @@ func _on_quest_started(quest : Quest) -> void: objective.connect("updated", self, "_on_Objective_updated") objective.connect("completed", self, "_on_Objective_completed") _add_tree_item( - quest_root, + quest_root, objective.as_text(), - objective_completed if objective.completed else objective_uncompleted, - objective) + objective_completed if objective.completed else objective_uncompleted, + objective + ) emit_signal("updated") -func _add_tree_item(root : TreeItem, text : String, icon : Texture = null, metadata = null, selectable : bool = false, collapsed : bool = true) -> TreeItem: + +func _add_tree_item( + root: TreeItem, + text: String, + icon: Texture = null, + metadata = null, + selectable: bool = false, + collapsed: bool = true +) -> TreeItem: var item = tree.create_item(root) item.set_icon(0, icon) item.set_text(0, text) @@ -47,34 +58,39 @@ func _add_tree_item(root : TreeItem, text : String, icon : Texture = null, metad item.set_metadata(0, metadata) return item -func _on_Objective_updated(objective : QuestObjective) -> void: + +func _on_Objective_updated(objective: QuestObjective) -> void: var objective_item = _find_objective_tree_item(objective) if objective_item == null: return objective_item.set_text(0, objective.as_text()) -func _on_Objective_completed(objective : QuestObjective) -> void: + +func _on_Objective_completed(objective: QuestObjective) -> void: var objective_item = _find_objective_tree_item(objective) if objective_item == null: return objective_item.set_icon(0, objective_completed) objective_item.set_text(0, objective.as_text()) -func _on_quest_completed(quest : Quest) -> void: + +func _on_quest_completed(quest: Quest) -> void: var quest_item = _find_quest_tree_item(quest) if quest_item == null: return quest_item.set_icon(0, completed_icon) emit_signal("updated") -func _on_quest_delivered(quest : Quest) -> void: + +func _on_quest_delivered(quest: Quest) -> void: var quest_item = _find_quest_tree_item(quest) if quest_item == null: return quest_item.set_icon(0, inactive_icon) emit_signal("updated") -func _find_quest_tree_item(quest : Quest) -> TreeItem: + +func _find_quest_tree_item(quest: Quest) -> TreeItem: var quest_item = tree_root.get_children() while quest_item != null: if quest_item.get_metadata(0) == quest: @@ -82,12 +98,16 @@ func _find_quest_tree_item(quest : Quest) -> TreeItem: quest_item = quest_item.get_next() return null -func _find_objective_tree_item(objective : QuestObjective) -> TreeItem: + +func _find_objective_tree_item(objective: QuestObjective) -> TreeItem: var quest_item = tree_root.get_children() while quest_item != null: var objective_item = quest_item.get_children() while objective_item != null: - if objective_item.get_metadata(0) != null and objective_item.get_metadata(0) == objective: + if ( + objective_item.get_metadata(0) != null + and objective_item.get_metadata(0) == objective + ): return objective_item objective_item = objective_item.get_next() quest_item = quest_item.get_next() diff --git a/godot/src/interface/gui/boss/BossLifebar.gd b/godot/src/interface/gui/boss/BossLifebar.gd index 60b4bb3..6cd23ec 100644 --- a/godot/src/interface/gui/boss/BossLifebar.gd +++ b/godot/src/interface/gui/boss/BossLifebar.gd @@ -1,29 +1,34 @@ tool extends Control -export(String) var boss_name = "Boss Name" +export (String) var boss_name = "Boss Name" onready var bar = $Bar onready var anim_player = $AnimationPlayer + func _ready(): set_as_toplevel(true) $Label.text = boss_name hide() + func initialize(health_node): bar.max_value = health_node.max_health bar.value = health_node.health health_node.connect('health_changed', self, '_on_Health_health_changed') + func appear(): show() anim_player.play("appear") + func disappear(): anim_player.play("disappear") yield(anim_player, "animation_finished") hide() + func _on_Health_health_changed(value): bar.value = value diff --git a/godot/src/interface/gui/player/PlayerGUI.gd b/godot/src/interface/gui/player/PlayerGUI.gd index 4fbb917..852d1ba 100644 --- a/godot/src/interface/gui/player/PlayerGUI.gd +++ b/godot/src/interface/gui/player/PlayerGUI.gd @@ -1,9 +1,11 @@ extends Control + func initialize(health_node, purse): $LifeBar.initialize(health_node) $CoinsCounter.initialize(purse) health_node.connect('health_depleted', self, '_on_Player_Health_health_depleted') + func _on_Player_Health_health_depleted(): $AnimationPlayer.play("fade_out") diff --git a/godot/src/interface/gui/player/life_bar/Lifebar.gd b/godot/src/interface/gui/player/life_bar/Lifebar.gd index 47013f5..e3fa201 100644 --- a/godot/src/interface/gui/player/life_bar/Lifebar.gd +++ b/godot/src/interface/gui/player/life_bar/Lifebar.gd @@ -5,6 +5,7 @@ signal maximum_changed(maximum) var maximum = 100 var current_health = 0 + func initialize(health_node): health_node.connect('health_changed', self, '_on_Player_Health_health_changed') maximum = health_node.max_health @@ -12,10 +13,12 @@ func initialize(health_node): emit_signal("maximum_changed", maximum) animate_bar(current_health) + func _on_Player_Health_health_changed(new_health): animate_bar(new_health) current_health = new_health + func animate_bar(target_health): $TextureProgress.animate_value(current_health, target_health) $TextureProgress.update_color(target_health) diff --git a/godot/src/interface/gui/player/life_bar/TextureProgress.gd b/godot/src/interface/gui/player/life_bar/TextureProgress.gd index fe89b91..dca8daf 100644 --- a/godot/src/interface/gui/player/life_bar/TextureProgress.gd +++ b/godot/src/interface/gui/player/life_bar/TextureProgress.gd @@ -1,23 +1,26 @@ tool extends TextureProgress -export(Color) var COLOR_FULL -export(Color) var COLOR_NORMAL -export(Color) var COLOR_LOW -export(Color) var COLOR_CRITICAL +export (Color) var COLOR_FULL +export (Color) var COLOR_NORMAL +export (Color) var COLOR_LOW +export (Color) var COLOR_CRITICAL -export(float, 0, 1) var THRESHOLD_LOW = 0.3 -export(float, 0, 1) var THRESHOLD_CRITICAL = 0.1 +export (float, 0, 1) var THRESHOLD_LOW = 0.3 +export (float, 0, 1) var THRESHOLD_CRITICAL = 0.1 var color_active = COLOR_NORMAL + func _on_Bar_maximum_changed(maximum): max_value = maximum + func animate_value(start, end): $Tween.interpolate_property(self, "value", start, end, 0.5, Tween.TRANS_QUART, Tween.EASE_OUT) $Tween.start() + func update_color(new_value): var new_color if new_value > THRESHOLD_LOW * max_value: @@ -33,5 +36,7 @@ func update_color(new_value): if new_color == color_active: return color_active = new_color - $Tween.interpolate_property(self, "modulate", modulate, new_color, 0.4, Tween.TRANS_QUART, Tween.EASE_OUT) + $Tween.interpolate_property( + self, "modulate", modulate, new_color, 0.4, Tween.TRANS_QUART, Tween.EASE_OUT + ) $Tween.start() diff --git a/godot/src/interface/items/ItemButton.gd b/godot/src/interface/items/ItemButton.gd index 8d2d1b4..29d524f 100644 --- a/godot/src/interface/items/ItemButton.gd +++ b/godot/src/interface/items/ItemButton.gd @@ -5,28 +5,32 @@ signal amount_changed(value) var description = "" var amount = 0 + func initialize(item, price, purse): $Name.text = item.display_name $Price.text = str(price) $Icon.texture = item.icon - + description = item.description amount = item.amount if purse.coins < price: disabled = true - + item.connect("amount_changed", self, "_on_Item_amount_changed") item.connect("depleted", self, "_on_Item_depleted") purse.connect("coins_changed", self, "_on_Purse_coins_changed", [price]) + func _on_Item_depleted(): disabled = true + func _on_Item_amount_changed(value): amount = value emit_signal("amount_changed", value) + func _on_Purse_coins_changed(coins, price): if price > coins: disabled = true diff --git a/godot/src/interface/items/ItemGrid.gd b/godot/src/interface/items/ItemGrid.gd index 07f34f3..06335ac 100644 --- a/godot/src/interface/items/ItemGrid.gd +++ b/godot/src/interface/items/ItemGrid.gd @@ -1,10 +1,12 @@ extends GridContainer + func initialize(): update_focus_neighbours() get_child(0).grab_focus() -func update_focus_neighbours(ignore=null): + +func update_focus_neighbours(ignore = null): var buttons_to_update = get_children() # There's a bug with the Node.tree_exited signal so the button is still in the tree if ignore: diff --git a/godot/src/interface/items/ItemsList.gd b/godot/src/interface/items/ItemsList.gd index e3972af..7402b67 100644 --- a/godot/src/interface/items/ItemsList.gd +++ b/godot/src/interface/items/ItemsList.gd @@ -4,12 +4,14 @@ signal focused_button_changed(button) signal item_amount_changed(amount) signal focused_item_changed(item) -export(PackedScene) var ItemButton = preload("res://interface/items/ItemButton.tscn") +export (PackedScene) var ItemButton = preload("res://interface/items/ItemButton.tscn") onready var _grid = $Grid + func initialize(): _grid.initialize() + func add_item_button(item, price, purse): var item_button = ItemButton.instance() item_button.initialize(item, price, purse) @@ -18,19 +20,25 @@ func add_item_button(item, price, purse): item_button.connect("amount_changed", self, "_on_ItemButton_amount_changed") return item_button + func _input(event): - if event.is_action_pressed('ui_left') or \ - event.is_action_pressed('ui_right') or \ - event.is_action_pressed('ui_up') or \ - event.is_action_pressed('ui_down'): + if ( + event.is_action_pressed('ui_left') + or event.is_action_pressed('ui_right') + or event.is_action_pressed('ui_up') + or event.is_action_pressed('ui_down') + ): $MenuSfx/Navigate.play() + func get_item_buttons(): return _grid.get_children() + func _on_ItemButton_focus_entered(button, item): emit_signal("focused_button_changed", button) emit_signal("focused_item_changed", item) + func _on_ItemButton_amount_changed(value): emit_signal("item_amount_changed", value) diff --git a/godot/src/interface/menus/Menu.gd b/godot/src/interface/menus/Menu.gd index cf7d545..a01d3c1 100644 --- a/godot/src/interface/menus/Menu.gd +++ b/godot/src/interface/menus/Menu.gd @@ -1,41 +1,47 @@ extends Control -signal open() -signal closed() +signal open +signal closed -export(NodePath) var SUB_MENU_PATH +export (NodePath) var SUB_MENU_PATH onready var sound_confirm = $MenuSfx/Confirm onready var sound_navigate = $MenuSfx/Navigate onready var sound_open = $MenuSfx/Open + func _ready(): set_process_input(false) -func open(args=[]): + +func open(args = []): emit_signal("open") set_process_input(true) show() sound_open.play() + func close(): emit_signal("closed") set_process_input(false) hide() sound_confirm.play() + func _input(event): if event.is_action_pressed("ui_cancel"): get_tree().set_input_as_handled() close() + # You can streamline opening sub menus with these methods # The main drawback is you lose the initialize method's signature # Instead you have to group the arguments in an array -func initialize(args=[]): +func initialize(args = []): return -func open_sub_menu(menu, args=[]): + +func open_sub_menu(menu, args = []): var sub_menu = menu.instance() if menu is PackedScene else menu if SUB_MENU_PATH: get_node(SUB_MENU_PATH).add_child(sub_menu) diff --git a/godot/src/items/ConsumableItem.gd b/godot/src/items/ConsumableItem.gd index 1616454..d103739 100644 --- a/godot/src/items/ConsumableItem.gd +++ b/godot/src/items/ConsumableItem.gd @@ -2,7 +2,8 @@ extends Item class_name ConsumableItem # action to execute when used in combat -export(Resource) var action = null setget ,_get_action - +export (Resource) var action = null setget , _get_action + + func _get_action() -> CombatAction: return action as CombatAction diff --git a/godot/src/items/Equipment.gd b/godot/src/items/Equipment.gd index 6f6f555..cbecb3e 100644 --- a/godot/src/items/Equipment.gd +++ b/godot/src/items/Equipment.gd @@ -1,17 +1,14 @@ extends Item class_name Equipment -enum Slot { - Weapon, - Armor, - Accessory -} +enum Slot { Weapon, Armor, Accessory } -export(Slot) var slot = Slot.Weapon +export (Slot) var slot = Slot.Weapon # stat boosts provided when equipped -export(Resource) var stats = null setget ,_get_stats - +export (Resource) var stats = null setget , _get_stats + + func _get_stats() -> CharacterStats: # TODO figure out a way to stack these stats onto battlers, # will probably require creating a new stats class for equipment diff --git a/godot/src/items/Item.gd b/godot/src/items/Item.gd index 7384353..a524ebd 100644 --- a/godot/src/items/Item.gd +++ b/godot/src/items/Item.gd @@ -3,7 +3,7 @@ class_name Item enum Category { CONSUMABLE, MATERIAL, KEY, EQUIPMENT } -export var name : String -export var description : String -export var unique : bool = false -export(int) var sell_value +export var name: String +export var description: String +export var unique: bool = false +export (int) var sell_value diff --git a/godot/src/main/Game.gd b/godot/src/main/Game.gd index 5fc7f21..d9d2f16 100644 --- a/godot/src/main/Game.gd +++ b/godot/src/main/Game.gd @@ -2,18 +2,19 @@ # combat, game over, and the map extends Node -signal combat_started() +signal combat_started const combat_arena_scene = preload("res://src/combat/CombatArena.tscn") onready var transition = $Overlays/TransitionColor onready var local_map = $LocalMap onready var party = $Party as Party onready var music_player = $MusicPlayer -onready var game_over_interface : = $GameOverInterface -onready var gui : = $GUI +onready var game_over_interface := $GameOverInterface +onready var gui := $GUI var transitioning = false -var combat_arena : CombatArena +var combat_arena: CombatArena + func _ready(): QuestSystem.initialize(self, party) @@ -21,6 +22,7 @@ func _ready(): local_map.visible = true local_map.connect("enemies_encountered", self, "enter_battle") + func enter_battle(formation: Formation): # Plays the combat transition animation and initializes the combat scene if transitioning: @@ -37,7 +39,9 @@ func enter_battle(formation: Formation): add_child(combat_arena) combat_arena.connect("victory", self, "_on_CombatArena_player_victory") combat_arena.connect("game_over", self, "_on_CombatArena_game_over") - combat_arena.connect("battle_completed", self, "_on_CombatArena_battle_completed", [combat_arena]) + combat_arena.connect( + "battle_completed", self, "_on_CombatArena_battle_completed", [combat_arena] + ) combat_arena.initialize(formation, party.get_active_members()) yield(transition.fade_from_color(), "completed") @@ -46,23 +50,26 @@ func enter_battle(formation: Formation): combat_arena.battle_start() emit_signal("combat_started") + func _on_CombatArena_battle_completed(arena): # At the end of an encounter, fade the screen, remove the combat arena # and add the local map back gui.show() - + transitioning = true yield(transition.fade_to_color(), "completed") combat_arena.queue_free() - + add_child(local_map) yield(transition.fade_from_color(), "completed") transitioning = false music_player.stop() + func _on_CombatArena_player_victory(): music_player.play_victory_fanfare() + func _on_CombatArena_game_over() -> void: transitioning = true yield(transition.fade_to_color(), "completed") @@ -70,6 +77,7 @@ func _on_CombatArena_game_over() -> void: yield(transition.fade_from_color(), "completed") transitioning = false + func _on_GameOverInterface_restart_requested(): game_over_interface.hide() var formation = combat_arena.initial_formation diff --git a/godot/src/main/MusicPlayer.gd b/godot/src/main/MusicPlayer.gd index dc42325..005781e 100644 --- a/godot/src/main/MusicPlayer.gd +++ b/godot/src/main/MusicPlayer.gd @@ -3,10 +3,12 @@ extends AudioStreamPlayer const battle_theme = preload("res://assets/audio/bgm/battle_theme.ogg") const victory_fanfare = preload("res://assets/audio/bgm/victory_fanfare.ogg") + func play_battle_theme(): stream = battle_theme play() + func play_victory_fanfare(): stream = victory_fanfare play() diff --git a/godot/src/main/save/GameSaver.gd b/godot/src/main/save/GameSaver.gd index 76249fb..da12068 100644 --- a/godot/src/main/save/GameSaver.gd +++ b/godot/src/main/save/GameSaver.gd @@ -5,35 +5,37 @@ extends Node const SaveGame = preload('res://src/main/save/SaveGame.gd') # TODO: Use project setting to save to res://debug vs user:// -var SAVE_FOLDER : String = "res://debug/save" -var SAVE_NAME_TEMPLATE : String = "save_%03d.tres" +var SAVE_FOLDER: String = "res://debug/save" +var SAVE_NAME_TEMPLATE: String = "save_%03d.tres" -func save(id : int): + +func save(id: int): # Passes a SaveGame resource to all nodes to save data from # and writes it to the disk var save_game := SaveGame.new() save_game.game_version = ProjectSettings.get_setting("application/config/version") for node in get_tree().get_nodes_in_group('save'): node.save(save_game) - - var directory : Directory = Directory.new() + + var directory: Directory = Directory.new() if not directory.dir_exists(SAVE_FOLDER): directory.make_dir_recursive(SAVE_FOLDER) - + var save_path = SAVE_FOLDER.plus_file(SAVE_NAME_TEMPLATE % id) - var error : int = ResourceSaver.save(save_path, save_game) + var error: int = ResourceSaver.save(save_path, save_game) if error != OK: print('There was an issue writing the save %s to %s' % [id, save_path]) -func load(id : int): + +func load(id: int): # Reads a saved game from the disk and delegates loading # to the individual nodes to load - var save_file_path : String = SAVE_FOLDER.plus_file(SAVE_NAME_TEMPLATE % id) - var file : File = File.new() + var save_file_path: String = SAVE_FOLDER.plus_file(SAVE_NAME_TEMPLATE % id) + var file: File = File.new() if not file.file_exists(save_file_path): print("Save file %s doesn't exist" % save_file_path) return - var save_game : Resource = load(save_file_path) + var save_game: Resource = load(save_file_path) for node in get_tree().get_nodes_in_group('save'): node.load(save_game) diff --git a/godot/src/main/save/SaveGame.gd b/godot/src/main/save/SaveGame.gd index 2006018..c328913 100644 --- a/godot/src/main/save/SaveGame.gd +++ b/godot/src/main/save/SaveGame.gd @@ -5,5 +5,5 @@ extends Resource class_name SaveGame -export var game_version : String = '' -export var data : Dictionary = {} +export var game_version: String = '' +export var data: Dictionary = {} diff --git a/godot/src/main/utils/RectExtents.gd b/godot/src/main/utils/RectExtents.gd index 2056b9c..ddcfc7c 100644 --- a/godot/src/main/utils/RectExtents.gd +++ b/godot/src/main/utils/RectExtents.gd @@ -5,34 +5,40 @@ extends Node2D class_name RectExtents -export var size : Vector2 = Vector2(40.0, 40.0) setget set_size -export var color : Color = Color("#ff0ea7") setget set_color -export var offset : Vector2 setget set_offset +export var size: Vector2 = Vector2(40.0, 40.0) setget set_size +export var color: Color = Color("#ff0ea7") setget set_color +export var offset: Vector2 setget set_offset -var _rect : Rect2 +var _rect: Rect2 -func set_offset(value : Vector2) -> void: + +func set_offset(value: Vector2) -> void: offset = value _recalculate_rect() update() -func set_size(value : Vector2) -> void: + +func set_size(value: Vector2) -> void: size = value _recalculate_rect() update() + func _recalculate_rect(): _rect = Rect2(-1.0 * size / 2 + offset, size) -func set_color(value : Color) -> void: + +func set_color(value: Color) -> void: color = value update() + func _draw() -> void: if not Engine.editor_hint: return draw_rect(_rect, color, false) -func has_point(point : Vector2) -> bool: + +func has_point(point: Vector2) -> bool: var rect_global = Rect2(global_position + _rect.position, _rect.size) return rect_global.has_point(point) diff --git a/godot/src/map/DialogueBox.gd b/godot/src/map/DialogueBox.gd index 679c33c..185566f 100644 --- a/godot/src/map/DialogueBox.gd +++ b/godot/src/map/DialogueBox.gd @@ -1,19 +1,20 @@ extends Control class_name DialogueBox -signal dialogue_ended() +signal dialogue_ended -onready var dialogue_player : DialoguePlayer = get_node("DialoguePlayer") +onready var dialogue_player: DialoguePlayer = get_node("DialoguePlayer") -onready var name_label : = get_node("Panel/Colums/Name") as Label -onready var text_label : = get_node("Panel/Colums/Text") as Label +onready var name_label := get_node("Panel/Colums/Name") as Label +onready var text_label := get_node("Panel/Colums/Text") as Label -onready var button_next : = get_node("Panel/Colums/ButtonNext") as Button -onready var button_finished : = get_node("Panel/Colums/ButtonFinished") as Button +onready var button_next := get_node("Panel/Colums/ButtonNext") as Button +onready var button_finished := get_node("Panel/Colums/ButtonFinished") as Button -onready var portrait : = $Portrait as TextureRect +onready var portrait := $Portrait as TextureRect -func start(dialogue : Dictionary) -> void: + +func start(dialogue: Dictionary) -> void: # Reinitializes the UI and asks the DialoguePlayer to # play the dialogue button_finished.hide() @@ -24,21 +25,27 @@ func start(dialogue : Dictionary) -> void: update_content() show() + func _on_ButtonNext_pressed() -> void: dialogue_player.next() update_content() + func _on_DialoguePlayer_finished() -> void: button_next.hide() button_finished.grab_focus() button_finished.show() + func _on_ButtonFinished_pressed() -> void: emit_signal("dialogue_ended") hide() + func update_content() -> void: var dialogue_player_name = dialogue_player.title name_label.text = dialogue_player_name text_label.text = dialogue_player.text - portrait.texture = DialogueDatabase.get_texture(dialogue_player_name, dialogue_player.expression) + portrait.texture = DialogueDatabase.get_texture( + dialogue_player_name, dialogue_player.expression + ) diff --git a/godot/src/map/LocalMap.gd b/godot/src/map/LocalMap.gd index 1e8d5b9..e3ca14c 100644 --- a/godot/src/map/LocalMap.gd +++ b/godot/src/map/LocalMap.gd @@ -5,22 +5,26 @@ extends Node class_name LocalMap signal enemies_encountered(formation) -signal dialogue_finished() +signal dialogue_finished onready var dialogue_box = $MapInterface/DialogueBox onready var grid = $GameBoard + func _ready() -> void: assert(dialogue_box) for action in get_tree().get_nodes_in_group("map_action"): (action as MapAction).initialize(self) + func spawn_party(party) -> void: grid.pawns.spawn_party(grid, party) + func start_encounter(formation) -> void: emit_signal("enemies_encountered", formation.instance()) + func play_dialogue(data): dialogue_box.start(data) yield(dialogue_box, "dialogue_ended") diff --git a/godot/src/map/grid/GameBoard.gd b/godot/src/map/grid/GameBoard.gd index 2133b90..846a781 100644 --- a/godot/src/map/grid/GameBoard.gd +++ b/godot/src/map/grid/GameBoard.gd @@ -7,10 +7,11 @@ class_name GameBoard enum CELL_TYPES { EMPTY = -1, ACTOR, OBSTACLE, OBJECT } -var pathfinder : Pathfinder = Pathfinder.new() -onready var pawns : YSort = $Pawns +var pathfinder: Pathfinder = Pathfinder.new() +onready var pawns: YSort = $Pawns onready var spawning_point = $SpawningPoint + func _ready(): for pawn in pawns.get_children(): pawn.position = request_move(pawn, Vector2(0, 0)) @@ -18,27 +19,30 @@ func _ready(): set_cellv(world_to_map(pawn.position), pawn.type) pathfinder.initialize(self, [0, 1, 2]) -func get_cell_pawn(coordinates : Vector2) -> Pawn: + +func get_cell_pawn(coordinates: Vector2) -> Pawn: for pawn in pawns.get_children(): if not world_to_map(pawn.position) == coordinates: continue return pawn return null -func request_move(pawn : PawnActor, direction : Vector2) -> Vector2: + +func request_move(pawn: PawnActor, direction: Vector2) -> Vector2: # Checks if the Pawn can move in the given direction # If so, updates the grid's content and returns # the target cell's position in world coordinates # If not, returns Vector2(0, 0) - var cell_start : Vector2 = world_to_map(pawn.position) - var cell_target : Vector2 = cell_start + direction - - var cell_target_type : int = get_cellv(cell_target) + var cell_start: Vector2 = world_to_map(pawn.position) + var cell_target: Vector2 = cell_start + direction + + var cell_target_type: int = get_cellv(cell_target) if cell_target_type == CELL_TYPES.EMPTY or cell_target_type == CELL_TYPES.OBJECT: return update_pawn_position(pawn, cell_start, cell_target) return Vector2() -func find_path(start_world_position, end_world_position : Vector2) -> PoolVector3Array: + +func find_path(start_world_position, end_world_position: Vector2) -> PoolVector3Array: # Returns an array of grid points that connect the start and end world position var end = world_to_map(end_world_position) if get_cellv(end) != CELL_TYPES.EMPTY: @@ -46,10 +50,12 @@ func find_path(start_world_position, end_world_position : Vector2) -> PoolVector var start = world_to_map(start_world_position) return pathfinder.find_path(start, end) -func update_pawn_position(pawn : PawnActor, cell_start : Vector2, cell_target : Vector2) -> Vector2: + +func update_pawn_position(pawn: PawnActor, cell_start: Vector2, cell_target: Vector2) -> Vector2: set_cellv(cell_target, pawn.type) set_cellv(cell_start, CELL_TYPES.EMPTY) return map_to_world(cell_target) + cell_size / 2 -func calculate_world_pos(grid_pos : Vector2) -> Vector2: + +func calculate_world_pos(grid_pos: Vector2) -> Vector2: return map_to_world(grid_pos) - cell_size / 2 diff --git a/godot/src/map/grid/Pathfinder.gd b/godot/src/map/grid/Pathfinder.gd index c9df2fb..b7ac2c9 100644 --- a/godot/src/map/grid/Pathfinder.gd +++ b/godot/src/map/grid/Pathfinder.gd @@ -1,12 +1,13 @@ # Finds the path between two points using AStar, in grid coordinates class_name Pathfinder -var astar : AStar = AStar.new() +var astar: AStar = AStar.new() -var _obstacles : Array -var _map_size : Vector2 +var _obstacles: Array +var _map_size: Vector2 -func initialize(grid : TileMap, obstacle_tile_ids : Array) -> void: + +func initialize(grid: TileMap, obstacle_tile_ids: Array) -> void: # Initializes the AStar node: finds all walkable cells # and connects all walkable paths # Initialize map size and obstacles array @@ -15,9 +16,9 @@ func initialize(grid : TileMap, obstacle_tile_ids : Array) -> void: var occupied_cells = (grid as TileMap).get_used_cells_by_id(id) for cell in occupied_cells: _obstacles.append(cell) - + # Find all walkable cells and store them in an array - var points_array : = [] + var points_array := [] for y in range(_map_size.y): for x in range(_map_size.x): var point = Vector2(x, y) @@ -41,13 +42,16 @@ func initialize(grid : TileMap, obstacle_tile_ids : Array) -> void: continue astar.connect_points(point_index, point_relative_index, true) -func is_outside_map_bounds(point : Vector2) -> bool: + +func is_outside_map_bounds(point: Vector2) -> bool: return point.x < 0 or point.y < 0 or point.x >= _map_size.x or point.y >= _map_size.y -func calculate_point_index(point : Vector2) -> int: + +func calculate_point_index(point: Vector2) -> int: return int(point.x + _map_size.x * point.y) -func find_path(start : Vector2, end : Vector2) -> PoolVector3Array: + +func find_path(start: Vector2, end: Vector2) -> PoolVector3Array: # Returns an array of cells that connect the start and end positions # in grid coordinates var start_index = calculate_point_index(start) diff --git a/godot/src/map/grid/PawnContainer.gd b/godot/src/map/grid/PawnContainer.gd index 5b5b568..4580176 100644 --- a/godot/src/map/grid/PawnContainer.gd +++ b/godot/src/map/grid/PawnContainer.gd @@ -3,28 +3,28 @@ # Spawns and rebuilds the player's party extends YSort -export var party_scene : PackedScene +export var party_scene: PackedScene const Leader = preload("res://src/map/pawns/PawnLeader.tscn") const Follower = preload("res://src/map/pawns/PawnFollower.tscn") -var party_members : = [] +var party_members := [] var party -func spawn_party(game_board, party : Object) -> void: + +func spawn_party(game_board, party: Object) -> void: self.party = party var pawn_previous = null var party_size = min(get_child_count(), party.PARTY_SIZE) - 1 for index in range(party_size): - pawn_previous = spawn_pawn( - party.get_child(index), - game_board, - pawn_previous, - index == 0) + pawn_previous = spawn_pawn(party.get_child(index), game_board, pawn_previous, index == 0) party_members.append(pawn_previous) -func spawn_pawn(party_member : PartyMember, game_board : GameBoard, pawn_previous : Object, is_leader : bool = false) -> Object: - var new_pawn : PawnActor = Leader.instance() if is_leader else Follower.instance() + +func spawn_pawn( + party_member: PartyMember, game_board: GameBoard, pawn_previous: Object, is_leader: bool = false +) -> Object: + var new_pawn: PawnActor = Leader.instance() if is_leader else Follower.instance() new_pawn.name = party_member.name new_pawn.position = game_board.spawning_point.position new_pawn.initialize(game_board) @@ -34,6 +34,7 @@ func spawn_pawn(party_member : PartyMember, game_board : GameBoard, pawn_previou new_pawn.change_skin(party_member.get_pawn_anim()) return new_pawn + func rebuild_party() -> void: var Leader_pos = party_members[0].position for member in party_members: diff --git a/godot/src/map/grid/SpawningPoint.gd b/godot/src/map/grid/SpawningPoint.gd index 8457f84..62129c3 100644 --- a/godot/src/map/grid/SpawningPoint.gd +++ b/godot/src/map/grid/SpawningPoint.gd @@ -1,7 +1,8 @@ tool extends Position2D -export var DRAW_COLOR : = Color("#e231b6") +export var DRAW_COLOR := Color("#e231b6") + func _draw() -> void: if not Engine.editor_hint: diff --git a/godot/src/map/pawns/Pawn.gd b/godot/src/map/pawns/Pawn.gd index d9353c3..e24aa4d 100644 --- a/godot/src/map/pawns/Pawn.gd +++ b/godot/src/map/pawns/Pawn.gd @@ -3,4 +3,4 @@ extends Node2D class_name Pawn enum CELL_TYPES { ACTOR, OBSTACLE, OBJECT } -export(CELL_TYPES) var type = CELL_TYPES.ACTOR +export (CELL_TYPES) var type = CELL_TYPES.ACTOR diff --git a/godot/src/map/pawns/PawnActor.gd b/godot/src/map/pawns/PawnActor.gd index 880b4c7..77fb263 100644 --- a/godot/src/map/pawns/PawnActor.gd +++ b/godot/src/map/pawns/PawnActor.gd @@ -8,17 +8,21 @@ signal moved(last_position, current_position) onready var pivot = $Pivot onready var tween = $Tween -onready var anim : PawnAnim = pivot.get_node("PawnAnim") +onready var anim: PawnAnim = pivot.get_node("PawnAnim") + func _ready(): update_look_direction(Vector2(1, 0)) + func initialize(board): game_board = board + func update_look_direction(direction): return + func move_to(target_position): emit_signal("moved", position, target_position) set_process(false) @@ -27,18 +31,28 @@ func move_to(target_position): # and animate the sprite moving from the start to the target cell var move_direction = (target_position - position).normalized() position = target_position - pivot.position = - move_direction * 40.0 - tween.interpolate_property($Pivot, "position", pivot.position, Vector2(), anim.get_current_animation_length(), Tween.TRANS_LINEAR, Tween.EASE_IN) + pivot.position = -move_direction * 40.0 + tween.interpolate_property( + $Pivot, + "position", + pivot.position, + Vector2(), + anim.get_current_animation_length(), + Tween.TRANS_LINEAR, + Tween.EASE_IN + ) tween.start() yield(anim.play_walk(), "completed") set_process(true) - + + func bump(): set_process(false) yield(anim.play_bump(), "completed") set_process(true) -func change_skin(pawn_anim : PawnAnim): + +func change_skin(pawn_anim: PawnAnim): # Replaces the pawn's animated character with another if anim: anim.queue_free() diff --git a/godot/src/map/pawns/PawnAnim.gd b/godot/src/map/pawns/PawnAnim.gd index 68b2003..9c80c8c 100644 --- a/godot/src/map/pawns/PawnAnim.gd +++ b/godot/src/map/pawns/PawnAnim.gd @@ -4,16 +4,20 @@ class_name PawnAnim onready var anim = $AnimationPlayer + func _ready(): anim.set_current_animation('walk') + func play_walk(): anim.play("walk") yield(anim, "animation_finished") + func play_bump(): anim.play("bump") yield(anim, "animation_finished") + func get_current_animation_length(): return anim.current_animation_length diff --git a/godot/src/map/pawns/PawnFollower.gd b/godot/src/map/pawns/PawnFollower.gd index 5d2b687..c3cb539 100644 --- a/godot/src/map/pawns/PawnFollower.gd +++ b/godot/src/map/pawns/PawnFollower.gd @@ -2,11 +2,13 @@ extends PawnActor class_name PawnFollower + func _on_target_Pawn_moved(last_position, current_position): follow(last_position) + func follow(target_position): var direction = (target_position - position).normalized() update_look_direction(direction) - + move_to(target_position) diff --git a/godot/src/map/pawns/PawnInteractive.gd b/godot/src/map/pawns/PawnInteractive.gd index cfdfeb0..7affa1b 100644 --- a/godot/src/map/pawns/PawnInteractive.gd +++ b/godot/src/map/pawns/PawnInteractive.gd @@ -8,25 +8,21 @@ class_name PawnInteractive signal interaction_finished(pawn) -onready var raycasts : Node2D = $Raycasts -onready var dialogue_balloon : Sprite = $DialogueBalloon -onready var collision_shape : CollisionShape2D = $CollisionShape2D -onready var actions : Node = $Actions +onready var raycasts: Node2D = $Raycasts +onready var dialogue_balloon: Sprite = $DialogueBalloon +onready var collision_shape: CollisionShape2D = $CollisionShape2D +onready var actions: Node = $Actions -onready var quest_bubble : Node = $QuestBubble +onready var quest_bubble: Node = $QuestBubble -export var vanish_on_interaction : = false -export var AUTO_START_INTERACTION : = false +export var vanish_on_interaction := false +export var AUTO_START_INTERACTION := false export var sight_distance = 50 -export var facing = { - "up": true, - "left": true, - "right": true, - "down": true -} +export var facing = {"up": true, "left": true, "right": true, "down": true} var active_raycasts := [] + func _ready(): # Initializes raycast nodes, deactivates the area if using raycasts # for player detection @@ -38,7 +34,7 @@ func _ready(): raycast.cast_to = raycast.cast_to.normalized() * sight_distance active_raycasts.append(raycast) use_area = false - + if use_area: connect('body_entered', self, '_on_body_entered') connect('body_exited', self, '_on_body_exited') @@ -46,7 +42,7 @@ func _ready(): # Quests # Send quest-related MapActions, if any, to the QuestBubble - var quest_actions : Array = [] + var quest_actions: Array = [] for action in actions.get_children(): if not (action is GiveQuestAction or action is CompleteQuestAction): continue @@ -55,6 +51,7 @@ func _ready(): return quest_bubble.initialize(quest_actions) + func _unhandled_input(event: InputEvent) -> void: # Use the area to detect if the user is clicking on the NPCs' interaction zone if event is InputEventMouseButton: @@ -66,7 +63,8 @@ func _unhandled_input(event: InputEvent) -> void: start_interaction() get_tree().set_input_as_handled() -func _physics_process(delta : float) -> void: + +func _physics_process(delta: float) -> void: # Only runs if using raycasts/specific directions for player detection if not dialogue_balloon.visible: for raycast in active_raycasts: @@ -76,22 +74,25 @@ func _physics_process(delta : float) -> void: start_interaction() dialogue_balloon.show() else: - var inactive_count : int = 0 + var inactive_count: int = 0 for raycast in active_raycasts: if not raycast.is_colliding(): inactive_count += 1 if inactive_count == active_raycasts.size(): dialogue_balloon.visible = false -func _on_body_entered(body : PhysicsBody2D) -> void: + +func _on_body_entered(body: PhysicsBody2D) -> void: if AUTO_START_INTERACTION: start_interaction() else: dialogue_balloon.show() -func _on_body_exited(body : PhysicsBody2D) -> void: + +func _on_body_exited(body: PhysicsBody2D) -> void: dialogue_balloon.hide() + func start_interaction() -> void: # Pauses the game and play each action under the $Actions node # Actions that transition to another scene (e.g. StartCombatAction) may unpause diff --git a/godot/src/map/pawns/PawnLeader.gd b/godot/src/map/pawns/PawnLeader.gd index 6fa1eb5..d7d0d08 100644 --- a/godot/src/map/pawns/PawnLeader.gd +++ b/godot/src/map/pawns/PawnLeader.gd @@ -3,46 +3,52 @@ extends PawnActor class_name PawnLeader -onready var destination_point : = $DestinationPoint +onready var destination_point := $DestinationPoint + +var _path_current := PoolVector3Array() +var _direction := Vector2() -var _path_current : = PoolVector3Array() -var _direction : = Vector2() func _ready() -> void: destination_point.set_as_toplevel(true) destination_point.hide() + func _process(delta: float) -> void: if _path_current.size() > 0: - var next_point : = Vector2(_path_current[0].x, _path_current[0].y) + var next_point := Vector2(_path_current[0].x, _path_current[0].y) _direction = next_point - game_board.world_to_map(global_position) _path_current.remove(0) - + if _direction != Vector2(): update_look_direction(_direction) - var target_position : Vector2 = game_board.request_move(self, _direction) + var target_position: Vector2 = game_board.request_move(self, _direction) if target_position: move_to(target_position) else: bump() - + if _path_current.size() == 0: destination_point.hide() _direction = Vector2() + func get_key_input_direction(event: InputEventKey) -> Vector2: return Vector2( int(event.is_action_pressed("ui_right")) - int(event.is_action_pressed("ui_left")), int(event.is_action_pressed("ui_down")) - int(event.is_action_pressed("ui_up")) ) + func _unhandled_input(event: InputEvent) -> void: if event is InputEventKey: _direction = get_key_input_direction(event) - elif event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed \ - or event is InputEventScreenTouch and event.pressed: + elif ( + event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed + or event is InputEventScreenTouch and event.pressed + ): _path_current = game_board.find_path(global_position, get_global_mouse_position()) if _path_current.size() > 0: - var pos : = _path_current[_path_current.size()-1] + var pos := _path_current[_path_current.size() - 1] destination_point.position = game_board.map_to_world(Vector2(pos.x, pos.y)) - destination_point.show() \ No newline at end of file + destination_point.show() diff --git a/godot/src/map/pawns/actions/CompleteQuestAction.gd b/godot/src/map/pawns/actions/CompleteQuestAction.gd index 9414788..fccc79b 100644 --- a/godot/src/map/pawns/actions/CompleteQuestAction.gd +++ b/godot/src/map/pawns/actions/CompleteQuestAction.gd @@ -3,8 +3,9 @@ extends MapAction class_name CompleteQuestAction -export var quest_reference : PackedScene -var quest : Quest = null +export var quest_reference: PackedScene +var quest: Quest = null + func _ready() -> void: assert(quest_reference) @@ -12,9 +13,11 @@ func _ready() -> void: active = false quest.connect("completed", self, "_on_Quest_completed") + func _on_Quest_completed() -> void: active = true + func interact() -> void: get_tree().paused = false if not active: diff --git a/godot/src/map/pawns/actions/DialogueAction.gd b/godot/src/map/pawns/actions/DialogueAction.gd index c854d19..eab9371 100644 --- a/godot/src/map/pawns/actions/DialogueAction.gd +++ b/godot/src/map/pawns/actions/DialogueAction.gd @@ -1,14 +1,16 @@ extends MapAction class_name DialogueAction -export (String, FILE, "*.json") var dialogue_file_path : String +export (String, FILE, "*.json") var dialogue_file_path: String signal dialogue_loaded(data) + func interact() -> void: - var dialogue : Dictionary = load_dialogue(dialogue_file_path) + var dialogue: Dictionary = load_dialogue(dialogue_file_path) yield(local_map.play_dialogue(dialogue), "completed") emit_signal("finished") + func load_dialogue(file_path) -> Dictionary: # Parses a JSON file and returns it as a dictionary var file = File.new() diff --git a/godot/src/map/pawns/actions/GiveQuestAction.gd b/godot/src/map/pawns/actions/GiveQuestAction.gd index 03b389a..eda09c4 100644 --- a/godot/src/map/pawns/actions/GiveQuestAction.gd +++ b/godot/src/map/pawns/actions/GiveQuestAction.gd @@ -2,23 +2,26 @@ extends MapAction class_name GiveQuestAction -export var quest_reference : PackedScene -var quest : Quest = null +export var quest_reference: PackedScene +var quest: Quest = null + func _ready() -> void: assert(quest_reference) quest = QuestSystem.find_available(quest_reference.instance()) quest.connect("started", self, "_on_Quest_started") + func _on_Quest_started(): active = false + func interact() -> void: get_tree().paused = false if not active: emit_signal("finished") return - var quest : Quest = quest_reference.instance() + var quest: Quest = quest_reference.instance() if not QuestSystem.is_available(quest): return QuestSystem.start(quest) diff --git a/godot/src/map/pawns/actions/MapAction.gd b/godot/src/map/pawns/actions/MapAction.gd index a3bb10c..491f6bc 100644 --- a/godot/src/map/pawns/actions/MapAction.gd +++ b/godot/src/map/pawns/actions/MapAction.gd @@ -6,17 +6,20 @@ extends Node class_name MapAction -signal finished() +signal finished var local_map -var active : bool = true +var active: bool = true + func _ready() -> void: # using a group so LocalMap can initialize all MapActions add_to_group("map_action") + func initialize(_local_map): local_map = _local_map + func interact() -> void: print("You forgot to override the interact method in " + name) emit_signal("finished") diff --git a/godot/src/map/pawns/actions/StartCombatAction.gd b/godot/src/map/pawns/actions/StartCombatAction.gd index 08a9456..4d1faaf 100644 --- a/godot/src/map/pawns/actions/StartCombatAction.gd +++ b/godot/src/map/pawns/actions/StartCombatAction.gd @@ -1,7 +1,8 @@ extends MapAction class_name StartCombatAction -export var formation : PackedScene +export var formation: PackedScene + func interact() -> void: get_tree().paused = false diff --git a/godot/src/party/Inventory.gd b/godot/src/party/Inventory.gd index 1918a3c..47a4d54 100644 --- a/godot/src/party/Inventory.gd +++ b/godot/src/party/Inventory.gd @@ -2,19 +2,21 @@ extends Reference class_name Inventory -export(int) var MAX_COINS = 999 -var coins : int = 0 +export (int) var MAX_COINS = 999 +var coins: int = 0 var content = {} signal item_count_changed(item, amount) signal coins_count_changed(amount) + func add(item: Item, amount: int = 1) -> void: if item in content: content[item] += amount else: content[item] = 1 if item.unique else amount + func remove(item: Item, amount: int = 1): assert(item in content) assert(amount <= content[item]) @@ -25,15 +27,18 @@ func remove(item: Item, amount: int = 1): emit_signal("item_count_changed", item, 0) else: emit_signal("item_count_changed", item, content[item]) - + + func add_coins(amount: int) -> void: coins = min(coins + amount, MAX_COINS) emit_signal("coins_changed", coins) + func remove_coins(amount: int) -> void: coins = max(0, coins - amount) emit_signal("coins_changed", coins) + func get_consumables() -> Array: var consumable: Array for item in content.keys(): @@ -41,6 +46,7 @@ func get_consumables() -> Array: consumable.append(item) return consumable + func get_equipment() -> Array: var equipment: Array for item in content.keys(): @@ -48,6 +54,7 @@ func get_equipment() -> Array: equipment.append(item) return equipment + func get_unique_items() -> Array: var unique: Array for item in content.keys(): diff --git a/godot/src/party/Party.gd b/godot/src/party/Party.gd index eb0defc..1498892 100644 --- a/godot/src/party/Party.gd +++ b/godot/src/party/Party.gd @@ -6,10 +6,11 @@ extends Node2D class_name Party -export var PARTY_SIZE : int = 3 +export var PARTY_SIZE: int = 3 var inventory = Inventory.new() + func get_active_members(): # Returns the first unlocked children until the party is filled var active = [] @@ -17,7 +18,8 @@ func get_active_members(): for i in range(min(len(available), PARTY_SIZE)): active.append(available[i]) return active - + + func get_unlocked_characters() -> Array: # Returns all the characters that can be active in the party var has_unlocked = [] diff --git a/godot/src/party/PartyMember.gd b/godot/src/party/PartyMember.gd index f4c5eda..03658b9 100644 --- a/godot/src/party/PartyMember.gd +++ b/godot/src/party/PartyMember.gd @@ -7,14 +7,15 @@ class_name PartyMember signal level_changed(new_value, old_value) -export var pawn_anim_path : NodePath -export var growth : Resource +export var pawn_anim_path: NodePath +export var growth: Resource -export var experience : int setget _set_experience -var stats : Resource +export var experience: int setget _set_experience +var stats: Resource + +onready var battler: Battler = $Battler +onready var SAVE_KEY: String = "party_member_" + name -onready var battler : Battler = $Battler -onready var SAVE_KEY : String = "party_member_" + name func _ready(): assert(pawn_anim_path) @@ -22,7 +23,8 @@ func _ready(): stats = growth.create_stats(experience) battler.stats = stats -func update_stats(before_stats : CharacterStats): + +func update_stats(before_stats: CharacterStats): # Update this character's stats to match select changes # that occurred during combat or through menu actions var before_level = before_stats.level @@ -32,32 +34,37 @@ func update_stats(before_stats : CharacterStats): emit_signal("level_changed", after_level, before_level) battler.stats = stats + func get_battler_copy(): # Returns a copy of the battler to add to the CombatArena # at the start of a battle return battler.duplicate() + func get_pawn_anim(): # Returns a copy of the PawnAnim that represents this character, # e.g. to add it as a child of the currently loaded game map return get_node(pawn_anim_path).duplicate() -func _set_experience(value : int): + +func _set_experience(value: int): if value == null: return experience = max(0, value) if stats: update_stats(stats) -func save(save_game : Resource): + +func save(save_game: Resource): save_game.data[SAVE_KEY] = { - 'experience' : experience, - 'health' : stats.health, - 'mana' : stats.mana, + 'experience': experience, + 'health': stats.health, + 'mana': stats.mana, } -func load(save_game : Resource): - var data : Dictionary = save_game.data[SAVE_KEY] + +func load(save_game: Resource): + var data: Dictionary = save_game.data[SAVE_KEY] experience = data['experience'] stats.health = data['health'] stats.mana = data['mana'] diff --git a/godot/src/quest/Quest.gd b/godot/src/quest/Quest.gd index e108729..94c813c 100644 --- a/godot/src/quest/Quest.gd +++ b/godot/src/quest/Quest.gd @@ -4,57 +4,62 @@ extends Node class_name Quest -signal started() -signal completed() -signal delivered() +signal started +signal completed +signal delivered onready var objectives = $Objectives -export var title : String -export var description : String +export var title: String +export var description: String + +export var reward_on_delivery: bool = false +export var _reward_experience: int +onready var _reward_items: Node = $ItemRewards -export var reward_on_delivery : bool = false -export var _reward_experience : int -onready var _reward_items : Node = $ItemRewards func _start(): for objective in get_objectives(): objective.connect("completed", self, "_on_Objective_completed") emit_signal("started") + func get_objectives(): return objectives.get_children() + func get_completed_objectives(): - var completed : Array = [] + var completed: Array = [] for objective in get_objectives(): if not objective.completed: continue completed.append(objective) return completed + func _on_Objective_completed(objective) -> void: if get_completed_objectives().size() == get_objectives().size(): emit_signal("completed") + func _deliver(): emit_signal("delivered") + func notify_slay_objectives() -> void: for objective in get_objectives(): if not objective is QuestSlayObjective: continue (objective as QuestSlayObjective).connect_signals() + func get_rewards() -> Dictionary: # Returns the rewards from the quest as a dictionary - return { - 'experience' : _reward_experience, # int - 'items': _reward_items.get_children() # Array of Item - } + return {'experience': _reward_experience, 'items': _reward_items.get_children()} # int # Array of Item + func get_rewards_as_text() -> Array: - var text : = [] + var text := [] text.append(" - Experience: %s" % str(_reward_experience)) for item in _reward_items.get_children(): text.append(" - [%s] x (%s)\n" % [item.item.name, str(item.amount)]) diff --git a/godot/src/quest/QuestBubble.gd b/godot/src/quest/QuestBubble.gd index e43df87..b16e867 100644 --- a/godot/src/quest/QuestBubble.gd +++ b/godot/src/quest/QuestBubble.gd @@ -2,18 +2,20 @@ # an InteractivePawn can start or end a quest extends Position2D -onready var animated_sprite : AnimatedSprite = $AnimatedSprite -onready var animation_player : AnimationPlayer = $AnimationPlayer +onready var animated_sprite: AnimatedSprite = $AnimatedSprite +onready var animation_player: AnimationPlayer = $AnimationPlayer + func _ready() -> void: hide() animation_player.play("wobble") -func initialize(quest_actions : Array): + +func initialize(quest_actions: Array): var quest = quest_actions[0].quest var name = get_parent().name - var action_give : GiveQuestAction - var action_complete : CompleteQuestAction + var action_give: GiveQuestAction + var action_complete: CompleteQuestAction for action in quest_actions: if action is GiveQuestAction: action_give = action @@ -29,13 +31,16 @@ func initialize(quest_actions : Array): quest.connect("completed", self, "_on_Quest_completed") quest.connect("delivered", self, "_on_Quest_delivered") + func _on_Quest_started(): animated_sprite.animation = "quest_active" + func _on_Quest_completed(): show() animated_sprite.animation = "quest_complete" + func _on_Quest_delivered(): animation_player.stop() hide() diff --git a/godot/src/quest/QuestContainer.gd b/godot/src/quest/QuestContainer.gd index 469acdf..24037f2 100644 --- a/godot/src/quest/QuestContainer.gd +++ b/godot/src/quest/QuestContainer.gd @@ -1,12 +1,14 @@ # Utility to represent a list of active, available, or finished quests extends Node -func find(_quest : Quest) -> Quest: + +func find(_quest: Quest) -> Quest: # Finds a quest by reference and returns it for quest in get_children(): if quest.name == _quest.name: return quest return null + func get_quests() -> Array: return get_children() diff --git a/godot/src/quest/QuestItemReward.gd b/godot/src/quest/QuestItemReward.gd index 539f184..7441bbb 100644 --- a/godot/src/quest/QuestItemReward.gd +++ b/godot/src/quest/QuestItemReward.gd @@ -1,5 +1,5 @@ extends Node class_name QuestItemReward -export var item : Resource -export var amount : int +export var item: Resource +export var amount: int diff --git a/godot/src/quest/QuestSystem.gd b/godot/src/quest/QuestSystem.gd index a91d784..ac18f1e 100644 --- a/godot/src/quest/QuestSystem.gd +++ b/godot/src/quest/QuestSystem.gd @@ -9,36 +9,43 @@ onready var active_quests = $Active onready var completed_quests = $Completed onready var delivered_quests = $Delivered -var party : Party +var party: Party -func initialize(game, _party : Party ) -> void: + +func initialize(game, _party: Party) -> void: game.connect("combat_started", self, "_on_Game_combat_started") party = _party -func find_available(reference : Quest) -> Quest: + +func find_available(reference: Quest) -> Quest: # Returns the Quest corresponding to the reference instance, # to track its state or connect to it return available_quests.find(reference) + func get_available_quests() -> Array: # Returns an Array of all quests under the Available node return available_quests.get_quests() -func is_available(reference : Quest) -> bool: + +func is_available(reference: Quest) -> bool: return available_quests.find(reference) != null -func start(reference : Quest): - var quest : Quest = available_quests.find(reference) + +func start(reference: Quest): + var quest: Quest = available_quests.find(reference) quest.connect("completed", self, "_on_Quest_completed", [quest]) available_quests.remove_child(quest) active_quests.add_child(quest) quest._start() + func _on_Quest_completed(quest): active_quests.remove_child(quest) completed_quests.add_child(quest) -func deliver(quest : Quest): + +func deliver(quest: Quest): # Marks the quest as complete, rewards the player, # and removes it from completed quests quest._deliver() @@ -55,6 +62,7 @@ func deliver(quest : Quest): completed_quests.remove_child(quest) delivered_quests.add_child(quest) + func _on_Game_combat_started() -> void: for quest in active_quests.get_quests(): quest.notify_slay_objectives() diff --git a/godot/src/quest/objectives/QuestInteractObjective.gd b/godot/src/quest/objectives/QuestInteractObjective.gd index bac129e..f206a63 100644 --- a/godot/src/quest/objectives/QuestInteractObjective.gd +++ b/godot/src/quest/objectives/QuestInteractObjective.gd @@ -1,15 +1,20 @@ extends QuestObjective class_name QuestInteractObjective -export var interact_with : PackedScene +export var interact_with: PackedScene + func _ready() -> void: for interactive_pawn in get_tree().get_nodes_in_group("interactive_pawns"): - interactive_pawn.connect("interaction_finished", self, "_on_InteractivePawn_interaction_finished") + interactive_pawn.connect( + "interaction_finished", self, "_on_InteractivePawn_interaction_finished" + ) + func _on_InteractivePawn_interaction_finished(pawn) -> void: if pawn.filename == interact_with.resource_path and not completed: finish() + func as_text() -> String: return "Speak with: %s %s" % [interact_with.instance().name, "(completed)" if completed else ""] diff --git a/godot/src/quest/objectives/QuestObjective.gd b/godot/src/quest/objectives/QuestObjective.gd index 8534008..d65c8ac 100644 --- a/godot/src/quest/objectives/QuestObjective.gd +++ b/godot/src/quest/objectives/QuestObjective.gd @@ -6,11 +6,13 @@ class_name QuestObjective signal completed(objective) signal updated(objective) -var completed : bool = false +var completed: bool = false + func finish() -> void: completed = true emit_signal("completed", self) + func as_text() -> String: return "Objective %s as_text method should be overriden" % get_path() diff --git a/godot/src/quest/objectives/QuestSlayObjective.gd b/godot/src/quest/objectives/QuestSlayObjective.gd index ba47de6..60a23f1 100644 --- a/godot/src/quest/objectives/QuestSlayObjective.gd +++ b/godot/src/quest/objectives/QuestSlayObjective.gd @@ -1,13 +1,15 @@ extends QuestObjective class_name QuestSlayObjective -export var amount : int -export var battler_to_slay : PackedScene +export var amount: int +export var battler_to_slay: PackedScene + func connect_signals() -> void: for enemy in get_tree().get_nodes_in_group("enemies"): enemy.connect("died", self, "_on_enemy_died") + func _on_enemy_died(battler) -> void: if completed or battler.filename != battler_to_slay.resource_path: return @@ -16,5 +18,9 @@ func _on_enemy_died(battler) -> void: if amount == 0 and not completed: finish() + func as_text() -> String: - return "Slay %s %s(s) %s" % [str(amount), battler_to_slay.instance().name, "(completed)" if completed else ""] + return ( + "Slay %s %s(s) %s" + % [str(amount), battler_to_slay.instance().name, "(completed)" if completed else ""] + ) -- GitLab