Files
GameJamDungeon/src/items/effect/EffectItem.cs
2025-03-03 22:21:02 -08:00

193 lines
6.3 KiB
C#

using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using System;
using System.Linq;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class EffectItem : Node3D, IUsableItem
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] public IGame Game => this.DependOn<IGame>();
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
[Export]
private EffectItemStats _effectItemStats { get; set; }
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
[Node] private Area3D Pickup { get; set; } = default!;
public Guid ID => Guid.NewGuid();
public string ItemName => _effectItemStats.Name;
public string Description => _effectItemStats.Description;
public float SpawnRate => _effectItemStats.SpawnRate;
public Texture2D GetTexture() => _effectItemStats.Texture;
public double ThrowDamage => _effectItemStats.ThrowDamage;
public float ThrowSpeed => _effectItemStats.ThrowSpeed;
public void Use()
{
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.DoubleEXP))
Game.DoubleEXP(TimeSpan.FromSeconds(30));
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.TeleportAllEnemiesToRoom))
TeleportEnemiesToCurrentRoom();
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.KillHalfEnemiesInRoom))
KillHalfEnemiesInRoom();
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.TurnAllEnemiesIntoHealingItem))
TurnAllEnemiesInRoomIntoHealingItem();
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.HealsAllInRoomToMaxHP))
HealAllEnemiesAndPlayerInRoomToFull();
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.AbsorbHPFromAllEnemiesInRoom))
AbsorbHPFromAllEnemiesInRoom();
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.DealElementalDamageToAllEnemiesInRoom))
DealElementalDamageToAllEnemiesInRoom(ElementType.Hydric);
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.SwapHPAndVT))
SwapHPandVT();
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.RandomEffect))
RandomEffect();
}
public void SetItemStats(InventoryItemStats inventoryItemStats)
{
_effectItemStats = (EffectItemStats)inventoryItemStats;
}
public void OnReady()
{
Pickup.BodyEntered += OnEntered;
Sprite.Texture = _effectItemStats.Texture;
}
public void OnEntered(Node3D body)
{
var isAdded = Player.Inventory.TryAdd(this);
if (isAdded)
QueueFree();
}
private void TeleportEnemiesToCurrentRoom()
{
var currentFloor = Game.CurrentFloor;
var rooms = currentFloor.Rooms;
var currentRoom = Player.GetCurrentRoom();
if (currentRoom is not MonsterRoom)
return;
var validRooms = rooms.OfType<MonsterRoom>().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<Marker3D>().ToList();
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
enemy.SetEnemyGlobalPosition(randomSpawnPoint.GlobalPosition);
}
}
private void KillHalfEnemiesInRoom()
{
var currentRoom = Player.GetCurrentRoom();
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();
}
private void TurnAllEnemiesInRoomIntoHealingItem()
{
var currentRoom = Player.GetCurrentRoom();
var currentEnemies = currentRoom.EnemiesInRoom;
foreach (var enemy in currentEnemies)
{
enemy.Die();
DropHealingItem(enemy.GetEnemyGlobalPosition());
}
}
private 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.SetItemStats(randomFile);
Game.AddChild(consumable);
consumable.GlobalPosition = vector;
}
private void HealAllEnemiesAndPlayerInRoomToFull()
{
var currentRoom = Player.GetCurrentRoom();
var currentEnemies = currentRoom.EnemiesInRoom;
foreach (var enemy in currentEnemies)
enemy.SetCurrentHP(enemy.GetMaximumHP());
Player.Stats.SetCurrentHP(Player.Stats.MaximumHP.Value);
}
private void AbsorbHPFromAllEnemiesInRoom()
{
var currentRoom = Player.GetCurrentRoom();
var currentEnemies = currentRoom.EnemiesInRoom;
var hpToAbsorb = 0.0;
foreach (var enemy in currentEnemies)
hpToAbsorb += enemy.CurrentHP * 0.05;
Player.Stats.SetCurrentHP(Player.Stats.CurrentHP.Value + (int)hpToAbsorb);
GD.Print("HP to absorb: " + hpToAbsorb);
}
private void DealElementalDamageToAllEnemiesInRoom(ElementType elementType)
{
var currentRoom = Player.GetCurrentRoom();
var currentEnemies = currentRoom.EnemiesInRoom;
foreach (var enemy in currentEnemies)
enemy.TakeDamage(20, elementType);
}
private void SwapHPandVT()
{
var oldHp = Player.Stats.CurrentHP.Value;
var oldVt = Player.Stats.CurrentVT.Value;
Player.Stats.SetCurrentHP(oldVt);
Player.Stats.SetCurrentVT(oldHp);
}
private void RandomEffect()
{
var itemEffects = Enum.GetValues<UsableItemTag>().ToList();
itemEffects.Remove(UsableItemTag.RandomEffect);
var randomEffect = new Godot.Collections.Array<UsableItemTag>(itemEffects).PickRandom();
_effectItemStats.UsableItemTags.Clear();
_effectItemStats.UsableItemTags.Add(randomEffect);
Use();
}
}