diff --git a/godot/combat/CombatAction.gd b/godot/combat/CombatAction.gd index f309bb402de3c1ada012b05c142f31319c4fc769..3996db3d072779f99886231844aa557f78af49e3 100644 --- a/godot/combat/CombatAction.gd +++ b/godot/combat/CombatAction.gd @@ -2,11 +2,53 @@ extends Node class_name CombatAction -signal execute_finished() +var initialized = false + +var targets : Array = [] +var allys : Array = [] +var target : Battler = null +var skill_to_use : Skill = null + +# 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() export var icon : Texture export var description : String = "Base combat action" -func execute(actor : Battler, target : Battler) -> void: +func initialize(p_targets : Array, p_allys : Array, p_actor : Battler) -> void: + targets = p_targets + allys = p_allys + actor = p_actor + initialized = true + +func execute() -> void: + assert(initialized) print("%s missing overwrite of the execute method" % name) - emit_signal("execute_finished") + +func attack_routine(): + actor.attack(target) + yield(actor.get_tree().create_timer(1.0), "timeout") + +func move_to_target_routine(): + yield(actor.skin.move_to(target), "completed") + +func return_to_start_position_routine(): + yield(actor.skin.return_to_start(), "completed") + +func select_target_routine(): + var interface = actor.get_tree().get_nodes_in_group("interface")[0] + target = yield(interface.select_target(targets), "completed") + interface.action_list.hide() + +func use_skill_routine(): + if skill_to_use.success_chance == 1.0: + actor.use_skill(target, skill_to_use) + else: + randomize() + if rand_range(0, 1.0) < skill_to_use.success_chance: + actor.use_skill(target, skill_to_use) + yield(actor.get_tree().create_timer(1.0), "timeout") + + diff --git a/godot/combat/CombatArena.gd b/godot/combat/CombatArena.gd index d58cbf3aaeb5eac11e4867eb4370b61218823ad9..b1d8d76c8b7031237f0081a2a5a9e964f4517f08 100644 --- a/godot/combat/CombatArena.gd +++ b/godot/combat/CombatArena.gd @@ -25,8 +25,8 @@ func initialize(formation : Formation, party : Array): turn_queue.initialize() func battle_start(): - active = true yield(play_intro(), "completed") + active = true play_turn() func play_intro(): @@ -93,27 +93,28 @@ func battle_end(): func play_turn(): var battler : Battler = get_active_battler() - battler.selected = true - - var targets : Array = get_targets() - if not targets: - battle_end() - return - var target : Battler - var action : CombatAction - if battler.party_member: - interface.update_actions(battler) - target = yield(interface.select_target(targets), "completed") -# action = get_active_battler().actions.get_child(0) - action = interface.selected_action + if battler.stats.health > 0: + battler.selected = true + + var targets : Array = get_targets() + if not targets: + battle_end() + return + var target : Battler + var action : CombatAction + if battler.party_member: + interface.update_actions(battler) + action = yield(interface, "action_selected") + else: + # Temp random target selection for the monsters + action = get_active_battler().actions.get_child(0) + action.target = battler.choose_target(targets) + + yield(turn_queue.play_turn(action), "completed") + battler.selected = false else: - # Temp random target selection for the monsters - target = battler.choose_target(targets) - action = get_active_battler().actions.get_child(0) - - yield(turn_queue.play_turn(target, action), "completed") + turn_queue.skip_turn() - battler.selected = false if active: play_turn() diff --git a/godot/combat/CombatArena.tscn b/godot/combat/CombatArena.tscn index 4d5e56c22095f7d2ac761ca265e73856025ff3e1..08dfd2d3a293dd4d1843d6bbaa012d6f86611b45 100644 --- a/godot/combat/CombatArena.tscn +++ b/godot/combat/CombatArena.tscn @@ -26,7 +26,9 @@ position = Vector2( 1376, 672 ) [node name="TurnQueue" parent="." instance=ExtResource( 2 )] z_index = 10 -[node name="CombatInterface" type="CanvasLayer" parent="."] +[node name="CombatInterface" type="CanvasLayer" parent="." groups=[ +"interface", +]] layer = 100 offset = Vector2( 0, 0 ) rotation = 0.0 @@ -35,10 +37,8 @@ transform = Transform2D( 1, 0, 0, 1, 0, 0 ) script = ExtResource( 3 ) [node name="SelectArrow" parent="CombatInterface" instance=ExtResource( 4 )] -position = Vector2( -39, -51 ) [node name="OldSchoolUI" type="Control" parent="CombatInterface"] -visible = false anchor_left = 0.0 anchor_top = 1.0 anchor_right = 1.0 @@ -96,6 +96,44 @@ size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 0 +[node name="ActionSelector" type="Control" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel"] +anchor_left = 1.0 +anchor_top = 0.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = -251.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 + +[node name="ItemList" type="ItemList" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel/ActionSelector"] +visible = false +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = true +focus_neighbour_left = NodePath(".") +focus_neighbour_top = NodePath(".") +focus_neighbour_right = NodePath(".") +focus_neighbour_bottom = NodePath(".") +focus_next = NodePath(".") +focus_previous = NodePath(".") +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +items = [ "Slash", null, false, "Crush", null, true, "Anihilate", null, false ] +select_mode = 0 +allow_reselect = false +icon_mode = 1 +fixed_icon_size = Vector2( 0, 0 ) + [node name="PartyPanel" type="Panel" parent="CombatInterface/OldSchoolUI/Row"] anchor_left = 0.0 anchor_top = 0.0 @@ -155,42 +193,6 @@ mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 -[node name="ActionSelector" type="Control" parent="CombatInterface"] -anchor_left = 1.0 -anchor_top = 0.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_left = -171.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 0 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 - -[node name="ItemList" type="ItemList" parent="CombatInterface/ActionSelector"] -visible = false -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -margin_left = -65.0 -margin_top = -70.0 -margin_right = 65.0 -margin_bottom = 70.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = true -focus_mode = 2 -mouse_filter = 0 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -items = [ "Slash", null, false, "Crush", null, true, "Anihilate", null, false ] -select_mode = 0 -allow_reselect = false -icon_mode = 1 -fixed_icon_size = Vector2( 0, 0 ) - [node name="BattlersBarsBuilder" parent="CombatInterface" instance=ExtResource( 6 )] [node name="Rewards" type="CanvasLayer" parent="."] @@ -236,5 +238,4 @@ percent_visible = 1.0 lines_skipped = 0 max_lines_visible = -1 -[connection signal="victory" from="." to="Rewards" method="_on_victory"] -[connection signal="item_selected" from="CombatInterface/ActionSelector/ItemList" to="CombatInterface" method="_on_ItemList_item_selected"] +[connection signal="item_activated" from="CombatInterface/OldSchoolUI/Row/MonstersPanel/ActionSelector/ItemList" to="CombatInterface" method="_on_ItemList_item_activated"] diff --git a/godot/combat/battlers/Battler.gd b/godot/combat/battlers/Battler.gd index 503d27fff8d7d767f236c98fccc20d9ecd7c9a25..1cf3bfd78c7bbb4c17ef92f5f3fdd732985665eb 100644 --- a/godot/combat/battlers/Battler.gd +++ b/godot/combat/battlers/Battler.gd @@ -35,13 +35,6 @@ func _ready() -> void: skin.initialize() self.selectable = true -func play_turn(target : Battler, action): - yield(skin.move_forward(), "completed") - action.execute(self, target) - yield(skin.move_to(target), "completed") - yield(get_tree().create_timer(1.0), "timeout") - yield(skin.return_to_start(), "completed") - func set_selected(value): selected = value skin.blink = value @@ -50,6 +43,9 @@ func attack(target : Battler): var hit = Hit.new(stats.strength) target.take_damage(hit) +func can_use_skill(skill : Skill) -> bool: + return stats.mana >= skill.mana_cost + func use_skill(target : Battler, skill : Skill) -> void: if stats.mana < skill.mana_cost: return diff --git a/godot/combat/battlers/BattlerSkin.gd b/godot/combat/battlers/BattlerSkin.gd index 907583bffe76a2d732f7a360d9cafff41663fb20..3bdcc769e6837dad79a43b9b5c56f16715cc5803 100644 --- a/godot/combat/battlers/BattlerSkin.gd +++ b/godot/combat/battlers/BattlerSkin.gd @@ -20,7 +20,7 @@ func initialize(): break func move_forward(): - var direction = Vector2(-1.0, 0.0) if owner.is_in_group("party") else Vector2(1.0, 0.0) + var direction = Vector2(-1.0, 0.0) if owner.party_member else Vector2(1.0, 0.0) tween.interpolate_property( self, 'position', diff --git a/godot/combat/battlers/DanBattler.tscn b/godot/combat/battlers/DanBattler.tscn new file mode 100644 index 0000000000000000000000000000000000000000..9ab9b1b17ec12c2eae862708c067cb559dfc771b --- /dev/null +++ b/godot/combat/battlers/DanBattler.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://combat/battlers/Battler.tscn" type="PackedScene" id=1] +[ext_resource path="res://animation/DanAnim.tscn" type="PackedScene" id=2] + +[sub_resource type="Shader" id=1] + +code = "shader_type canvas_item; + + +" + +[sub_resource type="ShaderMaterial" id=2] + +render_priority = 0 +shader = SubResource( 1 ) + +[node name="Dan" index="0" instance=ExtResource( 1 )] +material = SubResource( 2 ) + +[node name="DanAnim" parent="Skin" index="0" instance=ExtResource( 2 )] + diff --git a/godot/combat/battlers/actions/Attack.gd b/godot/combat/battlers/actions/Attack.gd index bded17ac3dcf40604c9d129ee9fe9fa03cc34991..a36e376fb8b572a7cd895fd631cdec933449af8a 100644 --- a/godot/combat/battlers/actions/Attack.gd +++ b/godot/combat/battlers/actions/Attack.gd @@ -1,5 +1,11 @@ extends CombatAction -func execute(actor : Battler, target : Battler) -> void: - actor.attack(target) - emit_signal("execute_finished") +func execute(): + assert(initialized) + print("TODO: ATTACK -> at some point we should define the attack commands based on the equiped items\n" + + "ie: if you have a bow you should not move to the target!") + if actor.party_member: + yield(select_target_routine(), "completed") + yield(move_to_target_routine(), "completed") + yield(attack_routine(), "completed") + yield(return_to_start_position_routine(), "completed") diff --git a/godot/combat/battlers/actions/SkillAction.gd b/godot/combat/battlers/actions/SkillAction.gd index 957c01b762a5e8c5c4883fdf5db48dd2d991e573..849f9fcb0386a1135a2c5a64c6df17b7fdd0d710 100644 --- a/godot/combat/battlers/actions/SkillAction.gd +++ b/godot/combat/battlers/actions/SkillAction.gd @@ -1,16 +1,14 @@ extends CombatAction -var skill_to_use : Skill - func _ready() -> void: name = skill_to_use.skill_name randomize() -func execute(actor : Battler, target : Battler) -> void: - if skill_to_use.success_chance == 1.0: - actor.use_skill(target, skill_to_use) - else: - randomize() - if rand_range(0, 1.0) < skill_to_use.success_chance: - actor.use_skill(target, skill_to_use) - emit_signal("execute_finished") +func execute(): + assert(initialized) + if actor.party_member: + print("TODO: SKILL -> if skill can target all enemies this command should be changed to SelectAllCommand") + yield(select_target_routine(), "completed") + yield(move_to_target_routine(), "completed") + yield(use_skill_routine(), "completed") + yield(return_to_start_position_routine(), "completed") diff --git a/godot/combat/battlers/jobs/Fighter.tres b/godot/combat/battlers/jobs/Fighter.tres index c524b2949c8146e837ec4277bbba4edc8129697d..f4eb84e5054f074dc21b03a7f18a5bbac36791d4 100644 --- a/godot/combat/battlers/jobs/Fighter.tres +++ b/godot/combat/battlers/jobs/Fighter.tres @@ -21,7 +21,7 @@ _data = [ Vector2( 0, 68.7313 ), 0.0, 0.0, 0, 0, Vector2( 0.168959, 376.423 ), 1 min_value = 0.0 max_value = 80.0 bake_resolution = 10 -_data = [ Vector2( 0, 0 ), 0.0, 0.0, 0, 0, Vector2( 0.603628, 45.632 ), 6.7181, 291.117, 0, 0, Vector2( 1, 80 ), 0.0, 0.0, 0, 0 ] +_data = [ Vector2( 0, 7.616 ), 0.0, 0.0, 0, 0, Vector2( 0.603628, 45.632 ), 6.7181, 291.117, 0, 0, Vector2( 1, 80 ), 0.0, 0.0, 0, 0 ] [sub_resource type="Curve" id=4] diff --git a/godot/combat/interface/CombatInterface.gd b/godot/combat/interface/CombatInterface.gd index 1a64c7106782dfc92c51ddf7235ca4ef39336f9a..653b21442bee6b5da0f27313e64825b6d9777b7e 100644 --- a/godot/combat/interface/CombatInterface.gd +++ b/godot/combat/interface/CombatInterface.gd @@ -2,12 +2,15 @@ extends CanvasLayer onready var lifebar_builder = $BattlersBarsBuilder onready var select_arrow = $SelectArrow -onready var action_list = $ActionSelector/ItemList +onready var action_list = $OldSchoolUI/Row/MonstersPanel/ActionSelector/ItemList -var selected_action : CombatAction +var last_selected_action : CombatAction + +signal action_selected(action) func initialize(battlers : Array): lifebar_builder.initialize(battlers) + action_list.hide() func select_target(selectable_battlers : Array) -> Battler: var selected_target : Battler = yield(select_arrow.select_target(selectable_battlers), "completed") @@ -19,9 +22,12 @@ func update_actions(battler : Battler) -> void: for index in range(battler.actions.get_child_count()): var action = battler.actions.get_children()[index] action_list.add_item(action.name) + if action.skill_to_use != null: + action_list.set_item_disabled(index, not battler.can_use_skill(action.skill_to_use)) action_list.set_item_metadata(index, action) action_list.select(0) - action_list.emit_signal('item_selected', 0) + action_list.grab_focus() -func _on_ItemList_item_selected(index): - selected_action = action_list.get_item_metadata(index) as CombatAction +func _on_ItemList_item_activated(index): + last_selected_action = action_list.get_item_metadata(index) as CombatAction + emit_signal("action_selected", last_selected_action) diff --git a/godot/combat/interface/SelectArrow.gd b/godot/combat/interface/SelectArrow.gd index c4cf0ae2c20f847a8cc0279b0aad14375265607d..c095bdffb0938028898687bad4941e84f3e92b1f 100644 --- a/godot/combat/interface/SelectArrow.gd +++ b/godot/combat/interface/SelectArrow.gd @@ -1,4 +1,4 @@ -extends Position2D +extends Control signal target_selected(battler) @@ -17,9 +17,10 @@ func select_target(battlers : Array) -> Battler: visible = true targets = battlers target_active = targets[0] - scale.x = 1.0 if target_active.party_member else -1.0 - global_position = target_active.target_global_position + rect_scale.x = 1.0 if target_active.party_member else -1.0 + rect_global_position = target_active.target_global_position anim_player.play("wiggle") + grab_focus() var selected_target : Battler = yield(self, "target_selected") hide() return selected_target @@ -27,18 +28,18 @@ func select_target(battlers : Array) -> Battler: func move_to(battler : Battler): tween.interpolate_property( self, - 'global_position', - global_position, + 'rect_global_position', + rect_global_position, battler.target_global_position, MOVE_DURATION, Tween.TRANS_CUBIC, Tween.EASE_OUT) tween.start() -func _unhandled_input(event): - if not visible: +func _gui_input(event): + if !visible: return - + if event.is_action_pressed("ui_accept"): emit_signal("target_selected", target_active) get_tree().set_input_as_handled() diff --git a/godot/combat/interface/SelectArrow.tscn b/godot/combat/interface/SelectArrow.tscn index 93c6ad5fde567840f2047e499aec89e4f3a0959b..f8317c3cbbb5de2e50952c6e65d83414157f032f 100644 --- a/godot/combat/interface/SelectArrow.tscn +++ b/godot/combat/interface/SelectArrow.tscn @@ -41,14 +41,30 @@ tracks/0/keys = { "values": [ Vector2( 0, 0 ), Vector2( -8, 0 ) ] } -[node name="SelectArrow" type="Position2D"] +[node name="SelectArrow" type="Control"] +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +focus_neighbour_left = NodePath(".") +focus_neighbour_top = NodePath(".") +focus_neighbour_right = NodePath(".") +focus_neighbour_bottom = NodePath(".") +focus_next = NodePath(".") +focus_previous = NodePath(".") +focus_mode = 1 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 script = ExtResource( 1 ) MOVE_DURATION = null [node name="Sprite" type="Sprite" parent="."] position = Vector2( -5.39153, 0 ) texture = ExtResource( 2 ) -_sections_unfolded = [ "Transform" ] [node name="AnimationPlayer" type="AnimationPlayer" parent="Sprite"] root_node = NodePath("..") diff --git a/godot/combat/turn_queue/TurnQueue.gd b/godot/combat/turn_queue/TurnQueue.gd index bc4482c22bf17c5429444082159df0a2e6b38dc4..4f2e56512d746e65a82d43f298316d94a49cf1d2 100644 --- a/godot/combat/turn_queue/TurnQueue.gd +++ b/godot/combat/turn_queue/TurnQueue.gd @@ -11,8 +11,18 @@ func initialize(): battler.raise() active_battler = get_child(0) -func play_turn(target : Battler, action : CombatAction): - yield(active_battler.play_turn(target, action), "completed") +func play_turn(action : CombatAction): + yield(active_battler.skin.move_forward(), "completed") + if active_battler.party_member: + action.initialize(get_monsters(), get_party(), active_battler) + else: + action.initialize(get_party(), get_monsters(), active_battler) + yield(action.execute(), "completed") + + var new_index : int = (active_battler.get_index() + 1) % get_child_count() + active_battler = get_child(new_index) + +func skip_turn(): var new_index : int = (active_battler.get_index() + 1) % get_child_count() active_battler = get_child(new_index) @@ -35,7 +45,7 @@ func get_monsters(): func _get_targets(in_party : bool = false) -> Array: var targets : Array = [] for child in get_children(): - if child.party_member == in_party: + if child.party_member == in_party && child.stats.health > 0: targets.append(child) return targets diff --git a/godot/interface/default.theme b/godot/interface/default.theme index 3a6cd8d014d5e5c69606b15e436f69832760e2ac..0ec1a52c379e2cb872ad3a23e05977dce5b06894 100644 Binary files a/godot/interface/default.theme and b/godot/interface/default.theme differ diff --git a/godot/interface/theme/slider/slider.stylebox b/godot/interface/theme/slider/slider.stylebox index 1dbb0c32a92d07b39315b5d31ba587c310785aca..845882f184d477beb4b04c7ea214fdeacace53bf 100644 Binary files a/godot/interface/theme/slider/slider.stylebox and b/godot/interface/theme/slider/slider.stylebox differ diff --git a/godot/project.godot b/godot/project.godot index 58c256cfda0d165a679d5e457d3c7770d45cdf9e..42cec626669c932d6ed4b9fc59f1ddf60200b32c 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -35,6 +35,11 @@ _global_script_classes=[ { "path": "res://combat/CombatAction.gd" }, { "base": "Node", +"class": "DialoguePlayer", +"language": "GDScript", +"path": "res://dialogue/dialogue_player/DialoguePlayer.gd" +}, { +"base": "Node", "class": "Formation", "language": "GDScript", "path": "res://combat/battlers/Formation.gd" @@ -49,12 +54,12 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://combat/Hit.gd" }, { -"base": "Control", +"base": "", "class": "LifeBar", "language": "GDScript", "path": "res://combat/interface/bars/lifebar/LifeBar.gd" }, { -"base": "Control", +"base": "", "class": "ManaBar", "language": "GDScript", "path": "res://combat/interface/bars/manabar/ManaBar.gd" @@ -85,6 +90,7 @@ _global_script_class_icons={ "BattlerTemplate": "", "CharacterStats": "", "CombatAction": "", +"DialoguePlayer": "", "Formation": "", "GrowthStats": "", "Hit": "",