Damage calculation including elemental buff/resistance

This commit is contained in:
2024-09-04 01:24:37 -07:00
parent 9a24ebf058
commit d7a49ba974
23 changed files with 311 additions and 70 deletions

View File

@@ -1,7 +1,9 @@
using Chickensoft.AutoInject; using Chickensoft.AutoInject;
using Chickensoft.Collections;
using Chickensoft.GodotNodeInterfaces; using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Godot; using Godot;
using System;
using System.Linq; using System.Linq;
namespace GameJamDungeon; namespace GameJamDungeon;
@@ -10,9 +12,9 @@ public interface IEnemy : ICharacterBody3D
{ {
public IEnemyLogic EnemyLogic { get; } public IEnemyLogic EnemyLogic { get; }
public int CurrentHP { get; set; } public AutoProp<double> CurrentHP { get; set; }
public Resource EnemyStats { get; set; } public EnemyStatInfo EnemyStatInfo { get; set; }
public NavigationAgent3D NavAgent { get; set; } public NavigationAgent3D NavAgent { get; set; }
} }
@@ -31,28 +33,28 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
[Dependency] IGameRepo GameRepo => this.DependOn<IGameRepo>(); [Dependency] IGameRepo GameRepo => this.DependOn<IGameRepo>();
[Export] [Export]
public Resource EnemyStats { get; set; } = new(); public EnemyStatInfo EnemyStatInfo { get; set; } = new();
public static PackedScene CollisionDetectorScene => GD.Load<PackedScene>("res://src/enemy/CollisionDetector.tscn"); public static PackedScene CollisionDetectorScene => GD.Load<PackedScene>("res://src/enemy/CollisionDetector.tscn");
public static Area3D CollisionDetector { get; set; } = default!; public static Area3D CollisionDetector { get; set; } = default!;
public int CurrentHP { get; set; } public AutoProp<double> CurrentHP { get; set; }
[Node] public NavigationAgent3D NavAgent { get; set; } = default!; [Node] public NavigationAgent3D NavAgent { get; set; } = default!;
public void Setup() public void Setup()
{ {
EnemyLogic = new EnemyLogic(); EnemyLogic = new EnemyLogic();
EnemyLogic.Set(EnemyStats); EnemyLogic.Set(EnemyStatInfo);
EnemyLogic.Set(this as IEnemy); EnemyLogic.Set(this as IEnemy);
EnemyLogic.Set(GameRepo); EnemyLogic.Set(GameRepo);
} }
public void Initialize() public void Initialize()
{ {
var enemyResource = EnemyStats as EnemyStats; CurrentHP = new AutoProp<double>(EnemyStatInfo.MaximumHP);
CurrentHP = enemyResource.MaximumHP; CurrentHP.Sync += OnHPChanged;
} }
public void OnResolved() public void OnResolved()
@@ -71,7 +73,6 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
}) })
.Handle((in EnemyLogic.Output.Die output) => .Handle((in EnemyLogic.Output.Die output) =>
{ {
CollisionDetector.Dispose();
QueueFree(); QueueFree();
}) })
.Handle((in EnemyLogic.Output.HitByPlayer output) => .Handle((in EnemyLogic.Output.HitByPlayer output) =>
@@ -112,14 +113,21 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
{ {
if (body is IHitbox hitBox) if (body is IHitbox hitBox)
{ {
if (CurrentHP > 0) if (CurrentHP.Value > 0)
{ {
GD.Print("Enemy Hit"); var damage = DamageCalculator.CalculatePlayerDamage(hitBox.Damage, hitBox.GetParent<IPlayer>().PlayerStatInfo, EnemyStatInfo);
EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(hitBox.Damage)); GD.Print($"Enemy Hit for {damage} damage.");
EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(damage));
} }
} }
} }
private void OnHPChanged(double newHP)
{
if (newHP <= 0)
EnemyLogic.Input(new EnemyLogic.Input.Killed());
}
public void OnReady() public void OnReady()
{ {
SetPhysicsProcess(true); SetPhysicsProcess(true);

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=3 format=3 uid="uid://dbvr8ewajja6a"] [gd_scene load_steps=3 format=3 uid="uid://dbvr8ewajja6a"]
[ext_resource type="Script" path="res://src/enemy/EnemyDatabase.cs" id="1_ywy58"] [ext_resource type="Script" path="res://src/enemy/EnemyDatabase.cs" id="1_ywy58"]
[ext_resource type="PackedScene" uid="uid://dcgj5i52i76gj" path="res://src/enemy/enemy_types/FloatingEnemy.tscn" id="2_8cbrh"] [ext_resource type="PackedScene" uid="uid://dcgj5i52i76gj" path="res://src/enemy/enemy_types/floating_enemy/FloatingEnemy.tscn" id="2_8cbrh"]
[node name="EnemyDatabase" type="Node"] [node name="EnemyDatabase" type="Node"]
script = ExtResource("1_ywy58") script = ExtResource("1_ywy58")

View File

@@ -0,0 +1,26 @@
using Godot;
namespace GameJamDungeon
{
[GlobalClass]
public partial class EnemyStatInfo : Resource, ICharacterStats
{
[Export]
public double MaximumHP { get; set; }
[Export]
public int BaseAttack { get; set; }
[Export]
public int BaseDefense { get; set; }
[Export]
public double ElementAResistance { get; set; }
[Export]
public double ElementBResistance { get; set; }
[Export]
public double ElementCResistance { get; set; }
}
}

View File

@@ -1,14 +0,0 @@
using Godot;
namespace GameJamDungeon
{
[GlobalClass]
public partial class EnemyStats : Resource
{
[Export(PropertyHint.Range, "0, 100, 1")]
public int MaximumHP = 1;
[Export]
public string Name = string.Empty;
}
}

View File

@@ -1,8 +0,0 @@
[gd_resource type="Resource" script_class="EnemyStats" load_steps=2 format=3 uid="uid://bcsyqy7rmbpbl"]
[ext_resource type="Script" path="res://src/enemy/EnemyStats.cs" id="1_0ks7j"]
[resource]
script = ExtResource("1_0ks7j")
MaximumHP = 12
Name = "Floating Guy"

View File

@@ -4,12 +4,12 @@ importer="scene"
importer_version=1 importer_version=1
type="PackedScene" type="PackedScene"
uid="uid://cli0nlukrd4dc" uid="uid://cli0nlukrd4dc"
path="res://.godot/imported/DISSAPPEARING ENEMY.gltf-86890683bfa8a9cc2bc15c917a019516.scn" path="res://.godot/imported/DISSAPPEARING ENEMY.gltf-623f05c3c418a59abcec04651db9cb14.scn"
[deps] [deps]
source_file="res://src/enemy/enemy_types/DISSAPPEARING ENEMY.gltf" source_file="res://src/enemy/enemy_types/floating_enemy/DISSAPPEARING ENEMY.gltf"
dest_files=["res://.godot/imported/DISSAPPEARING ENEMY.gltf-86890683bfa8a9cc2bc15c917a019516.scn"] dest_files=["res://.godot/imported/DISSAPPEARING ENEMY.gltf-623f05c3c418a59abcec04651db9cb14.scn"]
[params] [params]

View File

@@ -0,0 +1,12 @@
[gd_resource type="Resource" script_class="EnemyStatInfo" load_steps=2 format=3 uid="uid://c8h26ip4ly18r"]
[ext_resource type="Script" path="res://src/enemy/EnemyStatInfo.cs" id="1_oabqi"]
[resource]
script = ExtResource("1_oabqi")
MaximumHP = 50.0
BaseAttack = 2
BaseDefense = 1
ElementAResistance = 15.0
ElementBResistance = -20.0
ElementCResistance = 0.0

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=9 format=4 uid="uid://dcgj5i52i76gj"] [gd_scene load_steps=9 format=4 uid="uid://dcgj5i52i76gj"]
[ext_resource type="Script" path="res://src/enemy/Enemy.cs" id="1_4d86o"] [ext_resource type="Script" path="res://src/enemy/Enemy.cs" id="1_jw471"]
[ext_resource type="Resource" uid="uid://bcsyqy7rmbpbl" path="res://src/enemy/enemy_types/FloatingEnemy.tres" id="2_q8v6p"] [ext_resource type="Resource" uid="uid://c8h26ip4ly18r" path="res://src/enemy/enemy_types/floating_enemy/FloatingEnemy.tres" id="2_ewaf6"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5tio6"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5tio6"]
resource_name = "Material.001" resource_name = "Material.001"
@@ -109,8 +109,8 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
collision_layer = 10 collision_layer = 10
collision_mask = 9 collision_mask = 9
motion_mode = 1 motion_mode = 1
script = ExtResource("1_4d86o") script = ExtResource("1_jw471")
EnemyStats = ExtResource("2_q8v6p") EnemyStatInfo = ExtResource("2_ewaf6")
[node name="DISSAPPEARING ENEMY" type="Node3D" parent="."] [node name="DISSAPPEARING ENEMY" type="Node3D" parent="."]

View File

@@ -10,7 +10,9 @@
public readonly record struct PhysicsTick(double Delta); public readonly record struct PhysicsTick(double Delta);
public readonly record struct HitByPlayer(int Damage); public readonly record struct HitByPlayer(double Damage);
public readonly record struct Killed();
} }
} }
} }

View File

@@ -10,7 +10,7 @@ namespace GameJamDungeon
public readonly record struct MovementComputed(Vector3 Velocity); public readonly record struct MovementComputed(Vector3 Velocity);
public readonly record struct HitByPlayer(int CurrentHP); public readonly record struct HitByPlayer(double CurrentHP);
public readonly record struct Die(); public readonly record struct Die();
} }

View File

@@ -8,23 +8,25 @@ namespace GameJamDungeon
public partial record State public partial record State
{ {
[Meta, Id("enemy_logic_state_alive")] [Meta, Id("enemy_logic_state_alive")]
public abstract partial record Alive : State, IGet<Input.HitByPlayer> public abstract partial record Alive : State, IGet<Input.HitByPlayer>, IGet<Input.Killed>
{ {
public Transition On(in Input.HitByPlayer input) public Transition On(in Input.HitByPlayer input)
{ {
var enemy = Get<IEnemy>(); var enemy = Get<IEnemy>();
var gameRepo = Get<IGameRepo>(); enemy.CurrentHP.OnNext(enemy.CurrentHP.Value - input.Damage);
enemy.CurrentHP -= input.Damage; GD.Print("Current HP: " + enemy.CurrentHP.Value);
GD.Print("Current HP: " + enemy.CurrentHP);
GD.Print($"Hit by {gameRepo.EquippedWeapon.Name}");
Output(new Output.HitByPlayer()); Output(new Output.HitByPlayer());
if (enemy.CurrentHP <= 0)
Output(new Output.Die());
Input(new Input.Alerted()); Input(new Input.Alerted());
return ToSelf(); return ToSelf();
} }
public Transition On(in Input.Killed input)
{
Output(new Output.Die());
return To<Idle>();
}
} }
} }
} }

View File

@@ -1,12 +1,14 @@
[gd_scene load_steps=12 format=3 uid="uid://33ek675mfb5n"] [gd_scene load_steps=14 format=3 uid="uid://33ek675mfb5n"]
[ext_resource type="Script" path="res://src/game/Game.cs" id="1_ytcii"] [ext_resource type="Script" path="res://src/game/Game.cs" id="1_ytcii"]
[ext_resource type="PackedScene" uid="uid://wg25dg65ksgg" path="res://src/map/dungeon/DungeonGenerator.tscn" id="2_cgboj"]
[ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="3_kk6ly"] [ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="3_kk6ly"]
[ext_resource type="PackedScene" uid="uid://dhpwwqow1ahrc" path="res://src/map/dungeon/rooms/Room1.tscn" id="4_56rmd"]
[ext_resource type="PackedScene" uid="uid://bbwgmqy3evhh2" path="res://src/map/dungeon/rooms/Room2.tscn" id="4_clpvl"]
[ext_resource type="PackedScene" uid="uid://dlj8qdg1c5048" path="res://src/inventory_menu/InventoryMenu.tscn" id="4_wk8gw"] [ext_resource type="PackedScene" uid="uid://dlj8qdg1c5048" path="res://src/inventory_menu/InventoryMenu.tscn" id="4_wk8gw"]
[ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonGenerator3D.gd" id="5_fqkhg"]
[ext_resource type="PackedScene" uid="uid://dhpwwqow1ahrc" path="res://src/map/dungeon/rooms/Room1.tscn" id="6_04w8n"]
[ext_resource type="PackedScene" uid="uid://bwbofurcvf3yh" path="res://src/minimap/Minimap.tscn" id="6_owlf4"] [ext_resource type="PackedScene" uid="uid://bwbofurcvf3yh" path="res://src/minimap/Minimap.tscn" id="6_owlf4"]
[ext_resource type="PackedScene" uid="uid://bn4gslp2gk8ds" path="res://src/map/dungeon/corridor/Corridor.tscn" id="6_swtay"]
[ext_resource type="PackedScene" uid="uid://bbwgmqy3evhh2" path="res://src/map/dungeon/rooms/Room2.tscn" id="7_1ynbc"]
[ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="9_p0lbc"]
[sub_resource type="Environment" id="Environment_fke5g"] [sub_resource type="Environment" id="Environment_fke5g"]
@@ -57,8 +59,100 @@ omni_attenuation = -0.183
unique_name_in_owner = true unique_name_in_owner = true
navigation_mesh = SubResource("NavigationMesh_xligp") navigation_mesh = SubResource("NavigationMesh_xligp")
[node name="DungeonGenerator3D" parent="NavigationRegion" instance=ExtResource("2_cgboj")] [node name="DungeonGenerator3D" type="Node3D" parent="."]
room_scenes = Array[PackedScene]([ExtResource("4_56rmd"), ExtResource("4_clpvl")]) script = ExtResource("5_fqkhg")
corridor_cost_multiplier = 1.0 room_scenes = Array[PackedScene]([ExtResource("6_04w8n"), ExtResource("7_1ynbc")])
room_cost_multiplier = 8.0 corridor_room_scene = ExtResource("6_swtay")
room_cost_at_end_for_required_doors = 1.0 dungeon_size = Vector3i(10, 1, 10)
[node name="RoomsContainer" type="Node3D" parent="DungeonGenerator3D"]
[node name="DungeonRoom3D_0" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("7_1ynbc")]
transform = Transform3D(1.19249e-08, 0, -1, 0, 1, 0, 1, 0, 1.19249e-08, -15, 0, 15)
script = ExtResource("9_p0lbc")
size_in_voxels = Vector3i(5, 1, 1)
[node name="DungeonRoom3D_1" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_04w8n")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -35)
script = ExtResource("9_p0lbc")
[node name="DungeonRoom3D_2" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_04w8n")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 25, 0, -45)
script = ExtResource("9_p0lbc")
[node name="DungeonRoom3D_3" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("7_1ynbc")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 15, 0, -25)
script = ExtResource("9_p0lbc")
size_in_voxels = Vector3i(5, 1, 1)
[node name="Corridor_4" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -15)
script = ExtResource("9_p0lbc")
[node name="Corridor_5" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -25)
script = ExtResource("9_p0lbc")
[node name="Corridor_6" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -45)
script = ExtResource("9_p0lbc")
[node name="Corridor_7" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, -45)
script = ExtResource("9_p0lbc")
[node name="Corridor_8" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0, -45)
script = ExtResource("9_p0lbc")
[node name="Corridor_9" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0, -45)
script = ExtResource("9_p0lbc")
[node name="Corridor_10" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, 45)
script = ExtResource("9_p0lbc")
[node name="Corridor_11" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 45)
script = ExtResource("9_p0lbc")
[node name="Corridor_12" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 35)
script = ExtResource("9_p0lbc")
[node name="Corridor_13" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 25)
script = ExtResource("9_p0lbc")
[node name="Corridor_14" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 15)
script = ExtResource("9_p0lbc")
[node name="Corridor_15" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, 5)
script = ExtResource("9_p0lbc")
[node name="Corridor_16" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, -5)
script = ExtResource("9_p0lbc")
[node name="Corridor_17" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, -15)
script = ExtResource("9_p0lbc")
[node name="Corridor_18" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 35, 0, -45)
script = ExtResource("9_p0lbc")
[node name="Corridor_19" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 35, 0, -35)
script = ExtResource("9_p0lbc")
[node name="Corridor_20" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45, 0, -35)
script = ExtResource("9_p0lbc")
[node name="Corridor_21" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_swtay")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45, 0, -25)
script = ExtResource("9_p0lbc")

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=19 format=3 uid="uid://dhpwwqow1ahrc"] [gd_scene load_steps=17 format=3 uid="uid://dhpwwqow1ahrc"]
[ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="1_0tfda"] [ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="1_0tfda"]
[ext_resource type="Script" path="res://src/map/dungeon/rooms/DungeonRoom.cs" id="1_ti7ur"] [ext_resource type="Script" path="res://src/map/dungeon/rooms/DungeonRoom.cs" id="1_ti7ur"]
@@ -6,10 +6,8 @@
[ext_resource type="PackedScene" uid="uid://twrj4wixcbu7" path="res://src/items/ItemDatabase.tscn" id="4_2mnb7"] [ext_resource type="PackedScene" uid="uid://twrj4wixcbu7" path="res://src/items/ItemDatabase.tscn" id="4_2mnb7"]
[ext_resource type="PackedScene" uid="uid://b6atdgf2e6e2t" path="res://src/items/weapons/models/CommonSword.tscn" id="4_chdi8"] [ext_resource type="PackedScene" uid="uid://b6atdgf2e6e2t" path="res://src/items/weapons/models/CommonSword.tscn" id="4_chdi8"]
[ext_resource type="PackedScene" uid="uid://dbvr8ewajja6a" path="res://src/enemy/EnemyDatabase.tscn" id="5_owpbq"] [ext_resource type="PackedScene" uid="uid://dbvr8ewajja6a" path="res://src/enemy/EnemyDatabase.tscn" id="5_owpbq"]
[ext_resource type="PackedScene" uid="uid://dcgj5i52i76gj" path="res://src/enemy/enemy_types/FloatingEnemy.tscn" id="5_urvkv"]
[ext_resource type="PackedScene" uid="uid://cbb1fxllrnlyr" path="res://src/items/weapons/models/UncommonSword.tscn" id="5_viqv4"] [ext_resource type="PackedScene" uid="uid://cbb1fxllrnlyr" path="res://src/items/weapons/models/UncommonSword.tscn" id="5_viqv4"]
[ext_resource type="PackedScene" uid="uid://c10nhqq8su6pp" path="res://src/items/weapons/models/RareSword.tscn" id="6_c8gn4"] [ext_resource type="PackedScene" uid="uid://c10nhqq8su6pp" path="res://src/items/weapons/models/RareSword.tscn" id="6_c8gn4"]
[ext_resource type="PackedScene" uid="uid://u1vmmakcoplh" path="res://src/enemy/enemy_types/Capricorn/Capricorn.tscn" id="6_hp0mx"]
[ext_resource type="PackedScene" uid="uid://dorr7v1tkeiy0" path="res://src/items/armor/Armor.tscn" id="7_bm50w"] [ext_resource type="PackedScene" uid="uid://dorr7v1tkeiy0" path="res://src/items/armor/Armor.tscn" id="7_bm50w"]
[sub_resource type="PlaneMesh" id="PlaneMesh_luhnj"] [sub_resource type="PlaneMesh" id="PlaneMesh_luhnj"]
@@ -71,8 +69,6 @@ DropRate = PackedFloat32Array(0.25, 0.25, 0.25, 0.25)
[node name="EnemyDatabase" parent="." instance=ExtResource("5_owpbq")] [node name="EnemyDatabase" parent="." instance=ExtResource("5_owpbq")]
unique_name_in_owner = true unique_name_in_owner = true
EnemyList = Array[PackedScene]([ExtResource("5_urvkv"), ExtResource("6_hp0mx")])
SpawnRate = PackedFloat32Array(0.1, 0.9)
[node name="CSGBox3D" type="CSGBox3D" parent="."] [node name="CSGBox3D" type="CSGBox3D" parent="."]
use_collision = true use_collision = true

View File

@@ -11,6 +11,8 @@ namespace GameJamDungeon
{ {
public interface IPlayer : ICharacterBody3D public interface IPlayer : ICharacterBody3D
{ {
PlayerStatInfo PlayerStatInfo { get; }
PlayerLogic PlayerLogic { get; } PlayerLogic PlayerLogic { get; }
PlayerData PlayerData { get; } PlayerData PlayerData { get; }
@@ -46,6 +48,9 @@ namespace GameJamDungeon
[Export(PropertyHint.Range, "0, 100, 0.1")] [Export(PropertyHint.Range, "0, 100, 0.1")]
public float Acceleration { get; set; } = 4f; public float Acceleration { get; set; } = 4f;
[Export]
public PlayerStatInfo PlayerStatInfo { get; set; }
public PlayerLogic.Settings Settings { get; set; } = default!; public PlayerLogic.Settings Settings { get; set; } = default!;
public PlayerLogic PlayerLogic { get; set; } = default!; public PlayerLogic PlayerLogic { get; set; } = default!;
@@ -62,6 +67,10 @@ namespace GameJamDungeon
private IAutoProp<WeaponInfo> EquippedWeapon { get; set; } = default!; private IAutoProp<WeaponInfo> EquippedWeapon { get; set; } = default!;
private AutoProp<double> _currentHP { get; set; } = default!;
private IAutoProp<int> _currentVT { get; set; } = default!;
public void Initialize() public void Initialize()
{ {
AnimationPlayer.AnimationFinished += OnAnimationFinished; AnimationPlayer.AnimationFinished += OnAnimationFinished;
@@ -69,9 +78,7 @@ namespace GameJamDungeon
public void Setup() public void Setup()
{ {
Settings = new PlayerLogic.Settings( Settings = new PlayerLogic.Settings(RotationSpeed, MoveSpeed);
RotationSpeed,
MoveSpeed);
PlayerLogic = new PlayerLogic(); PlayerLogic = new PlayerLogic();
PlayerLogic.Set(this as IPlayer); PlayerLogic.Set(this as IPlayer);
@@ -82,6 +89,8 @@ namespace GameJamDungeon
GameRepo.SetPlayerGlobalPosition(GlobalPosition); GameRepo.SetPlayerGlobalPosition(GlobalPosition);
EquippedWeapon = new AutoProp<WeaponInfo>(WeaponInfo.Default); EquippedWeapon = new AutoProp<WeaponInfo>(WeaponInfo.Default);
_currentHP = new AutoProp<double>(PlayerStatInfo.MaximumHP);
_currentVT = new AutoProp<int>(PlayerStatInfo.MaximumVT);
GameRepo.PlayerGlobalPosition.Sync += OnPlayerPositionUpdated; GameRepo.PlayerGlobalPosition.Sync += OnPlayerPositionUpdated;
} }
@@ -108,6 +117,7 @@ namespace GameJamDungeon
PlayerLogic.Start(); PlayerLogic.Start();
EquippedWeapon.Sync += OnEquippedWeaponChanged; EquippedWeapon.Sync += OnEquippedWeaponChanged;
_currentHP.Sync += OnHPChanged;
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2; SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
} }
@@ -166,6 +176,12 @@ namespace GameJamDungeon
private void OnEquippedWeaponChanged(WeaponInfo info) => Hitbox.Damage = info.Damage; private void OnEquippedWeaponChanged(WeaponInfo info) => Hitbox.Damage = info.Damage;
private void OnHPChanged(double newHP)
{
if (newHP <= 0.0)
PlayerLogic.Input(new PlayerLogic.Input.Killed());
}
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition; private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
} }
} }

View File

@@ -1,8 +1,9 @@
[gd_scene load_steps=16 format=3 uid="uid://cfecvvav8kkp6"] [gd_scene load_steps=17 format=3 uid="uid://cfecvvav8kkp6"]
[ext_resource type="Script" path="res://src/player/Player.cs" id="1_xcol5"] [ext_resource type="Script" path="res://src/player/Player.cs" id="1_xcol5"]
[ext_resource type="Texture2D" uid="uid://bokx3h8kfdo5i" path="res://src/player/slash_0000_Classic_30.png" id="2_la11l"] [ext_resource type="Texture2D" uid="uid://bokx3h8kfdo5i" path="res://src/player/slash_0000_Classic_30.png" id="2_la11l"]
[ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="2_lb3qc"] [ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="2_lb3qc"]
[ext_resource type="Resource" uid="uid://cofd1ylluj24" path="res://src/player/PlayerStats.tres" id="2_nuh2a"]
[ext_resource type="Texture2D" uid="uid://byosr5gk51237" path="res://src/player/slash_0001_Classic_29.png" id="3_ux3f1"] [ext_resource type="Texture2D" uid="uid://byosr5gk51237" path="res://src/player/slash_0001_Classic_29.png" id="3_ux3f1"]
[ext_resource type="Texture2D" uid="uid://nh071o6ii03j" path="res://src/player/slash_0002_Classic_28.png" id="4_gqnq0"] [ext_resource type="Texture2D" uid="uid://nh071o6ii03j" path="res://src/player/slash_0002_Classic_28.png" id="4_gqnq0"]
[ext_resource type="Texture2D" uid="uid://bodfblud4kea3" path="res://src/player/slash_0003_Classic_27.png" id="5_eebal"] [ext_resource type="Texture2D" uid="uid://bodfblud4kea3" path="res://src/player/slash_0003_Classic_27.png" id="5_eebal"]
@@ -117,6 +118,7 @@ axis_lock_angular_z = true
motion_mode = 1 motion_mode = 1
script = ExtResource("1_xcol5") script = ExtResource("1_xcol5")
RotationSpeed = 0.025 RotationSpeed = 0.025
PlayerStatInfo = ExtResource("2_nuh2a")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."] [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.937567, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.937567, 0)

View File

@@ -18,5 +18,14 @@ namespace GameJamDungeon
[Save("PlayerInventory")] [Save("PlayerInventory")]
public required IEnumerable<InventoryItemInfo> Inventory { get; set; } public required IEnumerable<InventoryItemInfo> Inventory { get; set; }
[Save("PlayerStats")]
public required PlayerStatInfo PlayerStats { get; set; }
[Save("CurrentHP")]
public required int CurrentHP { get; set; }
[Save("CurrentVT")]
public required int CurrentVT { get; set; }
} }
} }

View File

@@ -0,0 +1,38 @@
using Godot;
namespace GameJamDungeon
{
[GlobalClass]
public partial class PlayerStatInfo : Resource, ICharacterStats
{
[Export]
public double MaximumHP { get; set; }
[Export]
public int MaximumVT { get; set; }
[Export]
public int BaseAttack { get; set; }
[Export]
public int BaseDefense { get; set; }
[Export]
public double ElementAResistance { get; set; }
[Export]
public double ElementBResistance { get; set; }
[Export]
public double ElementCResistance { get; set; }
[Export]
public double BaseElementADamageBonus { get; set; }
[Export]
public double BaseElementBDamageBonus { get; set; }
[Export]
public double BaseElementCDamageBonus { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="PlayerStatInfo" load_steps=2 format=3 uid="uid://cofd1ylluj24"]
[ext_resource type="Script" path="res://src/player/PlayerStatInfo.cs" id="1_a84hi"]
[resource]
script = ExtResource("1_a84hi")
MaximumHP = 120.0
MaximumVT = 90
BaseAttack = 10
BaseDefense = 0
ElementAResistance = 0.0
ElementBResistance = 0.0
ElementCResistance = 15.0
BaseElementADamageBonus = 30.0
BaseElementBDamageBonus = 15.0
BaseElementCDamageBonus = 20.0

View File

@@ -15,6 +15,8 @@ namespace GameJamDungeon
public readonly record struct Attack; public readonly record struct Attack;
public readonly record struct AttackAnimationFinished; public readonly record struct AttackAnimationFinished;
public readonly record struct Killed;
} }
} }
} }

View File

@@ -8,7 +8,7 @@ namespace GameJamDungeon
public partial record State public partial record State
{ {
[Meta, Id("player_logic_alive")] [Meta, Id("player_logic_alive")]
public abstract partial record Alive : State, IGet<Input.PhysicsTick>, IGet<Input.Moved> public abstract partial record Alive : State, IGet<Input.PhysicsTick>, IGet<Input.Moved>, IGet<Input.Killed>
{ {
public virtual Transition On(in Input.PhysicsTick input) public virtual Transition On(in Input.PhysicsTick input)
{ {
@@ -36,9 +36,14 @@ namespace GameJamDungeon
{ {
var gameRepo = Get<IGameRepo>(); var gameRepo = Get<IGameRepo>();
gameRepo.SetPlayerGlobalPosition(input.GlobalPosition); gameRepo.SetPlayerGlobalPosition(input.GlobalPosition);
GD.Print($"Current position: {input.GlobalPosition}");
return ToSelf(); return ToSelf();
} }
public Transition On(in Input.Killed input)
{
GD.Print("Player died");
return To<Disabled>();
}
} }
} }
} }

View File

@@ -0,0 +1,18 @@
using Godot;
namespace GameJamDungeon
{
public static class DamageCalculator
{
public static double CalculatePlayerDamage(int attackDamage, PlayerStatInfo playerStatInfo, EnemyStatInfo enemyStatInfo)
{
var baseDamage = attackDamage + playerStatInfo.BaseAttack;
var elementADamage = (playerStatInfo.BaseElementADamageBonus > 0 ? playerStatInfo.BaseElementADamageBonus - enemyStatInfo.ElementAResistance : 0) / 100;
var elementBDamage = (playerStatInfo.BaseElementBDamageBonus > 0 ? playerStatInfo.BaseElementBDamageBonus - enemyStatInfo.ElementBResistance : 0) / 100;
var elementCDamage = (playerStatInfo.BaseElementCDamageBonus > 0 ? playerStatInfo.BaseElementCDamageBonus - enemyStatInfo.ElementCResistance : 0) / 100;
var elementalBonusDamage = baseDamage + (baseDamage * elementADamage) + (baseDamage * elementBDamage) + (baseDamage * elementCDamage);
var calculatedDamage = elementalBonusDamage - enemyStatInfo.BaseDefense;
return calculatedDamage;
}
}
}

View File

@@ -0,0 +1,17 @@
namespace GameJamDungeon
{
public interface ICharacterStats
{
public double MaximumHP { get; }
public int BaseAttack { get; }
public int BaseDefense { get; }
public double ElementAResistance { get; }
public double ElementBResistance { get; }
public double ElementCResistance { get; }
}
}