Split equipment status from Inventory, fix equip/unequip bonuses being reflected correctly in code and inventory menu

This commit is contained in:
2025-02-19 16:04:40 -08:00
parent f71412d946
commit 5404f8e7b0
16 changed files with 200 additions and 170 deletions

View File

@@ -1,4 +1,5 @@
using Godot;
using Chickensoft.Collections;
using Godot;
namespace GameJamDungeon;
@@ -32,11 +33,15 @@ public interface IPlayer : IKillable
public void RaiseVT(int amount);
public void RaiseBonusAttack(int amount);
public void ModifyBonusAttack(int amount);
public void RaiseBonusDefense(int amount);
public void ModifyBonusDefense(int amount);
public void RaiseBonusLuck(int amount);
public void ModifyMaximumHP(int amount);
public void ModifyMaximumVT(int amount);
public void ModifyBonusLuck(double amount);
public IInventory Inventory { get; }
@@ -45,4 +50,14 @@ public interface IPlayer : IKillable
public Vector3 CurrentPosition { get; }
public Basis CurrentBasis { get; }
public IAutoProp<Weapon> EquippedWeapon { get; }
public IAutoProp<Armor> EquippedArmor { get; }
public IAutoProp<Accessory> EquippedAccessory { get; }
public void Equip(IEquipableItem equipable);
public void Unequip(IEquipableItem equipable);
}

View File

@@ -1,9 +1,11 @@
using Chickensoft.AutoInject;
using Chickensoft.Collections;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Chickensoft.SaveFileBuilder;
using Godot;
using Godot.Collections;
using System;
namespace GameJamDungeon;
@@ -25,6 +27,15 @@ public partial class Player : CharacterBody3D, IPlayer
public IInventory Inventory { get; private set; } = default!;
public IAutoProp<Weapon> EquippedWeapon => _equippedWeapon;
private AutoProp<Weapon> _equippedWeapon { get; set; } = new AutoProp<Weapon>(new Weapon());
public IAutoProp<Armor> EquippedArmor => _equippedArmor;
private AutoProp<Armor> _equippedArmor { get; set; } = new AutoProp<Armor>(new Armor());
public IAutoProp<Accessory> EquippedAccessory => _equippedAccessory;
private AutoProp<Accessory> _equippedAccessory { get; set; } = new AutoProp<Accessory>(new Accessory());
private PlayerLogic.Settings Settings { get; set; } = default!;
private PlayerLogic PlayerLogic { get; set; } = default!;
@@ -129,13 +140,15 @@ public partial class Player : CharacterBody3D, IPlayer
Inventory.TryAdd(defaultWeapon);
Inventory.TryAdd(defaultArmor);
Inventory.Equip(defaultWeapon);
Inventory.Equip(defaultArmor);
Inventory.EquippedAccessory.Sync += EquippedAccessory_Sync;
EquippedWeapon.Sync += EquippedWeapon_Sync;
EquippedArmor.Sync += EquippedArmor_Sync;
EquippedAccessory.Sync += EquippedAccessory_Sync;
Stats.CurrentHP.Sync += CurrentHP_Sync;
Stats.CurrentExp.Sync += CurrentEXP_Sync;
Equip(defaultWeapon);
Equip(defaultArmor);
HealthTimer.WaitTime = _healthTimerWaitTime;
}
@@ -146,7 +159,7 @@ public partial class Player : CharacterBody3D, IPlayer
PlayerBinding
.Handle((in PlayerLogic.Output.Animations.Attack output) =>
{
var attackSpeed = Inventory.EquippedWeapon.Value.AttackSpeed;
var attackSpeed = EquippedWeapon.Value.AttackSpeed;
AnimationPlayer.SetSpeedScale((float)attackSpeed);
AnimationPlayer.Play("attack");
@@ -219,19 +232,29 @@ public partial class Player : CharacterBody3D, IPlayer
Game.AnnounceMessageOnInventoryScreen($"{raiseString}VT Restored.");
}
public void RaiseBonusAttack(int amount)
public void ModifyBonusAttack(int amount)
{
Stats.SetBonusAttack(Stats.BonusAttack.Value + amount);
}
public void RaiseBonusDefense(int amount)
public void ModifyBonusDefense(int amount)
{
Stats.SetBonusDefense(Stats.BonusDefense.Value + amount);
}
public void RaiseBonusLuck(int amount)
public void ModifyMaximumHP(int amount)
{
Stats.SetLuck(amount);
Stats.SetMaximumHP(Stats.MaximumHP.Value + amount);
}
public void ModifyMaximumVT(int amount)
{
Stats.SetMaximumVT(Stats.MaximumVT.Value + amount);
}
public void ModifyBonusLuck(double amount)
{
Stats.SetLuck(Stats.Luck.Value + amount);
}
public void Move(float delta)
@@ -310,6 +333,61 @@ public partial class Player : CharacterBody3D, IPlayer
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
}
public void Equip(IEquipableItem equipable)
{
if (equipable is Weapon weapon)
{
Unequip(_equippedWeapon.Value);
weapon.IsEquipped = true;
_equippedWeapon.OnNext(weapon);
}
else if (equipable is Armor armor)
{
Unequip(_equippedArmor.Value);
armor.IsEquipped = true;
_equippedArmor.OnNext(armor);
}
else if (equipable is Accessory accessory)
{
Unequip(_equippedAccessory.Value);
accessory.IsEquipped = true;
_equippedAccessory.OnNext(accessory);
}
else
throw new NotImplementedException("Item type is not supported.");
}
public void Unequip(IEquipableItem equipable)
{
if (equipable is Weapon weapon)
{
weapon.IsEquipped = false;
ModifyBonusAttack(-weapon.Damage);
_equippedWeapon.OnNext(new Weapon());
}
else if (equipable is Armor armor)
{
armor.IsEquipped = false;
ModifyBonusDefense(-armor.Defense);
_equippedArmor.OnNext(new Armor());
}
else if (equipable is Accessory accessory)
{
accessory.IsEquipped = false;
ModifyMaximumHP(-accessory.MaxHPUp);
ModifyMaximumVT(-accessory.MaxVTUp);
ModifyBonusAttack(-accessory.ATKUp);
ModifyBonusDefense(-accessory.DEFUp);
ModifyBonusLuck(-accessory.LuckUp);
_equippedAccessory.OnNext(new Accessory());
}
else
throw new NotImplementedException("Item type is not supported.");
if (equipable.ItemTags.Contains(ItemTag.BreaksOnChange))
Inventory.Remove(equipable);
}
private static Vector3 GlobalInputVector
{
get
@@ -371,7 +449,7 @@ public partial class Player : CharacterBody3D, IPlayer
if (Stats.CurrentVT.Value > 0)
{
if (Inventory.EquippedAccessory.Value.AccessoryTags.Contains(AccessoryTag.HalfVTConsumption))
if (EquippedAccessory.Value.AccessoryTags.Contains(AccessoryTag.HalfVTConsumption))
{
reduceOnTick = !reduceOnTick;
}
@@ -383,18 +461,23 @@ public partial class Player : CharacterBody3D, IPlayer
Stats.SetCurrentHP(Stats.CurrentHP.Value - 1);
}
private void EquippedAccessory_Sync(Accessory accessory)
private void EquippedWeapon_Sync(Weapon obj)
{
Stats.SetMaximumHP(Stats.MaximumHP.Value + accessory.MaxHPUp);
Stats.SetMaximumVT(Stats.MaximumVT.Value + accessory.MaxVTUp);
Stats.SetLuck(Stats.Luck.Value + accessory.LuckUp);
ModifyBonusAttack(obj.Damage);
}
private void Inventory_AccessoryUnequipped(Accessory accessory)
private void EquippedArmor_Sync(Armor obj)
{
Stats.SetMaximumHP(Stats.MaximumHP.Value - accessory.MaxHPUp);
Stats.SetMaximumVT(Stats.MaximumVT.Value - accessory.MaxVTUp);
Stats.SetLuck(Stats.Luck.Value - accessory.LuckUp);
ModifyBonusDefense(obj.Defense);
}
private void EquippedAccessory_Sync(Accessory accessory)
{
ModifyMaximumHP(accessory.MaxHPUp);
ModifyMaximumVT(accessory.MaxVTUp);
ModifyBonusAttack(accessory.ATKUp);
ModifyBonusDefense(accessory.DEFUp);
ModifyBonusLuck(accessory.LuckUp);
}
private void CurrentHP_Sync(int newHealth)
@@ -411,7 +494,7 @@ public partial class Player : CharacterBody3D, IPlayer
private double CalculateDefenseResistance(double incomingDamage)
{
return Mathf.Max(incomingDamage - Stats.CurrentDefense.Value, 0.0);
return Mathf.Max(incomingDamage - Stats.CurrentDefense.Value - Stats.BonusDefense.Value, 0.0);
}
private void Hitbox_AreaEntered(Area3D area)
@@ -423,19 +506,19 @@ public partial class Player : CharacterBody3D, IPlayer
private void HitEnemy(IEnemy enemy)
{
var attackValue = PlayerStatResource.CurrentAttack + Inventory.EquippedWeapon.Value.Damage;
var ignoreElementalResistance = Inventory.EquippedWeapon.Value.WeaponTags.Contains(WeaponTag.IgnoreAffinity);
var attackValue = Stats.CurrentAttack.Value + Stats.BonusAttack.Value;
var ignoreElementalResistance = EquippedWeapon.Value.WeaponTags.Contains(WeaponTag.IgnoreAffinity);
var isCriticalHit = BattleExtensions.IsCriticalHit(Stats.Luck.Value);
var element = Inventory.EquippedWeapon.Value.WeaponElement;
var element = EquippedWeapon.Value.WeaponElement;
enemy.TakeDamage(
attackValue * Inventory.EquippedWeapon.Value.ElementalDamageBonus,
attackValue * EquippedWeapon.Value.ElementalDamageBonus,
element,
isCriticalHit,
false,
ignoreElementalResistance);
if (Inventory.EquippedWeapon.Value.WeaponTags.Contains(WeaponTag.Knockback))
if (EquippedWeapon.Value.WeaponTags.Contains(WeaponTag.Knockback))
enemy.Knockback(0.3f, -CurrentBasis.Z.Normalized());
}
}