Add more NPCs, update dialogue manager to 4.4 compatible version
This commit is contained in:
@@ -20,7 +20,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
||||
|
||||
private PlayerLogic.IBinding PlayerBinding { get; set; } = default!;
|
||||
|
||||
[Dependency] private IGameRepo _gameRepo => this.DependOn<IGameRepo>();
|
||||
[Dependency] private IGameRepo _gameRepo => this.DependOn<IGameRepo>(() => new GameRepo());
|
||||
#endregion
|
||||
|
||||
#region Save
|
||||
@@ -106,508 +106,508 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<ISaveChunk<Play
|
||||
#region Initialization
|
||||
public void Initialize()
|
||||
{
|
||||
AnimationPlayer.AnimationFinished += OnAnimationFinished;
|
||||
_expToNextLevel = new Dictionary<int, int>
|
||||
{
|
||||
{ 2, 12 },
|
||||
{ 3, 39 },
|
||||
{ 4, 87 },
|
||||
{ 5, 162 },
|
||||
{ 6, 270 },
|
||||
{ 7, 417 },
|
||||
{ 8, 609 }
|
||||
};
|
||||
AnimationPlayer.AnimationFinished += OnAnimationFinished;
|
||||
_expToNextLevel = new Dictionary<int, int>
|
||||
{
|
||||
{ 2, 12 },
|
||||
{ 3, 39 },
|
||||
{ 4, 87 },
|
||||
{ 5, 162 },
|
||||
{ 6, 270 },
|
||||
{ 7, 417 },
|
||||
{ 8, 609 }
|
||||
};
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
var container = new SimpleInjector.Container();
|
||||
container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
|
||||
container.Verify();
|
||||
var container = new SimpleInjector.Container();
|
||||
container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
|
||||
container.Verify();
|
||||
|
||||
Settings = new PlayerLogic.Settings() { RotationSpeed = PlayerStatResource.RotationSpeed, MoveSpeed = PlayerStatResource.MoveSpeed, Acceleration = PlayerStatResource.Acceleration };
|
||||
Stats = new PlayerStatController();
|
||||
Stats.Init(
|
||||
new PlayerStats
|
||||
{
|
||||
CurrentHP = PlayerStatResource.CurrentHP,
|
||||
MaximumHP = PlayerStatResource.MaximumHP,
|
||||
CurrentVT = PlayerStatResource.CurrentVT,
|
||||
MaximumVT = PlayerStatResource.MaximumVT,
|
||||
CurrentAttack = PlayerStatResource.CurrentAttack,
|
||||
BonusAttack = PlayerStatResource.BonusAttack,
|
||||
MaxAttack = PlayerStatResource.MaxAttack,
|
||||
CurrentDefense = PlayerStatResource.CurrentDefense,
|
||||
BonusDefense = PlayerStatResource.BonusDefense,
|
||||
MaxDefense = PlayerStatResource.MaxDefense,
|
||||
CurrentExp = PlayerStatResource.CurrentExp,
|
||||
CurrentLevel = PlayerStatResource.CurrentLevel,
|
||||
ExpToNextLevel = PlayerStatResource.ExpToNextLevel,
|
||||
Luck = PlayerStatResource.Luck
|
||||
});
|
||||
Settings = new PlayerLogic.Settings() { RotationSpeed = PlayerStatResource.RotationSpeed, MoveSpeed = PlayerStatResource.MoveSpeed, Acceleration = PlayerStatResource.Acceleration };
|
||||
Stats = new PlayerStatController();
|
||||
Stats.Init(
|
||||
new PlayerStats
|
||||
{
|
||||
CurrentHP = PlayerStatResource.CurrentHP,
|
||||
MaximumHP = PlayerStatResource.MaximumHP,
|
||||
CurrentVT = PlayerStatResource.CurrentVT,
|
||||
MaximumVT = PlayerStatResource.MaximumVT,
|
||||
CurrentAttack = PlayerStatResource.CurrentAttack,
|
||||
BonusAttack = PlayerStatResource.BonusAttack,
|
||||
MaxAttack = PlayerStatResource.MaxAttack,
|
||||
CurrentDefense = PlayerStatResource.CurrentDefense,
|
||||
BonusDefense = PlayerStatResource.BonusDefense,
|
||||
MaxDefense = PlayerStatResource.MaxDefense,
|
||||
CurrentExp = PlayerStatResource.CurrentExp,
|
||||
CurrentLevel = PlayerStatResource.CurrentLevel,
|
||||
ExpToNextLevel = PlayerStatResource.ExpToNextLevel,
|
||||
Luck = PlayerStatResource.Luck
|
||||
});
|
||||
|
||||
Inventory = new Inventory();
|
||||
Inventory = new Inventory();
|
||||
|
||||
PlayerLogic = container.GetInstance<IPlayerLogic>();
|
||||
PlayerLogic.Set(this as IPlayer);
|
||||
PlayerLogic.Set(Settings);
|
||||
PlayerLogic.Set(Stats);
|
||||
PlayerLogic.Set(_gameRepo);
|
||||
PlayerLogic = container.GetInstance<IPlayerLogic>();
|
||||
PlayerLogic.Set(this as IPlayer);
|
||||
PlayerLogic.Set(Settings);
|
||||
PlayerLogic.Set(Stats);
|
||||
PlayerLogic.Set(_gameRepo);
|
||||
|
||||
var defaultWeapon = new Weapon();
|
||||
defaultWeapon.Stats = _defaultWeapon;
|
||||
var defaultArmor = new Armor();
|
||||
defaultArmor.Stats = _defaultArmor;
|
||||
Inventory.TryAdd(defaultWeapon);
|
||||
Inventory.TryAdd(defaultArmor);
|
||||
var defaultWeapon = new Weapon();
|
||||
defaultWeapon.Stats = _defaultWeapon;
|
||||
var defaultArmor = new Armor();
|
||||
defaultArmor.Stats = _defaultArmor;
|
||||
Inventory.TryAdd(defaultWeapon);
|
||||
Inventory.TryAdd(defaultArmor);
|
||||
|
||||
EquippedWeapon.Sync += EquippedWeapon_Sync;
|
||||
EquippedArmor.Sync += EquippedArmor_Sync;
|
||||
EquippedAccessory.Sync += EquippedAccessory_Sync;
|
||||
Stats.CurrentHP.Sync += CurrentHP_Sync;
|
||||
Stats.CurrentExp.Sync += CurrentEXP_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);
|
||||
Equip(defaultWeapon);
|
||||
Equip(defaultArmor);
|
||||
|
||||
HealthTimer.WaitTime = _healthTimerWaitTime;
|
||||
HealthTimer.Timeout += OnHealthTimerTimeout;
|
||||
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
|
||||
HealthTimer.WaitTime = _healthTimerWaitTime;
|
||||
HealthTimer.Timeout += OnHealthTimerTimeout;
|
||||
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
|
||||
}
|
||||
|
||||
public void OnResolved()
|
||||
{
|
||||
PlayerChunk = new SaveChunk<PlayerData>(
|
||||
onSave: (chunk) => new PlayerData()
|
||||
{
|
||||
PlayerStats = new PlayerStats()
|
||||
{
|
||||
CurrentHP = Stats.CurrentHP.Value,
|
||||
MaximumHP = Stats.MaximumHP.Value,
|
||||
CurrentVT = Stats.CurrentVT.Value,
|
||||
MaximumVT = Stats.MaximumVT.Value,
|
||||
CurrentAttack = Stats.CurrentAttack.Value,
|
||||
BonusAttack = Stats.BonusAttack.Value,
|
||||
MaxAttack = Stats.MaxAttack.Value,
|
||||
CurrentDefense = Stats.CurrentDefense.Value,
|
||||
BonusDefense = Stats.BonusDefense.Value,
|
||||
MaxDefense = Stats.MaxDefense.Value,
|
||||
CurrentExp = Stats.CurrentExp.Value,
|
||||
CurrentLevel = Stats.CurrentLevel.Value,
|
||||
ExpToNextLevel = Stats.ExpToNextLevel.Value,
|
||||
Luck = Stats.Luck.Value
|
||||
},
|
||||
Inventory = Inventory
|
||||
},
|
||||
onLoad: (chunk, data) =>
|
||||
{
|
||||
Stats.Init(data.PlayerStats);
|
||||
Inventory = data.Inventory;
|
||||
}
|
||||
);
|
||||
PlayerChunk = new SaveChunk<PlayerData>(
|
||||
onSave: (chunk) => new PlayerData()
|
||||
{
|
||||
PlayerStats = new PlayerStats()
|
||||
{
|
||||
CurrentHP = Stats.CurrentHP.Value,
|
||||
MaximumHP = Stats.MaximumHP.Value,
|
||||
CurrentVT = Stats.CurrentVT.Value,
|
||||
MaximumVT = Stats.MaximumVT.Value,
|
||||
CurrentAttack = Stats.CurrentAttack.Value,
|
||||
BonusAttack = Stats.BonusAttack.Value,
|
||||
MaxAttack = Stats.MaxAttack.Value,
|
||||
CurrentDefense = Stats.CurrentDefense.Value,
|
||||
BonusDefense = Stats.BonusDefense.Value,
|
||||
MaxDefense = Stats.MaxDefense.Value,
|
||||
CurrentExp = Stats.CurrentExp.Value,
|
||||
CurrentLevel = Stats.CurrentLevel.Value,
|
||||
ExpToNextLevel = Stats.ExpToNextLevel.Value,
|
||||
Luck = Stats.Luck.Value
|
||||
},
|
||||
Inventory = Inventory
|
||||
},
|
||||
onLoad: (chunk, data) =>
|
||||
{
|
||||
Stats.Init(data.PlayerStats);
|
||||
Inventory = data.Inventory;
|
||||
}
|
||||
);
|
||||
|
||||
PlayerBinding = PlayerLogic.Bind();
|
||||
PlayerBinding = PlayerLogic.Bind();
|
||||
|
||||
PlayerBinding
|
||||
.Handle((in PlayerLogic.Output.Animations.Attack output) =>
|
||||
{
|
||||
if (PlayerIsHittingGeometry())
|
||||
{
|
||||
AnimationPlayer.Play("hit_wall");
|
||||
_gameRepo.OnPlayerAttackedWall();
|
||||
}
|
||||
else
|
||||
{
|
||||
var attackSpeed = ((Weapon)EquippedWeapon.Value).AttackSpeed;
|
||||
AnimationPlayer.SetSpeedScale((float)attackSpeed);
|
||||
AnimationPlayer.Play("attack");
|
||||
_gameRepo.OnPlayerAttack();
|
||||
}
|
||||
})
|
||||
.Handle((in PlayerLogic.Output.ThrowItem output) =>
|
||||
{
|
||||
})
|
||||
.Handle((in PlayerLogic.Output.Move output) =>
|
||||
{
|
||||
Move(output.delta);
|
||||
});
|
||||
PlayerBinding
|
||||
.Handle((in PlayerLogic.Output.Animations.Attack output) =>
|
||||
{
|
||||
if (PlayerIsHittingGeometry())
|
||||
{
|
||||
AnimationPlayer.Play("hit_wall");
|
||||
_gameRepo.OnPlayerAttackedWall();
|
||||
}
|
||||
else
|
||||
{
|
||||
var attackSpeed = ((Weapon)EquippedWeapon.Value).AttackSpeed;
|
||||
AnimationPlayer.SetSpeedScale((float)attackSpeed);
|
||||
AnimationPlayer.Play("attack");
|
||||
_gameRepo.OnPlayerAttack();
|
||||
}
|
||||
})
|
||||
.Handle((in PlayerLogic.Output.ThrowItem output) =>
|
||||
{
|
||||
})
|
||||
.Handle((in PlayerLogic.Output.Move output) =>
|
||||
{
|
||||
Move(output.delta);
|
||||
});
|
||||
|
||||
GameChunk.AddChunk(PlayerChunk);
|
||||
GameChunk.AddChunk(PlayerChunk);
|
||||
|
||||
PlayerLogic.Start();
|
||||
this.Provide();
|
||||
PlayerLogic.Start();
|
||||
this.Provide();
|
||||
}
|
||||
|
||||
public void OnReady()
|
||||
{
|
||||
SetPhysicsProcess(true);
|
||||
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
|
||||
SetPhysicsProcess(true);
|
||||
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Attack()
|
||||
{
|
||||
PlayerLogic.Input(new PlayerLogic.Input.Attack());
|
||||
PlayerLogic.Input(new PlayerLogic.Input.Attack());
|
||||
}
|
||||
|
||||
public void PlayerPause()
|
||||
{
|
||||
Game.TogglePause();
|
||||
Game.TogglePause();
|
||||
}
|
||||
|
||||
public void RaiseHP(int amountToRaise)
|
||||
{
|
||||
Stats.SetMaximumHP(Stats.MaximumHP.Value + amountToRaise);
|
||||
Stats.SetCurrentHP(Stats.MaximumHP.Value);
|
||||
_gameRepo.AnnounceMessageInInventory($"{amountToRaise}MAXHP Up.");
|
||||
Stats.SetMaximumHP(Stats.MaximumHP.Value + amountToRaise);
|
||||
Stats.SetCurrentHP(Stats.MaximumHP.Value);
|
||||
_gameRepo.AnnounceMessageInInventory($"{amountToRaise}MAXHP Up.");
|
||||
}
|
||||
|
||||
public void HealHP(int amountToRestore)
|
||||
{
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
_gameRepo.AnnounceMessageInInventory($"{raiseString}HP Restored.");
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
_gameRepo.AnnounceMessageInInventory($"{raiseString}HP Restored.");
|
||||
}
|
||||
|
||||
public void RaiseVT(int amountToRaise)
|
||||
{
|
||||
if (Stats.CurrentVT == Stats.MaximumVT)
|
||||
{
|
||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amountToRaise);
|
||||
Stats.SetCurrentVT(Stats.MaximumVT.Value);
|
||||
_gameRepo.AnnounceMessageInInventory($"{amountToRaise}MAXVT Up.");
|
||||
}
|
||||
if (Stats.CurrentVT == Stats.MaximumVT)
|
||||
{
|
||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amountToRaise);
|
||||
Stats.SetCurrentVT(Stats.MaximumVT.Value);
|
||||
_gameRepo.AnnounceMessageInInventory($"{amountToRaise}MAXVT Up.");
|
||||
}
|
||||
}
|
||||
|
||||
public void HealVT(int amountToRestore)
|
||||
{
|
||||
Stats.SetCurrentVT(Stats.CurrentVT.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
_gameRepo.AnnounceMessageInInventory($"{raiseString}VT Restored.");
|
||||
Stats.SetCurrentVT(Stats.CurrentVT.Value + amountToRestore);
|
||||
var raiseString = amountToRestore == 1000 ? "MAX" : $"{amountToRestore}";
|
||||
_gameRepo.AnnounceMessageInInventory($"{raiseString}VT Restored.");
|
||||
}
|
||||
|
||||
public void ModifyBonusAttack(int amount)
|
||||
{
|
||||
Stats.SetBonusAttack(Stats.BonusAttack.Value + amount);
|
||||
Stats.SetBonusAttack(Stats.BonusAttack.Value + amount);
|
||||
}
|
||||
|
||||
public void ModifyBonusDefense(int amount)
|
||||
{
|
||||
Stats.SetBonusDefense(Stats.BonusDefense.Value + amount);
|
||||
Stats.SetBonusDefense(Stats.BonusDefense.Value + amount);
|
||||
}
|
||||
|
||||
public void ModifyMaximumHP(int amount)
|
||||
{
|
||||
Stats.SetMaximumHP(Stats.MaximumHP.Value + amount);
|
||||
Stats.SetMaximumHP(Stats.MaximumHP.Value + amount);
|
||||
}
|
||||
|
||||
public void ModifyMaximumVT(int amount)
|
||||
{
|
||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amount);
|
||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amount);
|
||||
}
|
||||
|
||||
public void ModifyBonusLuck(double amount)
|
||||
{
|
||||
Stats.SetLuck(Stats.Luck.Value + amount);
|
||||
Stats.SetLuck(Stats.Luck.Value + amount);
|
||||
}
|
||||
|
||||
public void Move(float delta)
|
||||
{
|
||||
var rawInput = GlobalInputVector;
|
||||
var strafeLeftInput = LeftStrafeInputVector;
|
||||
var strafeRightInput = RightStrafeInputVector;
|
||||
var rawInput = GlobalInputVector;
|
||||
var strafeLeftInput = LeftStrafeInputVector;
|
||||
var strafeRightInput = RightStrafeInputVector;
|
||||
|
||||
var transform = Transform;
|
||||
transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis;
|
||||
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized();
|
||||
var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration;
|
||||
_knockbackStrength = _knockbackStrength * 0.9f;
|
||||
Transform = Transform with { Basis = transform.Basis };
|
||||
Velocity = velocity + (_knockbackDirection * _knockbackStrength);
|
||||
MoveAndSlide();
|
||||
var transform = Transform;
|
||||
transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis;
|
||||
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized();
|
||||
var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration;
|
||||
_knockbackStrength = _knockbackStrength * 0.9f;
|
||||
Transform = Transform with { Basis = transform.Basis };
|
||||
Velocity = velocity + (_knockbackDirection * _knockbackStrength);
|
||||
MoveAndSlide();
|
||||
}
|
||||
|
||||
public void TeleportPlayer(Transform3D newTransform)
|
||||
{
|
||||
Transform = newTransform;
|
||||
Transform = newTransform;
|
||||
}
|
||||
|
||||
public void TakeDamage(double damage, ElementType elementType, bool isCriticalHit = false)
|
||||
{
|
||||
if (Stats.CurrentHP.Value > 0)
|
||||
{
|
||||
damage = CalculateDefenseResistance(damage);
|
||||
if (isCriticalHit)
|
||||
damage *= 2;
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value - (int)damage);
|
||||
}
|
||||
if (Stats.CurrentHP.Value > 0)
|
||||
{
|
||||
damage = CalculateDefenseResistance(damage);
|
||||
if (isCriticalHit)
|
||||
damage *= 2;
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value - (int)damage);
|
||||
}
|
||||
}
|
||||
|
||||
public void Knockback(float impulse)
|
||||
{
|
||||
_knockbackStrength = impulse;
|
||||
_knockbackDirection = GlobalBasis.Z.Normalized();
|
||||
_knockbackStrength = impulse;
|
||||
_knockbackDirection = GlobalBasis.Z.Normalized();
|
||||
}
|
||||
|
||||
public void GainExp(double expGained)
|
||||
{
|
||||
Stats.SetCurrentExp(Stats.CurrentExp.Value + expGained);
|
||||
Stats.SetCurrentExp(Stats.CurrentExp.Value + expGained);
|
||||
}
|
||||
|
||||
public void LevelUp()
|
||||
{
|
||||
var nextLevel = Stats.CurrentLevel.Value + 1;
|
||||
var expToNextLevel = _expToNextLevel[nextLevel];
|
||||
var newCurrentExp = Mathf.Max(Stats.CurrentExp.Value - Stats.ExpToNextLevel.Value, 0);
|
||||
Stats.SetCurrentLevel(nextLevel);
|
||||
Stats.SetExpToNextLevel(expToNextLevel);
|
||||
Stats.SetCurrentExp(newCurrentExp);
|
||||
var nextLevel = Stats.CurrentLevel.Value + 1;
|
||||
var expToNextLevel = _expToNextLevel[nextLevel];
|
||||
var newCurrentExp = Mathf.Max(Stats.CurrentExp.Value - Stats.ExpToNextLevel.Value, 0);
|
||||
Stats.SetCurrentLevel(nextLevel);
|
||||
Stats.SetExpToNextLevel(expToNextLevel);
|
||||
Stats.SetCurrentExp(newCurrentExp);
|
||||
}
|
||||
|
||||
public void Die() => PlayerLogic.Input(new PlayerLogic.Input.Die());
|
||||
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
{
|
||||
if (@event.IsActionPressed(GameInputs.Pause))
|
||||
PlayerPause();
|
||||
if (@event.IsActionPressed(GameInputs.Pause))
|
||||
PlayerPause();
|
||||
|
||||
if (@event.IsActionPressed(GameInputs.Attack))
|
||||
Attack();
|
||||
if (@event.IsActionPressed(GameInputs.Attack))
|
||||
Attack();
|
||||
}
|
||||
|
||||
public void OnPhysicsProcess(double delta)
|
||||
{
|
||||
PlayerLogic.Input(new PlayerLogic.Input.PhysicsTick(delta));
|
||||
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
|
||||
PlayerLogic.Input(new PlayerLogic.Input.PhysicsTick(delta));
|
||||
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
|
||||
}
|
||||
|
||||
public void Equip(EquipableItem 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.");
|
||||
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(EquipableItem 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 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.ItemTag == ItemTag.BreaksOnChange)
|
||||
Inventory.Remove(equipable);
|
||||
if (equipable.ItemTag == ItemTag.BreaksOnChange)
|
||||
Inventory.Remove(equipable);
|
||||
}
|
||||
|
||||
private static Vector3 GlobalInputVector
|
||||
{
|
||||
get
|
||||
{
|
||||
var rawInput = Input.GetVector(GameInputs.MoveLeft, GameInputs.MoveRight, GameInputs.MoveUp, GameInputs.MoveDown);
|
||||
var input = new Vector3
|
||||
{
|
||||
X = rawInput.X,
|
||||
Z = rawInput.Y
|
||||
};
|
||||
return input with { Y = 0f };
|
||||
}
|
||||
get
|
||||
{
|
||||
var rawInput = Input.GetVector(GameInputs.MoveLeft, GameInputs.MoveRight, GameInputs.MoveUp, GameInputs.MoveDown);
|
||||
var input = new Vector3
|
||||
{
|
||||
X = rawInput.X,
|
||||
Z = rawInput.Y
|
||||
};
|
||||
return input with { Y = 0f };
|
||||
}
|
||||
}
|
||||
|
||||
private static float LeftStrafeInputVector
|
||||
{
|
||||
get
|
||||
{
|
||||
return Input.GetActionStrength(GameInputs.StrafeLeft);
|
||||
}
|
||||
get
|
||||
{
|
||||
return Input.GetActionStrength(GameInputs.StrafeLeft);
|
||||
}
|
||||
}
|
||||
|
||||
private static float RightStrafeInputVector
|
||||
{
|
||||
get
|
||||
{
|
||||
return Input.GetActionStrength(GameInputs.StrafeRight);
|
||||
}
|
||||
get
|
||||
{
|
||||
return Input.GetActionStrength(GameInputs.StrafeRight);
|
||||
}
|
||||
}
|
||||
|
||||
private void ThrowItem()
|
||||
{
|
||||
var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn");
|
||||
var throwItem = itemScene.Instantiate<ThrowableItem>();
|
||||
GetTree().Root.AddChildEx(throwItem);
|
||||
throwItem.GlobalPosition = CurrentPosition + new Vector3(0, 3.5f, 0);
|
||||
throwItem.GlobalRotation = GlobalRotation;
|
||||
var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn");
|
||||
var throwItem = itemScene.Instantiate<ThrowableItem>();
|
||||
GetTree().Root.AddChildEx(throwItem);
|
||||
throwItem.GlobalPosition = CurrentPosition + new Vector3(0, 3.5f, 0);
|
||||
throwItem.GlobalRotation = GlobalRotation;
|
||||
}
|
||||
|
||||
private void OnAnimationFinished(StringName animation)
|
||||
{
|
||||
PlayerLogic.Input(new PlayerLogic.Input.AttackAnimationFinished());
|
||||
PlayerLogic.Input(new PlayerLogic.Input.AttackAnimationFinished());
|
||||
}
|
||||
|
||||
private void OnExitTree()
|
||||
{
|
||||
PlayerLogic.Stop();
|
||||
PlayerBinding.Dispose();
|
||||
AnimationPlayer.AnimationFinished -= OnAnimationFinished;
|
||||
PlayerLogic.Stop();
|
||||
PlayerBinding.Dispose();
|
||||
AnimationPlayer.AnimationFinished -= OnAnimationFinished;
|
||||
}
|
||||
|
||||
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
|
||||
|
||||
private void OnHealthTimerTimeout()
|
||||
{
|
||||
if (Stats.CurrentHP.Value <= 0)
|
||||
return;
|
||||
if (Stats.CurrentHP.Value <= 0)
|
||||
return;
|
||||
|
||||
if (Stats.CurrentVT.Value > 0)
|
||||
{
|
||||
if (((Accessory)EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption)
|
||||
{
|
||||
reduceOnTick = !reduceOnTick;
|
||||
}
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value + 1);
|
||||
if (reduceOnTick)
|
||||
Stats.SetCurrentVT(Stats.CurrentVT.Value - 1);
|
||||
}
|
||||
else
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value - 1);
|
||||
if (Stats.CurrentVT.Value > 0)
|
||||
{
|
||||
if (((Accessory)EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption)
|
||||
{
|
||||
reduceOnTick = !reduceOnTick;
|
||||
}
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value + 1);
|
||||
if (reduceOnTick)
|
||||
Stats.SetCurrentVT(Stats.CurrentVT.Value - 1);
|
||||
}
|
||||
else
|
||||
Stats.SetCurrentHP(Stats.CurrentHP.Value - 1);
|
||||
}
|
||||
|
||||
private void EquippedWeapon_Sync(EquipableItem obj)
|
||||
{
|
||||
ModifyBonusAttack(((Weapon)obj).Damage);
|
||||
ModifyBonusAttack(((Weapon)obj).Damage);
|
||||
}
|
||||
|
||||
private void EquippedArmor_Sync(EquipableItem obj)
|
||||
{
|
||||
ModifyBonusDefense(((Armor)obj).Defense);
|
||||
ModifyBonusDefense(((Armor)obj).Defense);
|
||||
}
|
||||
|
||||
private void EquippedAccessory_Sync(EquipableItem accessory)
|
||||
{
|
||||
ModifyMaximumHP(((Accessory)accessory).MaxHPUp);
|
||||
ModifyMaximumVT(((Accessory)accessory).MaxVTUp);
|
||||
ModifyBonusAttack(((Accessory)accessory).ATKUp);
|
||||
ModifyBonusDefense(((Accessory)accessory).DEFUp);
|
||||
ModifyBonusLuck(((Accessory)accessory).LuckUp);
|
||||
ModifyMaximumHP(((Accessory)accessory).MaxHPUp);
|
||||
ModifyMaximumVT(((Accessory)accessory).MaxVTUp);
|
||||
ModifyBonusAttack(((Accessory)accessory).ATKUp);
|
||||
ModifyBonusDefense(((Accessory)accessory).DEFUp);
|
||||
ModifyBonusLuck(((Accessory)accessory).LuckUp);
|
||||
}
|
||||
|
||||
private void CurrentHP_Sync(int newHealth)
|
||||
{
|
||||
if (newHealth <= 0)
|
||||
Die();
|
||||
if (newHealth <= 0)
|
||||
Die();
|
||||
}
|
||||
|
||||
private void CurrentEXP_Sync(double newExp)
|
||||
{
|
||||
if (Stats.CurrentExp.Value >= Stats.ExpToNextLevel.Value)
|
||||
LevelUp();
|
||||
if (Stats.CurrentExp.Value >= Stats.ExpToNextLevel.Value)
|
||||
LevelUp();
|
||||
}
|
||||
|
||||
private double CalculateDefenseResistance(double incomingDamage)
|
||||
{
|
||||
return Mathf.Max(incomingDamage - Stats.CurrentDefense.Value - Stats.BonusDefense.Value, 0.0);
|
||||
return Mathf.Max(incomingDamage - Stats.CurrentDefense.Value - Stats.BonusDefense.Value, 0.0);
|
||||
}
|
||||
|
||||
private void Hitbox_AreaEntered(Area3D area)
|
||||
{
|
||||
var target = area.GetOwner();
|
||||
if (target is IEnemy enemy)
|
||||
HitEnemy(enemy);
|
||||
var target = area.GetOwner();
|
||||
if (target is IEnemy enemy)
|
||||
HitEnemy(enemy);
|
||||
}
|
||||
|
||||
private void HitEnemy(IEnemy enemy)
|
||||
{
|
||||
var attackValue = Stats.CurrentAttack.Value + Stats.BonusAttack.Value;
|
||||
var ignoreElementalResistance = ((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.IgnoreAffinity;
|
||||
var isCriticalHit = BattleExtensions.IsCriticalHit(Stats.Luck.Value);
|
||||
var element = ((Weapon)EquippedWeapon.Value).WeaponElement;
|
||||
var attackValue = Stats.CurrentAttack.Value + Stats.BonusAttack.Value;
|
||||
var ignoreElementalResistance = ((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.IgnoreAffinity;
|
||||
var isCriticalHit = BattleExtensions.IsCriticalHit(Stats.Luck.Value);
|
||||
var element = ((Weapon)EquippedWeapon.Value).WeaponElement;
|
||||
|
||||
enemy.TakeDamage(
|
||||
attackValue * ((Weapon)EquippedWeapon.Value).ElementalDamageBonus,
|
||||
element,
|
||||
isCriticalHit,
|
||||
false,
|
||||
ignoreElementalResistance);
|
||||
enemy.TakeDamage(
|
||||
attackValue * ((Weapon)EquippedWeapon.Value).ElementalDamageBonus,
|
||||
element,
|
||||
isCriticalHit,
|
||||
false,
|
||||
ignoreElementalResistance);
|
||||
|
||||
if (((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback)
|
||||
enemy.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
||||
if (((Weapon)EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback)
|
||||
enemy.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
||||
|
||||
_gameRepo.OnPlayerAttackedEnemy();
|
||||
_gameRepo.OnPlayerAttackedEnemy();
|
||||
}
|
||||
|
||||
private void CollisionDetector_AreaEntered(Area3D area)
|
||||
{
|
||||
if (area.GetParent() is InventoryItem inventoryItem)
|
||||
{
|
||||
var isAdded = Inventory.TryAdd(inventoryItem);
|
||||
if (isAdded)
|
||||
{
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"{inventoryItem.ItemName} picked up.");
|
||||
inventoryItem.QueueFree();
|
||||
}
|
||||
else
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {inventoryItem.ItemName}.");
|
||||
}
|
||||
if (area.GetParent() is DroppedItem droppedItem)
|
||||
{
|
||||
var isAdded = Inventory.TryAdd(droppedItem.Item);
|
||||
if (isAdded)
|
||||
{
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"{droppedItem.Item.ItemName} picked up.");
|
||||
droppedItem.QueueFree();
|
||||
}
|
||||
else
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {droppedItem.Item.ItemName}.");
|
||||
}
|
||||
if (area.GetParent() is InventoryItem inventoryItem)
|
||||
{
|
||||
var isAdded = Inventory.TryAdd(inventoryItem);
|
||||
if (isAdded)
|
||||
{
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"{inventoryItem.ItemName} picked up.");
|
||||
inventoryItem.QueueFree();
|
||||
}
|
||||
else
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {inventoryItem.ItemName}.");
|
||||
}
|
||||
if (area.GetParent() is DroppedItem droppedItem)
|
||||
{
|
||||
var isAdded = Inventory.TryAdd(droppedItem.Item);
|
||||
if (isAdded)
|
||||
{
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"{droppedItem.Item.ItemName} picked up.");
|
||||
droppedItem.QueueFree();
|
||||
}
|
||||
else
|
||||
_gameRepo.AnnounceMessageOnMainScreen($"Could not pick up {droppedItem.Item.ItemName}.");
|
||||
}
|
||||
}
|
||||
|
||||
private bool PlayerIsHittingGeometry()
|
||||
{
|
||||
var collisions = WallCheck.GetCollidingBodies();
|
||||
return collisions.Count > 0;
|
||||
var collisions = WallCheck.GetCollidingBodies();
|
||||
return collisions.Count > 0;
|
||||
}
|
||||
|
||||
private void WallCheck_BodyEntered(Node body)
|
||||
{
|
||||
PlayerLogic.Input(new PlayerLogic.Input.AttackAnimationFinished());
|
||||
GD.Print("Hit wall");
|
||||
AnimationPlayer.Stop();
|
||||
PlayerLogic.Input(new PlayerLogic.Input.AttackAnimationFinished());
|
||||
GD.Print("Hit wall");
|
||||
AnimationPlayer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user