Small Changes

This commit is contained in:
Pal
2026-02-10 01:21:47 -08:00
parent 8001556f37
commit 843a100218
7 changed files with 1019 additions and 273 deletions

View File

@@ -81,6 +81,7 @@ import/blender/enabled=false
[importer_defaults] [importer_defaults]
texture={ texture={
&"compress/high_quality": true,
&"compress/mode": 2, &"compress/mode": 2,
&"detect_3d/compress_to": 0 &"detect_3d/compress_to": 0
} }

View File

@@ -8,6 +8,7 @@ script = ExtResource("2_4aje4")
AttackSpeed = 1.0 AttackSpeed = 1.0
WeaponElement = 0 WeaponElement = 0
WeaponTag = 2 WeaponTag = 2
SelfDamage = 0
SoundEffect = 22 SoundEffect = 22
Name = "Nebula Chain" Name = "Nebula Chain"
Description = "Chain Whip that strikes through time and dimension." Description = "Chain Whip that strikes through time and dimension."

View File

@@ -3,7 +3,7 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://cr2jhtawg0lsw" uid="uid://cr2jhtawg0lsw"
path.s3tc="res://.godot/imported/Nebula Chain.png-99ddad7d70f9e8aa9060816e05a6f73d.s3tc.ctex" path.bptc="res://.godot/imported/Nebula Chain.png-99ddad7d70f9e8aa9060816e05a6f73d.bptc.ctex"
metadata={ metadata={
"imported_formats": ["s3tc_bptc"], "imported_formats": ["s3tc_bptc"],
"vram_texture": true "vram_texture": true
@@ -12,12 +12,12 @@ metadata={
[deps] [deps]
source_file="res://src/items/weapons/textures/Nebula Chain.png" source_file="res://src/items/weapons/textures/Nebula Chain.png"
dest_files=["res://.godot/imported/Nebula Chain.png-99ddad7d70f9e8aa9060816e05a6f73d.s3tc.ctex"] dest_files=["res://.godot/imported/Nebula Chain.png-99ddad7d70f9e8aa9060816e05a6f73d.bptc.ctex"]
[params] [params]
compress/mode=2 compress/mode=2
compress/high_quality=false compress/high_quality=true
compress/lossy_quality=0.7 compress/lossy_quality=0.7
compress/hdr_compression=1 compress/hdr_compression=1
compress/normal_map=0 compress/normal_map=0

View File

@@ -20,9 +20,9 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
public void InitializeDungeon() public void InitializeDungeon()
{ {
Rooms = []; Rooms = [];
Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms); Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms);
_playerSpawnPoint = RandomizePlayerSpawnPoint(); _playerSpawnPoint = RandomizePlayerSpawnPoint();
} }
public void FadeOutAudio() public void FadeOutAudio()
@@ -32,27 +32,27 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
public void SpawnEnemies(DungeonFloorNode floorNode) public void SpawnEnemies(DungeonFloorNode floorNode)
{ {
var enemyOdds = new Godot.Collections.Dictionary<EnemyType, float> var enemyOdds = new Godot.Collections.Dictionary<EnemyType, float>
{ {
{ EnemyType.Sproingy, floorNode.Sproingy }, { EnemyType.Sproingy, floorNode.Sproingy },
{ EnemyType.Michael, floorNode.Michael }, { EnemyType.Michael, floorNode.Michael },
{ EnemyType.FilthEater, floorNode.FilthEater }, { EnemyType.FilthEater, floorNode.FilthEater },
{ EnemyType.Sara, floorNode.Sara }, { EnemyType.Sara, floorNode.Sara },
{ EnemyType.Ballos, floorNode.Ballos }, { EnemyType.Ballos, floorNode.Ballos },
{ EnemyType.Chariot, floorNode.Chariot }, { EnemyType.Chariot, floorNode.Chariot },
{ EnemyType.Chinthe, floorNode.Chinthe }, { EnemyType.Chinthe, floorNode.Chinthe },
{ EnemyType.AmbassadorGreen, floorNode.GreenAmbassador }, { EnemyType.AmbassadorGreen, floorNode.GreenAmbassador },
{ EnemyType.AmbassadorRed, floorNode.RedAmbassador }, { EnemyType.AmbassadorRed, floorNode.RedAmbassador },
{ EnemyType.AmbassadorSteel, floorNode.SteelAmbassador }, { EnemyType.AmbassadorSteel, floorNode.SteelAmbassador },
{ EnemyType.AgniDemon, floorNode.AgniDemon }, { EnemyType.AgniDemon, floorNode.AgniDemon },
{ EnemyType.AqueousDemon, floorNode.AqueosDemon }, { EnemyType.AqueousDemon, floorNode.AqueosDemon },
{ EnemyType.Palan, floorNode.Palan }, { EnemyType.Palan, floorNode.Palan },
{ EnemyType.ShieldOfHeaven, floorNode.ShieldOfHeaven }, { EnemyType.ShieldOfHeaven, floorNode.ShieldOfHeaven },
{ EnemyType.GoldSproingy, floorNode.GoldSproingy }, { EnemyType.GoldSproingy, floorNode.GoldSproingy },
}; };
var monsterRooms = Rooms.OfType<MonsterRoom>(); var monsterRooms = Rooms.OfType<MonsterRoom>();
foreach (var room in monsterRooms) foreach (var room in monsterRooms)
room.SpawnEnemies(enemyOdds); room.SpawnEnemies(enemyOdds);
} }
public (Vector3 Rotation, Vector3 Position) GetPlayerSpawnPoint() { return (_playerSpawnPoint.Rotation, new Vector3(_playerSpawnPoint.GlobalPosition.X, 0, _playerSpawnPoint.GlobalPosition.Z)); } public (Vector3 Rotation, Vector3 Position) GetPlayerSpawnPoint() { return (_playerSpawnPoint.Rotation, new Vector3(_playerSpawnPoint.GlobalPosition.X, 0, _playerSpawnPoint.GlobalPosition.Z)); }
@@ -60,25 +60,25 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
private Marker3D RandomizePlayerSpawnPoint() private Marker3D RandomizePlayerSpawnPoint()
{ {
var randomSpawnLocations = Rooms var randomSpawnLocations = Rooms
.OfType<MonsterRoom>() .OfType<MonsterRoom>()
.Select(x => x.PlayerSpawn); .Select(x => x.PlayerSpawn);
var godotCollection = new Godot.Collections.Array<Marker3D>(randomSpawnLocations); var godotCollection = new Godot.Collections.Array<Marker3D>(randomSpawnLocations);
var result = godotCollection.PickRandom(); var result = godotCollection.PickRandom();
return result; return result;
} }
private static ImmutableList<IDungeonRoom> FindAllDungeonRooms(List<Node> nodesToSearch, ImmutableList<IDungeonRoom> roomsFound) private static ImmutableList<IDungeonRoom> FindAllDungeonRooms(List<Node> nodesToSearch, ImmutableList<IDungeonRoom> roomsFound)
{ {
if (nodesToSearch.Count == 0) if (nodesToSearch.Count == 0)
return roomsFound; return roomsFound;
foreach (var node in nodesToSearch) foreach (var node in nodesToSearch)
{ {
if (node is IDungeonRoom dungeonRoom) if (node is IDungeonRoom dungeonRoom)
roomsFound = roomsFound.Add(dungeonRoom); roomsFound = roomsFound.Add(dungeonRoom);
} }
return FindAllDungeonRooms([.. nodesToSearch.SelectMany(x => x.GetChildren())], roomsFound); return FindAllDungeonRooms([.. nodesToSearch.SelectMany(x => x.GetChildren())], roomsFound);
} }
} }

View File

@@ -18,21 +18,21 @@ public partial class ExitRoom : DungeonRoom
public override void _Ready() public override void _Ready()
{ {
_exit.AreaEntered += Exit_AreaEntered; _exit.AreaEntered += Exit_AreaEntered;
} }
public void ExitReached() public void ExitReached()
=> Game.FloorExitReached(); => Game.FloorExitReached();
private void Exit_AreaEntered(Area3D area) private void Exit_AreaEntered(Area3D area)
{ {
if (area.GetOwner() is IPlayer) if (area.GetOwner() is IPlayer)
ExitReached(); ExitReached();
} }
public new void OnExitTree() public new void OnExitTree()
{ {
base.OnExitTree(); base.OnExitTree();
_exit.AreaEntered -= Exit_AreaEntered; _exit.AreaEntered -= Exit_AreaEntered;
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -112,117 +112,117 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
public void Initialize() public void Initialize()
{ {
var container = new SimpleInjector.Container(); var container = new SimpleInjector.Container();
container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton); container.Register<IPlayerLogic, PlayerLogic>(Lifestyle.Singleton);
PlayerLogic = container.GetInstance<IPlayerLogic>(); PlayerLogic = container.GetInstance<IPlayerLogic>();
PlayerLogic.Set(this as IPlayer); PlayerLogic.Set(this as IPlayer);
PlayerLogic.Set(Settings); PlayerLogic.Set(Settings);
Inventory = new Inventory(); Inventory = new Inventory();
HealthComponent = new HealthComponent(InitialHP); HealthComponent = new HealthComponent(InitialHP);
VTComponent = new VTComponent(InitialVT); VTComponent = new VTComponent(InitialVT);
AttackComponent = new AttackComponent(InitialAttack); AttackComponent = new AttackComponent(InitialAttack);
DefenseComponent = new DefenseComponent(InitialDefense); DefenseComponent = new DefenseComponent(InitialDefense);
ExperiencePointsComponent = new ExperiencePointsComponent(); ExperiencePointsComponent = new ExperiencePointsComponent();
LuckComponent = new LuckComponent(InitialLuck); LuckComponent = new LuckComponent(InitialLuck);
EquipmentComponent = new EquipmentComponent(); EquipmentComponent = new EquipmentComponent();
_itemReroller = new ItemReroller(ItemDatabase.Instance); _itemReroller = new ItemReroller(ItemDatabase.Instance);
_playerEffectService = new PlayerEffectService(this); _playerEffectService = new PlayerEffectService(this);
Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed, Acceleration = Acceleration }; Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed, Acceleration = Acceleration };
PlayerBinding = PlayerLogic.Bind(); PlayerBinding = PlayerLogic.Bind();
PlayerBinding PlayerBinding
.Handle((in PlayerLogic.Output.ThrowItem output) => .Handle((in PlayerLogic.Output.ThrowItem output) =>
{ {
}) })
.Handle((in PlayerLogic.Output.Move output) => .Handle((in PlayerLogic.Output.Move output) =>
{ {
Move(output.delta); Move(output.delta);
}); });
PlayerLogic.Start(); PlayerLogic.Start();
this.Provide(); this.Provide();
} }
public void ResetPlayerData() public void ResetPlayerData()
{ {
PlayerFXAnimations.Play("RESET"); PlayerFXAnimations.Play("RESET");
foreach (var item in Inventory.Items) foreach (var item in Inventory.Items)
Inventory.Remove(item); Inventory.Remove(item);
HealthComponent.Reset(); HealthComponent.Reset();
VTComponent.Reset(); VTComponent.Reset();
AttackComponent.Reset(); AttackComponent.Reset();
DefenseComponent.Reset(); DefenseComponent.Reset();
ExperiencePointsComponent.Reset(); ExperiencePointsComponent.Reset();
LuckComponent.Reset(); LuckComponent.Reset();
EquipmentComponent.Reset(); EquipmentComponent.Reset();
HealthTimer.Timeout += OnHealthTimerTimeout; HealthTimer.Timeout += OnHealthTimerTimeout;
} }
#region Initialization #region Initialization
public void OnReady() public void OnReady()
{ {
Hitbox.AreaEntered += Hitbox_AreaEntered; Hitbox.AreaEntered += Hitbox_AreaEntered;
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered; CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
HealthComponent.CurrentHP.Changed += InverseHPToAttackPowerSync; HealthComponent.CurrentHP.Changed += InverseHPToAttackPowerSync;
HealthComponent.HealthReachedZero += Die; HealthComponent.HealthReachedZero += Die;
ExperiencePointsComponent.PlayerLevelUp += OnLevelUp; ExperiencePointsComponent.PlayerLevelUp += OnLevelUp;
PlayerFXAnimations.AnimationFinished += PlayerFXAnimations_AnimationFinished; PlayerFXAnimations.AnimationFinished += PlayerFXAnimations_AnimationFinished;
HealthTimer.WaitTime = _healthTimerWaitTime; HealthTimer.WaitTime = _healthTimerWaitTime;
SetProcessInput(false); SetProcessInput(false);
SetPhysicsProcess(false); SetPhysicsProcess(false);
} }
#endregion #endregion
public void Activate() public void Activate()
{ {
SetProcessInput(true); SetProcessInput(true);
SetPhysicsProcess(true); SetPhysicsProcess(true);
SetHealthTimerStatus(HealthTimerIsActive); SetHealthTimerStatus(HealthTimerIsActive);
} }
public void Deactivate() public void Deactivate()
{ {
Velocity = Vector3.Zero; Velocity = Vector3.Zero;
SetProcessInput(false); SetProcessInput(false);
SetPhysicsProcess(false); SetPhysicsProcess(false);
SetHealthTimerStatus(false); SetHealthTimerStatus(false);
} }
public void SetHealthTimerStatus(bool isActive) public void SetHealthTimerStatus(bool isActive)
{ {
if (isActive) if (isActive)
HealthTimer.Start(); HealthTimer.Start();
else else
HealthTimer.Stop(); HealthTimer.Stop();
} }
public void TeleportPlayer((Vector3 Rotation, Vector3 Position) newTransform) public void TeleportPlayer((Vector3 Rotation, Vector3 Position) newTransform)
{ {
Rotation = newTransform.Rotation; Rotation = newTransform.Rotation;
Position = newTransform.Position; Position = newTransform.Position;
} }
public void TakeDamage(AttackData damage) public void TakeDamage(AttackData damage)
{ {
_camera3D.AddShake(1.0f); _camera3D.AddShake(1.0f);
TakeDamageAnimationPlayer.Play("take_damage"); TakeDamageAnimationPlayer.Play("take_damage");
var damageReceived = DamageCalculator.CalculateDamage(damage, TotalDefense, EquipmentComponent.ElementalResistance); var damageReceived = DamageCalculator.CalculateDamage(damage, TotalDefense, EquipmentComponent.ElementalResistance);
HealthComponent.Damage(damageReceived); HealthComponent.Damage(damageReceived);
SfxDatabase.Instance.Play(SoundEffect.TakeDamage); SfxDatabase.Instance.Play(SoundEffect.TakeDamage);
} }
public void Knockback(float impulse) public void Knockback(float impulse)
{ {
_knockbackStrength = impulse; _knockbackStrength = impulse;
_knockbackDirection = GlobalBasis.Z.Normalized(); _knockbackDirection = GlobalBasis.Z.Normalized();
} }
public void PlayJumpScareAnimation() => PlayerFXAnimations.Play("jump_scare"); public void PlayJumpScareAnimation() => PlayerFXAnimations.Play("jump_scare");
@@ -235,82 +235,82 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
public void LevelUp() public void LevelUp()
{ {
ExperiencePointsComponent.LevelUp(); ExperiencePointsComponent.LevelUp();
} }
public void Die() public void Die()
{ {
PlayerFXAnimations.Play("death"); PlayerFXAnimations.Play("death");
HealthTimer.WaitTime = _healthTimerWaitTime; HealthTimer.WaitTime = _healthTimerWaitTime;
HealthTimer.Timeout -= OnHealthTimerTimeout; HealthTimer.Timeout -= OnHealthTimerTimeout;
SetProcessInput(false); SetProcessInput(false);
SetPhysicsProcess(false); SetPhysicsProcess(false);
} }
public override void _Input(InputEvent @event) public override void _Input(InputEvent @event)
{ {
if (@event.IsActionPressed(GameInputs.Attack)) if (@event.IsActionPressed(GameInputs.Attack))
Attack(); Attack();
if (@event.IsActionPressed(GameInputs.Sprint)) if (@event.IsActionPressed(GameInputs.Sprint))
_debugSprint = true; _debugSprint = true;
else if (@event.IsActionReleased(GameInputs.Sprint)) else if (@event.IsActionReleased(GameInputs.Sprint))
_debugSprint = false; _debugSprint = false;
} }
public void OnPhysicsProcess(double delta) public void OnPhysicsProcess(double delta)
{ {
PlayerLogic.Input(new PlayerLogic.Input.PhysicsTick(delta)); PlayerLogic.Input(new PlayerLogic.Input.PhysicsTick(delta));
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform)); PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
} }
public void Equip(EquipableItem equipable) public void Equip(EquipableItem equipable)
{ {
if (equipable.ItemTag == ItemTag.MysteryItem) if (equipable.ItemTag == ItemTag.MysteryItem)
{ {
var rerolledItem = _itemReroller.RerollItem(equipable, Inventory); var rerolledItem = _itemReroller.RerollItem(equipable, Inventory);
Equip(rerolledItem); Equip(rerolledItem);
return; return;
} }
HealthComponent.RaiseMaximumHP(equipable.BonusHP, false); HealthComponent.RaiseMaximumHP(equipable.BonusHP, false);
VTComponent.RaiseMaximumVT(equipable.BonusVT, false); VTComponent.RaiseMaximumVT(equipable.BonusVT, false);
EquipmentComponent.Equip(equipable); EquipmentComponent.Equip(equipable);
} }
public void Unequip(EquipableItem equipable) public void Unequip(EquipableItem equipable)
{ {
HealthComponent.SetMaximumHealth(HealthComponent.MaximumHP.Value - equipable.BonusHP); HealthComponent.SetMaximumHealth(HealthComponent.MaximumHP.Value - equipable.BonusHP);
VTComponent.SetMaximumVT(VTComponent.MaximumVT.Value - equipable.BonusVT); VTComponent.SetMaximumVT(VTComponent.MaximumVT.Value - equipable.BonusVT);
EquipmentComponent.Unequip(equipable); EquipmentComponent.Unequip(equipable);
} }
private static Vector3 GlobalInputVector private static Vector3 GlobalInputVector
{ {
get get
{ {
var rawInput = Input.GetVector(GameInputs.MoveLeft, GameInputs.MoveRight, GameInputs.MoveUp, GameInputs.MoveDown); var rawInput = Input.GetVector(GameInputs.MoveLeft, GameInputs.MoveRight, GameInputs.MoveUp, GameInputs.MoveDown);
var input = new Vector3 var input = new Vector3
{ {
X = rawInput.X, X = rawInput.X,
Z = rawInput.Y Z = rawInput.Y
}; };
return input with { Y = 0f }; return input with { Y = 0f };
} }
} }
private void OnLevelUp() private void OnLevelUp()
{ {
BoostPlayerHPFromLevelUp(); BoostPlayerHPFromLevelUp();
} }
private void BoostPlayerHPFromLevelUp() private void BoostPlayerHPFromLevelUp()
{ {
var rng = new RandomNumberGenerator(); var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
var hpIncrease = rng.RandiRange(3, 6); var hpIncrease = rng.RandiRange(3, 6);
HealthComponent.RaiseMaximumHP(hpIncrease); HealthComponent.RaiseMaximumHP(hpIncrease);
} }
private static float LeftStrafeInputVector => Input.GetActionStrength(GameInputs.StrafeLeft); private static float LeftStrafeInputVector => Input.GetActionStrength(GameInputs.StrafeLeft);
@@ -319,176 +319,176 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
private void Attack() private void Attack()
{ {
if (PlayerIsHittingGeometry()) if (PlayerIsHittingGeometry())
AnimationPlayer.Play("hit_wall"); AnimationPlayer.Play("hit_wall");
else if (!AnimationPlayer.IsPlaying()) else if (!AnimationPlayer.IsPlaying())
PlayAttackAnimation(); PlayAttackAnimation();
else else
return; return;
var weapon = EquipmentComponent.EquippedWeapon.Value as Weapon; var weapon = EquipmentComponent.EquippedWeapon.Value as Weapon;
if (weapon.WeaponTag == WeaponTag.DegradeOnSwing) if (weapon.WeaponTag == WeaponTag.DegradeOnSwing)
_playerEffectService.Degrade(); _playerEffectService.Degrade();
} }
private void ThrowItem() private void ThrowItem()
{ {
var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn"); var itemScene = GD.Load<PackedScene>("res://src/items/throwable/ThrowableItem.tscn");
var throwItem = itemScene.Instantiate<ThrowableItem>(); var throwItem = itemScene.Instantiate<ThrowableItem>();
GetTree().Root.AddChildEx(throwItem); GetTree().Root.AddChildEx(throwItem);
throwItem.GlobalPosition = CurrentPosition + new Vector3(0, 3.5f, 0); throwItem.GlobalPosition = CurrentPosition + new Vector3(0, 3.5f, 0);
throwItem.GlobalRotation = GlobalRotation; throwItem.GlobalRotation = GlobalRotation;
} }
private void PlayAttackAnimation() private void PlayAttackAnimation()
{ {
SfxDatabase.Instance.Play(((Weapon)EquipmentComponent.EquippedWeapon.Value).SoundEffect); SfxDatabase.Instance.Play(((Weapon)EquipmentComponent.EquippedWeapon.Value).SoundEffect);
var attackSpeed = ((Weapon)EquipmentComponent.EquippedWeapon.Value).AttackSpeed; var attackSpeed = ((Weapon)EquipmentComponent.EquippedWeapon.Value).AttackSpeed;
AnimationPlayer.SetSpeedScale((float)attackSpeed); AnimationPlayer.SetSpeedScale((float)attackSpeed);
AnimationPlayer.Play("attack"); AnimationPlayer.Play("attack");
} }
private void PlayerFXAnimations_AnimationFinished(StringName animName) private void PlayerFXAnimations_AnimationFinished(StringName animName)
{ {
if (animName == "death") if (animName == "death")
PlayerDied?.Invoke(); PlayerDied?.Invoke();
} }
private void InverseHPToAttackPowerSync(int obj) private void InverseHPToAttackPowerSync(int obj)
{ {
var weapon = (Weapon)EquipmentComponent.EquippedWeapon.Value; var weapon = (Weapon)EquipmentComponent.EquippedWeapon.Value;
if (weapon.WeaponTag == WeaponTag.InverseHPAttackPower) if (weapon.WeaponTag == WeaponTag.InverseHPAttackPower)
{ {
var healthPercentage = (HealthComponent.CurrentHP.Value * 10) / HealthComponent.MaximumHP.Value; var healthPercentage = (HealthComponent.CurrentHP.Value * 10) / HealthComponent.MaximumHP.Value;
weapon.SetWeaponAttack(10 - healthPercentage); weapon.SetWeaponAttack(10 - healthPercentage);
EquipmentComponent.Equip(weapon); EquipmentComponent.Equip(weapon);
} }
} }
private void OnExitTree() private void OnExitTree()
{ {
PlayerLogic.Stop(); PlayerLogic.Stop();
PlayerBinding.Dispose(); PlayerBinding.Dispose();
Hitbox.AreaEntered -= Hitbox_AreaEntered; Hitbox.AreaEntered -= Hitbox_AreaEntered;
CollisionDetector.AreaEntered -= CollisionDetector_AreaEntered; CollisionDetector.AreaEntered -= CollisionDetector_AreaEntered;
HealthComponent.HealthReachedZero -= Die; HealthComponent.HealthReachedZero -= Die;
HealthTimer.Timeout -= OnHealthTimerTimeout; HealthTimer.Timeout -= OnHealthTimerTimeout;
HealthComponent.CurrentHP.Changed -= InverseHPToAttackPowerSync; HealthComponent.CurrentHP.Changed -= InverseHPToAttackPowerSync;
HealthComponent.HealthReachedZero -= Die; HealthComponent.HealthReachedZero -= Die;
ExperiencePointsComponent.PlayerLevelUp -= OnLevelUp; ExperiencePointsComponent.PlayerLevelUp -= OnLevelUp;
PlayerFXAnimations.AnimationFinished -= PlayerFXAnimations_AnimationFinished; PlayerFXAnimations.AnimationFinished -= PlayerFXAnimations_AnimationFinished;
} }
private void Move(float delta) private void Move(float delta)
{ {
var rawInput = GlobalInputVector; var rawInput = GlobalInputVector;
var strafeLeftInput = LeftStrafeInputVector; var strafeLeftInput = LeftStrafeInputVector;
var strafeRightInput = RightStrafeInputVector; var strafeRightInput = RightStrafeInputVector;
var transform = Transform; var transform = Transform;
transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis; transform.Basis = new Basis(Vector3.Up, Settings.RotationSpeed * -rawInput.X * delta) * transform.Basis;
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized(); var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z).Normalized();
var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration; var velocity = Basis * moveDirection * Settings.MoveSpeed * Settings.Acceleration;
if (_debugSprint) if (_debugSprint)
velocity *= 2; velocity *= 2;
_knockbackStrength *= 0.9f; _knockbackStrength *= 0.9f;
Transform = Transform with { Basis = transform.Basis }; Transform = Transform with { Basis = transform.Basis };
Velocity = velocity + (_knockbackDirection * _knockbackStrength); Velocity = velocity + (_knockbackDirection * _knockbackStrength);
var rng = new RandomNumberGenerator(); var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
WalkSFX.PitchScale = rng.RandfRange(0.5f, 1.5f); WalkSFX.PitchScale = rng.RandfRange(0.5f, 1.5f);
if (!WalkSFX.Playing && !Velocity.IsZeroApprox()) if (!WalkSFX.Playing && !Velocity.IsZeroApprox())
WalkSFX.Play(); WalkSFX.Play();
else if (Velocity.IsZeroApprox()) else if (Velocity.IsZeroApprox())
WalkSFX.Stop(); WalkSFX.Stop();
MoveAndSlide(); MoveAndSlide();
} }
private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition; private void OnPlayerPositionUpdated(Vector3 globalPosition) => GlobalPosition = globalPosition;
private void OnHealthTimerTimeout() private void OnHealthTimerTimeout()
{ {
if (VTComponent.CurrentVT.Value > 0) if (VTComponent.CurrentVT.Value > 0)
{ {
if (((Accessory)EquipmentComponent.EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption) if (((Accessory)EquipmentComponent.EquippedAccessory.Value).AccessoryTag == AccessoryTag.HalfVTConsumption)
_healthTimerActive = !_healthTimerActive; _healthTimerActive = !_healthTimerActive;
HealthComponent.Heal(1); HealthComponent.Heal(1);
if (_healthTimerActive) if (_healthTimerActive)
VTComponent.Reduce(1); VTComponent.Reduce(1);
} }
else else
HealthComponent.Damage(1); HealthComponent.Damage(1);
} }
private void Hitbox_AreaEntered(Area3D area) private void Hitbox_AreaEntered(Area3D area)
{ {
var target = area.GetOwner(); var target = area.GetOwner();
if (target is IEnemy enemy) if (target is IEnemy enemy)
HitEnemy(enemy); HitEnemy(enemy);
} }
private void HitEnemy(IEnemy enemy) private void HitEnemy(IEnemy enemy)
{ {
var weapon = EquipmentComponent.EquippedWeapon.Value as Weapon; var weapon = EquipmentComponent.EquippedWeapon.Value as Weapon;
var isCriticalHit = BattleExtensions.IsCriticalHit(TotalLuck); var isCriticalHit = BattleExtensions.IsCriticalHit(TotalLuck);
var totalDamage = TotalAttack; var totalDamage = TotalAttack;
if (isCriticalHit) if (isCriticalHit)
{ {
totalDamage += (int)(totalDamage * 0.5f); totalDamage += (int)(totalDamage * 0.5f);
SfxDatabase.Instance.Play(SoundEffect.Crit); SfxDatabase.Instance.Play(SoundEffect.Crit);
} }
var baseAttack = new AttackData(totalDamage, weapon.WeaponElement, weapon.WeaponTag == WeaponTag.IgnoreDefense, weapon.WeaponTag == WeaponTag.IgnoreAffinity); var baseAttack = new AttackData(totalDamage, weapon.WeaponElement, weapon.WeaponTag == WeaponTag.IgnoreDefense, weapon.WeaponTag == WeaponTag.IgnoreAffinity);
var damageDealt = DamageCalculator.CalculateDamage(baseAttack, enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet); var damageDealt = DamageCalculator.CalculateDamage(baseAttack, enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet);
enemy.HealthComponent.Damage(damageDealt); enemy.HealthComponent.Damage(damageDealt);
if (weapon.WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable) if (weapon.WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable)
knockbackable.Knockback(0.3f, -CurrentBasis.Z.Normalized()); knockbackable.Knockback(0.3f, -CurrentBasis.Z.Normalized());
if (weapon.WeaponTag == WeaponTag.SelfDamage) if (weapon.WeaponTag == WeaponTag.SelfDamage)
_playerEffectService.TakeSelfDamage(weapon.Stats.SelfDamage); _playerEffectService.TakeSelfDamage(weapon.Stats.SelfDamage);
if (weapon.WeaponTag == WeaponTag.Instakill) if (weapon.WeaponTag == WeaponTag.Instakill)
_playerEffectService.Instakill(enemy); _playerEffectService.Instakill(enemy);
} }
private void CollisionDetector_AreaEntered(Area3D area) private void CollisionDetector_AreaEntered(Area3D area)
{ {
if (area.GetParent() is InventoryItem inventoryItem) if (area.GetParent() is InventoryItem inventoryItem)
{ {
var isAdded = Inventory.PickUpItem(inventoryItem); var isAdded = Inventory.PickUpItem(inventoryItem);
if (isAdded) if (isAdded)
inventoryItem.QueueFree(); inventoryItem.QueueFree();
} }
if (area.GetParent() is DroppedItem droppedItem) if (area.GetParent() is DroppedItem droppedItem)
{ {
var isAdded = Inventory.PickUpItem(droppedItem.Item); var isAdded = Inventory.PickUpItem(droppedItem.Item);
if (isAdded) if (isAdded)
droppedItem.QueueFree(); droppedItem.QueueFree();
} }
if (area.GetParent() is ThrownItem thrownItem) if (area.GetParent() is ThrownItem thrownItem)
{ {
var isAdded = Inventory.PickUpItem(thrownItem.ItemThatIsThrown); var isAdded = Inventory.PickUpItem(thrownItem.ItemThatIsThrown);
if (isAdded) if (isAdded)
thrownItem.QueueFree(); thrownItem.QueueFree();
} }
if (area.GetParent() is Restorative restorative) if (area.GetParent() is Restorative restorative)
{ {
restorative.QueueFree(); restorative.QueueFree();
} }
} }
private bool PlayerIsHittingGeometry() private bool PlayerIsHittingGeometry()
{ {
var collisions = WallCheck.GetCollidingBodies(); var collisions = WallCheck.GetCollidingBodies();
return collisions.Count > 0; return collisions.Count > 0;
} }
private void WallCheck_BodyEntered(Node body) private void WallCheck_BodyEntered(Node body)
{ {
GD.Print("Hit wall"); GD.Print("Hit wall");
AnimationPlayer.Stop(); AnimationPlayer.Stop();
} }
} }