leveling up
parent
a07642c3af
commit
385ed4ffdb
|
@ -11,6 +11,7 @@ public partial class Hurtbox : BoundingBox, IFaction
|
|||
float damage,
|
||||
Character inflictor,
|
||||
float knockback,
|
||||
Items.Weapon weapon = null,
|
||||
Vector2 knockbackDir = default);
|
||||
|
||||
/// <summary>
|
||||
|
@ -39,6 +40,7 @@ public partial class Hurtbox : BoundingBox, IFaction
|
|||
float damage,
|
||||
Character inflictor,
|
||||
float knockback,
|
||||
Items.Weapon weapon = default,
|
||||
Vector2 knockbackOrigin = default,
|
||||
Vector2 knockbackVector = default)
|
||||
{
|
||||
|
@ -83,6 +85,7 @@ public partial class Hurtbox : BoundingBox, IFaction
|
|||
damage,
|
||||
inflictor,
|
||||
knockback,
|
||||
weapon,
|
||||
knockbackDir);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -308,6 +308,7 @@ public partial class Character : CharacterBody2D, IFaction
|
|||
float damage,
|
||||
Character inflictor,
|
||||
float knockback,
|
||||
Weapon weapon = null,
|
||||
Vector2 knockbackDir = default)
|
||||
{
|
||||
if (Health <= 0)
|
||||
|
@ -352,11 +353,17 @@ public partial class Character : CharacterBody2D, IFaction
|
|||
Attacker = inflictor,
|
||||
OldHealth = oldHealth,
|
||||
NewHealth = Health,
|
||||
Weapon = weapon,
|
||||
Damage = damage,
|
||||
};
|
||||
|
||||
EmitSignal(SignalName.Hurt, args);
|
||||
|
||||
if (inflictor is Player)
|
||||
{
|
||||
EmitPlayerHitSignal(args);
|
||||
}
|
||||
|
||||
if (Health <= 0)
|
||||
{
|
||||
EmitSignal(SignalName.Death, args);
|
||||
|
@ -366,6 +373,25 @@ public partial class Character : CharacterBody2D, IFaction
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a HurtArgs to HitArgs if the attacker was a player and emits
|
||||
/// the <c>EventBus.PlayerHit</c> signal.
|
||||
/// </summary>
|
||||
private void EmitPlayerHitSignal(Events.HurtArgs args)
|
||||
{
|
||||
var newArgs = new Events.HitArgs
|
||||
{
|
||||
OldHealth = args.OldHealth,
|
||||
NewHealth = args.NewHealth,
|
||||
Damage = args.Damage,
|
||||
Weapon = args.Weapon,
|
||||
Victim = this,
|
||||
};
|
||||
|
||||
var bus = Events.EventBus.Instance;
|
||||
bus.EmitSignal(Events.EventBus.SignalName.PlayerHit, newArgs);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// For debugging purposes
|
||||
|
|
|
@ -81,6 +81,7 @@ public sealed partial class Player : Character
|
|||
float damage,
|
||||
Character inflictor,
|
||||
float knockback,
|
||||
Items.Weapon weapon = null,
|
||||
Vector2 knockbackDir = default)
|
||||
{
|
||||
if (damage >= 10 && IsAlive)
|
||||
|
@ -91,7 +92,11 @@ public sealed partial class Player : Character
|
|||
GetNode<GpuParticles2D>("Effects/HurtParticles")
|
||||
.SetDirection(knockbackDir);
|
||||
|
||||
base.OnReceivedDamage(damage, inflictor, knockback, knockbackDir);
|
||||
base.OnReceivedDamage(damage,
|
||||
inflictor,
|
||||
knockback,
|
||||
weapon,
|
||||
knockbackDir);
|
||||
}
|
||||
|
||||
public override void Die()
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
[gd_scene load_steps=63 format=3 uid="uid://b2254pup8k161"]
|
||||
[gd_scene load_steps=66 format=3 uid="uid://b2254pup8k161"]
|
||||
|
||||
[ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"]
|
||||
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"]
|
||||
[ext_resource type="Texture2D" uid="uid://dpepm54hjuyga" path="res://Assets/Sprites/Characters/forsen-hand.png" id="3_3dqh7"]
|
||||
[ext_resource type="Texture2D" uid="uid://bej8thq7ruyty" path="res://Assets/Sprites/Characters/forsen2.png" id="4_5vird"]
|
||||
[ext_resource type="Script" path="res://Utils/PlayerStats.cs" id="4_06oya"]
|
||||
[ext_resource type="PackedScene" uid="uid://cl56eadpklnbo" path="res://Utils/PlayerCamera.tscn" id="4_ym125"]
|
||||
[ext_resource type="Script" path="res://State/Character/CharacterStateMachine.cs" id="5_rgckv"]
|
||||
[ext_resource type="Script" path="res://Utils/Values/DoubleValue.cs" id="5_txl0r"]
|
||||
[ext_resource type="Script" path="res://State/Character/CharacterDashState.cs" id="6_rft7p"]
|
||||
[ext_resource type="Script" path="res://Utils/Values/IntValue.cs" id="6_sunc5"]
|
||||
[ext_resource type="Script" path="res://State/Character/PlayerIdleState.cs" id="6_wkfdm"]
|
||||
[ext_resource type="PackedScene" uid="uid://dvqap2uhcah63" path="res://Items/Weapons/Sword.tscn" id="7_4rxuv"]
|
||||
[ext_resource type="Script" path="res://State/Character/PlayerMoveState.cs" id="7_dfqd8"]
|
||||
|
@ -331,6 +334,15 @@ StateMachine = NodePath("StateMachine")
|
|||
Hurtbox = NodePath("Hurtbox")
|
||||
Faction = 1
|
||||
|
||||
[node name="Stats" type="Node" parent="."]
|
||||
script = ExtResource("4_06oya")
|
||||
|
||||
[node name="XP" type="Node" parent="Stats"]
|
||||
script = ExtResource("5_txl0r")
|
||||
|
||||
[node name="Level" type="Node" parent="Stats"]
|
||||
script = ExtResource("6_sunc5")
|
||||
|
||||
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState", "Character")]
|
||||
script = ExtResource("5_rgckv")
|
||||
InitialState = NodePath("Idle")
|
||||
|
|
|
@ -43,8 +43,11 @@ public partial class Projectile : RigidBody2D
|
|||
[Export]
|
||||
public double Delay { get; set; } = 0;
|
||||
|
||||
[System.Obsolete]
|
||||
public Character Character { get; set; }
|
||||
|
||||
public Items.Weapon Weapon { get; set; }
|
||||
|
||||
public bool IsDead { get; set; }
|
||||
|
||||
public override void _Ready()
|
||||
|
@ -87,8 +90,9 @@ public partial class Projectile : RigidBody2D
|
|||
{
|
||||
hurtbox.InflictDamage(
|
||||
Hitbox.Damage,
|
||||
Character,
|
||||
Hitbox.Inflictor,
|
||||
Hitbox.Knockback,
|
||||
weapon: Weapon,
|
||||
knockbackVector: Direction
|
||||
);
|
||||
EmitSignal(SignalName.Hit, box);
|
||||
|
|
|
@ -63,6 +63,7 @@ public partial class ShungiteSpike : Projectile
|
|||
float damage,
|
||||
Characters.Character inflictor,
|
||||
float knockback,
|
||||
Items.Weapon weapon,
|
||||
Vector2 knockbackDir)
|
||||
{
|
||||
// if we were hit by the player before the spike freezes,
|
||||
|
|
|
@ -4,6 +4,8 @@ namespace SupaLidlGame.Events;
|
|||
|
||||
public partial class EventBus : Node
|
||||
{
|
||||
public static EventBus Instance { get; private set; }
|
||||
|
||||
[Signal]
|
||||
public delegate void RequestMoveToAreaEventHandler(RequestAreaArgs args);
|
||||
|
||||
|
@ -16,6 +18,15 @@ public partial class EventBus : Node
|
|||
[Signal]
|
||||
public delegate void PlayerHurtEventHandler(HurtArgs args);
|
||||
|
||||
[Signal]
|
||||
public delegate void PlayerHitEventHandler(HitArgs args);
|
||||
|
||||
[Signal]
|
||||
public delegate void PlayerXPChangedEventHandler(double xp);
|
||||
|
||||
[Signal]
|
||||
public delegate void PlayerLevelChangedEventHandler(int level);
|
||||
|
||||
[Signal]
|
||||
public delegate void PlayerHealthChangedEventHandler(HealthChangedArgs args);
|
||||
|
||||
|
@ -37,5 +48,10 @@ public partial class EventBus : Node
|
|||
public override void _Ready()
|
||||
{
|
||||
ProcessMode = ProcessModeEnum.Always;
|
||||
if (Instance is not null)
|
||||
{
|
||||
throw new MultipleSingletonsException();
|
||||
}
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
namespace SupaLidlGame.Events;
|
||||
|
||||
public partial class HitArgs : HurtArgs
|
||||
{
|
||||
public Characters.Character Victim { get; set; }
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace SupaLidlGame;
|
||||
|
||||
public class MultipleSingletonsException : System.Exception
|
||||
{
|
||||
|
||||
}
|
|
@ -60,6 +60,9 @@ public abstract partial class Weapon : Item
|
|||
[Export]
|
||||
public float MaxDistanceHint { get; set; }
|
||||
|
||||
[Export]
|
||||
public float PlayerLevelGain { get; set; }
|
||||
|
||||
[Export]
|
||||
public Sprite2D HandAnchor { get; set; }
|
||||
|
||||
|
|
|
@ -49,6 +49,9 @@ public partial class ProjectileSpawner : Ranged
|
|||
}
|
||||
}
|
||||
|
||||
projectile.Hitbox.Inflictor = Character;
|
||||
projectile.Weapon = this;
|
||||
|
||||
if (projectile is Utils.ITarget target)
|
||||
{
|
||||
if (Character is Characters.NPC npc)
|
||||
|
|
|
@ -370,35 +370,53 @@ shader_parameter/color = Quaternion(1, 1, 1, 1)
|
|||
shader_parameter/intensity = 0.0
|
||||
shader_parameter/alpha_modulate = 1.0
|
||||
|
||||
[node name="Pugio" type="Node2D"]
|
||||
[node name="Pugio" type="Node2D" node_paths=PackedStringArray("Hitbox", "AnimationPlayer", "ParryParticles", "StateMachine", "Anchor", "HandAnchor")]
|
||||
y_sort_enabled = true
|
||||
texture_filter = 3
|
||||
script = ExtResource("1_mai31")
|
||||
Hitbox = NodePath("Hitbox")
|
||||
AnimationPlayer = NodePath("AnimationPlayer")
|
||||
AttackTime = 0.2
|
||||
AttackAltTime = 0.75
|
||||
AttackAnimationDuration = 0.5
|
||||
ParryParticles = NodePath("Anchor/Node2D/Sprite2D/ParryParticles")
|
||||
NPCAnticipateTime = 0.3
|
||||
StateMachine = NodePath("State")
|
||||
Anchor = NodePath("Anchor")
|
||||
Damage = 20.0
|
||||
UseTime = 0.55
|
||||
UseAltTime = 1.5
|
||||
Knockback = 64.0
|
||||
PlayerLevelGain = 1.0
|
||||
HandAnchor = NodePath("Anchor/Node2D/Sprite2D/Hand")
|
||||
|
||||
[node name="State" type="Node" parent="."]
|
||||
[node name="State" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
|
||||
script = ExtResource("2_5ramr")
|
||||
InitialState = NodePath("Idle")
|
||||
UsedItemStates = Array[NodePath]([NodePath("Attack"), NodePath("Block")])
|
||||
DeusedItemStates = Array[NodePath]([NodePath("Idle")])
|
||||
|
||||
[node name="Idle" type="Node" parent="State"]
|
||||
[node name="Idle" type="Node" parent="State" node_paths=PackedStringArray("UseState", "UseAltState", "Sword")]
|
||||
script = ExtResource("3_fwkit")
|
||||
UseState = NodePath("../Anticipate")
|
||||
UseAltState = NodePath("../Block")
|
||||
Sword = NodePath("../..")
|
||||
|
||||
[node name="Anticipate" type="Node" parent="State"]
|
||||
[node name="Anticipate" type="Node" parent="State" node_paths=PackedStringArray("Sword", "AttackState")]
|
||||
script = ExtResource("4_nsn1q")
|
||||
Sword = NodePath("../..")
|
||||
AttackState = NodePath("../Attack")
|
||||
|
||||
[node name="Attack" type="Node" parent="State"]
|
||||
[node name="Attack" type="Node" parent="State" node_paths=PackedStringArray("Sword", "IdleState")]
|
||||
script = ExtResource("5_g1en5")
|
||||
Sword = NodePath("../..")
|
||||
IdleState = NodePath("../Idle")
|
||||
|
||||
[node name="Block" type="Node" parent="State"]
|
||||
[node name="Block" type="Node" parent="State" node_paths=PackedStringArray("Sword", "IdleState", "UseState")]
|
||||
script = ExtResource("6_yvm8x")
|
||||
Sword = NodePath("../..")
|
||||
IdleState = NodePath("../Idle")
|
||||
UseState = NodePath("../Anticipate")
|
||||
BlockAnimKey = "block"
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
|
|
@ -258,6 +258,7 @@ StateMachine = NodePath("State")
|
|||
Damage = 12.0
|
||||
UseTime = 1.5
|
||||
InitialVelocity = 220.0
|
||||
PlayerLevelGain = 0.5
|
||||
|
||||
[node name="State" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
|
||||
script = ExtResource("2_ag6rd")
|
||||
|
|
|
@ -191,7 +191,11 @@ public partial class Sword : Weapon, IParryable
|
|||
{
|
||||
if (box is Hurtbox hurtbox)
|
||||
{
|
||||
hurtbox.InflictDamage(Damage, Character, Knockback);
|
||||
hurtbox.InflictDamage(
|
||||
Damage,
|
||||
Character,
|
||||
Knockback,
|
||||
this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -354,31 +354,45 @@ graph_offset = Vector2(0, -104.073)
|
|||
|
||||
[sub_resource type="AnimationNodeStateMachinePlayback" id="AnimationNodeStateMachinePlayback_37556"]
|
||||
|
||||
[node name="Sword" type="Node2D"]
|
||||
[node name="Sword" type="Node2D" node_paths=PackedStringArray("Hitbox", "AnimationPlayer", "ParryParticles", "StateMachine", "Anchor", "HandAnchor")]
|
||||
y_sort_enabled = true
|
||||
texture_filter = 3
|
||||
script = ExtResource("1_mlo73")
|
||||
Hitbox = NodePath("Hitbox")
|
||||
AnimationPlayer = NodePath("AnimationPlayer")
|
||||
AttackTime = 0.2
|
||||
AttackAnimationDuration = 0.75
|
||||
ParryParticles = NodePath("Anchor/Node2D/Sprite2D/ParryParticles")
|
||||
NPCAnticipateTime = 0.3
|
||||
StateMachine = NodePath("State")
|
||||
Anchor = NodePath("Anchor")
|
||||
Damage = 20.0
|
||||
UseTime = 0.55
|
||||
Knockback = 64.0
|
||||
ShouldHideIdle = true
|
||||
PlayerLevelGain = 1.0
|
||||
HandAnchor = NodePath("Anchor/Node2D/Sprite2D/Hand")
|
||||
|
||||
[node name="State" type="Node" parent="."]
|
||||
[node name="State" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
|
||||
script = ExtResource("2_vwirq")
|
||||
InitialState = NodePath("Idle")
|
||||
UsedItemStates = Array[NodePath]([NodePath("Attack")])
|
||||
DeusedItemStates = Array[NodePath]([NodePath("Idle")])
|
||||
|
||||
[node name="Idle" type="Node" parent="State"]
|
||||
[node name="Idle" type="Node" parent="State" node_paths=PackedStringArray("UseState", "Sword")]
|
||||
script = ExtResource("3_nw6r0")
|
||||
UseState = NodePath("../Anticipate")
|
||||
Sword = NodePath("../..")
|
||||
|
||||
[node name="Anticipate" type="Node" parent="State"]
|
||||
[node name="Anticipate" type="Node" parent="State" node_paths=PackedStringArray("Sword", "AttackState")]
|
||||
script = ExtResource("4_j3cud")
|
||||
Sword = NodePath("../..")
|
||||
AttackState = NodePath("../Attack")
|
||||
|
||||
[node name="Attack" type="Node" parent="State"]
|
||||
[node name="Attack" type="Node" parent="State" node_paths=PackedStringArray("Sword", "IdleState")]
|
||||
script = ExtResource("5_hmisb")
|
||||
Sword = NodePath("../..")
|
||||
IdleState = NodePath("../Idle")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_72txp")
|
||||
|
|
21
UI/Base.tscn
21
UI/Base.tscn
|
@ -1,9 +1,10 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://c271rdjhd1gfo"]
|
||||
[gd_scene load_steps=8 format=3 uid="uid://c271rdjhd1gfo"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://73jm5qjy52vq" path="res://Dialogue/balloon.tscn" id="1_atjb1"]
|
||||
[ext_resource type="Script" path="res://UI/UIController.cs" id="2_b4b6l"]
|
||||
[ext_resource type="PackedScene" uid="uid://bxo553hblp6nf" path="res://UI/HealthBar.tscn" id="3_j1j6h"]
|
||||
[ext_resource type="PackedScene" uid="uid://01d24ij5av1y" path="res://UI/BossBar.tscn" id="4_igi28"]
|
||||
[ext_resource type="PackedScene" uid="uid://cr7tkxctmyags" path="res://UI/LevelBar.tscn" id="4_rcekd"]
|
||||
[ext_resource type="PackedScene" uid="uid://c77754nvmckn" path="res://UI/LocationDisplay.tscn" id="5_cr6vo"]
|
||||
[ext_resource type="PackedScene" uid="uid://d3q1yu3n7cqfj" path="res://UI/SceneTransition.tscn" id="6_j0nhv"]
|
||||
|
||||
|
@ -47,7 +48,7 @@ BossBar = NodePath("Bottom/BossBar")
|
|||
layout_mode = 1
|
||||
anchors_preset = 10
|
||||
anchor_right = 1.0
|
||||
offset_bottom = 40.0
|
||||
offset_bottom = 64.0
|
||||
grow_horizontal = 2
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main/Top"]
|
||||
|
@ -55,9 +56,21 @@ layout_mode = 2
|
|||
theme_override_constants/margin_left = 16
|
||||
theme_override_constants/margin_top = 16
|
||||
|
||||
[node name="HealthBar" parent="SubViewportContainer/UIViewport/MainUILayer/Main/Top/Margin" instance=ExtResource("3_j1j6h")]
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main/Top/Margin"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/separation = 12
|
||||
|
||||
[node name="HealthBar" parent="SubViewportContainer/UIViewport/MainUILayer/Main/Top/Margin/VBoxContainer" instance=ExtResource("3_j1j6h")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="LevelBar" parent="SubViewportContainer/UIViewport/MainUILayer/Main/Top/Margin/VBoxContainer" instance=ExtResource("4_rcekd")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Margin2" type="MarginContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main/Top/Margin/VBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 16
|
||||
theme_override_constants/margin_top = 16
|
||||
|
||||
[node name="Bottom" type="HBoxContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main"]
|
||||
layout_mode = 1
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
using Godot;
|
||||
using SupaLidlGame.Events;
|
||||
|
||||
namespace SupaLidlGame.UI;
|
||||
|
||||
public partial class LevelBar : Control
|
||||
{
|
||||
public TextureProgressBar XPBar { get; set; }
|
||||
|
||||
private TextureProgressBar[] _levelBars = new TextureProgressBar[4];
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
XPBar = GetNode<TextureProgressBar>("%XPBar");
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
_levelBars[i] = GetNode<TextureProgressBar>($"%Level{i + 1}Bar");
|
||||
}
|
||||
|
||||
EventBus.Instance.PlayerXPChanged += (xp) =>
|
||||
{
|
||||
XPBar.Value = xp;
|
||||
};
|
||||
|
||||
EventBus.Instance.PlayerLevelChanged += (level) =>
|
||||
{
|
||||
for (int i = 0; i < _levelBars.Length; i++)
|
||||
{
|
||||
// level 0: 0 is not less than 0
|
||||
// level 1: 0 is less than 1
|
||||
_levelBars[i].Value = i < level ? 1 : 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
[gd_scene load_steps=4 format=3 uid="uid://cr7tkxctmyags"]
|
||||
|
||||
[ext_resource type="Script" path="res://UI/LevelBar.cs" id="1_eqetx"]
|
||||
[ext_resource type="Texture2D" uid="uid://b75oak1nd2q6x" path="res://Assets/Sprites/UI/over-under-bar.png" id="2_f332l"]
|
||||
[ext_resource type="Texture2D" uid="uid://co7xm7i5f6n51" path="res://Assets/Sprites/UI/progress-bar.png" id="3_arvub"]
|
||||
|
||||
[node name="LevelBar" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
offset_right = 128.0
|
||||
offset_bottom = 8.0
|
||||
script = ExtResource("1_eqetx")
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
offset_right = 128.0
|
||||
offset_bottom = 8.0
|
||||
|
||||
[node name="XPBar" type="TextureProgressBar" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
texture_filter = 1
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
max_value = 4.0
|
||||
step = 0.01
|
||||
nine_patch_stretch = true
|
||||
stretch_margin_left = 3
|
||||
stretch_margin_top = 3
|
||||
stretch_margin_right = 3
|
||||
stretch_margin_bottom = 3
|
||||
texture_under = ExtResource("2_f332l")
|
||||
texture_progress = ExtResource("3_arvub")
|
||||
|
||||
[node name="Level1Bar" type="TextureProgressBar" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
texture_filter = 1
|
||||
layout_mode = 2
|
||||
max_value = 1.0
|
||||
nine_patch_stretch = true
|
||||
stretch_margin_left = 3
|
||||
stretch_margin_top = 3
|
||||
stretch_margin_right = 3
|
||||
stretch_margin_bottom = 3
|
||||
texture_under = ExtResource("2_f332l")
|
||||
texture_progress = ExtResource("3_arvub")
|
||||
|
||||
[node name="Level2Bar" type="TextureProgressBar" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
texture_filter = 1
|
||||
layout_mode = 2
|
||||
max_value = 1.0
|
||||
nine_patch_stretch = true
|
||||
stretch_margin_left = 3
|
||||
stretch_margin_top = 3
|
||||
stretch_margin_right = 3
|
||||
stretch_margin_bottom = 3
|
||||
texture_under = ExtResource("2_f332l")
|
||||
texture_progress = ExtResource("3_arvub")
|
||||
|
||||
[node name="Level3Bar" type="TextureProgressBar" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
texture_filter = 1
|
||||
layout_mode = 2
|
||||
max_value = 1.0
|
||||
nine_patch_stretch = true
|
||||
stretch_margin_left = 3
|
||||
stretch_margin_top = 3
|
||||
stretch_margin_right = 3
|
||||
stretch_margin_bottom = 3
|
||||
texture_under = ExtResource("2_f332l")
|
||||
texture_progress = ExtResource("3_arvub")
|
||||
|
||||
[node name="Level4Bar" type="TextureProgressBar" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
texture_filter = 1
|
||||
layout_mode = 2
|
||||
max_value = 1.0
|
||||
nine_patch_stretch = true
|
||||
stretch_margin_left = 3
|
||||
stretch_margin_top = 3
|
||||
stretch_margin_right = 3
|
||||
stretch_margin_bottom = 3
|
||||
texture_under = ExtResource("2_f332l")
|
||||
texture_progress = ExtResource("3_arvub")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_constants/separation = 4
|
|
@ -0,0 +1,75 @@
|
|||
using Godot;
|
||||
using SupaLidlGame.Events;
|
||||
|
||||
namespace SupaLidlGame.Utils;
|
||||
|
||||
public partial class PlayerStats : Node
|
||||
{
|
||||
public const int MAX_XP_PER_LEVEL = 4;
|
||||
|
||||
public const int MAX_LEVELS = 4;
|
||||
|
||||
public DoubleValue XP { get; set; }
|
||||
|
||||
public IntValue Level { get; set; }
|
||||
|
||||
public double XPDecayVelocity { get; set; } = 1;
|
||||
|
||||
protected bool _shouldDecayXP = true;
|
||||
|
||||
protected Timer _xpDecayTimer;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
XP = GetNode<DoubleValue>("XP");
|
||||
Level = GetNode<IntValue>("Level");
|
||||
|
||||
_xpDecayTimer = new Timer();
|
||||
_xpDecayTimer.Timeout += () => _shouldDecayXP = true;
|
||||
_xpDecayTimer.Stop();
|
||||
AddChild(_xpDecayTimer);
|
||||
|
||||
var bus = EventBus.Instance;
|
||||
XP.Changed += (oldValue, newValue) =>
|
||||
{
|
||||
bus.EmitSignal(EventBus.SignalName.PlayerXPChanged, newValue);
|
||||
};
|
||||
|
||||
Level.Changed += (oldValue, newValue) =>
|
||||
{
|
||||
bus.EmitSignal(EventBus.SignalName.PlayerLevelChanged, newValue);
|
||||
};
|
||||
|
||||
bus.PlayerHit += (args) =>
|
||||
{
|
||||
double xp = XP.Value;
|
||||
xp += args.Weapon?.PlayerLevelGain ?? 0;
|
||||
|
||||
if (xp >= MAX_XP_PER_LEVEL)
|
||||
{
|
||||
int deltaLevel = (int)(xp / MAX_XP_PER_LEVEL);
|
||||
xp %= MAX_XP_PER_LEVEL;
|
||||
Level.Value = Mathf.Min(Level.Value + deltaLevel, MAX_LEVELS);
|
||||
}
|
||||
|
||||
if (Level.Value == MAX_LEVELS)
|
||||
{
|
||||
// if max level, can only go up to 1 xp
|
||||
xp = Mathf.Min(xp, 1);
|
||||
}
|
||||
|
||||
XP.Value = xp;
|
||||
|
||||
_shouldDecayXP = false;
|
||||
_xpDecayTimer.Start(1);
|
||||
};
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (_shouldDecayXP)
|
||||
{
|
||||
XP.Value = Mathf.MoveToward(XP.Value, 1, XPDecayVelocity * delta);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using Godot;
|
||||
|
||||
namespace SupaLidlGame;
|
||||
|
||||
public partial class DoubleValue : Node, IValue<double>
|
||||
{
|
||||
[Signal]
|
||||
public delegate void ChangedEventHandler(double oldValue, double newValue);
|
||||
|
||||
protected double _value = default;
|
||||
|
||||
[Export]
|
||||
public double Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
EmitSignal(SignalName.Changed, _value, value);
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using Godot;
|
||||
|
||||
namespace SupaLidlGame;
|
||||
|
||||
public partial class FloatValue : Node, IValue<float>
|
||||
{
|
||||
[Signal]
|
||||
public delegate void ChangedEventHandler(float oldValue, float newValue);
|
||||
|
||||
protected float _value = default;
|
||||
|
||||
[Export]
|
||||
public float Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
EmitSignal(SignalName.Changed, _value, value);
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace SupaLidlGame;
|
||||
|
||||
public interface IValue<T>
|
||||
{
|
||||
public delegate void ChangedEventHandler(T oldValue, T newValue);
|
||||
|
||||
public T Value { get; set; }
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using Godot;
|
||||
|
||||
namespace SupaLidlGame;
|
||||
|
||||
public partial class IntValue : Node, IValue<int>
|
||||
{
|
||||
[Signal]
|
||||
public delegate void ChangedEventHandler(int oldValue, int newValue);
|
||||
|
||||
protected int _value = default;
|
||||
|
||||
[Export]
|
||||
public int Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
EmitSignal(SignalName.Changed, _value, value);
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue