using Godot; using System.Linq; using System; using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; public class EffectService { private readonly IGame _game; private readonly IPlayer _player; private readonly IMap _map; public EffectService(IGame game, IPlayer player, IMap map) { _game = game; _player = player; _map = map; } public void TeleportEnemiesToCurrentRoom() { var currentFloor = _game.CurrentFloor; var rooms = currentFloor.Rooms; var currentRoom = _map.GetPlayersCurrentRoom(); if (currentRoom is not MonsterRoom) return; var validRooms = rooms.OfType().ToList(); if (currentRoom is MonsterRoom monsterRoom) validRooms.Remove(monsterRoom); var currentMonsterRoom = (MonsterRoom)currentRoom; var enemyList = validRooms.SelectMany(x => x.GetEnemiesInCurrentRoom()); foreach (var enemy in enemyList) { var spawnPoints = currentMonsterRoom.EnemySpawnPoints.GetChildren().OfType().ToList(); var spawnPointsGodotCollection = new Godot.Collections.Array(spawnPoints); var randomSpawnPoint = spawnPointsGodotCollection.PickRandom(); enemy.SetEnemyGlobalPosition(randomSpawnPoint.GlobalPosition); } } public void KillHalfEnemiesInRoom() { var currentRoom = _map.GetPlayersCurrentRoom(); if (currentRoom is not MonsterRoom) return; var currentMonsterRoom = (MonsterRoom)currentRoom; var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().ToList(); var enemiesToKill = enemyList.Count / 2; for (var i = 0; i < enemiesToKill; i++) enemyList[i].Die(); } public void TurnAllEnemiesInRoomIntoHealingItem() { var currentRoom = _map.GetPlayersCurrentRoom(); if (currentRoom is not MonsterRoom) return; var currentEnemies = currentRoom.EnemiesInRoom; foreach (var enemy in currentEnemies) { enemy.Die(); DropHealingItem(enemy.GetEnemyGlobalPosition()); } } public void DropHealingItem(Vector3 vector) { var consumableFolder = "res://src/items/consumable"; var restorativeScene = GD.Load($"{consumableFolder}/ConsumableItem.tscn"); var consumable = restorativeScene.Instantiate(); 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($"{consumableFolder}/resources/{randomResource}"); consumable.Stats = randomFile; _game.AddChild(consumable); consumable.GlobalPosition = vector; } public void HealAllEnemiesAndPlayerInRoomToFull() { var currentRoom = _map.GetPlayersCurrentRoom(); if (currentRoom is not MonsterRoom) return; var currentEnemies = currentRoom.EnemiesInRoom; foreach (var enemy in currentEnemies) enemy.SetCurrentHP(enemy.GetMaximumHP()); _player.Stats.SetCurrentHP(_player.Stats.MaximumHP.Value); } public void AbsorbHPFromAllEnemiesInRoom() { var currentRoom = _map.GetPlayersCurrentRoom(); if (currentRoom is not MonsterRoom) return; var currentEnemies = currentRoom.EnemiesInRoom; var hpToAbsorb = 0.0; foreach (var enemy in currentEnemies) hpToAbsorb += enemy.CurrentHP.Value * 0.05; _player.Stats.SetCurrentHP(_player.Stats.CurrentHP.Value + (int)hpToAbsorb); GD.Print("HP to absorb: " + hpToAbsorb); } public void DealElementalDamageToAllEnemiesInRoom(ElementType elementType) { var currentRoom = _map.GetPlayersCurrentRoom(); if (currentRoom is not MonsterRoom) return; var currentEnemies = currentRoom.EnemiesInRoom; foreach (var enemy in currentEnemies) enemy.TakeDamage(20, elementType); } public void SwapHPandVT() { var oldHp = _player.Stats.CurrentHP.Value; var oldVt = _player.Stats.CurrentVT.Value; _player.Stats.SetCurrentHP(oldVt); _player.Stats.SetCurrentVT(oldHp); } public void RandomEffect(EffectItem item) { var itemEffects = Enum.GetValues().ToList(); itemEffects.Remove(UsableItemTag.RandomEffect); itemEffects.Remove(UsableItemTag.None); var randomEffect = new Godot.Collections.Array(itemEffects).PickRandom(); item.SetEffectTag(randomEffect); _game.UseItem(item); } public void RaiseCurrentWeaponAttack() { if (string.IsNullOrEmpty(_player.EquippedWeapon.Value.ItemName)) return; var currentWeapon = (Weapon)_player.EquippedWeapon.Value; currentWeapon.IncreaseWeaponAttack(1); _player.ModifyBonusAttack(1); } public void RaiseCurrentArmorDefense() { if (string.IsNullOrEmpty(_player.EquippedArmor.Value.ItemName)) return; var currentArmor = (Armor)_player.EquippedArmor.Value; currentArmor.IncreaseArmorDefense(1); _player.ModifyBonusDefense(1); } public void RaiseLevel() { _player.LevelUp(); } public void TeleportToRandomRoom(IEnemy enemy) { var currentFloor = _game.CurrentFloor; var rooms = currentFloor.Rooms; var currentRoom = enemy.GetCurrentRoom(); var validRooms = rooms.OfType().ToList(); if (currentRoom is MonsterRoom currentMonsterRoom) validRooms.Remove(currentMonsterRoom); if (validRooms.Count == 0) return; var roomsGodotCollection = new Godot.Collections.Array(validRooms); var randomRoom = roomsGodotCollection.PickRandom(); var spawnPoints = randomRoom.EnemySpawnPoints.GetChildren().OfType().ToList(); var spawnPointsGodotCollection = new Godot.Collections.Array(spawnPoints); var randomSpawnPoint = spawnPointsGodotCollection.PickRandom(); enemy.SetEnemyGlobalPosition(randomSpawnPoint.GlobalPosition); } public void TeleportToRandomRoom(IPlayer player) { var currentFloor = _game.CurrentFloor; var rooms = currentFloor.Rooms; var currentRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom); var validRooms = rooms.OfType().ToList(); if (currentRoom is MonsterRoom currentMonsterRoom) validRooms.Remove(currentMonsterRoom); if (validRooms.Count == 0) return; var roomsGodotCollection = new Godot.Collections.Array(validRooms); var randomRoom = roomsGodotCollection.PickRandom(); var spawnPoint = randomRoom.PlayerSpawn; player.TeleportPlayer(spawnPoint.Transform); } public void ChangeAffinity(ThrowableItem throwableItem) { 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."); throwableItem.SetCount(throwableItem.Count + 1); } public void WarpToExit(IPlayer player) { var exitRoom = _game.CurrentFloor.Rooms.OfType().Single(); if (exitRoom.PlayerDiscoveredRoom) player.TeleportPlayer(exitRoom.PlayerSpawn.Transform); } public void WarpToExit(IEnemy enemy) { var exitRoom = _game.CurrentFloor.Rooms.OfType().Single(); enemy.SetEnemyGlobalPosition(exitRoom.PlayerSpawn.GlobalPosition); } }