Implement plasma sword instakill
This commit is contained in:
@@ -15,301 +15,301 @@ public class EffectService
|
||||
|
||||
public EffectService(IGame game, IPlayer player, IMap map)
|
||||
{
|
||||
_game = game;
|
||||
_player = player;
|
||||
_map = map;
|
||||
_game = game;
|
||||
_player = player;
|
||||
_map = map;
|
||||
}
|
||||
|
||||
public void TeleportEnemiesToCurrentRoom()
|
||||
{
|
||||
var currentFloor = _game.CurrentFloor;
|
||||
var rooms = currentFloor.Rooms;
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
var currentFloor = _game.CurrentFloor;
|
||||
var rooms = currentFloor.Rooms;
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
|
||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||
if (currentRoom is MonsterRoom monsterRoom)
|
||||
validRooms.Remove(monsterRoom);
|
||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||
if (currentRoom is MonsterRoom monsterRoom)
|
||||
validRooms.Remove(monsterRoom);
|
||||
|
||||
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
||||
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
||||
|
||||
var enemyList = validRooms.SelectMany(x => x.GetEnemiesInCurrentRoom()).OfType<Enemy>();
|
||||
var enemyList = validRooms.SelectMany(x => x.GetEnemiesInCurrentRoom()).OfType<Enemy>();
|
||||
|
||||
foreach (var enemy in enemyList)
|
||||
enemy.MoveEnemyToNewRoom(currentMonsterRoom);
|
||||
foreach (var enemy in enemyList)
|
||||
enemy.MoveEnemyToNewRoom(currentMonsterRoom);
|
||||
}
|
||||
|
||||
public void KillHalfEnemiesInRoom()
|
||||
{
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
|
||||
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
||||
var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().OfType<Enemy>().ToList();
|
||||
var enemiesToKill = enemyList.Count / 2;
|
||||
for (var i = 0; i < enemiesToKill; i++)
|
||||
enemyList[i].Die();
|
||||
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
||||
var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().OfType<Enemy>().ToList();
|
||||
var enemiesToKill = enemyList.Count / 2;
|
||||
for (var i = 0; i < enemiesToKill; i++)
|
||||
enemyList[i].Die();
|
||||
}
|
||||
|
||||
public void TurnAllEnemiesInRoomIntoHealingItem()
|
||||
{
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
|
||||
var currentEnemies = currentRoom.EnemiesInRoom.OfType<Enemy>().ToList();
|
||||
foreach (var enemy in currentEnemies)
|
||||
{
|
||||
enemy.OnMorph();
|
||||
DropHealingItem(enemy.GlobalPosition);
|
||||
}
|
||||
if (currentEnemies.Any())
|
||||
SfxDatabase.Instance.Play(SoundEffect.TurnAllEnemiesIntoHealingItems);
|
||||
var currentEnemies = currentRoom.EnemiesInRoom.OfType<Enemy>().ToList();
|
||||
foreach (var enemy in currentEnemies)
|
||||
{
|
||||
enemy.OnMorph();
|
||||
DropHealingItem(enemy.GlobalPosition);
|
||||
}
|
||||
if (currentEnemies.Any())
|
||||
SfxDatabase.Instance.Play(SoundEffect.TurnAllEnemiesIntoHealingItems);
|
||||
}
|
||||
|
||||
public void DropHealingItem(Vector3 vector)
|
||||
{
|
||||
var consumableFolder = "res://src/items/consumable";
|
||||
var restorativeScene = GD.Load<PackedScene>($"{consumableFolder}/ConsumableItem.tscn");
|
||||
var consumable = restorativeScene.Instantiate<ConsumableItem>();
|
||||
var resourceFiles = DirAccess.GetFilesAt($"{consumableFolder}/resources");
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomResource = resourceFiles[rng.RandiRange(0, resourceFiles.Length - 1)];
|
||||
var randomFile = ResourceLoader.Load<ConsumableItemStats>($"{consumableFolder}/resources/{randomResource}");
|
||||
consumable.Stats = randomFile;
|
||||
_game.AddChild(consumable);
|
||||
consumable.GlobalPosition = vector;
|
||||
var consumableFolder = "res://src/items/consumable";
|
||||
var restorativeScene = GD.Load<PackedScene>($"{consumableFolder}/ConsumableItem.tscn");
|
||||
var consumable = restorativeScene.Instantiate<ConsumableItem>();
|
||||
var resourceFiles = DirAccess.GetFilesAt($"{consumableFolder}/resources");
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomResource = resourceFiles[rng.RandiRange(0, resourceFiles.Length - 1)];
|
||||
var randomFile = ResourceLoader.Load<ConsumableItemStats>($"{consumableFolder}/resources/{randomResource}".TrimSuffix(".remap"));
|
||||
consumable.Stats = randomFile;
|
||||
_game.AddChild(consumable);
|
||||
consumable.GlobalPosition = vector;
|
||||
}
|
||||
|
||||
public void HealAllEnemiesAndPlayerInRoomToFull()
|
||||
{
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
|
||||
currentRoom.EnemiesInRoom.ForEach(e => e.HealthComponent.SetCurrentHealth(e.HealthComponent.MaximumHP.Value));
|
||||
_player.HealthComponent.SetCurrentHealth(_player.HealthComponent.MaximumHP.Value);
|
||||
currentRoom.EnemiesInRoom.ForEach(e => e.HealthComponent.SetCurrentHealth(e.HealthComponent.MaximumHP.Value));
|
||||
_player.HealthComponent.SetCurrentHealth(_player.HealthComponent.MaximumHP.Value);
|
||||
}
|
||||
|
||||
public void AbsorbHPFromAllEnemiesInRoom()
|
||||
{
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
|
||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||
var hpToAbsorb = 0.0;
|
||||
foreach (var enemy in currentEnemies)
|
||||
{
|
||||
var absorbAmount = enemy.HealthComponent.MaximumHP.Value * 0.05;
|
||||
enemy.HealthComponent.Damage((int)absorbAmount);
|
||||
hpToAbsorb += absorbAmount;
|
||||
enemy.OnAbsorb();
|
||||
}
|
||||
_player.HealthComponent.Heal((int)hpToAbsorb);
|
||||
GD.Print("HP to absorb: " + hpToAbsorb);
|
||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||
var hpToAbsorb = 0.0;
|
||||
foreach (var enemy in currentEnemies)
|
||||
{
|
||||
var absorbAmount = enemy.HealthComponent.MaximumHP.Value * 0.05;
|
||||
enemy.HealthComponent.Damage((int)absorbAmount);
|
||||
hpToAbsorb += absorbAmount;
|
||||
enemy.OnAbsorb();
|
||||
}
|
||||
_player.HealthComponent.Heal((int)hpToAbsorb);
|
||||
GD.Print("HP to absorb: " + hpToAbsorb);
|
||||
}
|
||||
|
||||
public void DealElementalDamageToAllEnemiesInRoom(ElementType elementType)
|
||||
{
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
var currentRoom = _map.GetPlayersCurrentRoom();
|
||||
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
if (currentRoom is not MonsterRoom)
|
||||
return;
|
||||
|
||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||
foreach (var enemy in currentEnemies)
|
||||
{
|
||||
var damageDealt = DamageCalculator.CalculateDamage(new AttackData(20, elementType), 10, enemy.ElementalResistanceSet);
|
||||
enemy.HealthComponent.Damage(damageDealt);
|
||||
}
|
||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||
foreach (var enemy in currentEnemies)
|
||||
{
|
||||
var damageDealt = DamageCalculator.CalculateDamage(new AttackData(20, elementType), 10, enemy.ElementalResistanceSet);
|
||||
enemy.HealthComponent.Damage(damageDealt);
|
||||
}
|
||||
}
|
||||
|
||||
public void SwapHPandVT()
|
||||
{
|
||||
var oldHp = _player.HealthComponent.CurrentHP.Value;
|
||||
var oldVt = _player.VTComponent.CurrentVT.Value;
|
||||
var oldHp = _player.HealthComponent.CurrentHP.Value;
|
||||
var oldVt = _player.VTComponent.CurrentVT.Value;
|
||||
|
||||
_player.HealthComponent.SetCurrentHealth(oldVt);
|
||||
_player.VTComponent.SetVT(oldHp);
|
||||
SfxDatabase.Instance.Play(SoundEffect.SwapHPAndVT);
|
||||
_player.HealthComponent.SetCurrentHealth(oldVt);
|
||||
_player.VTComponent.SetVT(oldHp);
|
||||
SfxDatabase.Instance.Play(SoundEffect.SwapHPAndVT);
|
||||
}
|
||||
|
||||
public void RandomEffect(EffectItem item)
|
||||
{
|
||||
var itemEffects = Enum.GetValues<UsableItemTag>().ToList();
|
||||
itemEffects.Remove(UsableItemTag.RandomEffect);
|
||||
itemEffects.Remove(UsableItemTag.None);
|
||||
var randomEffect = new Godot.Collections.Array<UsableItemTag>(itemEffects).PickRandom();
|
||||
item.SetEffectTag(randomEffect);
|
||||
_game.UseItem(item);
|
||||
var itemEffects = Enum.GetValues<UsableItemTag>().ToList();
|
||||
itemEffects.Remove(UsableItemTag.RandomEffect);
|
||||
itemEffects.Remove(UsableItemTag.None);
|
||||
var randomEffect = new Godot.Collections.Array<UsableItemTag>(itemEffects).PickRandom();
|
||||
item.SetEffectTag(randomEffect);
|
||||
_game.UseItem(item);
|
||||
}
|
||||
|
||||
public void RaiseCurrentWeaponAttack()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedWeapon.Value.ItemName))
|
||||
return;
|
||||
if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedWeapon.Value.ItemName))
|
||||
return;
|
||||
|
||||
var currentWeapon = (Weapon)_player.EquipmentComponent.EquippedWeapon.Value;
|
||||
currentWeapon.IncreaseWeaponAttack(1);
|
||||
SfxDatabase.Instance.Play(SoundEffect.IncreaseStat);
|
||||
var currentWeapon = (Weapon)_player.EquipmentComponent.EquippedWeapon.Value;
|
||||
currentWeapon.IncreaseWeaponAttack(1);
|
||||
SfxDatabase.Instance.Play(SoundEffect.IncreaseStat);
|
||||
}
|
||||
|
||||
public void RaiseCurrentArmorDefense()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedArmor.Value.ItemName))
|
||||
return;
|
||||
if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedArmor.Value.ItemName))
|
||||
return;
|
||||
|
||||
var currentArmor = (Armor)_player.EquipmentComponent.EquippedArmor.Value;
|
||||
currentArmor.IncreaseArmorDefense(1);
|
||||
SfxDatabase.Instance.Play(SoundEffect.IncreaseStat);
|
||||
var currentArmor = (Armor)_player.EquipmentComponent.EquippedArmor.Value;
|
||||
currentArmor.IncreaseArmorDefense(1);
|
||||
SfxDatabase.Instance.Play(SoundEffect.IncreaseStat);
|
||||
}
|
||||
|
||||
public void RaiseLevel() => _player.LevelUp();
|
||||
|
||||
public void TeleportToRandomRoom(IEnemy enemy)
|
||||
{
|
||||
var currentFloor = _game.CurrentFloor;
|
||||
var rooms = currentFloor.Rooms;
|
||||
var currentRoom = enemy.GetCurrentRoom(rooms);
|
||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||
if (currentRoom is MonsterRoom currentMonsterRoom)
|
||||
validRooms.Remove(currentMonsterRoom);
|
||||
var currentFloor = _game.CurrentFloor;
|
||||
var rooms = currentFloor.Rooms;
|
||||
var currentRoom = enemy.GetCurrentRoom(rooms);
|
||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||
if (currentRoom is MonsterRoom currentMonsterRoom)
|
||||
validRooms.Remove(currentMonsterRoom);
|
||||
|
||||
if (validRooms.Count == 0)
|
||||
return;
|
||||
if (validRooms.Count == 0)
|
||||
return;
|
||||
|
||||
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
||||
var randomRoom = roomsGodotCollection.PickRandom();
|
||||
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
||||
var randomRoom = roomsGodotCollection.PickRandom();
|
||||
|
||||
enemy.MoveEnemyToNewRoom(randomRoom);
|
||||
enemy.MoveEnemyToNewRoom(randomRoom);
|
||||
}
|
||||
|
||||
public void TeleportToRandomRoom(IPlayer player)
|
||||
{
|
||||
var currentFloor = _game.CurrentFloor;
|
||||
var rooms = currentFloor.Rooms;
|
||||
var currentFloor = _game.CurrentFloor;
|
||||
var rooms = currentFloor.Rooms;
|
||||
|
||||
var currentRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom);
|
||||
var currentRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom);
|
||||
|
||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||
if (currentRoom is MonsterRoom currentMonsterRoom)
|
||||
validRooms.Remove(currentMonsterRoom);
|
||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||
if (currentRoom is MonsterRoom currentMonsterRoom)
|
||||
validRooms.Remove(currentMonsterRoom);
|
||||
|
||||
if (validRooms.Count == 0)
|
||||
return;
|
||||
if (validRooms.Count == 0)
|
||||
return;
|
||||
|
||||
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
||||
var randomRoom = roomsGodotCollection.PickRandom();
|
||||
var spawnPoint = randomRoom.PlayerSpawn;
|
||||
player.TeleportPlayer((spawnPoint.Rotation, new Vector3(spawnPoint.Position.X, 0, spawnPoint.Position.Z)));
|
||||
SfxDatabase.Instance.Play(SoundEffect.TeleportToRandomRoom);
|
||||
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
||||
var randomRoom = roomsGodotCollection.PickRandom();
|
||||
var spawnPoint = randomRoom.PlayerSpawn;
|
||||
player.TeleportPlayer((spawnPoint.Rotation, new Vector3(spawnPoint.Position.X, 0, spawnPoint.Position.Z)));
|
||||
SfxDatabase.Instance.Play(SoundEffect.TeleportToRandomRoom);
|
||||
}
|
||||
|
||||
public void ChangeAffinity(ThrowableItem throwableItem)
|
||||
{
|
||||
var maximumElements = Enum.GetNames(typeof(ElementType)).Length;
|
||||
var newElement = ((int)throwableItem.ElementType + 1) % maximumElements;
|
||||
throwableItem.SetElementType((ElementType)newElement);
|
||||
var maximumElements = Enum.GetNames(typeof(ElementType)).Length;
|
||||
var newElement = ((int)throwableItem.ElementType + 1) % maximumElements;
|
||||
throwableItem.SetElementType((ElementType)newElement);
|
||||
|
||||
// TODO: Make this an inventory animation to cycle through elements.
|
||||
throwableItem.SetDescription(
|
||||
$"Inflicts {throwableItem.ElementType} damage when thrown." +
|
||||
$"{System.Environment.NewLine}Use item to change Affinity.");
|
||||
// TODO: Make this an inventory animation to cycle through elements.
|
||||
throwableItem.SetDescription(
|
||||
$"Inflicts {throwableItem.ElementType} damage when thrown." +
|
||||
$"{System.Environment.NewLine}Use item to change Affinity.");
|
||||
|
||||
throwableItem.SetCount(throwableItem.Count + 1);
|
||||
throwableItem.SetCount(throwableItem.Count + 1);
|
||||
}
|
||||
|
||||
public void WarpToExit()
|
||||
{
|
||||
var exitRoom = _game.CurrentFloor.Rooms.OfType<ExitRoom>().Single();
|
||||
if (exitRoom.PlayerDiscoveredRoom)
|
||||
{
|
||||
SfxDatabase.Instance.Play(SoundEffect.TeleportToExit);
|
||||
_player.TeleportPlayer((exitRoom.PlayerSpawn.Rotation, exitRoom.PlayerSpawn.Position));
|
||||
}
|
||||
var exitRoom = _game.CurrentFloor.Rooms.OfType<ExitRoom>().Single();
|
||||
if (exitRoom.PlayerDiscoveredRoom)
|
||||
{
|
||||
SfxDatabase.Instance.Play(SoundEffect.TeleportToExit);
|
||||
_player.TeleportPlayer((exitRoom.PlayerSpawn.Rotation, exitRoom.PlayerSpawn.Position));
|
||||
}
|
||||
}
|
||||
|
||||
public void DamagesPlayer(int damage)
|
||||
{
|
||||
_player.TakeDamage(new AttackData(damage, ElementType.None, true, true));
|
||||
_player.TakeDamage(new AttackData(damage, ElementType.None, true, true));
|
||||
}
|
||||
|
||||
public void RerollItem(InventoryItem itemToReroll)
|
||||
{
|
||||
var itemReroller = new ItemReroller(ItemDatabase.Instance);
|
||||
itemReroller.RerollItem(itemToReroll, _player.Inventory);
|
||||
var itemReroller = new ItemReroller(ItemDatabase.Instance);
|
||||
itemReroller.RerollItem(itemToReroll, _player.Inventory);
|
||||
}
|
||||
|
||||
public T GetRandomItemOfType<T>(T itemToExclude = null)
|
||||
where T : InventoryItem => ItemDatabase.Instance.PickItem(itemToExclude);
|
||||
where T : InventoryItem => ItemDatabase.Instance.PickItem(itemToExclude);
|
||||
|
||||
public void RandomSpell()
|
||||
{
|
||||
throw new NotImplementedException("Spells not implemented yet.");
|
||||
throw new NotImplementedException("Spells not implemented yet.");
|
||||
}
|
||||
|
||||
public void DropTo1HPAndGainRareItem<T>()
|
||||
where T : InventoryItem
|
||||
where T : InventoryItem
|
||||
{
|
||||
_player.HealthComponent.SetCurrentHealth(1);
|
||||
_player.Inventory.TryAdd(ItemDatabase.Instance.PickRareItem<T>());
|
||||
_player.HealthComponent.SetCurrentHealth(1);
|
||||
_player.Inventory.TryAdd(ItemDatabase.Instance.PickRareItem<T>());
|
||||
}
|
||||
|
||||
public void TradeRandomItem<T>(BoxItem box)
|
||||
where T : InventoryItem
|
||||
where T : InventoryItem
|
||||
{
|
||||
var tradableItems = _player.Inventory.Items.OfType<T>().Where(x => x != box).ToList();
|
||||
var tradableItems = _player.Inventory.Items.OfType<T>().Where(x => x != box).ToList();
|
||||
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomIndex = rng.RandiRange(0, tradableItems.Count - 1);
|
||||
var randomItem = tradableItems[randomIndex];
|
||||
if (randomItem is EquipableItem equipableItem)
|
||||
{
|
||||
if (_player.EquipmentComponent.IsItemEquipped(equipableItem))
|
||||
_player.Unequip(equipableItem);
|
||||
}
|
||||
_player.Inventory.Remove(randomItem);
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomIndex = rng.RandiRange(0, tradableItems.Count - 1);
|
||||
var randomItem = tradableItems[randomIndex];
|
||||
if (randomItem is EquipableItem equipableItem)
|
||||
{
|
||||
if (_player.EquipmentComponent.IsItemEquipped(equipableItem))
|
||||
_player.Unequip(equipableItem);
|
||||
}
|
||||
_player.Inventory.Remove(randomItem);
|
||||
|
||||
GetRandomItemOfType<T>();
|
||||
GetRandomItemOfType<T>();
|
||||
}
|
||||
|
||||
public IEnumerable<InventoryItem> TradeAllRandomItems<T>(BoxItem box)
|
||||
where T : InventoryItem
|
||||
where T : InventoryItem
|
||||
{
|
||||
var newInventory = new List<InventoryItem>();
|
||||
var items = _player.Inventory.Items.OfType<T>().Where(x => x != box).ToList();
|
||||
foreach (var item in items)
|
||||
newInventory.Add(GetRandomItemOfType<T>());
|
||||
var newInventory = new List<InventoryItem>();
|
||||
var items = _player.Inventory.Items.OfType<T>().Where(x => x != box).ToList();
|
||||
foreach (var item in items)
|
||||
newInventory.Add(GetRandomItemOfType<T>());
|
||||
|
||||
return newInventory;
|
||||
return newInventory;
|
||||
}
|
||||
|
||||
public void GetUnobtainedItem()
|
||||
{
|
||||
var pickableItems = ItemDatabase.Instance.Items.Except(_player.Inventory.Items).ToList();
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomIndex = rng.RandiRange(0, pickableItems.Count - 1);
|
||||
var selectedItem = pickableItems[randomIndex];
|
||||
var pickableItems = ItemDatabase.Instance.Items.Except(_player.Inventory.Items).ToList();
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var randomIndex = rng.RandiRange(0, pickableItems.Count - 1);
|
||||
var selectedItem = pickableItems[randomIndex];
|
||||
|
||||
if (selectedItem is ThrowableItem throwableItem)
|
||||
throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount));
|
||||
if (selectedItem is ThrowableItem throwableItem)
|
||||
throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount));
|
||||
|
||||
_player.Inventory.TryAdd(selectedItem);
|
||||
_player.Inventory.TryAdd(selectedItem);
|
||||
}
|
||||
|
||||
public void GetBasicItem<T>()
|
||||
where T : InventoryItem
|
||||
where T : InventoryItem
|
||||
{
|
||||
_player.Inventory.TryAdd(ItemDatabase.Instance.PickBasicItem<T>());
|
||||
_player.Inventory.TryAdd(ItemDatabase.Instance.PickBasicItem<T>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public abstract partial class InventoryItemStats : Resource
|
||||
|
||||
[Export]
|
||||
[Save("weapon_luck")]
|
||||
public double BonusLuck { get; set; } = 0.05;
|
||||
public int BonusLuck { get; set; } = 5;
|
||||
|
||||
[Export]
|
||||
[Save("equipment_bonus_hp")]
|
||||
|
||||
@@ -36,6 +36,8 @@ public partial class Accessory : EquipableItem
|
||||
|
||||
public override int BonusVT => Stats.BonusVT;
|
||||
|
||||
public override int BonusLuck { get => Stats.BonusLuck + _bonusLuck; }
|
||||
|
||||
public override ElementalResistanceSet ElementalResistance => new ElementalResistanceSet(Stats.AeolicResistance, Stats.HydricResistance, Stats.IgneousResistance, Stats.FerrumResistance, Stats.TelluricResistance, Stats.HolyResistance);
|
||||
|
||||
[Save("accessory_tag")]
|
||||
@@ -43,6 +45,9 @@ public partial class Accessory : EquipableItem
|
||||
|
||||
public override ItemTag ItemTag => Stats.ItemTag;
|
||||
|
||||
[Save("accessory_bonus_luck")]
|
||||
private int _bonusLuck { get; set; } = 0;
|
||||
|
||||
[Export]
|
||||
[Save("accessory_stats")]
|
||||
public AccessoryStats Stats { get; set; } = new AccessoryStats();
|
||||
|
||||
@@ -31,9 +31,14 @@ public partial class Armor : EquipableItem
|
||||
|
||||
public override int BonusDefense => Stats.BonusDefense + _bonusDefense;
|
||||
|
||||
public override int BonusLuck { get => Stats.BonusLuck + _bonusLuck; }
|
||||
|
||||
[Save("bonus_defense")]
|
||||
private int _bonusDefense { get; set; } = 0;
|
||||
|
||||
[Save("armor_bonus_luck")]
|
||||
private int _bonusLuck { get; set; } = 0;
|
||||
|
||||
public override ElementalResistanceSet ElementalResistance => new ElementalResistanceSet(Stats.AeolicResistance, Stats.HydricResistance, Stats.IgneousResistance, Stats.FerrumResistance, Stats.TelluricResistance, Stats.HolyResistance);
|
||||
|
||||
public void IncreaseArmorDefense(int bonus) => _bonusDefense += bonus;
|
||||
|
||||
@@ -55,12 +55,17 @@ public partial class Weapon : EquipableItem
|
||||
|
||||
public override int BonusDefense { get => Stats.BonusDefense + _bonusDefense; }
|
||||
|
||||
public override int BonusLuck { get => Stats.BonusLuck + _bonusLuck; }
|
||||
|
||||
[Save("weapon_bonus_damage")]
|
||||
private int _bonusDamage { get; set; } = 0;
|
||||
|
||||
[Save("weapon_bonus_damage")]
|
||||
private int _bonusDefense { get; set; } = 0;
|
||||
|
||||
[Save("weapon_bonus_luck")]
|
||||
private int _bonusLuck { get; set; } = 0;
|
||||
|
||||
[Export]
|
||||
[Save("weapon_stats")]
|
||||
public WeaponStats Stats { get; set; } = new WeaponStats();
|
||||
|
||||
@@ -21,6 +21,10 @@ public partial class WeaponStats : InventoryItemStats
|
||||
[Save("weapon_tag")]
|
||||
public WeaponTag WeaponTag { get; set; } = WeaponTag.None;
|
||||
|
||||
[Export]
|
||||
[Save("weapon_self_damage")]
|
||||
public int SelfDamage { get; set; } = 0;
|
||||
|
||||
[Export]
|
||||
public SoundEffect SoundEffect { get; set; } = SoundEffect.WeaponQuickSlash;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
script = ExtResource("2_rgna4")
|
||||
AttackSpeed = 1.0
|
||||
WeaponElement = 0
|
||||
WeaponTag = 0
|
||||
WeaponTag = 7
|
||||
SelfDamage = 0
|
||||
SoundEffect = 22
|
||||
Name = "Plasma Sword"
|
||||
Description = "Has the power to occasionally instantly disintegrate an enemy"
|
||||
SpawnRate = 0.05
|
||||
BonusAttack = 14
|
||||
SpawnRate = 0.5
|
||||
BonusAttack = 0
|
||||
BonusDefense = 0
|
||||
BonusLuck = 0.05
|
||||
BonusLuck = 10
|
||||
BonusHP = 0
|
||||
BonusVT = 0
|
||||
AeolicResistance = 0
|
||||
|
||||
@@ -108,6 +108,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
private Vector3 _knockbackDirection = Vector3.Zero;
|
||||
|
||||
private ItemReroller _itemReroller;
|
||||
private PlayerEffectService _playerEffectService;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
@@ -128,6 +129,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
EquipmentComponent = new EquipmentComponent();
|
||||
|
||||
_itemReroller = new ItemReroller(ItemDatabase.Instance);
|
||||
_playerEffectService = new PlayerEffectService(this);
|
||||
|
||||
Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed, Acceleration = Acceleration };
|
||||
|
||||
@@ -212,7 +214,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
{
|
||||
_camera3D.AddShake(1.0f);
|
||||
TakeDamageAnimationPlayer.Play("take_damage");
|
||||
var damageReceived = DamageCalculator.CalculateDamage(damage, DefenseComponent.CurrentDefense.Value + EquipmentComponent.BonusDefense, EquipmentComponent.ElementalResistance);
|
||||
var damageReceived = DamageCalculator.CalculateDamage(damage, TotalDefense, EquipmentComponent.ElementalResistance);
|
||||
HealthComponent.Damage(damageReceived);
|
||||
SfxDatabase.Instance.Play(SoundEffect.TakeDamage);
|
||||
}
|
||||
@@ -225,6 +227,12 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
|
||||
public void PlayJumpScareAnimation() => PlayerFXAnimations.Play("jump_scare");
|
||||
|
||||
public int TotalAttack => AttackComponent.CurrentAttack.Value + EquipmentComponent.BonusAttack;
|
||||
|
||||
public int TotalDefense => DefenseComponent.CurrentDefense.Value + EquipmentComponent.BonusDefense;
|
||||
|
||||
public int TotalLuck => LuckComponent.Luck.Value + EquipmentComponent.BonusLuck;
|
||||
|
||||
public void LevelUp()
|
||||
{
|
||||
ExperiencePointsComponent.LevelUp();
|
||||
@@ -414,11 +422,9 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
|
||||
private void HitEnemy(IEnemy enemy)
|
||||
{
|
||||
var ignoreElementalResistance = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponTag == WeaponTag.IgnoreAffinity;
|
||||
var ignoreDefense = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponTag == WeaponTag.IgnoreDefense;
|
||||
var isCriticalHit = BattleExtensions.IsCriticalHit(LuckComponent.Luck.Value + EquipmentComponent.BonusLuck);
|
||||
var totalDamage = AttackComponent.CurrentAttack.Value + EquipmentComponent.BonusAttack;
|
||||
var element = (EquipmentComponent.EquippedWeapon.Value as Weapon).WeaponElement;
|
||||
var weapon = EquipmentComponent.EquippedWeapon.Value as Weapon;
|
||||
var isCriticalHit = BattleExtensions.IsCriticalHit(TotalLuck);
|
||||
var totalDamage = TotalAttack;
|
||||
|
||||
if (isCriticalHit)
|
||||
{
|
||||
@@ -426,21 +432,16 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
SfxDatabase.Instance.Play(SoundEffect.Crit);
|
||||
}
|
||||
|
||||
var baseAttack = new AttackData(totalDamage, element, ignoreDefense, ignoreElementalResistance);
|
||||
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);
|
||||
enemy.HealthComponent.Damage(damageDealt);
|
||||
|
||||
if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable)
|
||||
if (weapon.WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable)
|
||||
knockbackable.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
||||
if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.SelfDamage)
|
||||
HealthComponent.Damage(5);
|
||||
if (((Weapon)EquipmentComponent.EquippedWeapon.Value).WeaponTag == WeaponTag.Instakill)
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
if (rng.Randf() <= LuckComponent.Luck.Value)
|
||||
enemy.Die();
|
||||
}
|
||||
if (weapon.WeaponTag == WeaponTag.SelfDamage)
|
||||
_playerEffectService.TakeSelfDamage(weapon.Stats.SelfDamage);
|
||||
if (weapon.WeaponTag == WeaponTag.Instakill)
|
||||
_playerEffectService.Instakill(enemy);
|
||||
}
|
||||
|
||||
private void CollisionDetector_AreaEntered(Area3D area)
|
||||
|
||||
@@ -427,6 +427,34 @@ tracks/1/keys = {
|
||||
"values": [0, 29]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_wvcio"]
|
||||
resource_name = "jump_scare"
|
||||
length = 5.0005
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("SubViewportContainer/SubViewport/Prosc Message:texture")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 4.2),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 1,
|
||||
"values": [ExtResource("6_bj1ma"), ExtResource("6_bj1ma")]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("SubViewportContainer/SubViewport/Prosc Message:modulate")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 0.6, 1.6, 2.6, 3.6, 4.16667),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 0.48), Color(1, 1, 1, 1), Color(1, 1, 1, 0.48), Color(1, 1, 1, 0)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_v5qoq"]
|
||||
resource_name = "normal_attack"
|
||||
length = 0.666669
|
||||
@@ -456,34 +484,6 @@ tracks/1/keys = {
|
||||
"values": [0, 30]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_wvcio"]
|
||||
resource_name = "jump_scare"
|
||||
length = 5.0005
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("SubViewportContainer/SubViewport/Prosc Message:texture")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 4.2),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 1,
|
||||
"values": [ExtResource("6_bj1ma"), ExtResource("6_bj1ma")]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("SubViewportContainer/SubViewport/Prosc Message:modulate")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 0.6, 1.6, 2.6, 3.6, 4.16667),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 0.48), Color(1, 1, 1, 1), Color(1, 1, 1, 0.48), Color(1, 1, 1, 0)]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ebyyx"]
|
||||
_data = {
|
||||
&"Divinity_Recall": SubResource("Animation_j5wmh"),
|
||||
@@ -12094,6 +12094,7 @@ animations = [{
|
||||
collision_layer = 802
|
||||
collision_mask = 775
|
||||
script = ExtResource("1_xcol5")
|
||||
HealthTimerIsActive = true
|
||||
|
||||
[node name="MainCollision" type="CollisionShape3D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
@@ -12112,6 +12113,7 @@ unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, 0.999848, -0.0174524, 0, 0.0174524, 0.999848, 0.003, 2.1, -0.01)
|
||||
current = true
|
||||
fov = 52.9
|
||||
_maxZ = null
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Camera/Camera3D"]
|
||||
extra_cull_margin = 16384.0
|
||||
|
||||
26
Zennysoft.Game.Ma/src/player/PlayerEffectService.cs
Normal file
26
Zennysoft.Game.Ma/src/player/PlayerEffectService.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Godot;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
using Zennysoft.Ma.Adapter.Entity;
|
||||
|
||||
internal class PlayerEffectService
|
||||
{
|
||||
private IPlayer _player;
|
||||
public PlayerEffectService(IPlayer player)
|
||||
{
|
||||
_player = player;
|
||||
}
|
||||
|
||||
public void TakeSelfDamage(int damage)
|
||||
{
|
||||
_player.TakeDamage(new AttackData(5, ElementType.None, true, true));
|
||||
}
|
||||
|
||||
public void Instakill(IEnemy enemy)
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var rand = rng.RandiRange(1, 100);
|
||||
if (rand <= _player.TotalLuck)
|
||||
enemy.Die();
|
||||
}
|
||||
}
|
||||
1
Zennysoft.Game.Ma/src/player/PlayerEffectService.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/player/PlayerEffectService.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dgbhf31crsdmi
|
||||
Reference in New Issue
Block a user