Demon wall implementation (attack data, takes damage, dies, etc) but mostly placeholders

This commit is contained in:
2025-03-25 00:09:33 -07:00
parent f69c6b94a1
commit 84c4d1b9ce
40 changed files with 20732 additions and 625 deletions

View File

@@ -0,0 +1,52 @@
using Godot;
using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Ma.Adapter
{
public class DamageCalculator : IDamageCalculator
{
public double CalculateDamage(double damage,
ElementType elementType,
double defense,
ElementalResistanceSet elementalResistanceSet,
bool isCriticalHit = false,
bool ignoreDefense = false,
bool ignoreElementalResistance = false)
{
var calculatedDamage = damage;
if (!ignoreElementalResistance)
calculatedDamage = CalculateElementalResistance(calculatedDamage, elementType, elementalResistanceSet);
if (!ignoreDefense)
calculatedDamage = CalculateDefenseResistance(calculatedDamage, defense);
if (isCriticalHit)
calculatedDamage *= 2;
return calculatedDamage;
}
private static double CalculateDefenseResistance(double incomingDamage, double defense)
{
return Mathf.Max(incomingDamage - defense, 0.0);
}
private static double CalculateElementalResistance(
double incomingDamage,
ElementType incomingElementType,
ElementalResistanceSet elementalResistanceSet)
{
var resistance = elementalResistanceSet.ElementalResistance[incomingElementType];
return Mathf.Max(incomingDamage - (incomingDamage * resistance), 0.0);
}
}
public interface IDamageCalculator
{
public double CalculateDamage(double damage,
ElementType elementType,
double defense,
ElementalResistanceSet elementalResistanceSet,
bool isCriticalHit = false,
bool ignoreDefense = false,
bool ignoreElementalResistance = false);
}
}

View File

@@ -0,0 +1,20 @@
namespace Zennysoft.Ma.Adapter.Entity
{
public record ElementalResistanceSet
{
public Dictionary<ElementType, double> ElementalResistance { get; }
public ElementalResistanceSet(double aeolicResistance, double hydricResistance, double igneousResistance, double ferrumResistance, double telluricResistance)
{
ElementalResistance = new Dictionary<ElementType, double>
{
{ ElementType.None, 0 },
{ ElementType.Aeolic, aeolicResistance },
{ ElementType.Hydric, hydricResistance },
{ ElementType.Igneous, igneousResistance },
{ ElementType.Ferrum, ferrumResistance },
{ ElementType.Telluric, telluricResistance },
};
}
}
}

View File

@@ -1,7 +1,5 @@
using Chickensoft.Collections; using Chickensoft.Introspection;
using Chickensoft.Introspection;
using Chickensoft.Serialization; using Chickensoft.Serialization;
using Godot;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;

View File

@@ -21,7 +21,7 @@ public partial class BossTypeA : Enemy, IHasPrimaryAttack, IHasSecondaryAttack,
public double SecondaryAttackElementalDamageBonus { get; set; } = 1.0; public double SecondaryAttackElementalDamageBonus { get; set; } = 1.0;
[Node] public new EnemyModelView3D _enemyModelView { get; set; } [Node] public new BossTypeAEnemyModelView _enemyModelView { get; set; }
[Node] public CollisionShape3D EnemyHitbox { get; set; } = default!; [Node] public CollisionShape3D EnemyHitbox { get; set; } = default!;

View File

@@ -52,6 +52,8 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
private Vector3 _knockbackDirection = Vector3.Zero; private Vector3 _knockbackDirection = Vector3.Zero;
private IDamageCalculator _damageCalculator;
#region Godot methods #region Godot methods
public void Setup() public void Setup()
{ {
@@ -59,6 +61,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
_enemyLogic.Set(_enemyStatResource); _enemyLogic.Set(_enemyStatResource);
_enemyLogic.Set(this as IEnemy); _enemyLogic.Set(this as IEnemy);
_enemyLogic.Set(_player); _enemyLogic.Set(_player);
_damageCalculator = new DamageCalculator();
} }
public void OnResolved() public void OnResolved()
@@ -118,12 +121,13 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
{ {
if (CurrentHP.Value > 0) if (CurrentHP.Value > 0)
{ {
if (!ignoreElementalResistance) _damageCalculator.CalculateDamage(damage,
damage = CalculateElementalResistance(damage, elementType); elementType,
if (!ignoreDefense) _player.Stats.CurrentDefense.Value + _player.Stats.BonusDefense.Value,
damage = CalculateDefenseResistance(damage); _enemyStatResource.ElementalResistance,
if (isCriticalHit) isCriticalHit,
damage *= 2; ignoreDefense,
ignoreElementalResistance);
GD.Print($"Enemy Hit for {damage} damage."); GD.Print($"Enemy Hit for {damage} damage.");
CurrentHP.OnNext(CurrentHP.Value - damage); CurrentHP.OnNext(CurrentHP.Value - damage);
GD.Print("Current HP: " + CurrentHP.Value); GD.Print("Current HP: " + CurrentHP.Value);
@@ -151,7 +155,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
_enemyLogic.Input(new EnemyLogic.Input.EnemyDefeated()); _enemyLogic.Input(new EnemyLogic.Input.EnemyDefeated());
_collisionShape.SetDeferred("disabled", true); _collisionShape.SetDeferred("disabled", true);
_enemyModelView.PlayDeathAnimation(); _enemyModelView.PlayDeathAnimation();
var tweener = GetTree().CreateTween(); var tweener = CreateTween();
tweener.TweenInterval(1.0f); tweener.TweenInterval(1.0f);
tweener.TweenCallback(Callable.From(QueueFree)); tweener.TweenCallback(Callable.From(QueueFree));
Game.EnemyDefeated(GlobalPosition, _enemyStatResource); Game.EnemyDefeated(GlobalPosition, _enemyStatResource);
@@ -238,22 +242,6 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
Die(); Die();
} }
private double CalculateElementalResistance(double incomingDamage, ElementType incomingElementType)
{
if (incomingElementType == ElementType.Aeolic)
return Mathf.Max(incomingDamage - (incomingDamage * _enemyStatResource.AeolicResistance), 0.0);
if (incomingElementType == ElementType.Hydric)
return Mathf.Max(incomingDamage - (incomingDamage * _enemyStatResource.HydricResistance), 0.0);
if (incomingElementType == ElementType.Igneous)
return Mathf.Max(incomingDamage - (incomingDamage * _enemyStatResource.IgneousResistance), 0.0);
if (incomingElementType == ElementType.Ferrum)
return Mathf.Max(incomingDamage - (incomingDamage * _enemyStatResource.FerrumResistance), 0.0);
if (incomingElementType == ElementType.Telluric)
return Mathf.Max(incomingDamage - (incomingDamage * _enemyStatResource.TelluricResistance), 0.0);
return Mathf.Max(incomingDamage, 0.0);
}
private double CalculateDefenseResistance(double incomingDamage) private double CalculateDefenseResistance(double incomingDamage)
{ {
return Mathf.Max(incomingDamage - _enemyStatResource.CurrentDefense, 0.0); return Mathf.Max(incomingDamage - _enemyStatResource.CurrentDefense, 0.0);

View File

@@ -24,14 +24,8 @@ public partial class EnemyModelView3D : Node3D, IEnemyModelView
[Node] public AnimationTree AnimationTree { get; set; } = default!; [Node] public AnimationTree AnimationTree { get; set; } = default!;
[Node] public IHitbox Hitbox { get; set; } = default!;
[Node] public MeshInstance3D MeshInstance { get; set; } = default!; [Node] public MeshInstance3D MeshInstance { get; set; } = default!;
public void Setup()
{
}
public void PlayPrimaryAttackAnimation() public void PlayPrimaryAttackAnimation()
{ {
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK); AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK);
@@ -49,7 +43,7 @@ public partial class EnemyModelView3D : Node3D, IEnemyModelView
public void PlayHitAnimation() public void PlayHitAnimation()
{ {
var tweener = GetTree().CreateTween(); var tweener = CreateTween();
ChangeMaterial(); ChangeMaterial();
tweener.TweenMethod(Callable.From((float x) => SetTransparency(x)), 0.0f, 0.5f, 0.3f); tweener.TweenMethod(Callable.From((float x) => SetTransparency(x)), 0.0f, 0.5f, 0.3f);
tweener.TweenCallback(Callable.From(ClearDamageEffect)); tweener.TweenCallback(Callable.From(ClearDamageEffect));
@@ -58,7 +52,7 @@ public partial class EnemyModelView3D : Node3D, IEnemyModelView
public void PlayDeathAnimation() public void PlayDeathAnimation()
{ {
LoadShader("res://src/enemy/EnemyDie.tres"); LoadShader("res://src/enemy/EnemyDie.tres");
var tweener = GetTree().CreateTween(); var tweener = CreateTween();
tweener.TweenMethod(Callable.From((float x) => SetTransparency(x)), 0.0f, 1.0f, 0.8f); tweener.TweenMethod(Callable.From((float x) => SetTransparency(x)), 0.0f, 1.0f, 0.8f);
tweener.TweenCallback(Callable.From(QueueFree)); tweener.TweenCallback(Callable.From(QueueFree));
} }

View File

@@ -1,4 +1,5 @@
using Godot; using Godot;
using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
@@ -30,19 +31,21 @@ public partial class EnemyStatResource : Resource
public double Luck { get; set; } = 0.05f; public double Luck { get; set; } = 0.05f;
[Export] [Export]
public double TelluricResistance { get; set; } private double _telluricResistance { get; set; }
[Export] [Export]
public double AeolicResistance { get; set; } private double _aeolicResistance { get; set; }
[Export] [Export]
public double HydricResistance { get; set; } private double _hydricResistance { get; set; }
[Export] [Export]
public double IgneousResistance { get; set; } private double _igneousResistance { get; set; }
[Export] [Export]
public double FerrumResistance { get; set; } private double _ferrumResistance { get; set; }
public ElementalResistanceSet ElementalResistance => new ElementalResistanceSet(_aeolicResistance, _hydricResistance, _igneousResistance, _ferrumResistance, _telluricResistance);
[Export] [Export]
public float DropsSoulGemChance { get; set; } = 0.75f; public float DropsSoulGemChance { get; set; } = 0.75f;

View File

@@ -15,11 +15,11 @@ MaxAttack = 15
MaxDefense = 0 MaxDefense = 0
ExpFromDefeat = 5 ExpFromDefeat = 5
Luck = 0.05 Luck = 0.05
TelluricResistance = 0.0 _telluricResistance = 0.0
AeolicResistance = 0.0 _aeolicResistance = 0.0
HydricResistance = 0.0 _hydricResistance = 0.0
IgneousResistance = 0.0 _igneousResistance = 0.0
FerrumResistance = 0.0 _ferrumResistance = 0.0
DropsSoulGemChance = 0.75 DropsSoulGemChance = 0.75
metadata/_custom_type_script = ExtResource("2_wrps7") metadata/_custom_type_script = ExtResource("2_wrps7")

View File

@@ -2,30 +2,6 @@
[sub_resource type="Animation" id="Animation_ttkyx"] [sub_resource type="Animation" id="Animation_ttkyx"]
length = 0.001 length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Hitbox/CollisionShape3D:disabled")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Hitbox/CollisionShape3D:disabled")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [true]
}
[sub_resource type="Animation" id="Animation_sfyuh"] [sub_resource type="Animation" id="Animation_sfyuh"]
resource_name = "idle" resource_name = "idle"
@@ -594,18 +570,6 @@ tracks/39/path = NodePath("Armature/Skeleton3D:heelIK_R")
tracks/39/interp = 0 tracks/39/interp = 0
tracks/39/loop_wrap = true tracks/39/loop_wrap = true
tracks/39/keys = PackedFloat32Array(0, 1, -0.456756, -0.539878, 0.539587, 0.456893) tracks/39/keys = PackedFloat32Array(0, 1, -0.456756, -0.539878, 0.539587, 0.456893)
tracks/40/type = "value"
tracks/40/imported = false
tracks/40/enabled = true
tracks/40/path = NodePath("Hitbox/CollisionShape3D:disabled")
tracks/40/interp = 1
tracks/40/loop_wrap = true
tracks/40/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [true, false, true]
}
[sub_resource type="Animation" id="Animation_fdnqs"] [sub_resource type="Animation" id="Animation_fdnqs"]
resource_name = "SHIELD BASH" resource_name = "SHIELD BASH"
@@ -890,18 +854,6 @@ tracks/39/path = NodePath("Armature/Skeleton3D:heelIK_R")
tracks/39/interp = 0 tracks/39/interp = 0
tracks/39/loop_wrap = true tracks/39/loop_wrap = true
tracks/39/keys = PackedFloat32Array(0, 1, -0.456756, -0.539878, 0.539587, 0.456893) tracks/39/keys = PackedFloat32Array(0, 1, -0.456756, -0.539878, 0.539587, 0.456893)
tracks/40/type = "value"
tracks/40/imported = false
tracks/40/enabled = true
tracks/40/path = NodePath("Hitbox/CollisionShape3D:disabled")
tracks/40/interp = 1
tracks/40/loop_wrap = true
tracks/40/keys = {
"times": PackedFloat32Array(0, 0.533333, 0.633333),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [true, false, true]
}
[sub_resource type="Animation" id="Animation_ui3ue"] [sub_resource type="Animation" id="Animation_ui3ue"]
resource_name = "WALK" resource_name = "WALK"

View File

@@ -14,11 +14,11 @@ MaxAttack = 0
MaxDefense = 0 MaxDefense = 0
ExpFromDefeat = 0 ExpFromDefeat = 0
Luck = 0.05 Luck = 0.05
TelluricResistance = 0.0 _telluricResistance = 0.0
AeolicResistance = 0.0 _aeolicResistance = 0.0
HydricResistance = 0.0 _hydricResistance = 0.0
IgneousResistance = 0.0 _igneousResistance = 0.0
FerrumResistance = 0.0 _ferrumResistance = 0.0
DropsSoulGemChance = 0.75 DropsSoulGemChance = 0.75
metadata/_custom_type_script = "uid://dnkmr0eq1sij0" metadata/_custom_type_script = "uid://dnkmr0eq1sij0"

View File

@@ -200,7 +200,7 @@ bones/0/name = "spine1"
bones/0/parent = -1 bones/0/parent = -1
bones/0/rest = Transform3D(1.49012e-06, 0.00846654, -0.999964, 2.93367e-08, 0.999964, 0.00846654, 1, -4.23752e-08, 1.49012e-06, 0.000155807, -0.00105953, -2.01735) bones/0/rest = Transform3D(1.49012e-06, 0.00846654, -0.999964, 2.93367e-08, 0.999964, 0.00846654, 1, -4.23752e-08, 1.49012e-06, 0.000155807, -0.00105953, -2.01735)
bones/0/enabled = true bones/0/enabled = true
bones/0/position = Vector3(-0.260278, -1.0541, -1.96767) bones/0/position = Vector3(-0.259488, -0.96383, -1.97376)
bones/0/rotation = Quaternion(0.0915277, -0.692111, -0.0341586, 0.715149) bones/0/rotation = Quaternion(0.0915277, -0.692111, -0.0341586, 0.715149)
bones/0/scale = Vector3(1, 1, 1) bones/0/scale = Vector3(1, 1, 1)
bones/1/name = "spine0" bones/1/name = "spine0"
@@ -243,7 +243,7 @@ bones/6/parent = 5
bones/6/rest = Transform3D(0.0598389, 0.98531, 0.15995, -0.975271, 0.0235553, 0.219755, 0.212759, -0.169144, 0.962353, 3.65078e-07, 1.40318, 0) bones/6/rest = Transform3D(0.0598389, 0.98531, 0.15995, -0.975271, 0.0235553, 0.219755, 0.212759, -0.169144, 0.962353, 3.65078e-07, 1.40318, 0)
bones/6/enabled = true bones/6/enabled = true
bones/6/position = Vector3(3.65078e-07, 1.40318, 0) bones/6/position = Vector3(3.65078e-07, 1.40318, 0)
bones/6/rotation = Quaternion(-0.0474983, -0.294201, -0.744151, 0.597854) bones/6/rotation = Quaternion(-0.0697867, -0.302352, -0.744713, 0.59086)
bones/6/scale = Vector3(1, 1, 1) bones/6/scale = Vector3(1, 1, 1)
bones/7/name = "Bone.007" bones/7/name = "Bone.007"
bones/7/parent = 6 bones/7/parent = 6
@@ -278,7 +278,7 @@ bones/11/parent = 1
bones/11/rest = Transform3D(0.981457, 0.0769315, -0.175568, 0.18837, -0.217537, 0.957703, 0.035485, -0.973015, -0.227995, -1.09896e-07, 3.84743, -2.10479e-07) bones/11/rest = Transform3D(0.981457, 0.0769315, -0.175568, 0.18837, -0.217537, 0.957703, 0.035485, -0.973015, -0.227995, -1.09896e-07, 3.84743, -2.10479e-07)
bones/11/enabled = true bones/11/enabled = true
bones/11/position = Vector3(-1.09896e-07, 3.84743, -2.10479e-07) bones/11/position = Vector3(-1.09896e-07, 3.84743, -2.10479e-07)
bones/11/rotation = Quaternion(-0.779754, -0.0572995, 0.0817541, 0.618075) bones/11/rotation = Quaternion(-0.784729, -0.0616535, 0.0718257, 0.612568)
bones/11/scale = Vector3(1, 0.999999, 1) bones/11/scale = Vector3(1, 0.999999, 1)
bones/12/name = "arm2_L" bones/12/name = "arm2_L"
bones/12/parent = 11 bones/12/parent = 11
@@ -306,7 +306,7 @@ bones/15/parent = 1
bones/15/rest = Transform3D(-0.98213, 0.0512573, -0.181089, -0.187541, -0.185921, 0.964501, 0.0157694, 0.981227, 0.192212, 0.00107862, 3.8461, -0.0821097) bones/15/rest = Transform3D(-0.98213, 0.0512573, -0.181089, -0.187541, -0.185921, 0.964501, 0.0157694, 0.981227, 0.192212, 0.00107862, 3.8461, -0.0821097)
bones/15/enabled = true bones/15/enabled = true
bones/15/position = Vector3(0.00107886, 3.8461, -0.0821095) bones/15/position = Vector3(0.00107886, 3.8461, -0.0821095)
bones/15/rotation = Quaternion(-0.215469, 0.745349, 0.613517, -0.147056) bones/15/rotation = Quaternion(-0.210671, 0.737877, 0.621635, -0.157245)
bones/15/scale = Vector3(1, 1, 1) bones/15/scale = Vector3(1, 1, 1)
bones/16/name = "arm2_R" bones/16/name = "arm2_R"
bones/16/parent = 15 bones/16/parent = 15
@@ -333,22 +333,22 @@ bones/19/name = "hip_L"
bones/19/parent = -1 bones/19/parent = -1
bones/19/rest = Transform3D(0.138486, 0.897208, 0.419333, -0.129033, -0.403458, 0.905854, 0.981923, -0.179556, 0.059896, 0.000155807, -0.00105953, -2.01735) bones/19/rest = Transform3D(0.138486, 0.897208, 0.419333, -0.129033, -0.403458, 0.905854, 0.981923, -0.179556, 0.059896, 0.000155807, -0.00105953, -2.01735)
bones/19/enabled = true bones/19/enabled = true
bones/19/position = Vector3(-0.381736, -1.20058, -1.71562) bones/19/position = Vector3(-0.309033, -1.1318, -1.95517)
bones/19/rotation = Quaternion(0.627802, 0.292645, 0.544916, -0.472536) bones/19/rotation = Quaternion(0.612762, 0.310855, 0.569327, -0.451397)
bones/19/scale = Vector3(1, 1, 1) bones/19/scale = Vector3(1, 1, 1)
bones/20/name = "leg1_L" bones/20/name = "leg1_L"
bones/20/parent = 19 bones/20/parent = 19
bones/20/rest = Transform3D(0.945603, 0.113405, 0.304916, -0.324072, 0.410457, 0.852351, -0.0284943, -0.9048, 0.424881, 2.08616e-07, 2.00996, -7.1153e-07) bones/20/rest = Transform3D(0.945603, 0.113405, 0.304916, -0.324072, 0.410457, 0.852351, -0.0284943, -0.9048, 0.424881, 2.08616e-07, 2.00996, -7.1153e-07)
bones/20/enabled = true bones/20/enabled = true
bones/20/position = Vector3(2.08616e-07, 2.00996, -7.1153e-07) bones/20/position = Vector3(2.08616e-07, 2.00996, -7.1153e-07)
bones/20/rotation = Quaternion(-0.327961, -0.422555, -0.300918, 0.789517) bones/20/rotation = Quaternion(-0.312233, -0.440038, -0.274881, 0.795813)
bones/20/scale = Vector3(1, 0.999999, 1) bones/20/scale = Vector3(1, 0.999999, 1)
bones/21/name = "leg2_L" bones/21/name = "leg2_L"
bones/21/parent = 20 bones/21/parent = 20
bones/21/rest = Transform3D(0.990336, -0.138679, 0.00180777, 0.138628, 0.990193, 0.0173138, -0.00419111, -0.0168959, 0.999848, 5.96046e-08, 5.85994, -5.23403e-07) bones/21/rest = Transform3D(0.990336, -0.138679, 0.00180777, 0.138628, 0.990193, 0.0173138, -0.00419111, -0.0168959, 0.999848, 5.96046e-08, 5.85994, -5.23403e-07)
bones/21/enabled = true bones/21/enabled = true
bones/21/position = Vector3(5.96046e-08, 5.85994, -5.23403e-07) bones/21/position = Vector3(5.96046e-08, 5.85994, -5.23403e-07)
bones/21/rotation = Quaternion(-0.0604978, 0.00129835, 0.489732, 0.869771) bones/21/rotation = Quaternion(-0.0601745, 0.00130057, 0.487115, 0.871261)
bones/21/scale = Vector3(1, 1, 1) bones/21/scale = Vector3(1, 1, 1)
bones/22/name = "foot1_L" bones/22/name = "foot1_L"
bones/22/parent = 21 bones/22/parent = 21
@@ -382,7 +382,7 @@ bones/26/name = "hip_R"
bones/26/parent = -1 bones/26/parent = -1
bones/26/rest = Transform3D(0.138486, -0.897208, -0.419333, 0.129033, -0.403458, 0.905854, -0.981923, -0.179556, 0.059896, -0.000155807, -0.00105953, -2.01735) bones/26/rest = Transform3D(0.138486, -0.897208, -0.419333, 0.129033, -0.403458, 0.905854, -0.981923, -0.179556, 0.059896, -0.000155807, -0.00105953, -2.01735)
bones/26/enabled = true bones/26/enabled = true
bones/26/position = Vector3(-0.0213137, -1.11395, -2.01918) bones/26/position = Vector3(-0.235011, -1.11395, -2.01773)
bones/26/rotation = Quaternion(0.608697, -0.3155, -0.575514, -0.445793) bones/26/rotation = Quaternion(0.608697, -0.3155, -0.575514, -0.445793)
bones/26/scale = Vector3(1, 1, 1) bones/26/scale = Vector3(1, 1, 1)
bones/27/name = "leg1_R" bones/27/name = "leg1_R"
@@ -390,14 +390,14 @@ bones/27/parent = 26
bones/27/rest = Transform3D(0.945603, -0.113405, -0.304916, 0.324072, 0.410457, 0.852351, 0.0284943, -0.9048, 0.424881, -9.54606e-09, 2.00996, -3.52971e-07) bones/27/rest = Transform3D(0.945603, -0.113405, -0.304916, 0.324072, 0.410457, 0.852351, 0.0284943, -0.9048, 0.424881, -9.54606e-09, 2.00996, -3.52971e-07)
bones/27/enabled = true bones/27/enabled = true
bones/27/position = Vector3(-9.54606e-09, 2.00996, -3.52971e-07) bones/27/position = Vector3(-9.54606e-09, 2.00996, -3.52971e-07)
bones/27/rotation = Quaternion(-0.202201, 0.424694, 0.137914, 0.871625) bones/27/rotation = Quaternion(-0.207711, 0.421647, 0.141893, 0.871169)
bones/27/scale = Vector3(1, 0.999999, 1) bones/27/scale = Vector3(1, 0.999999, 1)
bones/28/name = "leg2_R" bones/28/name = "leg2_R"
bones/28/parent = 27 bones/28/parent = 27
bones/28/rest = Transform3D(0.990336, 0.138679, -0.00180777, -0.138628, 0.990193, 0.0173138, 0.00419111, -0.0168959, 0.999848, 4.51691e-08, 5.85994, -3.72529e-09) bones/28/rest = Transform3D(0.990336, 0.138679, -0.00180777, -0.138628, 0.990193, 0.0173138, 0.00419111, -0.0168959, 0.999848, 4.51691e-08, 5.85994, -3.72529e-09)
bones/28/enabled = true bones/28/enabled = true
bones/28/position = Vector3(4.51691e-08, 5.85994, -3.72529e-09) bones/28/position = Vector3(4.51691e-08, 5.85994, -3.72529e-09)
bones/28/rotation = Quaternion(-0.0627787, -0.00116448, -0.501219, 0.863039) bones/28/rotation = Quaternion(-0.0640421, -0.00115636, -0.511308, 0.857007)
bones/28/scale = Vector3(1, 1, 1) bones/28/scale = Vector3(1, 1, 1)
bones/29/name = "foot1_R" bones/29/name = "foot1_R"
bones/29/parent = 28 bones/29/parent = 28
@@ -429,7 +429,7 @@ bones/32/rotation = Quaternion(0.456756, 0.539878, -0.539587, -0.456893)
bones/32/scale = Vector3(1, 1, 1) bones/32/scale = Vector3(1, 1, 1)
[node name="BoneAttachment3D" type="BoneAttachment3D" parent="Armature/Skeleton3D"] [node name="BoneAttachment3D" type="BoneAttachment3D" parent="Armature/Skeleton3D"]
transform = Transform3D(-0.266252, -0.0359368, -0.963233, -0.333724, -0.934064, 0.127095, -0.904288, 0.355294, 0.236703, -1.68949, 8.19963, 4.95696) transform = Transform3D(-0.291816, -0.0758791, -0.95346, -0.329798, -0.927733, 0.174769, -0.897817, 0.36545, 0.245702, -1.66649, 8.30024, 4.94846)
bone_name = "TOP OF SKULL" bone_name = "TOP OF SKULL"
bone_idx = 8 bone_idx = 8

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,26 +1,7 @@
[gd_scene load_steps=11 format=3 uid="uid://dxrgfh28wj5su"] [gd_scene load_steps=10 format=3 uid="uid://dxrgfh28wj5su"]
[ext_resource type="Script" uid="uid://vgvrmwsrwakf" path="res://src/enemy/enemy_types/16. demon wall/DemonWallArm.cs" id="1_fhrhk"] [ext_resource type="Script" uid="uid://vgvrmwsrwakf" path="res://src/enemy/enemy_types/16. demon wall/DemonWallArm.cs" id="1_fhrhk"]
[ext_resource type="PackedScene" uid="uid://dafhaya5sejdj" path="res://src/enemy/enemy_types/16. demon wall/model/ARM3.glb" id="1_wuuwb"] [ext_resource type="PackedScene" uid="uid://dafhaya5sejdj" path="res://src/enemy/enemy_types/16. demon wall/model/ARM3.glb" id="1_wuuwb"]
[ext_resource type="Script" uid="uid://dnkmr0eq1sij0" path="res://src/enemy/EnemyStatResource.cs" id="2_afuej"]
[sub_resource type="Resource" id="Resource_gcbec"]
script = ExtResource("2_afuej")
CurrentHP = 20.0
MaximumHP = 20
CurrentAttack = 0
CurrentDefense = 0
MaxAttack = 0
MaxDefense = 0
ExpFromDefeat = 0
Luck = 0.05
TelluricResistance = 0.0
AeolicResistance = 0.0
HydricResistance = 0.0
IgneousResistance = 0.0
FerrumResistance = 0.0
DropsSoulGemChance = 0.0
metadata/_custom_type_script = "uid://dnkmr0eq1sij0"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_bpd8u"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_bpd8u"]
animation = &"ARM 3 WALL CALL" animation = &"ARM 3 WALL CALL"
@@ -46,11 +27,10 @@ states/idle/node = SubResource("AnimationNodeAnimation_ccv8a")
states/idle/position = Vector2(339, 112) states/idle/position = Vector2(339, 112)
transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_sjgs2"), "idle", "attack", SubResource("AnimationNodeStateMachineTransition_p21h7"), "attack", "idle", SubResource("AnimationNodeStateMachineTransition_1weac")] transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_sjgs2"), "idle", "attack", SubResource("AnimationNodeStateMachineTransition_p21h7"), "attack", "idle", SubResource("AnimationNodeStateMachineTransition_1weac")]
[sub_resource type="BoxShape3D" id="BoxShape3D_fhrhk"]
[node name="Arm3" type="Node3D"] [node name="Arm3" type="Node3D"]
script = ExtResource("1_fhrhk") script = ExtResource("1_fhrhk")
_enemyStatResource = SubResource("Resource_gcbec")
PrimaryAttackElementalType = null
PrimaryAttackElementalDamageBonus = null
[node name="ARM3" parent="." instance=ExtResource("1_wuuwb")] [node name="ARM3" parent="." instance=ExtResource("1_wuuwb")]
@@ -59,3 +39,12 @@ unique_name_in_owner = true
root_node = NodePath("%AnimationTree/..") root_node = NodePath("%AnimationTree/..")
tree_root = SubResource("AnimationNodeStateMachine_fhrhk") tree_root = SubResource("AnimationNodeStateMachine_fhrhk")
anim_player = NodePath("../AnimationPlayer") anim_player = NodePath("../AnimationPlayer")
[node name="Hitbox" type="Area3D" parent="ARM3"]
unique_name_in_owner = true
collision_layer = 0
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="ARM3/Hitbox"]
shape = SubResource("BoxShape3D_fhrhk")
disabled = true

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,5 @@
using Chickensoft.AutoInject; using Chickensoft.AutoInject;
using Chickensoft.Collections;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Godot; using Godot;
using System.Linq; using System.Linq;
@@ -7,7 +8,7 @@ using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
[Meta(typeof(IAutoNode))] [Meta(typeof(IAutoNode))]
public partial class DemonWall : CharacterBody3D public partial class DemonWall : CharacterBody3D, IEnemy
{ {
public override void _Notification(int what) => this.Notify(what); public override void _Notification(int what) => this.Notify(what);
@@ -15,89 +16,87 @@ public partial class DemonWall : CharacterBody3D
[Export] protected EnemyStatResource _enemyStatResource { get; set; } = default!; [Export] protected EnemyStatResource _enemyStatResource { get; set; } = default!;
[Node] private DemonWallArm _arm3 { get; set; } = default!; [Node] public DemonWallModelView EnemyModelView { get; set; } = default!;
[Node] public Node3D LeftArms { get; set; } = default!; public AutoProp<double> CurrentHP { get; private set; }
[Node] public Node3D RightArms { get; set; } = default!;
[Node] public MeshInstance3D Eye { get; set; } = default!;
[Node] private Node3D _rotation { get; set; } = default!;
[Node] private AnimatableBody3D _opposingWall { get; set; } = default!;
[Export] private double _maximumWallMoveAmount = 24; [Export] private double _maximumWallMoveAmount = 24;
private Timer _attackTimer; private Timer _attackTimer;
public void OnPhysicsProcess(double delta) private IDamageCalculator _damageCalculator;
public void OnReady()
{ {
var direction = GlobalPosition.DirectionTo(_player.CurrentPosition).Normalized(); CurrentHP = new AutoProp<double>(_enemyStatResource.MaximumHP);
var rotationAngle = GetRotationAngle(); _attackTimer = new Timer { WaitTime = 5f };
RotateToPlayer(rotationAngle); _attackTimer.Timeout += AttackTimer_Timeout;
AddChild(_attackTimer);
_damageCalculator = new DamageCalculator();
CurrentHP.Sync += CurrentHP_Sync;
} }
public void RotateToPlayer(float rotationAngle) private void CurrentHP_Sync(double newHP)
{ {
var tweener = GetTree().CreateTween(); if (newHP <= 0)
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(x)), Eye.Rotation.Y, rotationAngle, 1f); Die();
} }
public void Activate() public void Activate()
{ {
_opposingWall.Show(); EnemyModelView.Activate();
var collisionShape = _opposingWall.GetChildren().OfType<CollisionShape3D>().Single();
collisionShape.SetDeferred(CollisionShape3D.PropertyName.Disabled, false);
_attackTimer = new Timer { WaitTime = 5f };
_attackTimer.Timeout += AttackTimer_Timeout;
AddChild(_attackTimer);
SetPhysicsProcess(true); SetPhysicsProcess(true);
_attackTimer.Start(); StartAttackTimer();
} }
private void AttackTimer_Timeout() private void AttackTimer_Timeout()
{ {
var rng = new RandomNumberGenerator(); TakeAction();
rng.Randomize();
var leftArms = new Godot.Collections.Array<DemonWallArm>(LeftArms.GetChildren().Cast<DemonWallArm>());
var rightArms = new Godot.Collections.Array<DemonWallArm>(RightArms.GetChildren().Cast<DemonWallArm>());
var leftArm = leftArms.PickRandom();
var rightArm = rightArms.PickRandom();
leftArm.PrimaryAttack();
rightArm.PrimaryAttack();
if (leftArm == _arm3 && _opposingWall.Position.Z > -_maximumWallMoveAmount)
MoveWall();
}
private float GetRotationAngle()
{
var target = new Vector3(_player.CurrentPosition.X, Position.Y, _player.CurrentPosition.Z);
_rotation.LookAt(target, Vector3.Up, true);
_rotation.RotateY(Rotation.Y);
return _rotation.Rotation.Y;
}
private void MoveWall()
{
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => MoveWallTowardsPlayer(x)), _opposingWall.Position.Z, _opposingWall.Position.Z - 2, 3f);
}
private void RotateTowardsPlayer(float angle) => Eye.Rotation = new Vector3(Eye.Rotation.X, angle, Eye.Rotation.Z);
private void MoveWallTowardsPlayer(float moveAmount)
{
_opposingWall.Position = new Vector3(_opposingWall.Position.X, _opposingWall.Position.Y, moveAmount);
} }
public void OnExitTree() public void OnExitTree()
{ {
_attackTimer.Timeout -= AttackTimer_Timeout; _attackTimer.Timeout -= AttackTimer_Timeout;
} }
public void TakeAction()
{
EnemyModelView.Attack(_maximumWallMoveAmount);
}
public void Move(Vector3 velocity) => throw new System.NotImplementedException();
public void TakeDamage(double damage, ElementType elementType = ElementType.None, bool isCriticalHit = false, bool ignoreDefense = false, bool ignoreElementalResistance = false)
{
var damageTaken = _damageCalculator.CalculateDamage(
damage,
elementType,
_enemyStatResource.CurrentDefense,
_enemyStatResource.ElementalResistance,
isCriticalHit,
ignoreDefense,
ignoreElementalResistance);
CurrentHP.OnNext(CurrentHP.Value - damageTaken);
GD.Print($"Demon Wall HP Left: {CurrentHP.Value}");
EnemyModelView.PlayHitAnimation();
}
public void Knockback(float impulse, Vector3 direction) => throw new System.NotImplementedException();
public void SetCurrentHP(int newHP) => throw new System.NotImplementedException();
public int GetMaximumHP() => _enemyStatResource.MaximumHP;
public void StartAttackTimer() => _attackTimer.Start();
public void StopAttackTimer() => _attackTimer.Stop();
public void SetTarget(Vector3 target) => throw new System.NotImplementedException();
public void SetEnemyGlobalPosition(Vector3 target) => throw new System.NotImplementedException();
public Vector3 GetEnemyGlobalPosition() => throw new System.NotImplementedException();
public IDungeonRoom GetCurrentRoom() => throw new System.NotImplementedException();
public async void Die()
{
CurrentHP.OnCompleted();
EnemyModelView.PlayDeathAnimation();
await ToSignal(GetTree().CreateTimer(0.8f), "timeout");
CallDeferred(MethodName.QueueFree);
}
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,7 @@
using Chickensoft.AutoInject; using Chickensoft.AutoInject;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Godot; using Godot;
using System.Linq;
using Zennysoft.Ma.Adapter; using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
@@ -16,13 +17,29 @@ public partial class DemonWallArm : Node3D
private const string PARAMETERS_PLAYBACK = "parameters/playback"; private const string PARAMETERS_PLAYBACK = "parameters/playback";
private const string ATTACK = "attack"; private const string ATTACK = "attack";
[Dependency] protected IPlayer _player => this.DependOn(() => GetParent().GetChildren().OfType<IPlayer>().Single());
[Node] public AnimationTree AnimationTree { get; set; } = default!; [Node] public AnimationTree AnimationTree { get; set; } = default!;
[Export] protected EnemyStatResource _enemyStatResource { get; set; } = default!; [Node] public Area3D Hitbox { get; set; } = default!;
[Export] public double Damage { get; set; } = 15;
[Export] public ElementType PrimaryAttackElementalType { get; set; } = ElementType.None; [Export] public ElementType PrimaryAttackElementalType { get; set; } = ElementType.None;
[Export] public double PrimaryAttackElementalDamageBonus { get; set; } = 1.0f; [Export] public double PrimaryAttackElementalDamageBonus { get; set; } = 1.0f;
public void PrimaryAttack() => AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(ATTACK); public void PrimaryAttack() => AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(ATTACK);
public void OnReady()
{
Hitbox.AreaEntered += Hitbox_AreaEntered;
}
private void Hitbox_AreaEntered(Area3D area)
{
var target = area.GetOwner();
if (target is IPlayer player)
player.TakeDamage(Damage * PrimaryAttackElementalDamageBonus, PrimaryAttackElementalType, false);
}
} }

View File

@@ -0,0 +1,105 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using System.Linq;
using System.Threading.Tasks;
using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma;
[Meta(typeof(IAutoNode))]
public partial class DemonWallModelView : EnemyModelView3D
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] protected IPlayer _player => this.DependOn(() => GetParent().GetChildren().OfType<IPlayer>().Single());
[Node] public Node3D LeftArms { get; set; } = default!;
[Node] public Node3D RightArms { get; set; } = default!;
[Node] public MeshInstance3D Eye { get; set; } = default!;
[Node] private Node3D _rotation { get; set; } = default!;
[Node] private AnimatableBody3D _opposingWall { get; set; } = default!;
public void Activate()
{
_opposingWall.Show();
var collisionShape = _opposingWall.GetChildren().OfType<CollisionShape3D>().Single();
collisionShape.SetDeferred(CollisionShape3D.PropertyName.Disabled, false);
SetPhysicsProcess(true);
}
public void OnPhysicsProcess(double delta)
{
var direction = GlobalPosition.DirectionTo(_player.CurrentPosition).Normalized();
var rotationAngle = GetRotationAngle(_rotation);
RotateToPlayer(Eye, rotationAngle, 1f);
}
public void RotateToPlayer(Node3D rotateObject, float rotationAngle, float timeInSeconds)
{
var tweener = CreateTween();
tweener.TweenMethod(Callable.From((float x) => RotateTowardsPlayer(rotateObject, x)), rotateObject.Rotation.Y, rotationAngle, timeInSeconds);
}
public async void Attack(double maximumWallMoveAmount)
{
var rng = new RandomNumberGenerator();
rng.Randomize();
var leftArms = new Godot.Collections.Array<DemonWallArm>(LeftArms.GetChildren().Cast<DemonWallArm>());
var rightArms = new Godot.Collections.Array<DemonWallArm>(RightArms.GetChildren().Cast<DemonWallArm>());
var leftArm = leftArms.PickRandom();
var rightArm = rightArms.PickRandom();
leftArm.PrimaryAttack();
rightArm.PrimaryAttack();
var arm1 = GetNode<DemonWallArm>("%Arm1");
var arm2 = GetNode<DemonWallArm>("%Arm2");
var arm7 = GetNode<DemonWallArm>("%Arm2");
if (leftArm == arm1)
await AimAtPlayer(arm1, 2.1);
if (leftArm == arm2)
await AimAtPlayer(arm2, 1.5);
if (leftArm == GetNode<DemonWallArm>("%Arm3") && _opposingWall.Position.Z > -maximumWallMoveAmount)
MoveWall();
if (rightArm == arm7)
await AimAtPlayer(arm7, 2.5);
}
private async Task AimAtPlayer(DemonWallArm arm, double animationLengthInSeconds)
{
var rotationAngle = GetRotationAngle(arm.GetNode<Node3D>("%Rotation"));
RotateToPlayer(arm.GetNode<Node3D>("%Pivot"), rotationAngle, 0.3f);
await ToSignal(GetTree().CreateTimer(animationLengthInSeconds), "timeout");
RotateToPlayer(arm.GetNode<Node3D>("%Pivot"), 0, 0.3f);
}
private async void MoveWall()
{
await ToSignal(GetTree().CreateTimer(1.5f), "timeout");
var tweener = CreateTween();
tweener.TweenMethod(Callable.From((float x) => MoveWallTowardsPlayer(x)), _opposingWall.Position.Z, _opposingWall.Position.Z - 2, 3f);
}
private void MoveWallTowardsPlayer(float moveAmount)
{
_opposingWall.Position = new Vector3(_opposingWall.Position.X, _opposingWall.Position.Y, moveAmount);
}
private float GetRotationAngle(Node3D rotationNode)
{
var target = new Vector3(_player.CurrentPosition.X, Position.Y, _player.CurrentPosition.Z);
rotationNode.LookAt(target, Vector3.Up, true);
rotationNode.RotateY(Rotation.Y);
return rotationNode.Rotation.Y;
}
private void RotateTowardsPlayer(Node3D rotationNode, float angle) => rotationNode.Rotation = new Vector3(rotationNode.Rotation.X, angle, rotationNode.Rotation.Z);
}

View File

@@ -0,0 +1 @@
uid://d3cvsxlaohuqy

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
namespace Zennysoft.Game.Ma;
[Meta(typeof(IAutoNode))]
public partial class BossTypeAEnemyModelView : EnemyModelView3D
{
public override void _Notification(int what) => this.Notify(what);
[Node] public IHitbox Hitbox { get; set; } = default!;
}

View File

@@ -0,0 +1 @@
uid://bvcfww5827g74

View File

@@ -1,6 +1,7 @@
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Chickensoft.Serialization; using Chickensoft.Serialization;
using Godot; using Godot;
using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
@@ -22,21 +23,23 @@ public partial class ArmorStats : InventoryItemStats
[Export] [Export]
[Save("armor_telluric_resistance")] [Save("armor_telluric_resistance")]
public double TelluricResistance { get; set; } = 0; private double _telluricResistance { get; set; } = 0;
[Export] [Export]
[Save("armor_aeolic_resistance")] [Save("armor_aeolic_resistance")]
public double AeolicResistance { get; set; } = 0; private double _aeolicResistance { get; set; } = 0;
[Export] [Export]
[Save("armor_hydric_resistance")] [Save("armor_hydric_resistance")]
public double HydricResistance { get; set; } = 0; private double _hydricResistance { get; set; } = 0;
[Export] [Export]
[Save("armor_igneous_resistance")] [Save("armor_igneous_resistance")]
public double IgneousResistance { get; set; } = 0; private double _igneousResistance { get; set; } = 0;
[Export] [Export]
[Save("armor_ferrum_resistance")] [Save("armor_ferrum_resistance")]
public double FerrumResistance { get; set; } = 0; private double _ferrumResistance { get; set; } = 0;
public ElementalResistanceSet ElementalResistanceSet => new ElementalResistanceSet(_aeolicResistance, _hydricResistance, _igneousResistance, _ferrumResistance, _telluricResistance);
} }

View File

@@ -1946,3 +1946,4 @@ shape = SubResource("BoxShape3D_bxvob")
[node name="DemonWall" parent="." instance=ExtResource("25_k2q0o")] [node name="DemonWall" parent="." instance=ExtResource("25_k2q0o")]
unique_name_in_owner = true unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 21.2936, 55.334) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 21.2936, 55.334)
_maximumWallMoveAmount = 24.0

View File

@@ -7,7 +7,6 @@ using Godot;
using Godot.Collections; using Godot.Collections;
using SimpleInjector; using SimpleInjector;
using System; using System;
using System.Linq;
using Zennysoft.Ma.Adapter; using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
@@ -96,6 +95,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
private Dictionary<int, int> _expToNextLevel; private Dictionary<int, int> _expToNextLevel;
private IDamageCalculator _damageCalculator;
#region Initialization #region Initialization
public void Initialize() public void Initialize()
{ {
@@ -110,6 +111,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
{ 7, 417 }, { 7, 417 },
{ 8, 609 } { 8, 609 }
}; };
_damageCalculator = new DamageCalculator();
} }
public void Setup() public void Setup()
@@ -147,10 +149,14 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
PlayerLogic.Set(Stats); PlayerLogic.Set(Stats);
PlayerLogic.Set(_gameRepo); PlayerLogic.Set(_gameRepo);
var defaultWeapon = new Weapon(); var defaultWeapon = new Weapon
defaultWeapon.Stats = _defaultWeapon; {
var defaultArmor = new Armor(); Stats = _defaultWeapon
defaultArmor.Stats = _defaultArmor; };
var defaultArmor = new Armor
{
Stats = _defaultArmor
};
Inventory.TryAdd(defaultWeapon); Inventory.TryAdd(defaultWeapon);
Inventory.TryAdd(defaultArmor); Inventory.TryAdd(defaultArmor);
@@ -330,9 +336,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
{ {
if (Stats.CurrentHP.Value > 0) if (Stats.CurrentHP.Value > 0)
{ {
damage = CalculateDefenseResistance(damage); _damageCalculator.CalculateDamage(damage, elementType, Stats.CurrentDefense.Value + Stats.BonusDefense.Value, ((Armor)_equippedArmor.Value).Stats.ElementalResistanceSet);
if (isCriticalHit)
damage *= 2;
Stats.SetCurrentHP(Stats.CurrentHP.Value - (int)damage); Stats.SetCurrentHP(Stats.CurrentHP.Value - (int)damage);
} }
} }
@@ -537,11 +541,6 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
LevelUp(); LevelUp();
} }
private double CalculateDefenseResistance(double incomingDamage)
{
return Mathf.Max(incomingDamage - Stats.CurrentDefense.Value - Stats.BonusDefense.Value, 0.0);
}
private void Hitbox_AreaEntered(Area3D area) private void Hitbox_AreaEntered(Area3D area)
{ {
var target = area.GetOwner(); var target = area.GetOwner();