Skip to content

Commit

Permalink
Merge pull request #34 from nhydock/character-growth
Browse files Browse the repository at this point in the history
Add Character Growth
  • Loading branch information
NathanLovato committed Nov 20, 2018
2 parents 827dfe4 + 1be1379 commit d9477b9
Show file tree
Hide file tree
Showing 17 changed files with 320 additions and 39 deletions.
Binary file modified godot/assets/shaders/transition.material
Binary file not shown.
10 changes: 9 additions & 1 deletion godot/combat/CombatArena.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ extends Node2D

onready var turn_queue : TurnQueue = $TurnQueue
onready var interface = $CombatInterface
onready var rewards = $Rewards

var active : bool = false

signal victory
signal gameover

func initialize():
var battlers = turn_queue.get_battlers()
interface.initialize(battlers)
turn_queue.initialize()
rewards.initialize(battlers)

func battle_start():
active = true
Expand All @@ -29,7 +34,10 @@ func play_intro():
func battle_end():
active = false
var player_lost = get_active_battler().party_member
print('Player lost: %s' % player_lost)
if player_lost:
emit_signal("victory")
else:
emit_signal("gameover")

func play_turn():
var battler : Battler = get_active_battler()
Expand Down
49 changes: 48 additions & 1 deletion godot/combat/CombatArena.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=2]
[gd_scene load_steps=12 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]
Expand All @@ -10,6 +10,7 @@
[ext_resource path="res://combat/interface/SelectArrow.tscn" type="PackedScene" id=8]
[ext_resource path="res://interface/default.theme" type="Theme" id=9]
[ext_resource path="res://combat/interface/lifebar/LifebarsBuilder.tscn" type="PackedScene" id=10]
[ext_resource path="res://combat/Rewards.gd" type="Script" id=11]

[node name="CombatArena" type="Node2D"]
script = ExtResource( 1 )
Expand Down Expand Up @@ -37,6 +38,7 @@ position = Vector2( 1285.1, 453.096 )
position = Vector2( 1376, 672 )

[node name="TurnQueue" parent="." instance=ExtResource( 3 )]
editor/display_folded = true
z_index = 10

[node name="Porcupine" parent="TurnQueue" instance=ExtResource( 4 )]
Expand All @@ -57,6 +59,7 @@ position = Vector2( 1376, 672 )
party_member = true

[node name="CombatInterface" type="CanvasLayer" parent="."]
editor/display_folded = true
layer = 100
offset = Vector2( 0, 0 )
rotation = 0.0
Expand Down Expand Up @@ -332,4 +335,48 @@ fixed_icon_size = Vector2( 0, 0 )

[node name="LifebarsBuilder" parent="CombatInterface" instance=ExtResource( 10 )]

[node name="Rewards" type="CanvasLayer" parent="."]
layer = 1
offset = Vector2( 0, 0 )
rotation = 0.0
scale = Vector2( 1, 1 )
transform = Transform2D( 1, 0, 0, 1, 0, 0 )
script = ExtResource( 11 )

[node name="Panel" type="Panel" parent="Rewards"]
visible = false
anchor_left = 0.5
anchor_top = 0.0
anchor_right = 0.5
anchor_bottom = 0.0
margin_left = -766.0
margin_top = 22.0
margin_right = 767.0
margin_bottom = 136.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="Label" type="Label" parent="Rewards/Panel"]
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 = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "EXP Earned"
align = 1
valign = 1
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"]
69 changes: 69 additions & 0 deletions godot/combat/Rewards.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
extends Node

var experience_earned : int = 0
var party : Array = []
var drops : 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
"""
$Panel.visible = false
party = []
experience_earned = 0
for battler in battlers:
if not battler.party_member:
battler.stats.connect("health_depleted", self, "_add_reward", [battler])
else:
party.append(battler)

func _add_reward(battler : Battler):
experience_earned += battler.stats.experience
# TODO add item drops

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 member.stats.is_alive:
survived.append(member)

var exp_per_survivor = experience_earned / len(survived)
var leveled_up = []
for member in survived:
var level = member.stats.level
member.stats.experience += exp_per_survivor
if level < member.stats.level:
leveled_up.append(member)
return leveled_up

func _on_victory():
"""
On victory be sure to grant the battlers their earned exp
and show the interface
"""
var leveled_up = _reward_to_battlers()
$Panel.visible = true
$Panel/Label.text = "EXP Earned %d" % experience_earned
yield(get_tree().create_timer(2.0), "timeout")
for battler in leveled_up:
$Panel/Label.text = "%s Leveled Up to %d" % [battler.name, battler.stats.level + 1]
yield(get_tree().create_timer(2.0), "timeout")
for drop in drops:
$Panel/Label.text = "Found %s" % drop.name
yield(get_tree().create_timer(2.0), "timeout")
$Panel.visible = false
# TODO transition back to map

func _on_flee():
"""
End combat condition when the party flees
"""
experience_earned /= 2
_reward_to_battlers()
12 changes: 7 additions & 5 deletions godot/combat/battlers/Battler.gd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class_name Battler
export var TARGET_OFFSET_DISTANCE : float = 120.0

const DEFAULT_CHANCE = 0.75
onready var stats : CharacterStats = $Job/Stats as CharacterStats
onready var stats : CharacterStats = $Job.stats
onready var lifebar_anchor = $InterfaceAnchor
onready var skin = $Skin
onready var actions = $Actions
Expand Down Expand Up @@ -46,7 +46,7 @@ func use_skill(target : Battler, skill : CharacterSkill) -> void:
if stats.mana < skill.mana_cost:
return
stats.mana -= skill.mana_cost
var hit = Hit.new(stats.strength, skill.base_damage)
var hit = Hit.new(stats.strength, skill.base_damage)
target.take_damage(hit)

func take_damage(hit):
Expand All @@ -64,9 +64,11 @@ func appear():
skin.appear()

func choose_target(targets : Array):
""" This function will return a target with the following policy:
There is a chance of DEFAULT_CHANCE to target the foe with min health
else it will randomly choose an opponent"""
"""
This function will return a target with the following policy:
There is a chance of DEFAULT_CHANCE to target the foe with min health
else it will randomly choose an opponent
"""
var this_chance = randi() % 100
var target_min_health = targets[randi() % len(targets)]

Expand Down
2 changes: 2 additions & 0 deletions godot/combat/battlers/Battler.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ party_member = false
[node name="Skin" type="Position2D" parent="."]
modulate = Color( 1, 1, 1, 0 )
script = ExtResource( 2 )
TURN_START_MOVE_DISTANCE = null
TWEEN_DURATION = null

[node name="Tween" type="Tween" parent="Skin"]
repeat = false
Expand Down
4 changes: 2 additions & 2 deletions godot/combat/battlers/Job.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ extends Node
class_name Job


onready var stats = $Stats
var stats : CharacterStats
onready var skills = $Skills

export var starting_stats : Resource
export(Array, String) var starting_skills
export(PackedScene) var character_skill_scene : PackedScene

func _ready():
stats.initialize(starting_stats)
stats = CharacterStats.new(starting_stats)
if starting_skills != null and starting_skills.size() > 0:
for skill in starting_skills:
var new_skill = character_skill_scene.instance()
Expand Down
15 changes: 7 additions & 8 deletions godot/combat/battlers/PorcupineBattler.tscn
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
[gd_scene load_steps=5 format=2]
[gd_scene load_steps=4 format=2]

[ext_resource path="res://combat/battlers/Battler.tscn" type="PackedScene" id=1]
[ext_resource path="res://animation/PorcupineAnim.tscn" type="PackedScene" id=2]
[ext_resource path="res://combat/battlers/Job.tscn" type="PackedScene" id=3]
[ext_resource path="res://combat/battlers/jobs/Porcupine.tres" type="Resource" id=4]
[ext_resource path="res://combat/battlers/jobs/Porcupine.tres" type="Resource" id=3]

[node name="Porcupine" index="0" instance=ExtResource( 1 )]
[node name="Porcupine" instance=ExtResource( 1 )]

[node name="PorcupineAnim" parent="Skin" index="0" instance=ExtResource( 2 )]

[node name="Porcupine" parent="." index="1" instance=ExtResource( 3 )]
_sections_unfolded = [ "skills", "starting_stats" ]
starting_stats = ExtResource( 4 )
[node name="Job" parent="." index="1"]
starting_stats = ExtResource( 3 )
starting_skills = [ ]

[node name="InterfaceAnchor" parent="." index="4"]
[node name="InterfaceAnchor" parent="." index="3"]
position = Vector2( 0, 48.9708 )

5 changes: 3 additions & 2 deletions godot/combat/battlers/jobs/DefaultJob.tres
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
script = ExtResource( 1 )
job_name = "Job"
max_health = 6
max_mana = null
max_mana = 0
strength = 2
defense = 0
speed = null
speed = 0
experience = 0

51 changes: 43 additions & 8 deletions godot/combat/battlers/jobs/Fighter.tres
Original file line number Diff line number Diff line change
@@ -1,14 +1,49 @@
[gd_resource type="Resource" load_steps=2 format=2]
[gd_resource type="Resource" load_steps=7 format=2]

[ext_resource path="res://combat/battlers/jobs/StartingStats.gd" type="Script" id=1]
[ext_resource path="res://combat/battlers/jobs/GrowthStats.gd" type="Script" id=1]

[sub_resource type="Curve" id=1]

min_value = 0.99
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]

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]

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]

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]

min_value = 0.99
max_value = 233.0
bake_resolution = 10
_data = [ Vector2( 0, 8 ), 0.0, 803.058, 0, 0, Vector2( 0.251992, 114.45 ), -17.2645, 224.438, 0, 0, Vector2( 1, 233 ), 184.979, 0.0, 0, 0 ]

[resource]

script = ExtResource( 1 )
job_name = "Fighter"
max_health = 15
max_mana = 4
strength = 4
defense = 1
speed = 5
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 )
defense_curve = SubResource( 1 )
speed_curve = SubResource( 5 )

44 changes: 44 additions & 0 deletions godot/combat/battlers/jobs/GrowthStats.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
extends StartingStats

class_name GrowthStats

var MAX_LEVEL : int setget ,_get_max_level
var _interpolated_level : float
export var experience_curve : 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 _get_max_level() -> int:
return len(experience_curve)

func _get_interpolated_level() -> float:
return float(level) / float(self.MAX_LEVEL)

func _set_experience(value : int = 0):
"""
Calculate level, which updates all stats
"""
experience = value
var l = level
while l + 1 < self.MAX_LEVEL && experience > experience_curve[l + 1]:
l += 1
level = l
_interpolated_level = float(level) / float(self.MAX_LEVEL)

func _get_max_health() -> int:
return int(max_health_curve.interpolate_baked(_interpolated_level))

func _get_max_mana() -> int:
return int(max_mana_curve.interpolate_baked(_interpolated_level))

func _get_strength() -> int:
return int(strength_curve.interpolate_baked(_interpolated_level))

func _get_defense() -> int:
return int(defense_curve.interpolate_baked(_interpolated_level))

func _get_speed() -> int:
return int(speed_curve.interpolate_baked(_interpolated_level))
3 changes: 2 additions & 1 deletion godot/combat/battlers/jobs/Porcupine.tres
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
script = ExtResource( 1 )
job_name = "Porcupine"
max_health = 6
max_mana = null
max_mana = 0
strength = 3
defense = 0
speed = 2
experience = 5

Loading

0 comments on commit d9477b9

Please sign in to comment.