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); } } }