diff --git a/GameJamDungeon.csproj b/GameJamDungeon.csproj
index 4dc29676..f4d484c6 100644
--- a/GameJamDungeon.csproj
+++ b/GameJamDungeon.csproj
@@ -3,6 +3,10 @@
net8.0
true
+
+
+
+
diff --git a/project.godot b/project.godot
index 41441dc6..41b70bf8 100644
--- a/project.godot
+++ b/project.godot
@@ -19,7 +19,6 @@ boot_splash/show_image=false
DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
DialogueController="*res://src/game/DialogueController.cs"
-SettingsManager="*res://addons/deploy_to_steamos/SettingsManager.cs"
[dialogue_manager]
@@ -38,7 +37,7 @@ project/assembly_name="GameJamDungeon"
[editor_plugins]
-enabled=PackedStringArray("res://addons/SimpleDungeons/plugin.cfg", "res://addons/deploy_to_steamos/plugin.cfg", "res://addons/dialogue_manager/plugin.cfg")
+enabled=PackedStringArray("res://addons/SimpleDungeons/plugin.cfg", "res://addons/dialogue_manager/plugin.cfg")
[file_customization]
diff --git a/src/app/state/AppLogic.g.puml b/src/app/state/AppLogic.g.puml
index c9e48a24..885c336b 100644
--- a/src/app/state/AppLogic.g.puml
+++ b/src/app/state/AppLogic.g.puml
@@ -1,9 +1,9 @@
@startuml AppLogic
state "AppLogic State" as GameJamDungeon_AppLogic_State {
state "SetupGameScene" as GameJamDungeon_AppLogic_State_SetupGameScene
- state "MainMenu" as GameJamDungeon_AppLogic_State_MainMenu
- state "LoadingScreen" as GameJamDungeon_AppLogic_State_LoadingScreen
state "InGame" as GameJamDungeon_AppLogic_State_InGame
+ state "LoadingScreen" as GameJamDungeon_AppLogic_State_LoadingScreen
+ state "MainMenu" as GameJamDungeon_AppLogic_State_MainMenu
}
GameJamDungeon_AppLogic_State_InGame --> GameJamDungeon_AppLogic_State_MainMenu : GameOver
diff --git a/src/boss/Boss.cs b/src/boss/Boss.cs
index 00faba77..730a7f99 100644
--- a/src/boss/Boss.cs
+++ b/src/boss/Boss.cs
@@ -3,7 +3,6 @@ using Chickensoft.Collections;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
-using static System.Net.Mime.MediaTypeNames;
namespace GameJamDungeon
{
@@ -84,21 +83,21 @@ namespace GameJamDungeon
private void AttackBox_AreaEntered(Area3D area)
{
- var bossHitDamage = DamageCalculator.CalculateEnemyAttackDamage(GameRepo.PlayerData.CurrentDefense.Value + GameRepo.PlayerData.BonusDefense,
- BossResource,
- GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats,
- false);
- GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - Mathf.RoundToInt(bossHitDamage));
+ //var bossHitDamage = DamageCalculator.CalculateEnemyAttackDamage(GameRepo.PlayerData.CurrentDefense.Value + GameRepo.PlayerData.BonusDefense,
+ // BossResource,
+ // GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats,
+ // false);
+ //GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - Mathf.RoundToInt(bossHitDamage));
}
private void SecondaryAttackBox_AreaEntered(Area3D area)
{
- var bossHitDamage = DamageCalculator.CalculateEnemyAttackDamage(GameRepo.PlayerData.CurrentDefense.Value + GameRepo.PlayerData.BonusDefense,
- BossResource,
- GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats,
- false);
- var nerfDamage = bossHitDamage *= 0.25f;
- GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - Mathf.RoundToInt(nerfDamage));
+ //var bossHitDamage = DamageCalculator.CalculateEnemyAttackDamage(GameRepo.PlayerData.CurrentDefense.Value + GameRepo.PlayerData.BonusDefense,
+ // BossResource,
+ // GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats,
+ // false);
+ //var nerfDamage = bossHitDamage *= 0.25f;
+ //GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - Mathf.RoundToInt(nerfDamage));
Game.Player.ApplyCentralImpulseToPlayer(GlobalBasis.Z.Normalized());
}
@@ -118,9 +117,9 @@ namespace GameJamDungeon
var roll = rng.Randf();
if (roll <= GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.Luck)
isCriticalHit = true;
- var damage = DamageCalculator.CalculateWeaponAttackDamage(GameRepo.PlayerData.CurrentAttack.Value + GameRepo.PlayerData.BonusAttack, BossResource, GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats, isCriticalHit);
- GD.Print($"Enemy Hit for {damage} damage.");
- BossLogic.Input(new BossLogic.Input.HitByPlayer(damage));
+ //var damage = DamageCalculator.CalculateWeaponAttackDamage(GameRepo.PlayerData.CurrentAttack.Value + GameRepo.PlayerData.BonusAttack, BossResource, GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats, isCriticalHit);
+ //GD.Print($"Enemy Hit for {damage} damage.");
+ //BossLogic.Input(new BossLogic.Input.HitByPlayer(damage));
}
}
diff --git a/src/data_viewer/DataViewer.cs b/src/data_viewer/DataViewer.cs
index e8983e89..ea932851 100644
--- a/src/data_viewer/DataViewer.cs
+++ b/src/data_viewer/DataViewer.cs
@@ -56,7 +56,7 @@ public partial class DataViewer : Control
if (Input.IsActionJustPressed(GameInputs.Attack))
{
- _currentModel.PlayAttackAnimation();
+ _currentModel.PlayPrimaryAttackAnimation();
}
if (Input.IsActionJustPressed(GameInputs.Next))
{
diff --git a/src/enemy/Enemy.cs b/src/enemy/Enemy.cs
index 999ef10e..cc241e9a 100644
--- a/src/enemy/Enemy.cs
+++ b/src/enemy/Enemy.cs
@@ -10,119 +10,123 @@ public partial class Enemy : RigidBody3D, IEnemy, IProvide
{
public override void _Notification(int what) => this.Notify(what);
- public IEnemyLogic EnemyLogic { get; set; } = default!;
+ private IEnemyLogic _enemyLogic { get; set; } = default!;
- IEnemyLogic IProvide.Value() => EnemyLogic;
+ IEnemyLogic IProvide.Value() => _enemyLogic;
public EnemyLogic.IBinding EnemyBinding { get; set; } = default!;
+ #region Dependencies
+
[Dependency] IGameRepo GameRepo => this.DependOn();
[Dependency] IGameEventDepot GameEventDepot => this.DependOn();
+ #endregion
- [Export]
- public EnemyStatResource EnemyStatResource { get; set; } = default!;
+ #region Exports
+ [Export] private EnemyStatResource _enemyStatResource { get; set; } = default!;
+ #endregion
- public static PackedScene CollisionDetectorScene => GD.Load("res://src/enemy/CollisionDetector.tscn");
+ #region Node Dependencies
+ [Node] private NavigationAgent3D NavAgent { get; set; } = default!;
- public static Area3D CollisionDetector { get; set; } = default!;
+ [Node] private Area3D LineOfSight { get; set; } = default!;
- public AutoProp CurrentHP { get; set; }
+ [Node] private Timer PatrolTimer { get; set; } = default!;
- [Node] public NavigationAgent3D NavAgent { get; set; } = default!;
+ [Node] private Timer AttackTimer { get; set; } = default!;
- [Node] public Area3D LineOfSight { get; set; } = default!;
+ [Node] private RayCast3D Raycast { get; set; } = default!;
- [Node] public Timer PatrolTimer { get; set; } = default!;
+ [Node] protected EnemyModelView EnemyModelView { get; set; } = default!;
+ #endregion
- [Node] public Timer AttackTimer { get; set; } = default!;
+ public double CurrentHP => _currentHP.Value;
- [Node] public RayCast3D Raycast { get; set; } = default!;
-
- [Node] public EnemyModelView EnemyModelView { get; set; } = default!;
+ private AutoProp _currentHP { get; set; }
private float _knockbackStrength = 0.0f;
+
private Vector3 _knockbackDirection = Vector3.Zero;
public void Setup()
{
- EnemyLogic = new EnemyLogic();
- EnemyLogic.Set(EnemyStatResource);
- EnemyLogic.Set(this as IEnemy);
- EnemyLogic.Set(GameRepo);
+ _enemyLogic = new EnemyLogic();
+ _enemyLogic.Set(_enemyStatResource);
+ _enemyLogic.Set(this as IEnemy);
+ _enemyLogic.Set(GameRepo);
}
public void OnReady()
{
SetPhysicsProcess(true);
- CollisionDetector = CollisionDetectorScene.Instantiate();
- CollisionDetector.AreaEntered += OnPlayerHitboxEntered;
- AddChild(CollisionDetector);
- EnemyModelView.Hitbox.AreaEntered += Hitbox_AreaEntered;
}
- private void Hitbox_AreaEntered(Area3D area)
+ public void TakeDamage(double damage, ElementType elementType, bool isCriticalHit = false, bool ignoreDefense = false, bool ignoreElementalResistance = false)
{
- if (area.GetParent().GetParent() is IPlayer player)
+ if (_currentHP.Value > 0)
{
- var isCriticalHit = false;
- var rng = new RandomNumberGenerator();
- rng.Randomize();
- var roll = rng.Randf();
- if (roll <= EnemyStatResource.Luck)
- isCriticalHit = true;
- var damage = DamageCalculator.CalculateEnemyAttackDamage(
- GameRepo.PlayerData.CurrentDefense.Value + GameRepo.PlayerData.BonusDefense,
- EnemyStatResource,
- GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats,
- isCriticalHit);
- GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - Mathf.RoundToInt(damage));
- GD.Print($"Player hit for {damage} damage.");
+ ApplyKnockback();
+
+ if (!ignoreElementalResistance)
+ damage = CalculateElementalResistance(damage, elementType);
+ if (!ignoreDefense)
+ damage = CalculateDefenseResistance(damage);
+ if (isCriticalHit)
+ damage *= 2;
+ GD.Print($"Enemy Hit for {damage} damage.");
+ _currentHP.OnNext(_currentHP.Value - damage);
+ GD.Print("Current HP: " + _currentHP.Value);
+ EnemyModelView.PlayHitAnimation();
+ _enemyLogic.Input(new EnemyLogic.Input.Alerted());
}
}
+ public void MoveToLocation(Vector3 target, float delta)
+ {
+ NavAgent.TargetPosition = target;
+ var targetPosition = NavAgent.GetNextPathPosition();
+
+ var velocity = (targetPosition - GlobalTransform.Origin).Normalized() * 2f * delta;
+ var lookAtDir = GlobalTransform.Origin - velocity;
+ var lookAtPosition = new Vector3(lookAtDir.X, GlobalPosition.Y, lookAtDir.Z);
+ if (GlobalPosition.DistanceTo(target) > 1.0f && !velocity.IsEqualApprox(Vector3.Zero) && !GlobalPosition.IsEqualApprox(lookAtPosition))
+ LookAt(lookAtPosition);
+ EnemyModelView.RotateModel(GlobalTransform.Basis, -GameRepo.PlayerGlobalTransform.Value.Basis.Z);
+ _knockbackStrength = _knockbackStrength * 0.9f;
+ MoveAndCollide(velocity + (_knockbackDirection * _knockbackStrength));
+ }
+
+ public void Die()
+ {
+ _enemyLogic.Input(new EnemyLogic.Input.EnemyDefeated());
+ EnemyModelView.PlayDeathAnimation();
+ var tweener = GetTree().CreateTween();
+ tweener.TweenInterval(1.0f);
+ tweener.TweenCallback(Callable.From(QueueFree));
+ GameEventDepot.OnEnemyDefeated(GlobalPosition, _enemyStatResource);
+ }
+
public void OnResolved()
{
- EnemyBinding = EnemyLogic.Bind();
+ EnemyBinding = _enemyLogic.Bind();
EnemyBinding
- .Handle((in EnemyLogic.Output.MovementComputed output) =>
+ .Handle((in EnemyLogic.Output.TakeAction _) =>
{
- EnemyModelView.RotateModel(GlobalTransform.Basis, -GameRepo.PlayerGlobalTransform.Value.Basis.Z);
- _knockbackStrength = _knockbackStrength * 0.9f;
- MoveAndCollide(output.LinearVelocity + (_knockbackDirection * _knockbackStrength));
- })
- .Handle((in EnemyLogic.Output.HitByPlayer output) =>
- {
- EnemyModelView.PlayHitAnimation();
- // TODO: Make this an event to notify game that player hit someone
- if (GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponTags.Contains(WeaponTag.SelfDamage))
- GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - 5);
- if (GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponTags.Contains(WeaponTag.Knockback))
- {
- _knockbackDirection = -GameRepo.PlayerGlobalTransform.Value.Basis.Z.Normalized();
- _knockbackStrength = 0.3f;
- }
- })
- .Handle((in EnemyLogic.Output.Attack _) =>
- {
- EnemyModelView.PlayAttackAnimation();
+ TakeAction();
})
.Handle((in EnemyLogic.Output.Defeated output) =>
{
- EnemyModelView.PlayDeathAnimation();
- var tweener = GetTree().CreateTween();
- tweener.TweenInterval(1.0f);
- tweener.TweenCallback(Callable.From(QueueFree));
- GameEventDepot.OnEnemyDefeated(GlobalPosition, EnemyStatResource);
+ Die();
});
this.Provide();
- EnemyLogic.Start();
+ _enemyLogic.Start();
- CurrentHP = new AutoProp(EnemyStatResource.MaximumHP);
- CurrentHP.Sync += OnHPChanged;
+ _currentHP = new AutoProp(_enemyStatResource.MaximumHP);
+ _currentHP.Sync += OnHPChanged;
LineOfSight.BodyEntered += LineOfSight_BodyEntered;
PatrolTimer.Timeout += OnPatrolTimeout;
AttackTimer.Timeout += OnAttackTimeout;
@@ -133,7 +137,7 @@ public partial class Enemy : RigidBody3D, IEnemy, IProvide
public void OnExitTree()
{
- EnemyLogic.Stop();
+ _enemyLogic.Stop();
EnemyBinding.Dispose();
}
@@ -142,32 +146,13 @@ public partial class Enemy : RigidBody3D, IEnemy, IProvide
var rng = new RandomNumberGenerator();
rng.Randomize();
var randomizedSpot = new Vector3(rng.RandfRange(-7.0f, 7.0f), 0, rng.RandfRange(-7.0f, 7.0f));
- EnemyLogic.Input(new EnemyLogic.Input.PatrolToRandomSpot(GlobalPosition + randomizedSpot));
+ _enemyLogic.Input(new EnemyLogic.Input.PatrolToRandomSpot(GlobalPosition + randomizedSpot));
PatrolTimer.WaitTime = rng.RandfRange(5.0f, 10.0f);
}
public void OnPhysicsProcess(double delta)
{
- EnemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
- }
-
- public void OnPlayerHitboxEntered(Area3D body)
- {
- if (body is IHitbox hitBox)
- {
- if (CurrentHP.Value > 0)
- {
- var isCriticalHit = false;
- var rng = new RandomNumberGenerator();
- rng.Randomize();
- var roll = rng.Randf();
- if (roll <= GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.Luck)
- isCriticalHit = true;
- var damage = DamageCalculator.CalculateWeaponAttackDamage(GameRepo.PlayerData.CurrentAttack.Value + GameRepo.PlayerData.BonusAttack, EnemyStatResource, GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats, isCriticalHit);
- GD.Print($"Enemy Hit for {damage} damage.");
- EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(damage));
- }
- }
+ _enemyLogic.Input(new EnemyLogic.Input.PhysicsTick(delta));
}
private void OnAttackTimeout()
@@ -177,7 +162,7 @@ public partial class Enemy : RigidBody3D, IEnemy, IProvide
var rng = new RandomNumberGenerator();
rng.Randomize();
- EnemyLogic.Input(new EnemyLogic.Input.AttackTimer());
+ _enemyLogic.Input(new EnemyLogic.Input.AttackTimer());
AttackTimer.Stop();
AttackTimer.WaitTime = rng.RandfRange(2f, 5.0f);
AttackTimer.Start();
@@ -197,20 +182,49 @@ public partial class Enemy : RigidBody3D, IEnemy, IProvide
if (collider is IPlayer player)
{
Raycast.DebugShapeCustomColor = Color.FromString("Purple", Colors.Purple);
- EnemyLogic.Input(new EnemyLogic.Input.Alerted());
+ _enemyLogic.Input(new EnemyLogic.Input.Alerted());
}
}
}
}
+ private void ApplyKnockback()
+ {
+ if (GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponTags.Contains(WeaponTag.Knockback))
+ {
+ _knockbackDirection = -GameRepo.PlayerGlobalTransform.Value.Basis.Z.Normalized();
+ _knockbackStrength = 0.3f;
+ }
+ }
+
private void OnHPChanged(double newHP)
{
if (newHP <= 0)
- EnemyLogic.Input(new EnemyLogic.Input.EnemyDefeated());
+ Die();
}
- private void DoNothing()
+ 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)
+ {
+ return Mathf.Max(incomingDamage - _enemyStatResource.CurrentDefense, 0.0);
+ }
+
+ public virtual void TakeAction()
+ {
}
}
diff --git a/src/enemy/EnemyModelView.cs b/src/enemy/EnemyModelView.cs
index d8b260e5..26c8bccd 100644
--- a/src/enemy/EnemyModelView.cs
+++ b/src/enemy/EnemyModelView.cs
@@ -6,7 +6,11 @@ using Godot;
public interface IEnemyModelView : INode3D
{
- public void PlayAttackAnimation();
+ public void PlayPrimaryAttackAnimation();
+
+ public void PlaySecondaryAttackAnimation();
+
+ public void PlayPrimarySkillAnimation();
public void PlayHitAnimation();
public void PlayDeathAnimation();
@@ -19,7 +23,9 @@ public interface IEnemyModelView : INode3D
[Meta(typeof(IAutoNode))]
public partial class EnemyModelView : Node3D, IEnemyModelView
{
- private const string ATTACK = "attack";
+ private const string PRIMARY_ATTACK = "primary_attack";
+ private const string SECONDARY_ATTACK = "secondary_attack";
+ private const string PRIMARY_SKILL = "primary_skill";
private const string IDLE_FORWARD = "idle_front_walk";
private const string IDLE_LEFT = "idle_left_walk";
private const string IDLE_BACK = "idle_back_walk";
@@ -43,9 +49,19 @@ public partial class EnemyModelView : Node3D, IEnemyModelView
AnimationTree.Get(PARAMETERS_PLAYBACK).As().Start(IDLE_FORWARD);
}
- public void PlayAttackAnimation()
+ public void PlayPrimaryAttackAnimation()
{
- AnimationTree.Get(PARAMETERS_PLAYBACK).As().Travel(ATTACK);
+ AnimationTree.Get(PARAMETERS_PLAYBACK).As().Travel(PRIMARY_ATTACK);
+ }
+
+ public void PlaySecondaryAttackAnimation()
+ {
+ AnimationTree.Get(PARAMETERS_PLAYBACK).As().Travel(SECONDARY_ATTACK);
+ }
+
+ public void PlayPrimarySkillAnimation()
+ {
+ AnimationTree.Get(PARAMETERS_PLAYBACK).As().Travel(PRIMARY_SKILL);
}
public void PlayHitAnimation()
diff --git a/src/enemy/EnemyStatResource.cs b/src/enemy/EnemyStatResource.cs
index 82c26f82..77fb8456 100644
--- a/src/enemy/EnemyStatResource.cs
+++ b/src/enemy/EnemyStatResource.cs
@@ -45,19 +45,10 @@ namespace GameJamDungeon
public double FerrumResistance { get; set; }
[Export]
- public double TelluricDamageBonus { get; set; }
+ public ElementType SecondaryAttackElementalType { get; set; }
[Export]
- public double AeolicDamageBonus { get; set; }
-
- [Export]
- public double BaseHydricDamageBonus { get; set; }
-
- [Export]
- public double IgneousDamageBonus { get; set; }
-
- [Export]
- public double FerrumDamageBonus { get; set; }
+ public double SecondaryAttackElementalDamageBonus { get; set; } = 1.0;
[Export]
public float DropsSoulGemChance { get; set; } = 0.75f;
diff --git a/src/enemy/IEnemy.cs b/src/enemy/IEnemy.cs
index e600990e..cf961f74 100644
--- a/src/enemy/IEnemy.cs
+++ b/src/enemy/IEnemy.cs
@@ -1,20 +1,16 @@
-using Chickensoft.Collections;
-using Chickensoft.GodotNodeInterfaces;
-using Godot;
+using Godot;
namespace GameJamDungeon;
-public interface IEnemy : IRigidBody3D
+public interface IEnemy
{
- public IEnemyLogic EnemyLogic { get; }
+ public void TakeAction();
- public AutoProp CurrentHP { get; set; }
+ public void TakeDamage(double damage, ElementType elementType, bool isCriticalHit = false, bool ignoreDefense = false, bool ignoreElementalResistance = false);
- public EnemyStatResource EnemyStatResource { get; set; }
+ public void MoveToLocation(Vector3 target, float delta);
- public NavigationAgent3D NavAgent { get; set; }
+ public void Die();
- public Area3D LineOfSight { get; set; }
-
- public Timer AttackTimer { get; set; }
+ public double CurrentHP { get; }
}
diff --git a/src/enemy/enemy_types/chariot/Chariot.cs b/src/enemy/enemy_types/chariot/Chariot.cs
new file mode 100644
index 00000000..84106377
--- /dev/null
+++ b/src/enemy/enemy_types/chariot/Chariot.cs
@@ -0,0 +1,23 @@
+using Chickensoft.AutoInject;
+using Chickensoft.Introspection;
+using Godot;
+
+namespace GameJamDungeon;
+
+[Meta(typeof(IAutoNode))]
+public partial class Chariot : Enemy, IHasPrimaryAttack
+{
+ [Export]
+ public ElementType PrimaryAttackElementalType { get; set; } = ElementType.None;
+ [Export]
+ public double PrimaryAttackElementalDamageBonus { get; set; } = 1.0;
+
+ public override void TakeAction()
+ {
+ PrimaryAttack();
+ }
+ public void PrimaryAttack()
+ {
+ EnemyModelView.PlayPrimaryAttackAnimation();
+ }
+}
\ No newline at end of file
diff --git a/src/enemy/enemy_types/chariot/Chariot.tscn b/src/enemy/enemy_types/chariot/Chariot.tscn
index 00c86755..33dfedb4 100644
--- a/src/enemy/enemy_types/chariot/Chariot.tscn
+++ b/src/enemy/enemy_types/chariot/Chariot.tscn
@@ -1,8 +1,8 @@
[gd_scene load_steps=137 format=3 uid="uid://dlw5cvutvypxn"]
-[ext_resource type="Script" path="res://src/enemy/Enemy.cs" id="1_t62lw"]
-[ext_resource type="Script" path="res://src/enemy/EnemyStatResource.cs" id="2_77bk6"]
-[ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="3_lg405"]
+[ext_resource type="Script" path="res://src/enemy/enemy_types/chariot/Chariot.cs" id="1_hqeyd"]
+[ext_resource type="Script" uid="uid://dnkmr0eq1sij0" path="res://src/enemy/EnemyStatResource.cs" id="2_77bk6"]
+[ext_resource type="Script" uid="uid://6edayafleq8y" path="res://src/hitbox/Hitbox.cs" id="3_lg405"]
[ext_resource type="Texture2D" uid="uid://c6fvuw1escea1" path="res://src/enemy/enemy_types/chariot/animations/Chariot Back Walk/Layer 1.png" id="4_fokm1"]
[ext_resource type="Texture2D" uid="uid://drjnht11skb0l" path="res://src/enemy/enemy_types/chariot/animations/Chariot Front Walk/Layer 1.png" id="4_tav2y"]
[ext_resource type="Texture2D" uid="uid://yl1m0fik4fab" path="res://src/enemy/enemy_types/chariot/animations/Chariot Back Walk/Layer 2.png" id="5_gp46b"]
@@ -106,26 +106,25 @@
[ext_resource type="Texture2D" uid="uid://b1qg8g32xpddx" path="res://src/enemy/enemy_types/chariot/animations/2nd Sprite Fabrics/2nd Sprite Fabrics/Layer 63.png" id="104_1k5tm"]
[ext_resource type="Texture2D" uid="uid://upyfmmm6ksmo" path="res://src/enemy/enemy_types/chariot/animations/2nd Sprite Fabrics/2nd Sprite Fabrics/Layer 50.png" id="105_s26ni"]
-[sub_resource type="Resource" id="Resource_rxw8v"]
+[sub_resource type="Resource" id="Resource_dvne1"]
script = ExtResource("2_77bk6")
-CurrentHP = 45.0
-MaximumHP = 45.0
-CurrentAttack = 20
-CurrentDefense = 10
-MaxAttack = 20
-MaxDefense = 10
+CurrentHP = 50.0
+MaximumHP = 50.0
+CurrentAttack = 5
+CurrentDefense = 5
+MaxAttack = 5
+MaxDefense = 5
+ExpFromDefeat = 15
Luck = 0.05
TelluricResistance = 0.0
AeolicResistance = 0.0
HydricResistance = 0.0
IgneousResistance = 0.0
FerrumResistance = 0.0
-TelluricDamageBonus = 0.0
-AeolicDamageBonus = 0.0
-BaseHydricDamageBonus = 0.0
-IgneousDamageBonus = 0.0
-FerrumDamageBonus = 0.0
-DropsSoulGemChance = 0.9
+SecondaryAttackElementalType = 0
+SecondaryAttackElementalDamageBonus = 1.0
+DropsSoulGemChance = 0.75
+metadata/_custom_type_script = ExtResource("2_77bk6")
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cwfph"]
radius = 1.0
@@ -492,23 +491,6 @@ tracks/0/keys = {
"values": [true]
}
-[sub_resource type="Animation" id="Animation_ruc6s"]
-resource_name = "attack"
-length = 0.750008
-step = 0.0833333
-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, 0.25, 0.666666),
-"transitions": PackedFloat32Array(1, 1, 1),
-"update": 1,
-"values": [true, false, true]
-}
-
[sub_resource type="Animation" id="Animation_1tda5"]
resource_name = "idle_back_walk"
length = 1.25001
@@ -527,17 +509,31 @@ length = 1.25001
loop_mode = 1
step = 0.0833333
-[sub_resource type="AnimationLibrary" id="AnimationLibrary_6tj5r"]
-_data = {
-"RESET": SubResource("Animation_ch8ic"),
-"attack": SubResource("Animation_ruc6s"),
-"idle_back_walk": SubResource("Animation_1tda5"),
-"idle_front_walk": SubResource("Animation_31nry"),
-"idle_left_walk": SubResource("Animation_1870e")
+[sub_resource type="Animation" id="Animation_ruc6s"]
+resource_name = "attack"
+length = 0.750008
+step = 0.0833333
+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, 0.25, 0.666666),
+"transitions": PackedFloat32Array(1, 1, 1),
+"update": 1,
+"values": [true, false, true]
}
-[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_erbrx"]
-animation = &"attack"
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_6tj5r"]
+_data = {
+&"RESET": SubResource("Animation_ch8ic"),
+&"idle_back_walk": SubResource("Animation_1tda5"),
+&"idle_front_walk": SubResource("Animation_31nry"),
+&"idle_left_walk": SubResource("Animation_1870e"),
+&"primary_attack": SubResource("Animation_ruc6s")
+}
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_o0tmb"]
animation = &"idle_back_walk"
@@ -548,6 +544,9 @@ animation = &"idle_front_walk"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_dvj10"]
animation = &"idle_left_walk"
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_erbrx"]
+animation = &"attack"
+
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_vljb2"]
advance_mode = 2
@@ -588,15 +587,15 @@ switch_mode = 2
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_acrfn"]
states/End/position = Vector2(1464, 100)
-states/attack/node = SubResource("AnimationNodeAnimation_erbrx")
-states/attack/position = Vector2(1024, 92.9474)
states/idle_back_walk/node = SubResource("AnimationNodeAnimation_o0tmb")
states/idle_back_walk/position = Vector2(491, 92.9474)
states/idle_front_walk/node = SubResource("AnimationNodeAnimation_a6s5c")
states/idle_front_walk/position = Vector2(331, -12)
states/idle_left_walk/node = SubResource("AnimationNodeAnimation_dvj10")
states/idle_left_walk/position = Vector2(331, 196.947)
-transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")]
+states/primary_attack/node = SubResource("AnimationNodeAnimation_erbrx")
+states/primary_attack/position = Vector2(1024, 92.9474)
+transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "primary_attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "primary_attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "primary_attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")]
graph_offset = Vector2(-190, -62.0526)
[node name="Chariot" type="RigidBody3D"]
@@ -608,8 +607,8 @@ axis_lock_linear_y = true
axis_lock_angular_x = true
contact_monitor = true
max_contacts_reported = 1
-script = ExtResource("1_t62lw")
-EnemyStatResource = SubResource("Resource_rxw8v")
+script = ExtResource("1_hqeyd")
+_enemyStatResource = SubResource("Resource_dvne1")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
@@ -690,7 +689,7 @@ offset = Vector2(250, 250)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true
libraries = {
-"": SubResource("AnimationLibrary_6tj5r")
+&"": SubResource("AnimationLibrary_6tj5r")
}
[node name="AnimationTree" type="AnimationTree" parent="."]
diff --git a/src/enemy/enemy_types/filth_eater/FilthEater.cs b/src/enemy/enemy_types/filth_eater/FilthEater.cs
new file mode 100644
index 00000000..e80091ec
--- /dev/null
+++ b/src/enemy/enemy_types/filth_eater/FilthEater.cs
@@ -0,0 +1,38 @@
+using Chickensoft.AutoInject;
+using Chickensoft.Introspection;
+using Godot;
+using System;
+using System.Collections.Generic;
+
+namespace GameJamDungeon;
+
+[Meta(typeof(IAutoNode))]
+public partial class FilthEater : Enemy, IHasPrimaryAttack, IHasSecondaryAttack
+{
+ [Export]
+ public ElementType PrimaryAttackElementalType { get; set; } = ElementType.None;
+ [Export]
+ public double PrimaryAttackElementalDamageBonus { get; set; } = 1.0;
+
+ [Export]
+ public ElementType SecondaryAttackElementalType { get; set; } = ElementType.None;
+ [Export]
+ public double SecondaryAttackElementalDamageBonus { get; set; } = 1.0;
+
+ public override void TakeAction()
+ {
+ var rng = new RandomNumberGenerator();
+ var options = new List() { PrimaryAttack, SecondaryAttack };
+ var selection = rng.RandWeighted([0.875f, 0.125f]);
+ options[(int)selection].Invoke();
+ }
+ public void PrimaryAttack()
+ {
+ EnemyModelView.PlayPrimaryAttackAnimation();
+ }
+
+ public void SecondaryAttack()
+ {
+ EnemyModelView.PlaySecondaryAttackAnimation();
+ }
+}
\ No newline at end of file
diff --git a/src/enemy/enemy_types/filth_eater/FilthEater.tscn b/src/enemy/enemy_types/filth_eater/FilthEater.tscn
index 9ed597db..fba3a108 100644
--- a/src/enemy/enemy_types/filth_eater/FilthEater.tscn
+++ b/src/enemy/enemy_types/filth_eater/FilthEater.tscn
@@ -1,8 +1,8 @@
-[gd_scene load_steps=120 format=3 uid="uid://cvk007twac22c"]
+[gd_scene load_steps=127 format=3 uid="uid://cvk007twac22c"]
-[ext_resource type="Script" path="res://src/enemy/Enemy.cs" id="1_a8er3"]
-[ext_resource type="Script" path="res://src/enemy/EnemyStatResource.cs" id="2_mqiog"]
-[ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="3_ipypc"]
+[ext_resource type="Script" path="res://src/enemy/enemy_types/filth_eater/FilthEater.cs" id="1_fyc13"]
+[ext_resource type="Script" uid="uid://dnkmr0eq1sij0" path="res://src/enemy/EnemyStatResource.cs" id="2_mqiog"]
+[ext_resource type="Script" uid="uid://6edayafleq8y" path="res://src/hitbox/Hitbox.cs" id="3_ipypc"]
[ext_resource type="Texture2D" uid="uid://cx1wk7n77hdpu" path="res://src/enemy/enemy_types/filth_eater/animations/WALK BACK/Layer 1.png" id="4_ag3g0"]
[ext_resource type="Texture2D" uid="uid://bv4du7bb3m6ug" path="res://src/enemy/enemy_types/filth_eater/animations/SWIPE/Layer 1.png" id="4_qpdqy"]
[ext_resource type="Texture2D" uid="uid://bdl6xn7wskn2r" path="res://src/enemy/enemy_types/filth_eater/animations/WALK BACK/Layer 2.png" id="5_881nf"]
@@ -89,26 +89,27 @@
[ext_resource type="Texture2D" uid="uid://d32ej6fsx53io" path="res://src/enemy/enemy_types/filth_eater/animations/TELLERIC ATTACK/Layer 39.png" id="57_o526l"]
[ext_resource type="Texture2D" uid="uid://cy5dacfrmsxwe" path="res://src/enemy/enemy_types/filth_eater/animations/TELLERIC ATTACK/Layer 40.png" id="58_4tgv5"]
-[sub_resource type="Resource" id="Resource_rxw8v"]
+[sub_resource type="Resource" id="Resource_0y048"]
script = ExtResource("2_mqiog")
-CurrentHP = 45.0
-MaximumHP = 45.0
-CurrentAttack = 20
-CurrentDefense = 10
-MaxAttack = 20
-MaxDefense = 10
+CurrentHP = 50.0
+MaximumHP = 50.0
+CurrentAttack = 5
+CurrentDefense = 5
+MaxAttack = 5
+MaxDefense = 5
+ExpFromDefeat = 15
Luck = 0.05
TelluricResistance = 0.0
AeolicResistance = 0.0
HydricResistance = 0.0
IgneousResistance = 0.0
FerrumResistance = 0.0
-TelluricDamageBonus = 0.0
-AeolicDamageBonus = 0.0
-BaseHydricDamageBonus = 0.0
-IgneousDamageBonus = 0.0
-FerrumDamageBonus = 0.0
-DropsSoulGemChance = 0.9
+PrimaryAttackElementalType = 0
+PrimaryAttackElementalDamageBonus = 1.0
+SecondaryAttackElementalType = 2
+SecondaryAttackElementalDamageBonus = 1.15
+DropsSoulGemChance = 0.75
+metadata/_custom_type_script = ExtResource("2_mqiog")
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cwfph"]
radius = 1.0
@@ -445,6 +446,24 @@ tracks/2/keys = {
"values": [0]
}
+[sub_resource type="Animation" id="Animation_1tda5"]
+resource_name = "idle_back_walk"
+length = 1.25001
+loop_mode = 1
+step = 0.0833333
+
+[sub_resource type="Animation" id="Animation_31nry"]
+resource_name = "idle_front_walk"
+length = 1.25001
+loop_mode = 1
+step = 0.0833333
+
+[sub_resource type="Animation" id="Animation_1870e"]
+resource_name = "idle_left_walk"
+length = 1.25001
+loop_mode = 1
+step = 0.0833333
+
[sub_resource type="Animation" id="Animation_ruc6s"]
resource_name = "attack"
length = 0.750008
@@ -490,37 +509,16 @@ tracks/1/keys = {
"values": [0]
}
-[sub_resource type="Animation" id="Animation_1tda5"]
-resource_name = "idle_back_walk"
-length = 1.25001
-loop_mode = 1
-step = 0.0833333
-
-[sub_resource type="Animation" id="Animation_31nry"]
-resource_name = "idle_front_walk"
-length = 1.25001
-loop_mode = 1
-step = 0.0833333
-
-[sub_resource type="Animation" id="Animation_1870e"]
-resource_name = "idle_left_walk"
-length = 1.25001
-loop_mode = 1
-step = 0.0833333
-
[sub_resource type="AnimationLibrary" id="AnimationLibrary_6tj5r"]
_data = {
-"RESET": SubResource("Animation_ch8ic"),
-"attack": SubResource("Animation_ruc6s"),
-"attack2": SubResource("Animation_wwl4v"),
-"idle_back_walk": SubResource("Animation_1tda5"),
-"idle_front_walk": SubResource("Animation_31nry"),
-"idle_left_walk": SubResource("Animation_1870e")
+&"RESET": SubResource("Animation_ch8ic"),
+&"idle_back_walk": SubResource("Animation_1tda5"),
+&"idle_front_walk": SubResource("Animation_31nry"),
+&"idle_left_walk": SubResource("Animation_1870e"),
+&"primary_attack": SubResource("Animation_ruc6s"),
+&"secondary_attack": SubResource("Animation_wwl4v")
}
-[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_erbrx"]
-animation = &"attack"
-
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_o0tmb"]
animation = &"idle_back_walk"
@@ -530,6 +528,12 @@ animation = &"idle_front_walk"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_dvj10"]
animation = &"idle_left_walk"
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_erbrx"]
+animation = &"primary_attack"
+
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_fyc13"]
+animation = &"secondary_attack"
+
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_vljb2"]
advance_mode = 2
@@ -568,17 +572,37 @@ switch_mode = 2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_mxl7w"]
switch_mode = 2
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_0y048"]
+switch_mode = 2
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_uhpql"]
+switch_mode = 2
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_l7m4y"]
+switch_mode = 2
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_464kr"]
+switch_mode = 2
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_45of7"]
+switch_mode = 2
+
+[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_c482n"]
+switch_mode = 2
+
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_acrfn"]
states/End/position = Vector2(1464, 100)
-states/attack/node = SubResource("AnimationNodeAnimation_erbrx")
-states/attack/position = Vector2(1024, 92.9474)
states/idle_back_walk/node = SubResource("AnimationNodeAnimation_o0tmb")
-states/idle_back_walk/position = Vector2(491, 92.9474)
+states/idle_back_walk/position = Vector2(519, 75.9474)
states/idle_front_walk/node = SubResource("AnimationNodeAnimation_a6s5c")
states/idle_front_walk/position = Vector2(331, -12)
states/idle_left_walk/node = SubResource("AnimationNodeAnimation_dvj10")
states/idle_left_walk/position = Vector2(331, 196.947)
-transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")]
+states/primary_attack/node = SubResource("AnimationNodeAnimation_erbrx")
+states/primary_attack/position = Vector2(1067, 33.9474)
+states/secondary_attack/node = SubResource("AnimationNodeAnimation_fyc13")
+states/secondary_attack/position = Vector2(1057, 151.947)
+transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "primary_attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "primary_attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "primary_attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_mxl7w"), "idle_back_walk", "secondary_attack", SubResource("AnimationNodeStateMachineTransition_0y048"), "idle_left_walk", "secondary_attack", SubResource("AnimationNodeStateMachineTransition_uhpql"), "idle_front_walk", "secondary_attack", SubResource("AnimationNodeStateMachineTransition_l7m4y"), "secondary_attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_464kr"), "secondary_attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_45of7"), "secondary_attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_c482n")]
graph_offset = Vector2(-121, -17.0526)
[node name="FilthEater" type="RigidBody3D"]
@@ -590,8 +614,8 @@ axis_lock_linear_y = true
axis_lock_angular_x = true
contact_monitor = true
max_contacts_reported = 1
-script = ExtResource("1_a8er3")
-EnemyStatResource = SubResource("Resource_rxw8v")
+script = ExtResource("1_fyc13")
+_enemyStatResource = SubResource("Resource_0y048")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
@@ -662,7 +686,7 @@ offset = Vector2(150, 150)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true
libraries = {
-"": SubResource("AnimationLibrary_6tj5r")
+&"": SubResource("AnimationLibrary_6tj5r")
}
[node name="AnimationTree" type="AnimationTree" parent="."]
diff --git a/src/enemy/enemy_types/michael/Michael.cs b/src/enemy/enemy_types/michael/Michael.cs
new file mode 100644
index 00000000..150829d9
--- /dev/null
+++ b/src/enemy/enemy_types/michael/Michael.cs
@@ -0,0 +1,23 @@
+using Chickensoft.AutoInject;
+using Chickensoft.Introspection;
+using Godot;
+
+namespace GameJamDungeon;
+
+[Meta(typeof(IAutoNode))]
+public partial class Michael : Enemy, IHasPrimaryAttack
+{
+ [Export]
+ public ElementType PrimaryAttackElementalType { get; set; } = ElementType.None;
+ [Export]
+ public double PrimaryAttackElementalDamageBonus { get; set; } = 1.0;
+
+ public override void TakeAction()
+ {
+ PrimaryAttack();
+ }
+ public void PrimaryAttack()
+ {
+ EnemyModelView.PlayPrimaryAttackAnimation();
+ }
+}
\ No newline at end of file
diff --git a/src/enemy/enemy_types/michael/Michael.tscn b/src/enemy/enemy_types/michael/Michael.tscn
index a2196e64..09c24be9 100644
--- a/src/enemy/enemy_types/michael/Michael.tscn
+++ b/src/enemy/enemy_types/michael/Michael.tscn
@@ -1,31 +1,8 @@
-[gd_scene load_steps=7 format=3 uid="uid://b0gwivt7cw7nd"]
+[gd_scene load_steps=5 format=3 uid="uid://b0gwivt7cw7nd"]
-[ext_resource type="Script" uid="uid://2d34jler3rmv" path="res://src/enemy/Enemy.cs" id="1_a6wro"]
-[ext_resource type="Script" uid="uid://dnkmr0eq1sij0" path="res://src/enemy/EnemyStatResource.cs" id="2_x4pjh"]
+[ext_resource type="Script" path="res://src/enemy/enemy_types/michael/Michael.cs" id="1_wfjxm"]
[ext_resource type="PackedScene" uid="uid://bjg8wyvp8q6oc" path="res://src/enemy/enemy_types/michael/MichaelModelView.tscn" id="3_wrps7"]
-[sub_resource type="Resource" id="Resource_k2g1o"]
-script = ExtResource("2_x4pjh")
-CurrentHP = 45.0
-MaximumHP = 45.0
-CurrentAttack = 20
-CurrentDefense = 11
-MaxAttack = 20
-MaxDefense = 11
-ExpFromDefeat = 10
-Luck = 0.05
-TelluricResistance = 0.0
-AeolicResistance = 0.0
-HydricResistance = 0.0
-IgneousResistance = 0.0
-FerrumResistance = 0.0
-TelluricDamageBonus = 0.0
-AeolicDamageBonus = 0.0
-BaseHydricDamageBonus = 0.0
-IgneousDamageBonus = 0.0
-FerrumDamageBonus = 0.0
-DropsSoulGemChance = 0.75
-
[sub_resource type="CylinderShape3D" id="CylinderShape3D_jbgmx"]
height = 5.0
radius = 1.0
@@ -40,8 +17,7 @@ collision_layer = 10
collision_mask = 11
axis_lock_linear_y = true
axis_lock_angular_x = true
-script = ExtResource("1_a6wro")
-EnemyStatResource = SubResource("Resource_k2g1o")
+script = ExtResource("1_wfjxm")
[node name="LineOfSight" type="Area3D" parent="."]
unique_name_in_owner = true
diff --git a/src/enemy/enemy_types/michael/MichaelModelView.tscn b/src/enemy/enemy_types/michael/MichaelModelView.tscn
index 47e3bace..bc847104 100644
--- a/src/enemy/enemy_types/michael/MichaelModelView.tscn
+++ b/src/enemy/enemy_types/michael/MichaelModelView.tscn
@@ -1,6 +1,6 @@
[gd_scene load_steps=101 format=3 uid="uid://bjg8wyvp8q6oc"]
-[ext_resource type="Script" path="res://src/enemy/EnemyModelView.cs" id="1_iajg3"]
+[ext_resource type="Script" uid="uid://chymnqdw7hibn" path="res://src/enemy/EnemyModelView.cs" id="1_iajg3"]
[ext_resource type="Texture2D" uid="uid://clpqh2pyqljkn" path="res://src/enemy/enemy_types/michael/animations/IDLE_WALK/BACK/Michael_Walk_Idle_Back (1).png" id="2_3g180"]
[ext_resource type="Resource" uid="uid://6d7ivtna8dqb" path="res://src/enemy/enemy_types/michael/MichaelLoreInfo.tres" id="2_fssmb"]
[ext_resource type="Texture2D" uid="uid://b0dec8ak2bo5t" path="res://src/enemy/enemy_types/michael/animations/IDLE_WALK/BACK/Michael_Walk_Idle_Back (2).png" id="3_fssmb"]
@@ -71,7 +71,7 @@
[ext_resource type="Texture2D" uid="uid://vxphbifafq0q" path="res://src/enemy/enemy_types/michael/animations/IDLE_WALK/LEFT SIDE/Michael_IdleWalk_Left (21).png" id="68_msiau"]
[ext_resource type="Texture2D" uid="uid://7r30bjydumon" path="res://src/enemy/enemy_types/michael/animations/IDLE_WALK/LEFT SIDE/Michael_IdleWalk_Left (22).png" id="69_lec8c"]
[ext_resource type="Texture2D" uid="uid://djspx2smexhme" path="res://src/enemy/enemy_types/michael/animations/IDLE_WALK/LEFT SIDE/Michael_IdleWalk_Left (23).png" id="70_f0jo7"]
-[ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="71_ul4dn"]
+[ext_resource type="Script" uid="uid://6edayafleq8y" path="res://src/hitbox/Hitbox.cs" id="71_ul4dn"]
[sub_resource type="ViewportTexture" id="ViewportTexture_v7t0v"]
viewport_path = NodePath("Sprite/SubViewport")
@@ -345,47 +345,6 @@ tracks/2/keys = {
"values": [&"idle_front_walk"]
}
-[sub_resource type="Animation" id="Animation_0k3e8"]
-resource_name = "attack"
-length = 0.416668
-step = 0.0166667
-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, 0.0333333, 0.3),
-"transitions": PackedFloat32Array(1, 1, 1),
-"update": 1,
-"values": [true, false, true]
-}
-tracks/1/type = "value"
-tracks/1/imported = false
-tracks/1/enabled = true
-tracks/1/path = NodePath("Sprite/SubViewport/AnimatedSprite:animation")
-tracks/1/interp = 1
-tracks/1/loop_wrap = true
-tracks/1/keys = {
-"times": PackedFloat32Array(0),
-"transitions": PackedFloat32Array(1),
-"update": 1,
-"values": [&"idle_front_walk"]
-}
-tracks/2/type = "value"
-tracks/2/imported = false
-tracks/2/enabled = true
-tracks/2/path = NodePath("Sprite/SubViewport/AnimatedSprite:frame")
-tracks/2/interp = 1
-tracks/2/loop_wrap = true
-tracks/2/keys = {
-"times": PackedFloat32Array(0, 0.0166667, 0.0333334, 0.0500001, 0.0666668, 0.0833335, 0.1, 0.116667, 0.133334, 0.15, 0.166667, 0.183334, 0.2, 0.216667, 0.233334, 0.25, 0.266667, 0.283334, 0.300001, 0.316667, 0.333334, 0.350001, 0.366667),
-"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
-"update": 1,
-"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
-}
-
[sub_resource type="Animation" id="Animation_ppbeh"]
resource_name = "idle_back_walk"
length = 1.91667
@@ -476,18 +435,56 @@ tracks/1/keys = {
"values": [&"idle_left_walk"]
}
+[sub_resource type="Animation" id="Animation_0k3e8"]
+resource_name = "attack"
+length = 0.416668
+step = 0.0166667
+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, 0.0333333, 0.3),
+"transitions": PackedFloat32Array(1, 1, 1),
+"update": 1,
+"values": [true, false, true]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Sprite/SubViewport/AnimatedSprite:animation")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [&"idle_front_walk"]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("Sprite/SubViewport/AnimatedSprite:frame")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0, 0.0166667, 0.0333334, 0.0500001, 0.0666668, 0.0833335, 0.1, 0.116667, 0.133334, 0.15, 0.166667, 0.183334, 0.2, 0.216667, 0.233334, 0.25, 0.266667, 0.283334, 0.300001, 0.316667, 0.333334, 0.350001, 0.366667),
+"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+"update": 1,
+"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
+}
+
[sub_resource type="AnimationLibrary" id="AnimationLibrary_346xs"]
_data = {
&"RESET": SubResource("Animation_41ppy"),
-&"attack": SubResource("Animation_0k3e8"),
&"idle_back_walk": SubResource("Animation_ppbeh"),
&"idle_front_walk": SubResource("Animation_3dffb"),
-&"idle_left_walk": SubResource("Animation_0qxqf")
+&"idle_left_walk": SubResource("Animation_0qxqf"),
+&"primary_attack": SubResource("Animation_0k3e8")
}
-[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_erbrx"]
-animation = &"attack"
-
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_o0tmb"]
animation = &"idle_back_walk"
@@ -497,6 +494,9 @@ animation = &"idle_front_walk"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_dvj10"]
animation = &"idle_left_walk"
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_erbrx"]
+animation = &"primary_attack"
+
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_vljb2"]
advance_mode = 2
@@ -537,15 +537,15 @@ switch_mode = 2
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_r23qr"]
states/End/position = Vector2(1464, 100)
-states/attack/node = SubResource("AnimationNodeAnimation_erbrx")
-states/attack/position = Vector2(1151, 86.9474)
states/idle_back_walk/node = SubResource("AnimationNodeAnimation_o0tmb")
states/idle_back_walk/position = Vector2(490, 92.9474)
states/idle_front_walk/node = SubResource("AnimationNodeAnimation_a6s5c")
states/idle_front_walk/position = Vector2(331, -12)
states/idle_left_walk/node = SubResource("AnimationNodeAnimation_dvj10")
states/idle_left_walk/position = Vector2(331, 196.947)
-transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")]
+states/primary_attack/node = SubResource("AnimationNodeAnimation_erbrx")
+states/primary_attack/position = Vector2(1151, 86.9474)
+transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "primary_attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "primary_attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "primary_attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")]
graph_offset = Vector2(-190, -62.0526)
[node name="EnemyModelView" type="Node3D"]
diff --git a/src/enemy/enemy_types/sproingy/Sproingy.cs b/src/enemy/enemy_types/sproingy/Sproingy.cs
new file mode 100644
index 00000000..6d2e1ef9
--- /dev/null
+++ b/src/enemy/enemy_types/sproingy/Sproingy.cs
@@ -0,0 +1,23 @@
+using Chickensoft.AutoInject;
+using Chickensoft.Introspection;
+using Godot;
+
+namespace GameJamDungeon;
+
+[Meta(typeof(IAutoNode))]
+public partial class Sproingy : Enemy, IHasPrimaryAttack
+{
+ [Export]
+ public ElementType PrimaryAttackElementalType { get; set; } = ElementType.None;
+ [Export]
+ public double PrimaryAttackElementalDamageBonus { get; set; } = 1.0;
+
+ public override void TakeAction()
+ {
+ PrimaryAttack();
+ }
+ public void PrimaryAttack()
+ {
+ EnemyModelView.PlayPrimaryAttackAnimation();
+ }
+}
\ No newline at end of file
diff --git a/src/enemy/enemy_types/sproingy/Sproingy.tscn b/src/enemy/enemy_types/sproingy/Sproingy.tscn
index a85df759..cf6f7ccd 100644
--- a/src/enemy/enemy_types/sproingy/Sproingy.tscn
+++ b/src/enemy/enemy_types/sproingy/Sproingy.tscn
@@ -1,31 +1,8 @@
-[gd_scene load_steps=7 format=3 uid="uid://bksq62muhk3h5"]
+[gd_scene load_steps=5 format=3 uid="uid://bksq62muhk3h5"]
-[ext_resource type="Script" uid="uid://2d34jler3rmv" path="res://src/enemy/Enemy.cs" id="1_7tinp"]
-[ext_resource type="Script" uid="uid://dnkmr0eq1sij0" path="res://src/enemy/EnemyStatResource.cs" id="2_j3knd"]
+[ext_resource type="Script" path="res://src/enemy/enemy_types/sproingy/Sproingy.cs" id="1_ldo22"]
[ext_resource type="PackedScene" uid="uid://bli0t0d6ommvi" path="res://src/enemy/enemy_types/sproingy/SproingyModelView.tscn" id="4_o3b7p"]
-[sub_resource type="Resource" id="Resource_rxw8v"]
-script = ExtResource("2_j3knd")
-CurrentHP = 45.0
-MaximumHP = 45.0
-CurrentAttack = 20
-CurrentDefense = 10
-MaxAttack = 20
-MaxDefense = 10
-ExpFromDefeat = 8
-Luck = 0.05
-TelluricResistance = 0.0
-AeolicResistance = 0.0
-HydricResistance = 0.0
-IgneousResistance = 0.0
-FerrumResistance = 0.0
-TelluricDamageBonus = 0.0
-AeolicDamageBonus = 0.0
-BaseHydricDamageBonus = 0.0
-IgneousDamageBonus = 0.0
-FerrumDamageBonus = 0.0
-DropsSoulGemChance = 0.9
-
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cwfph"]
radius = 0.226425
height = 2.02807
@@ -43,8 +20,7 @@ axis_lock_linear_y = true
axis_lock_angular_x = true
contact_monitor = true
max_contacts_reported = 1
-script = ExtResource("1_7tinp")
-EnemyStatResource = SubResource("Resource_rxw8v")
+script = ExtResource("1_ldo22")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
diff --git a/src/enemy/enemy_types/sproingy/SproingyModelView.tscn b/src/enemy/enemy_types/sproingy/SproingyModelView.tscn
index d53a2066..6136939f 100644
--- a/src/enemy/enemy_types/sproingy/SproingyModelView.tscn
+++ b/src/enemy/enemy_types/sproingy/SproingyModelView.tscn
@@ -1,6 +1,6 @@
[gd_scene load_steps=86 format=3 uid="uid://bli0t0d6ommvi"]
-[ext_resource type="Script" path="res://src/enemy/EnemyModelView.cs" id="1_0vbio"]
+[ext_resource type="Script" uid="uid://chymnqdw7hibn" path="res://src/enemy/EnemyModelView.cs" id="1_0vbio"]
[ext_resource type="Texture2D" uid="uid://dd0ia6isdqg61" path="res://src/enemy/enemy_types/sproingy/animations/ATTACK/Layer 1.png" id="1_pbx41"]
[ext_resource type="Texture2D" uid="uid://bs4ico5ouo5d3" path="res://src/enemy/enemy_types/sproingy/animations/ATTACK/Layer 2.png" id="2_0vbio"]
[ext_resource type="Resource" uid="uid://bctxs1jlkhgmc" path="res://src/enemy/enemy_types/sproingy/SproingyLoreInfo.tres" id="2_53wuj"]
@@ -57,7 +57,7 @@
[ext_resource type="Texture2D" uid="uid://b3gndmrlrvexy" path="res://src/enemy/enemy_types/sproingy/animations/IDLE_WALK_SIDE/Layer 13.png" id="53_nr2vc"]
[ext_resource type="Texture2D" uid="uid://b1cmx8l4ia3fv" path="res://src/enemy/enemy_types/sproingy/animations/IDLE_WALK_SIDE/Layer 14.png" id="54_jdvn0"]
[ext_resource type="Texture2D" uid="uid://c7t4626rox02s" path="res://src/enemy/enemy_types/sproingy/animations/IDLE_WALK_SIDE/Layer 15.png" id="55_2eqor"]
-[ext_resource type="Script" path="res://src/hitbox/Hitbox.cs" id="57_lae8t"]
+[ext_resource type="Script" uid="uid://6edayafleq8y" path="res://src/hitbox/Hitbox.cs" id="57_lae8t"]
[sub_resource type="ViewportTexture" id="ViewportTexture_h1kaf"]
viewport_path = NodePath("Sprite3D/SubViewport")
@@ -281,35 +281,6 @@ tracks/1/keys = {
"values": [0]
}
-[sub_resource type="Animation" id="Animation_ruc6s"]
-resource_name = "attack"
-length = 0.750008
-step = 0.0833333
-tracks/0/type = "value"
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/path = NodePath("Sprite3D/SubViewport/AnimatedSprite:animation")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/keys = {
-"times": PackedFloat32Array(0),
-"transitions": PackedFloat32Array(1),
-"update": 0,
-"values": [&"attack"]
-}
-tracks/1/type = "value"
-tracks/1/imported = false
-tracks/1/enabled = true
-tracks/1/path = NodePath("Sprite3D/SubViewport/AnimatedSprite:frame")
-tracks/1/interp = 1
-tracks/1/loop_wrap = true
-tracks/1/keys = {
-"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667, 0.5, 0.583333, 0.666666, 0.75),
-"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
-"update": 0,
-"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-}
-
[sub_resource type="Animation" id="Animation_1tda5"]
resource_name = "idle_back_walk"
length = 1.16667
@@ -400,18 +371,44 @@ tracks/1/keys = {
"values": [&"idle_left_walk"]
}
+[sub_resource type="Animation" id="Animation_ruc6s"]
+resource_name = "attack"
+length = 0.750008
+step = 0.0833333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("Sprite3D/SubViewport/AnimatedSprite:animation")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [&"attack"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Sprite3D/SubViewport/AnimatedSprite:frame")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667, 0.5, 0.583333, 0.666666, 0.75),
+"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
+"update": 0,
+"values": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+}
+
[sub_resource type="AnimationLibrary" id="AnimationLibrary_6tj5r"]
_data = {
&"RESET": SubResource("Animation_ch8ic"),
-&"attack": SubResource("Animation_ruc6s"),
&"idle_back_walk": SubResource("Animation_1tda5"),
&"idle_front_walk": SubResource("Animation_31nry"),
-&"idle_left_walk": SubResource("Animation_1870e")
+&"idle_left_walk": SubResource("Animation_1870e"),
+&"primary_attack": SubResource("Animation_ruc6s")
}
-[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_erbrx"]
-animation = &"attack"
-
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_o0tmb"]
animation = &"idle_back_walk"
@@ -421,6 +418,9 @@ animation = &"idle_front_walk"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_dvj10"]
animation = &"idle_left_walk"
+[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_erbrx"]
+animation = &"primary_attack"
+
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_vljb2"]
advance_mode = 2
@@ -461,15 +461,15 @@ switch_mode = 2
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_d5bmw"]
states/End/position = Vector2(1464, 100)
-states/attack/node = SubResource("AnimationNodeAnimation_erbrx")
-states/attack/position = Vector2(1024, 92.9474)
states/idle_back_walk/node = SubResource("AnimationNodeAnimation_o0tmb")
states/idle_back_walk/position = Vector2(491, 92.9474)
states/idle_front_walk/node = SubResource("AnimationNodeAnimation_a6s5c")
states/idle_front_walk/position = Vector2(331, -12)
states/idle_left_walk/node = SubResource("AnimationNodeAnimation_dvj10")
states/idle_left_walk/position = Vector2(331, 196.947)
-transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")]
+states/primary_attack/node = SubResource("AnimationNodeAnimation_erbrx")
+states/primary_attack/position = Vector2(1024, 92.9474)
+transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "primary_attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "primary_attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "primary_attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "primary_attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")]
graph_offset = Vector2(46.1163, -62.0526)
[node name="EnemyModelView" type="Node3D"]
diff --git a/src/enemy/state/EnemyLogic.Input.cs b/src/enemy/state/EnemyLogic.Input.cs
index dfac1ae8..a5ca7da9 100644
--- a/src/enemy/state/EnemyLogic.Input.cs
+++ b/src/enemy/state/EnemyLogic.Input.cs
@@ -13,8 +13,6 @@ namespace GameJamDungeon
public readonly record struct PhysicsTick(double Delta);
- public readonly record struct HitByPlayer(double Damage);
-
public readonly record struct EnemyDefeated();
public readonly record struct PatrolToRandomSpot(Vector3 PatrolTarget);
diff --git a/src/enemy/state/EnemyLogic.Output.cs b/src/enemy/state/EnemyLogic.Output.cs
index ca46ccd6..d3812012 100644
--- a/src/enemy/state/EnemyLogic.Output.cs
+++ b/src/enemy/state/EnemyLogic.Output.cs
@@ -10,9 +10,7 @@ namespace GameJamDungeon
public readonly record struct MovementComputed(Vector3 LinearVelocity);
- public readonly record struct HitByPlayer(double CurrentHP);
-
- public readonly record struct Attack();
+ public readonly record struct TakeAction();
public readonly record struct Defeated();
}
diff --git a/src/enemy/state/EnemyLogic.g.puml b/src/enemy/state/EnemyLogic.g.puml
index b66004cb..e03deecc 100644
--- a/src/enemy/state/EnemyLogic.g.puml
+++ b/src/enemy/state/EnemyLogic.g.puml
@@ -1,14 +1,13 @@
@startuml EnemyLogic
state "EnemyLogic State" as GameJamDungeon_EnemyLogic_State {
- state "Defeated" as GameJamDungeon_EnemyLogic_State_Defeated
state "Alive" as GameJamDungeon_EnemyLogic_State_Alive {
state "FollowPlayer" as GameJamDungeon_EnemyLogic_State_FollowPlayer
state "Idle" as GameJamDungeon_EnemyLogic_State_Idle
}
+ state "Defeated" as GameJamDungeon_EnemyLogic_State_Defeated
}
GameJamDungeon_EnemyLogic_State_Alive --> GameJamDungeon_EnemyLogic_State_Alive : AttackTimer
-GameJamDungeon_EnemyLogic_State_Alive --> GameJamDungeon_EnemyLogic_State_Alive : HitByPlayer
GameJamDungeon_EnemyLogic_State_Alive --> GameJamDungeon_EnemyLogic_State_Defeated : EnemyDefeated
GameJamDungeon_EnemyLogic_State_FollowPlayer --> GameJamDungeon_EnemyLogic_State_FollowPlayer : PhysicsTick
GameJamDungeon_EnemyLogic_State_FollowPlayer --> GameJamDungeon_EnemyLogic_State_Idle : LostPlayer
@@ -16,11 +15,8 @@ GameJamDungeon_EnemyLogic_State_Idle --> GameJamDungeon_EnemyLogic_State_FollowP
GameJamDungeon_EnemyLogic_State_Idle --> GameJamDungeon_EnemyLogic_State_Idle : PatrolToRandomSpot
GameJamDungeon_EnemyLogic_State_Idle --> GameJamDungeon_EnemyLogic_State_Idle : PhysicsTick
-GameJamDungeon_EnemyLogic_State_Alive : OnAttackTimer → Attack
+GameJamDungeon_EnemyLogic_State_Alive : OnAttackTimer → TakeAction
GameJamDungeon_EnemyLogic_State_Alive : OnEnemyDefeated → Defeated
-GameJamDungeon_EnemyLogic_State_Alive : OnHitByPlayer → HitByPlayer
-GameJamDungeon_EnemyLogic_State_FollowPlayer : OnPhysicsTick → MovementComputed
-GameJamDungeon_EnemyLogic_State_Idle : OnPhysicsTick → MovementComputed
[*] --> GameJamDungeon_EnemyLogic_State_Idle
@enduml
\ No newline at end of file
diff --git a/src/enemy/state/states/EnemyLogic.State.Alive.cs b/src/enemy/state/states/EnemyLogic.State.Alive.cs
index 0544e2d8..ab2742ee 100644
--- a/src/enemy/state/states/EnemyLogic.State.Alive.cs
+++ b/src/enemy/state/states/EnemyLogic.State.Alive.cs
@@ -8,23 +8,11 @@ namespace GameJamDungeon
public partial record State
{
[Meta, Id("enemy_logic_state_alive")]
- public abstract partial record Alive : State, IGet, IGet, IGet
+ public abstract partial record Alive : State, IGet, IGet
{
- public Transition On(in Input.HitByPlayer input)
- {
- var enemy = Get();
- enemy.CurrentHP.OnNext(enemy.CurrentHP.Value - input.Damage);
- GD.Print("Current HP: " + enemy.CurrentHP.Value);
- Output(new Output.HitByPlayer());
-
- Input(new Input.Alerted());
-
- return ToSelf();
- }
-
public Transition On(in Input.AttackTimer input)
{
- Output(new Output.Attack());
+ Output(new Output.TakeAction());
return ToSelf();
}
diff --git a/src/enemy/state/states/EnemyLogic.State.FollowPlayer.cs b/src/enemy/state/states/EnemyLogic.State.FollowPlayer.cs
index 07a1214c..da37e32a 100644
--- a/src/enemy/state/states/EnemyLogic.State.FollowPlayer.cs
+++ b/src/enemy/state/states/EnemyLogic.State.FollowPlayer.cs
@@ -16,16 +16,7 @@ namespace GameJamDungeon
var enemy = Get();
var gameRepo = Get();
var target = gameRepo.PlayerGlobalPosition.Value;
- enemy.NavAgent.TargetPosition = target;
- var targetPosition = enemy.NavAgent.GetNextPathPosition();
-
- var velocity = (targetPosition - enemy.GlobalTransform.Origin).Normalized() * 2f * (float)delta;
- var lookAtDir = enemy.GlobalTransform.Origin - velocity;
- var lookAtPosition = new Vector3(lookAtDir.X, enemy.GlobalPosition.Y, lookAtDir.Z);
- if (enemy.GlobalPosition.DistanceTo(target) > 1.0f && !velocity.IsEqualApprox(Vector3.Zero) && !enemy.GlobalPosition.IsEqualApprox(lookAtPosition))
- enemy.LookAt(lookAtPosition);
-
- Output(new Output.MovementComputed(velocity));
+ enemy.MoveToLocation(target, (float)delta);
return ToSelf();
}
diff --git a/src/enemy/state/states/EnemyLogic.State.Idle.cs b/src/enemy/state/states/EnemyLogic.State.Idle.cs
index 4e865612..b3c610d9 100644
--- a/src/enemy/state/states/EnemyLogic.State.Idle.cs
+++ b/src/enemy/state/states/EnemyLogic.State.Idle.cs
@@ -10,6 +10,7 @@ public partial class EnemyLogic
[Meta, Id("enemy_logic_state_idle")]
public partial record Idle : Alive, IGet, IGet, IGet
{
+ private Vector3 _patrolTarget { get; set; }
public Transition On(in Input.Alerted _)
{
return To();
@@ -19,22 +20,13 @@ public partial class EnemyLogic
{
var delta = input.Delta;
var enemy = Get();
- var targetPosition = enemy.NavAgent.GetNextPathPosition();
- var velocity = (targetPosition - enemy.GlobalPosition).Normalized() * 1.0f * (float)delta;
- var lookAtDir = enemy.GlobalTransform.Origin - velocity;
-
- var lookAtPosition = new Vector3(lookAtDir.X, enemy.GlobalPosition.Y, lookAtDir.Z);
- if (enemy.GlobalPosition.DistanceTo(targetPosition) > 1.0f && !velocity.IsEqualApprox(Vector3.Zero) && !enemy.GlobalPosition.IsEqualApprox(lookAtPosition))
- enemy.LookAt(lookAtPosition);
-
- Output(new Output.MovementComputed(velocity));
+ enemy.MoveToLocation(_patrolTarget, (float)delta);
return ToSelf();
}
public Transition On(in Input.PatrolToRandomSpot input)
{
- var enemy = Get();
- enemy.NavAgent.TargetPosition = input.PatrolTarget;
+ _patrolTarget = input.PatrolTarget;
return ToSelf();
}
}
diff --git a/src/game/ElementType.cs b/src/game/ElementType.cs
new file mode 100644
index 00000000..3c5cae21
--- /dev/null
+++ b/src/game/ElementType.cs
@@ -0,0 +1,12 @@
+namespace GameJamDungeon
+{
+ public enum ElementType
+ {
+ None,
+ Aeolic,
+ Telluric,
+ Hydric,
+ Igneous,
+ Ferrum
+ }
+}
diff --git a/src/game/GameLogic.g.puml b/src/game/GameLogic.g.puml
index df2df1ed..1b460d73 100644
--- a/src/game/GameLogic.g.puml
+++ b/src/game/GameLogic.g.puml
@@ -1,15 +1,15 @@
@startuml GameLogic
state "GameLogic State" as GameJamDungeon_GameLogic_State {
- state "Quit" as GameJamDungeon_GameLogic_State_Quit
+ state "GameStarted" as GameJamDungeon_GameLogic_State_GameStarted
state "Playing" as GameJamDungeon_GameLogic_State_Playing {
+ state "AskForTeleport" as GameJamDungeon_GameLogic_State_AskForTeleport
+ state "FloorClearedDecisionState" as GameJamDungeon_GameLogic_State_FloorClearedDecisionState
+ state "InventoryOpened" as GameJamDungeon_GameLogic_State_InventoryOpened
state "MinimapOpen" as GameJamDungeon_GameLogic_State_MinimapOpen
state "Paused" as GameJamDungeon_GameLogic_State_Paused
- state "FloorClearedDecisionState" as GameJamDungeon_GameLogic_State_FloorClearedDecisionState
- state "AskForTeleport" as GameJamDungeon_GameLogic_State_AskForTeleport
- state "InventoryOpened" as GameJamDungeon_GameLogic_State_InventoryOpened
state "Resuming" as GameJamDungeon_GameLogic_State_Resuming
}
- state "GameStarted" as GameJamDungeon_GameLogic_State_GameStarted
+ state "Quit" as GameJamDungeon_GameLogic_State_Quit
}
GameJamDungeon_GameLogic_State_AskForTeleport --> GameJamDungeon_GameLogic_State_FloorClearedDecisionState : FloorExitReached
diff --git a/src/hitbox/Hitbox.cs b/src/hitbox/Hitbox.cs
index 2335b124..e2c6bda4 100644
--- a/src/hitbox/Hitbox.cs
+++ b/src/hitbox/Hitbox.cs
@@ -1,5 +1,7 @@
using Chickensoft.GodotNodeInterfaces;
+using GameJamDungeon;
using Godot;
+using System;
public interface IHitbox : IArea3D
{
diff --git a/src/items/throwable/ThrowableItem.cs b/src/items/throwable/ThrowableItem.cs
index a4b0d264..a57a7b44 100644
--- a/src/items/throwable/ThrowableItem.cs
+++ b/src/items/throwable/ThrowableItem.cs
@@ -3,7 +3,6 @@ using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
using System;
-using System.ComponentModel;
[Meta(typeof(IAutoNode))]
public partial class ThrowableItem : Node3D, IUsableItem
@@ -27,23 +26,10 @@ public partial class ThrowableItem : Node3D, IUsableItem
[Node] public Area3D Pickup { get; set; } = default!;
- private ThrowableItemTag[] _affinityTypes;
-
- private int _affinityIndex = 0;
-
public void OnResolved()
{
Sprite.Texture = ThrowableItemInfo.Texture;
Pickup.BodyEntered += OnEntered;
- _affinityTypes =
- [
- ThrowableItemTag.InflictBaseDamage,
- ThrowableItemTag.InflictHydricDamage,
- ThrowableItemTag.InflictIgneousDamage,
- ThrowableItemTag.InflictTelluricDamage,
- ThrowableItemTag.InflictAeolicDamage,
- ThrowableItemTag.InflictFerrumDamage
- ];
}
public void Use()
@@ -62,13 +48,12 @@ public partial class ThrowableItem : Node3D, IUsableItem
private void ChangeAffinity()
{
- ThrowableItemInfo.ThrowableItemTags.Remove(_affinityTypes[_affinityIndex]);
- _affinityIndex = (_affinityIndex + 1) % (_affinityTypes.Length);
- ThrowableItemInfo.ThrowableItemTags.Add(_affinityTypes[_affinityIndex]);
+ var maximumElements = Enum.GetNames(typeof(ElementType)).Length;
+ ThrowableItemInfo.ElementType = ThrowableItemInfo.ElementType + 1 % maximumElements;
// TODO: Make this an inventory animation to cycle through elements.
ThrowableItemInfo.Description =
- $"{GetDescription(_affinityTypes[_affinityIndex])} when thrown." +
+ $"Inflicts {ThrowableItemInfo.ElementType} damage when thrown." +
$"{System.Environment.NewLine}Use item to change Affinity.";
}
@@ -78,19 +63,4 @@ public partial class ThrowableItem : Node3D, IUsableItem
if (isAdded)
QueueFree();
}
-
- private static string GetDescription(ThrowableItemTag enumValue)
- {
- var field = enumValue.GetType().GetField(enumValue.ToString());
- if (field == null)
- return enumValue.ToString();
-
- var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
- if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
- {
- return attribute.Description;
- }
-
- return enumValue.ToString();
- }
}
diff --git a/src/items/throwable/ThrowableItem.tscn b/src/items/throwable/ThrowableItem.tscn
index 48e9eb7a..44253260 100644
--- a/src/items/throwable/ThrowableItem.tscn
+++ b/src/items/throwable/ThrowableItem.tscn
@@ -6,6 +6,7 @@
[sub_resource type="Resource" id="Resource_b0s4k"]
script = ExtResource("2_8h2lx")
ThrowableItemTags = Array[int]([])
+ElementType = 0
UsableItemTags = Array[int]([])
Name = ""
Description = ""
diff --git a/src/items/throwable/ThrowableItemStats.cs b/src/items/throwable/ThrowableItemStats.cs
index c5f527e5..5d1230d3 100644
--- a/src/items/throwable/ThrowableItemStats.cs
+++ b/src/items/throwable/ThrowableItemStats.cs
@@ -8,6 +8,9 @@ public partial class ThrowableItemStats : InventoryItemStats
[Export]
public Godot.Collections.Array ThrowableItemTags { get; set; } = new Godot.Collections.Array();
+ [Export]
+ public ElementType ElementType { get; set; } = ElementType.None;
+
[Export]
public Godot.Collections.Array UsableItemTags { get; set; } = new Godot.Collections.Array();
}
diff --git a/src/items/throwable/ThrowableItemTag.cs b/src/items/throwable/ThrowableItemTag.cs
index ca213eed..f6c84c11 100644
--- a/src/items/throwable/ThrowableItemTag.cs
+++ b/src/items/throwable/ThrowableItemTag.cs
@@ -2,18 +2,6 @@
public enum ThrowableItemTag
{
- [Description("Inflicts basic damage")]
- InflictBaseDamage,
- [Description("Inflicts Telluric damage")]
- InflictTelluricDamage,
- [Description("Inflicts Aeolic damage")]
- InflictAeolicDamage,
- [Description("Inflicts Hydric damage")]
- InflictHydricDamage,
- [Description("Inflicts Igneous damage")]
- InflictIgneousDamage,
- [Description("Inflicts Ferrum damage")]
- InflictFerrumDamage,
LowerTargetTo1HP,
CanChangeAffinity
}
diff --git a/src/items/thrown/ThrownItem.cs b/src/items/thrown/ThrownItem.cs
index 679d1960..933586ed 100644
--- a/src/items/thrown/ThrownItem.cs
+++ b/src/items/thrown/ThrownItem.cs
@@ -38,14 +38,16 @@ public partial class ThrownItem : RigidBody3D
private void CalculateEffect(IEnemy enemy)
{
- enemy.EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(ThrownItemStats.ThrowDamage));
-
if (ThrownItemStats is ThrowableItemStats throwableItemStats)
{
if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.LowerTargetTo1HP))
- enemy.EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(enemy.CurrentHP.Value - 1));
- enemy.EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(DamageCalculator.CalculateThrownItemDamage(throwableItemStats.ThrowDamage, enemy.EnemyStatResource, throwableItemStats)));
-
+ enemy.TakeDamage(enemy.CurrentHP - 1, ElementType.None, false, true, true);
+ else
+ enemy.TakeDamage(throwableItemStats.ThrowDamage, throwableItemStats.ElementType);
+ }
+ else
+ {
+ enemy.TakeDamage(ThrownItemStats.ThrowDamage, ElementType.None);
}
}
}
diff --git a/src/items/weapons/WeaponStats.cs b/src/items/weapons/WeaponStats.cs
index a9a399a9..0b07551f 100644
--- a/src/items/weapons/WeaponStats.cs
+++ b/src/items/weapons/WeaponStats.cs
@@ -14,19 +14,10 @@ public partial class WeaponStats : InventoryItemStats
public double AttackSpeed { get; set; } = 1;
[Export]
- public double TelluricDamageBonus { get; set; } = 0;
+ public ElementType WeaponElement { get; set; } = ElementType.None;
[Export]
- public double AeolicDamageBonus { get; set; } = 0;
-
- [Export]
- public double BaseHydricDamageBonus { get; set; } = 0;
-
- [Export]
- public double IgneousDamageBonus { get; set; } = 0;
-
- [Export]
- public double FerrumDamageBonus { get; set; } = 0;
+ public double ElementalDamageBonus { get; set; } = 1.0;
[Export]
public Godot.Collections.Array WeaponTags { get; set; } = new Godot.Collections.Array();
diff --git a/src/player/Player.cs b/src/player/Player.cs
index 11897140..a23213e1 100644
--- a/src/player/Player.cs
+++ b/src/player/Player.cs
@@ -9,8 +9,6 @@ namespace GameJamDungeon
{
public interface IPlayer : ICharacterBody3D, IKillable
{
- PlayerLogic PlayerLogic { get; }
-
public Vector3 GetGlobalInputVector();
public float GetLeftStrafeInputVector();
@@ -33,6 +31,13 @@ namespace GameJamDungeon
PlayerLogic IProvide.Value() => PlayerLogic;
+ public PlayerLogic.Settings Settings { get; set; } = default!;
+
+ private PlayerLogic PlayerLogic { get; set; } = default!;
+
+ private PlayerLogic.IBinding PlayerBinding { get; set; } = default!;
+
+ #region Dependencies
[Dependency]
public IAppRepo AppRepo => this.DependOn();
@@ -41,14 +46,18 @@ namespace GameJamDungeon
[Dependency]
public ISaveChunk GameChunk => this.DependOn>();
+ #endregion
+ #region Event Signals
[Signal]
public delegate void InventoryButtonPressedEventHandler();
[Signal]
public delegate void MinimapButtonHeldEventHandler();
[Signal]
public delegate void PauseButtonPressedEventHandler();
+ #endregion
+ #region Exports
[Export]
public PlayerStatResource PlayerStatResource { get; set; } = default!;
@@ -56,22 +65,17 @@ namespace GameJamDungeon
private WeaponStats _defaultWeapon { get; set; } = default!;
[Export]
private ArmorStats _defaultArmor { get; set; } = default!;
+ #endregion
- public PlayerLogic.Settings Settings { get; set; } = default!;
+ #region Node Dependencies
+ [Node] private IAnimationPlayer AnimationPlayer { get; set; } = default!;
- public PlayerLogic PlayerLogic { get; set; } = default!;
+ [Node] private AnimatedSprite2D SwordSlashAnimation { get; set; } = default!;
- public PlayerLogic.IBinding PlayerBinding { get; set; } = default!;
+ [Node] private IHitbox Hitbox { get; set; } = default!;
- [Node] public IAnimationPlayer AnimationPlayer { get; set; } = default!;
-
- [Node] public AnimatedSprite2D SwordSlashAnimation { get; set; } = default!;
-
- [Node] public IHitbox Hitbox { get; set; } = default!;
-
- [Node] public Timer HealthTimer { get; set; } = default!;
-
- [Node] public IArea3D CollisionDetector { get; set; } = default!;
+ [Node] private Timer HealthTimer { get; set; } = default!;
+ #endregion
private PlayerData PlayerData { get; set; } = default!;
@@ -177,8 +181,16 @@ namespace GameJamDungeon
GlobalPosition = GameRepo.PlayerGlobalPosition.Value;
GameRepo.PlayerGlobalPosition.Sync += PlayerGlobalPosition_Sync;
HealthTimer.Timeout += OnHealthTimerTimeout;
- CollisionDetector.BodyEntered += CollisionDetector_BodyEntered;
PlayerData.Inventory.AccessoryUnequipped += Inventory_AccessoryUnequipped;
+ Hitbox.AreaEntered += Hitbox_AreaEntered;
+ }
+
+ private void Hitbox_AreaEntered(Area3D area)
+ {
+ var enemy = Hitbox.GetParent();
+ enemy.TakeDamage((PlayerStatResource.CurrentAttack + PlayerStatResource.BonusAttack) * PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.ElementalDamageBonus,
+ PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponElement,
+ ignoreElementalResistance: PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponTags.Contains(WeaponTag.IgnoreAffinity));
}
public void OnReady()
@@ -319,24 +331,6 @@ namespace GameJamDungeon
PlayerData.SetLuck(PlayerData.Luck.Value - unequippedAccessory.LUCKUp);
}
- private void CollisionDetector_BodyEntered(Node3D body)
- {
- if (body is IHitbox hitBox)
- {
- var enemy = hitBox.GetParent();
- var isCriticalHit = false;
- var rng = new RandomNumberGenerator();
- rng.Randomize();
- var roll = rng.Randf();
- if (roll <= enemy.EnemyStatResource.Luck)
- isCriticalHit = true;
- var damage = DamageCalculator.CalculateEnemyAttackDamage(PlayerData.CurrentDefense.Value + PlayerData.BonusDefense, enemy.EnemyStatResource, GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats, isCriticalHit);
- PlayerData.SetCurrentHP(PlayerData.CurrentHP.Value - Mathf.RoundToInt(damage));
- GD.Print($"Player hit for {damage} damage.");
- }
- }
-
-
private void CurrentHP_Sync(int newHealth)
{
if (newHealth <= 0)
diff --git a/src/player/state/PlayerLogic.g.puml b/src/player/state/PlayerLogic.g.puml
index e65cfd2e..b83413f5 100644
--- a/src/player/state/PlayerLogic.g.puml
+++ b/src/player/state/PlayerLogic.g.puml
@@ -1,11 +1,11 @@
@startuml PlayerLogic
state "PlayerLogic State" as GameJamDungeon_PlayerLogic_State {
- state "Disabled" as GameJamDungeon_PlayerLogic_State_Disabled
- state "Dead" as GameJamDungeon_PlayerLogic_State_Dead
state "Alive" as GameJamDungeon_PlayerLogic_State_Alive {
state "Attacking" as GameJamDungeon_PlayerLogic_State_Attacking
state "Idle" as GameJamDungeon_PlayerLogic_State_Idle
}
+ state "Dead" as GameJamDungeon_PlayerLogic_State_Dead
+ state "Disabled" as GameJamDungeon_PlayerLogic_State_Disabled
}
GameJamDungeon_PlayerLogic_State_Alive --> GameJamDungeon_PlayerLogic_State_Alive : Moved
diff --git a/src/system/IHasPrimaryAttack.cs b/src/system/IHasPrimaryAttack.cs
new file mode 100644
index 00000000..8151e4e7
--- /dev/null
+++ b/src/system/IHasPrimaryAttack.cs
@@ -0,0 +1,23 @@
+namespace GameJamDungeon
+{
+ public interface IHasPrimaryAttack
+ {
+ public ElementType PrimaryAttackElementalType { set; }
+ public double PrimaryAttackElementalDamageBonus { set; }
+
+ public void PrimaryAttack();
+ }
+
+ public interface IHasSecondaryAttack
+ {
+ public ElementType SecondaryAttackElementalType { set; }
+ public double SecondaryAttackElementalDamageBonus { set; }
+
+ public void SecondaryAttack();
+ }
+
+ public interface IHasPrimarySkill
+ {
+ public void PrimarySkill();
+ }
+}
diff --git a/src/system/stats/DamageCalculator.cs b/src/system/stats/DamageCalculator.cs
index 0bc02179..56656ee1 100644
--- a/src/system/stats/DamageCalculator.cs
+++ b/src/system/stats/DamageCalculator.cs
@@ -4,68 +4,10 @@ namespace GameJamDungeon
{
public static class DamageCalculator
{
- public static double CalculateWeaponAttackDamage(int totalAttack, EnemyStatResource enemyStatResource, WeaponStats weapon, bool isCriticalHit)
+ public static double CalculateWeaponAttackDamage(int totalAttack, WeaponStats weapon)
{
- var hydricResistance = enemyStatResource.HydricResistance;
- var igneousResistance = enemyStatResource.IgneousResistance;
- var telluricResistance = enemyStatResource.TelluricResistance;
- var aeolicResistance = enemyStatResource.AeolicResistance;
- var ferrumResistance = enemyStatResource.FerrumResistance;
-
- if (weapon.WeaponTags.Contains(WeaponTag.IgnoreAffinity))
- {
- hydricResistance = 0;
- igneousResistance = 0;
- telluricResistance = 0;
- aeolicResistance = 0;
- ferrumResistance = 0;
- }
-
- var elementADamage = (weapon.BaseHydricDamageBonus > 0 ? weapon.BaseHydricDamageBonus - hydricResistance : 0) / 100;
- var elementBDamage = (weapon.IgneousDamageBonus > 0 ? weapon.IgneousDamageBonus - igneousResistance : 0) / 100;
- var elementCDamage = (weapon.TelluricDamageBonus > 0 ? weapon.TelluricDamageBonus - telluricResistance : 0) / 100;
- var elementDDamage = (weapon.AeolicDamageBonus > 0 ? weapon.AeolicDamageBonus - aeolicResistance : 0) / 100;
- var elementEDamage = (weapon.FerrumDamageBonus > 0 ? weapon.FerrumDamageBonus - ferrumResistance : 0) / 100;
- var elementalBonusDamage = totalAttack + (totalAttack * elementADamage) + (totalAttack * elementBDamage) + (totalAttack * elementCDamage) + (totalAttack * elementDDamage) + (totalAttack * elementEDamage);
- var calculatedDamage = elementalBonusDamage - enemyStatResource.CurrentDefense;
-
- if (isCriticalHit)
- calculatedDamage *= 2;
-
- return Mathf.Max(calculatedDamage, 0.0);
- }
-
- public static double CalculateEnemyAttackDamage(int playerTotalDefense, EnemyStatResource enemyStatResource, ArmorStats armor, bool isCriticalHit)
- {
- var totalAttack = enemyStatResource.CurrentAttack;
- var elementADamage = (enemyStatResource.BaseHydricDamageBonus > 0 ? enemyStatResource.BaseHydricDamageBonus - armor.HydricResistance : 0) / 100;
- var elementBDamage = (enemyStatResource.IgneousDamageBonus > 0 ? enemyStatResource.IgneousDamageBonus - armor.IgneousResistance : 0) / 100;
- var elementCDamage = (enemyStatResource.TelluricDamageBonus > 0 ? enemyStatResource.TelluricDamageBonus - armor.TelluricResistance : 0) / 100;
- var elementDDamage = (enemyStatResource.AeolicDamageBonus > 0 ? enemyStatResource.AeolicDamageBonus - armor.AeolicResistance : 0) / 100;
- var elementEDamage = (enemyStatResource.FerrumDamageBonus > 0 ? enemyStatResource.FerrumDamageBonus - armor.FerrumResistance : 0) / 100;
- var elementalBonusDamage = totalAttack + (totalAttack * elementADamage) + (totalAttack * elementBDamage) + (totalAttack * elementCDamage) + (totalAttack * elementDDamage) + (totalAttack * elementEDamage);
- var calculatedDamage = elementalBonusDamage - playerTotalDefense - (armor != null ? armor.Defense : 0);
-
- if (isCriticalHit)
- calculatedDamage *= 2;
-
- return Mathf.Max(calculatedDamage, 0.0);
- }
-
- public static double CalculateThrownItemDamage(int baseThrowDamage, EnemyStatResource enemyStatResource, ThrowableItemStats throwableItemStats)
- {
- if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictAeolicDamage))
- return Mathf.Max(baseThrowDamage * enemyStatResource.AeolicResistance, 0.0);
- if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictFerrumDamage))
- return Mathf.Max(baseThrowDamage * enemyStatResource.FerrumResistance, 0.0);
- if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictHydricDamage))
- return Mathf.Max(baseThrowDamage * enemyStatResource.HydricResistance, 0.0);
- if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictIgneousDamage))
- return Mathf.Max(baseThrowDamage * enemyStatResource.IgneousResistance, 0.0);
- if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictTelluricDamage))
- return Mathf.Max(baseThrowDamage * enemyStatResource.TelluricResistance, 0.0);
-
- return Mathf.Max(baseThrowDamage, 0.0);
+ var totalDamage = totalAttack * weapon.ElementalDamageBonus;
+ return Mathf.Max(totalDamage, 0.0);
}
}
}