From 4b85d6c3921b9c23aa486b7e89d14d5e1ad44ee1 Mon Sep 17 00:00:00 2001 From: Nicholas Hydock Date: Sat, 17 Nov 2018 13:45:01 -0500 Subject: [PATCH] Add Battle Formations --- godot/Game.gd | 3 +- godot/Game.tscn | 12 +- godot/combat/CombatArena.gd | 36 +++- godot/combat/CombatArena.tscn | 154 ++---------------- godot/combat/battlers/DanBattler.tscn | 2 +- godot/combat/battlers/Formation.gd | 5 + .../formations/PorcupineFormation001.tscn | 20 +++ godot/combat/battlers/jobs/Fighter.tres | 16 +- godot/combat/interface/CombatInterface.gd | 1 + godot/combat/interface/MonsterWidget.tscn | 76 +++++++++ godot/combat/interface/OldSchoolUI.gd | 13 ++ godot/project.godot | 12 ++ 12 files changed, 190 insertions(+), 160 deletions(-) create mode 100644 godot/combat/battlers/Formation.gd create mode 100644 godot/combat/battlers/formations/PorcupineFormation001.tscn create mode 100644 godot/combat/interface/MonsterWidget.tscn create mode 100644 godot/combat/interface/OldSchoolUI.gd diff --git a/godot/Game.gd b/godot/Game.gd index 4d6a82c..7014a45 100644 --- a/godot/Game.gd +++ b/godot/Game.gd @@ -4,6 +4,7 @@ var combat_arena = preload("res://combat/CombatArena.tscn").instance() onready var transition = $Overlays/TransitionColor onready var local_map = get_node("LocalMap") +onready var party = $Party var transitioning = false func _ready(): @@ -22,7 +23,7 @@ func enter_battle(formation_name : String): local_map.visible = false add_child(combat_arena) yield(get_tree().create_timer(0.8), "timeout") - combat_arena.initialize() + combat_arena.initialize(formation, party) yield(transition.fade_from_color(), "completed") combat_arena.battle_start() transitioning = false diff --git a/godot/Game.tscn b/godot/Game.tscn index 0eee125..1e14f2c 100644 --- a/godot/Game.tscn +++ b/godot/Game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=7 format=2] [ext_resource path="res://Game.gd" type="Script" id=1] [ext_resource path="res://local_map/LocalMap.tscn" type="PackedScene" id=2] @@ -10,7 +10,15 @@ script = ExtResource( 1 ) [node name="LocalMap" parent="." instance=ExtResource( 2 )] +[node name="Dan" parent="Party" instance=ExtResource( 3 )] +party_member = true + +[node name="Blue" parent="Party" instance=ExtResource( 4 )] +party_member = true + +[node name="CombatArena" parent="." instance=ExtResource( 5 )] + [node name="Overlays" type="CanvasLayer" parent="."] -[node name="TransitionColor" parent="Overlays" instance=ExtResource( 3 )] +[node name="TransitionColor" parent="Overlays" instance=ExtResource( 6 )] diff --git a/godot/combat/CombatArena.gd b/godot/combat/CombatArena.gd index b676beb..8641c48 100644 --- a/godot/combat/CombatArena.gd +++ b/godot/combat/CombatArena.gd @@ -8,13 +8,15 @@ var active : bool = false signal victory signal gameover - -func initialize(): +func initialize(formation : Formation, party : Party): + ready_field(formation, party) + + # reparent the enemy battlers into the turn queue var battlers = turn_queue.get_battlers() interface.initialize(battlers) - turn_queue.initialize() rewards.initialize(battlers) - + turn_queue.initialize() + func battle_start(): active = true yield(play_intro(), "completed") @@ -31,6 +33,32 @@ func play_intro(): yield(get_tree().create_timer(0.15), "timeout") yield(get_tree().create_timer(0.8), "timeout") +func ready_field(formation : Formation, party : Party): + """ + use a formation as a factory for the scene's content + """ + var spawn_positions = $SpawnPositions/Monsters + for enemy in formation.get_children(): + # spawn a platform where the enemy is supposed to stand + var platform = formation.platform_template.instance() + platform.position = enemy.position + spawn_positions.add_child(platform) + var combatant = enemy.duplicate() + turn_queue.add_child(combatant) + + var party_spawn_positions = $SpawnPositions/Party + var party_members = party.get_members() + for i in len(party_members): + var party_member = party_members[i].duplicate() + var platform = formation.platform_template.instance() + var spawn_point = party_spawn_positions.get_child(i) + platform.position = spawn_point.position + party_member.position = spawn_point.position + spawn_point.replace_by(platform) + turn_queue.add_child(party_member) + + formation.queue_free() + func battle_end(): active = false var player_lost = get_active_battler().party_member diff --git a/godot/combat/CombatArena.tscn b/godot/combat/CombatArena.tscn index d4f6ca2..eec6ee6 100644 --- a/godot/combat/CombatArena.tscn +++ b/godot/combat/CombatArena.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=2] +[gd_scene load_steps=11 format=2] [ext_resource path="res://combat/CombatArena.gd" type="Script" id=1] [ext_resource path="res://combat/background/StonePlatform.tscn" type="PackedScene" id=2] @@ -16,61 +16,32 @@ script = ExtResource( 1 ) [node name="SpawnPositions" type="Node" parent="."] -editor/display_folded = true [node name="Monsters" type="Node" parent="SpawnPositions"] -[node name="1" parent="SpawnPositions/Monsters" instance=ExtResource( 2 )] -position = Vector2( 746, 357.096 ) - -[node name="2" parent="SpawnPositions/Monsters" instance=ExtResource( 2 )] -position = Vector2( 426, 517.096 ) - -[node name="3" parent="SpawnPositions/Monsters" instance=ExtResource( 2 )] -position = Vector2( 618, 776.096 ) - [node name="Party" type="Node" parent="SpawnPositions"] -[node name="1" parent="SpawnPositions/Party" instance=ExtResource( 2 )] +[node name="1" type="Position2D" parent="SpawnPositions/Party"] position = Vector2( 1285.1, 453.096 ) -[node name="2" parent="SpawnPositions/Party" instance=ExtResource( 2 )] +[node name="2" type="Position2D" parent="SpawnPositions/Party"] position = Vector2( 1376, 672 ) -[node name="TurnQueue" parent="." instance=ExtResource( 3 )] -editor/display_folded = true +[node name="TurnQueue" parent="." instance=ExtResource( 2 )] z_index = 10 -[node name="Porcupine" parent="TurnQueue" instance=ExtResource( 4 )] -position = Vector2( 746, 357.096 ) - -[node name="Porcupine2" parent="TurnQueue" instance=ExtResource( 4 )] -position = Vector2( 426, 517.096 ) - -[node name="Porcupine3" parent="TurnQueue" instance=ExtResource( 4 )] -position = Vector2( 618, 776.096 ) - -[node name="Blue" parent="TurnQueue" instance=ExtResource( 5 )] -position = Vector2( 1285.1, 453.096 ) -party_member = true - -[node name="Dan" parent="TurnQueue" instance=ExtResource( 6 )] -position = Vector2( 1376, 672 ) -party_member = true - [node name="CombatInterface" type="CanvasLayer" parent="."] layer = 100 offset = Vector2( 0, 0 ) rotation = 0.0 scale = Vector2( 1, 1 ) transform = Transform2D( 1, 0, 0, 1, 0, 0 ) -script = ExtResource( 7 ) +script = ExtResource( 3 ) -[node name="SelectArrow" parent="CombatInterface" instance=ExtResource( 8 )] +[node name="SelectArrow" parent="CombatInterface" instance=ExtResource( 4 )] position = Vector2( -39, -51 ) [node name="OldSchoolUI" type="Control" parent="CombatInterface"] -editor/display_folded = true visible = false anchor_left = 0.0 anchor_top = 1.0 @@ -83,7 +54,8 @@ mouse_filter = 0 mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 -theme = ExtResource( 9 ) +theme = ExtResource( 5 ) +script = ExtResource( 6 ) [node name="Row" type="HBoxContainer" parent="CombatInterface/OldSchoolUI"] anchor_left = 0.0 @@ -113,7 +85,6 @@ size_flags_horizontal = 3 size_flags_vertical = 1 [node name="Column" type="VBoxContainer" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel"] -editor/display_folded = true anchor_left = 0.0 anchor_top = 0.0 anchor_right = 1.0 @@ -130,113 +101,6 @@ size_flags_horizontal = 1 size_flags_vertical = 1 alignment = 0 -[node name="MonsterWidget" type="HBoxContainer" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel/Column"] -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_right = 594.0 -margin_bottom = 23.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 1 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -alignment = 0 - -[node name="Name" type="Label" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel/Column/MonsterWidget"] -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_right = 99.0 -margin_bottom = 23.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 4 -text = "Porcupine" -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 - -[node name="Life" type="Label" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel/Column/MonsterWidget"] -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_left = 115.0 -margin_right = 594.0 -margin_bottom = 23.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 3 -size_flags_vertical = 4 -text = "85/120" -align = 2 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 - -[node name="MonsterWidget2" type="HBoxContainer" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel/Column"] -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_top = 39.0 -margin_right = 594.0 -margin_bottom = 62.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 1 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -alignment = 0 - -[node name="Name" type="Label" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel/Column/MonsterWidget2"] -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_right = 132.0 -margin_bottom = 23.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 4 -text = "Monster Name" -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 - -[node name="Life" type="Label" parent="CombatInterface/OldSchoolUI/Row/MonstersPanel/Column/MonsterWidget2"] -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_left = 148.0 -margin_right = 594.0 -margin_bottom = 23.0 -rect_pivot_offset = Vector2( 0, 0 ) -rect_clip_content = false -mouse_filter = 2 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 3 -size_flags_vertical = 4 -text = "85/120" -align = 2 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 - [node name="PartyPanel" type="Panel" parent="CombatInterface/OldSchoolUI/Row"] anchor_left = 0.0 anchor_top = 0.0 @@ -296,6 +160,8 @@ mouse_default_cursor_shape = 0 size_flags_horizontal = 3 size_flags_vertical = 1 +[node name="LifebarsBuilder" parent="CombatInterface" instance=ExtResource( 7 )] + [node name="ActionSelector" type="Control" parent="CombatInterface"] anchor_left = 1.0 anchor_top = 0.0 diff --git a/godot/combat/battlers/DanBattler.tscn b/godot/combat/battlers/DanBattler.tscn index 3d0a966..3d624f6 100644 --- a/godot/combat/battlers/DanBattler.tscn +++ b/godot/combat/battlers/DanBattler.tscn @@ -17,7 +17,7 @@ code = "shader_type canvas_item; render_priority = 0 shader = SubResource( 1 ) -[node name="Dan" index="0" instance=ExtResource( 1 )] +[node name="Dan" instance=ExtResource( 1 )] material = SubResource( 2 ) [node name="DanAnim" parent="Skin" index="0" instance=ExtResource( 2 )] diff --git a/godot/combat/battlers/Formation.gd b/godot/combat/battlers/Formation.gd new file mode 100644 index 0000000..0f7e7ec --- /dev/null +++ b/godot/combat/battlers/Formation.gd @@ -0,0 +1,5 @@ +extends Node +class_name Formation + +export(PackedScene) var platform_template +export(Texture) var background_image diff --git a/godot/combat/battlers/formations/PorcupineFormation001.tscn b/godot/combat/battlers/formations/PorcupineFormation001.tscn new file mode 100644 index 0000000..0b3eb0b --- /dev/null +++ b/godot/combat/battlers/formations/PorcupineFormation001.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://combat/battlers/Formation.gd" type="Script" id=1] +[ext_resource path="res://combat/background/StonePlatform.tscn" type="PackedScene" id=2] +[ext_resource path="res://combat/battlers/PorcupineBattler.tscn" type="PackedScene" id=3] + +[node name="Formation" type="Node"] +script = ExtResource( 1 ) +platform_template = ExtResource( 2 ) +background_image = null + +[node name="Porcupine" parent="." instance=ExtResource( 3 )] +position = Vector2( 391.654, 266.571 ) + +[node name="Porcupine2" parent="." instance=ExtResource( 3 )] +position = Vector2( 179.074, 475.377 ) + +[node name="Porcupine3" parent="." instance=ExtResource( 3 )] +position = Vector2( 462.049, 684.533 ) + diff --git a/godot/combat/battlers/jobs/Fighter.tres b/godot/combat/battlers/jobs/Fighter.tres index 009cabf..e367ad8 100644 --- a/godot/combat/battlers/jobs/Fighter.tres +++ b/godot/combat/battlers/jobs/Fighter.tres @@ -9,28 +9,28 @@ max_value = 210.0 bake_resolution = 10 _data = [ Vector2( 0, 0 ), 0.0, 210.0, 0, 1, Vector2( 1, 210 ), 210.0, 0.0, 1, 0 ] -[sub_resource type="Curve" id=3] +[sub_resource type="Curve" id=2] min_value = 0.0 max_value = 999.0 bake_resolution = 10 _data = [ Vector2( 0, 68.7313 ), 0.0, 0.0, 0, 0, Vector2( 0.168959, 376.423 ), 1283.12, 1283.12, 0, 0, Vector2( 1, 999 ), 2386.91, 0.0, 0, 0 ] -[sub_resource type="Curve" id=4] +[sub_resource type="Curve" id=3] 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 ] -[sub_resource type="Curve" id=5] +[sub_resource type="Curve" id=4] min_value = 0.99 max_value = 145.0 bake_resolution = 10 _data = [ Vector2( 0, 3 ), 0.0, 0.0, 0, 0, Vector2( 0.992522, 145 ), 198.8, 0.0, 0, 0 ] -[sub_resource type="Curve" id=6] +[sub_resource type="Curve" id=5] min_value = 0.99 max_value = 233.0 @@ -41,9 +41,9 @@ _data = [ Vector2( 0, 8 ), 0.0, 803.058, 0, 0, Vector2( 0.251992, 114.45 ), -17. script = ExtResource( 1 ) experience_curve = [ 0, 5, 15, 50, 120, 200, 325, 500, 800, 1250 ] -max_health_curve = SubResource( 3 ) -max_mana_curve = SubResource( 4 ) -strength_curve = SubResource( 6 ) +max_health_curve = SubResource( 2 ) +max_mana_curve = SubResource( 3 ) +strength_curve = SubResource( 5 ) defense_curve = SubResource( 1 ) -speed_curve = SubResource( 5 ) +speed_curve = SubResource( 4 ) diff --git a/godot/combat/interface/CombatInterface.gd b/godot/combat/interface/CombatInterface.gd index 1a64c71..c3252fd 100644 --- a/godot/combat/interface/CombatInterface.gd +++ b/godot/combat/interface/CombatInterface.gd @@ -8,6 +8,7 @@ var selected_action : CombatAction func initialize(battlers : Array): lifebar_builder.initialize(battlers) + oldschool_ui.initialize(battlers) func select_target(selectable_battlers : Array) -> Battler: var selected_target : Battler = yield(select_arrow.select_target(selectable_battlers), "completed") diff --git a/godot/combat/interface/MonsterWidget.tscn b/godot/combat/interface/MonsterWidget.tscn new file mode 100644 index 0000000..d2a6373 --- /dev/null +++ b/godot/combat/interface/MonsterWidget.tscn @@ -0,0 +1,76 @@ +[gd_scene load_steps=2 format=2] + +[sub_resource type="GDScript" id=1] + +script/source = "extends HBoxContainer + +var monster : Battler + +func _ready(): + monster.stats.connect(\"health_changed\", self, \"update_health\") + monster.stats.connect(\"health_depleted\", self, \"on_health_depleted\") + update_health(monster.stats.health) + +func update_health(health): + $Life.text = \"%d/%d\" % [health, monster.stats.max_health] + +func on_health_depleted(): + queue_free() +" + +[node name="MonsterWidget" type="HBoxContainer"] +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 594.0 +margin_bottom = 23.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +alignment = 0 +script = SubResource( 1 ) + +[node name="Name" type="Label" parent="."] +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_top = 4.0 +margin_right = 64.0 +margin_bottom = 18.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 4 +text = "Porcupine" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="Life" type="Label" parent="."] +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 68.0 +margin_top = 4.0 +margin_right = 594.0 +margin_bottom = 18.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 3 +size_flags_vertical = 4 +text = "85/120" +align = 2 +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + diff --git a/godot/combat/interface/OldSchoolUI.gd b/godot/combat/interface/OldSchoolUI.gd new file mode 100644 index 0000000..16d8a17 --- /dev/null +++ b/godot/combat/interface/OldSchoolUI.gd @@ -0,0 +1,13 @@ +extends Control + +onready var monster_info = $Row/MonstersPanel/Column + +func initialize(battlers : Array): + for b in battlers: + var battler = b as Battler + if battler.party_member: + continue + + var widget = preload("res://combat/interface/MonsterWidget.tscn").instance() + widget.monster = battler + monster_info.add_child(widget) diff --git a/godot/project.godot b/godot/project.godot index 7349671..000025a 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -34,6 +34,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://combat/CombatAction.gd" }, { +"base": "Node", +"class": "Formation", +"language": "GDScript", +"path": "res://combat/battlers/Formation.gd" +}, { "base": "Resource", "class": "GrowthStats", "language": "GDScript", @@ -49,6 +54,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://combat/battlers/Job.gd" }, { +"base": "Node", +"class": "Party", +"language": "GDScript", +"path": "res://Party.gd" +}, { "base": "Resource", "class": "Skill", "language": "GDScript", @@ -70,9 +80,11 @@ _global_script_class_icons={ "CharacterSkill": "", "CharacterStats": "", "CombatAction": "", +"Formation": "", "GrowthStats": "", "Hit": "", "Job": "", +"Party": "", "Skill": "", "StartingStats": "", "TurnQueue": "" -- GitLab