From d45bc6772253625883ca7d666bfdd8b0d72ab40e Mon Sep 17 00:00:00 2001 From: Zenny Date: Wed, 4 Feb 2026 22:30:10 -0800 Subject: [PATCH] Partially implementation of box items --- Zennysoft.Game.Ma/src/game/Game.cs | 26 ++ Zennysoft.Game.Ma/src/items/EffectService.cs | 350 +++++++++--------- Zennysoft.Game.Ma/src/items/ItemDatabase.cs | 22 +- .../items/box/resources/BloodAcquisition.tres | 26 ++ .../items/box/resources/ChaoticPrayer.tres | 26 ++ .../box/resources/FashionableAcquisition.tres | 26 ++ .../box/resources/FuriousAcquisition.tres | 26 ++ .../box/resources/HealthyAcquisition.tres | 26 ++ .../box/resources/IdentityAcquisition.tres | 26 ++ .../src/items/box/resources/Malfunction.tres | 26 ++ .../box/resources/SpeculativeAcquisition.tres | 26 ++ .../src/map/dungeon/code/DungeonFloor.cs | 76 ++-- .../src/map/dungeon/code/DungeonRoom.cs | 46 +-- .../floors/Special Floors/Overworld.tscn | 6 +- 14 files changed, 489 insertions(+), 245 deletions(-) create mode 100644 Zennysoft.Game.Ma/src/items/box/resources/BloodAcquisition.tres create mode 100644 Zennysoft.Game.Ma/src/items/box/resources/ChaoticPrayer.tres create mode 100644 Zennysoft.Game.Ma/src/items/box/resources/FashionableAcquisition.tres create mode 100644 Zennysoft.Game.Ma/src/items/box/resources/FuriousAcquisition.tres create mode 100644 Zennysoft.Game.Ma/src/items/box/resources/HealthyAcquisition.tres create mode 100644 Zennysoft.Game.Ma/src/items/box/resources/IdentityAcquisition.tres create mode 100644 Zennysoft.Game.Ma/src/items/box/resources/Malfunction.tres create mode 100644 Zennysoft.Game.Ma/src/items/box/resources/SpeculativeAcquisition.tres diff --git a/Zennysoft.Game.Ma/src/game/Game.cs b/Zennysoft.Game.Ma/src/game/Game.cs index 7530eb065..1738977bd 100644 --- a/Zennysoft.Game.Ma/src/game/Game.cs +++ b/Zennysoft.Game.Ma/src/game/Game.cs @@ -435,6 +435,32 @@ public partial class Game : Node3D, IGame { case ItemTag.DamagesPlayer: _effectService.DamagesPlayer(boxItem.Stats.DamageToPlayer); + GameRepo.CloseInventory(); + break; + case ItemTag.ContainsAccessory: + _player.Inventory.TryAdd(_effectService.GetRandomItemOfType()); + break; + case ItemTag.ContainsArmor: + _player.Inventory.TryAdd(_effectService.GetRandomItemOfType()); + break; + case ItemTag.ContainsWeapon: + _player.Inventory.TryAdd(_effectService.GetRandomItemOfType()); + break; + case ItemTag.ContainsBox: + _player.Inventory.TryAdd(_effectService.GetRandomItemOfType()); + break; + case ItemTag.ContainsRestorative: + _player.Inventory.TryAdd(_effectService.GetRandomItemOfType()); + break; + case ItemTag.DropTo1HPAndGainRareItem: + _effectService.DropTo1HPAndGainRareItem(); + break; + case ItemTag.TradeAllRandomItems: + var newInventory = _effectService.TradeAllRandomItems(boxItem); + _player.Inventory.Items.Clear(); + _player.Inventory.TryAdd(boxItem); + foreach (var item in newInventory) + _player.Inventory.TryAdd(item); break; } } diff --git a/Zennysoft.Game.Ma/src/items/EffectService.cs b/Zennysoft.Game.Ma/src/items/EffectService.cs index c634b5a46..7a595b6e4 100644 --- a/Zennysoft.Game.Ma/src/items/EffectService.cs +++ b/Zennysoft.Game.Ma/src/items/EffectService.cs @@ -1,8 +1,9 @@ -using Godot; +using Godot; using System.Linq; using System; using Zennysoft.Ma.Adapter; using Zennysoft.Ma.Adapter.Entity; +using System.Collections.Generic; namespace Zennysoft.Game.Ma; @@ -14,302 +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().ToList(); - if (currentRoom is MonsterRoom monsterRoom) - validRooms.Remove(monsterRoom); + var validRooms = rooms.OfType().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(); + var enemyList = validRooms.SelectMany(x => x.GetEnemiesInCurrentRoom()).OfType(); - 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().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().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().ToList(); - foreach (var enemy in currentEnemies) - { - enemy.OnMorph(); - DropHealingItem(enemy.GlobalPosition); - } - if (currentEnemies.Any()) - SfxDatabase.Instance.Play(SoundEffect.TurnAllEnemiesIntoHealingItems); + var currentEnemies = currentRoom.EnemiesInRoom.OfType().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($"{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; + 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(); + 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().ToList(); - itemEffects.Remove(UsableItemTag.RandomEffect); - itemEffects.Remove(UsableItemTag.None); - var randomEffect = new Godot.Collections.Array(itemEffects).PickRandom(); - item.SetEffectTag(randomEffect); - _game.UseItem(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.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().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().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(validRooms); - var randomRoom = roomsGodotCollection.PickRandom(); + var roomsGodotCollection = new Godot.Collections.Array(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().ToList(); - if (currentRoom is MonsterRoom currentMonsterRoom) - validRooms.Remove(currentMonsterRoom); + var validRooms = rooms.OfType().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(validRooms); - var randomRoom = roomsGodotCollection.PickRandom(); - var spawnPoint = randomRoom.PlayerSpawn; - player.TeleportPlayer((spawnPoint.Rotation, spawnPoint.Position)); - SfxDatabase.Instance.Play(SoundEffect.TeleportToRandomRoom); + var roomsGodotCollection = new Godot.Collections.Array(validRooms); + var randomRoom = roomsGodotCollection.PickRandom(); + var spawnPoint = randomRoom.PlayerSpawn; + player.TeleportPlayer((spawnPoint.Rotation, spawnPoint.Position)); + 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().Single(); - if (exitRoom.PlayerDiscoveredRoom) - { - SfxDatabase.Instance.Play(SoundEffect.TeleportToExit); - _player.TeleportPlayer((exitRoom.PlayerSpawn.Rotation, exitRoom.PlayerSpawn.Position)); - } + var exitRoom = _game.CurrentFloor.Rooms.OfType().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 void GetRandomItemOfType(T itemToExclude = null) - where T : InventoryItem - { - _player.Inventory.TryAdd(ItemDatabase.Instance.PickItem(itemToExclude)); - } + public T GetRandomItemOfType(T itemToExclude = null) + 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() - where T : InventoryItem + where T : InventoryItem { - _player.HealthComponent.SetCurrentHealth(1); - _player.Inventory.TryAdd(ItemDatabase.Instance.PickRareItem()); + _player.HealthComponent.SetCurrentHealth(1); + _player.Inventory.TryAdd(ItemDatabase.Instance.PickRareItem()); } - public void TradeRandomItem(BoxItem box) + public void TradeRandomItem(BoxItem box) + where T : InventoryItem { - if (_player.Inventory.Items.Count == 1) - return; + var tradableItems = _player.Inventory.Items.OfType().Where(x => x != box).ToList(); - var tradableItems = _player.Inventory.Items.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, _player.Inventory.Items.Count - 1); - var randomItem = tradableItems[randomIndex]; - if (randomItem is EquipableItem equipableItem) - { - if (_player.EquipmentComponent.IsItemEquipped(equipableItem)) - _player.Unequip(equipableItem); - } - _player.Inventory.Remove(randomItem); - - GetRandomItemOfType(box); + GetRandomItemOfType(); } - public void TradeAllRandomItems(BoxItem box) + public IEnumerable TradeAllRandomItems(BoxItem box) + where T : InventoryItem { - var tradableItems = _player.Inventory.Items.Where(x => x != box); - foreach (var item in tradableItems) - TradeRandomItem(box); + var newInventory = new List(); + var items = _player.Inventory.Items.OfType().Where(x => x != box).ToList(); + foreach (var item in items) + newInventory.Add(GetRandomItemOfType()); + + 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() - where T : InventoryItem + where T : InventoryItem { - _player.Inventory.TryAdd(ItemDatabase.Instance.PickBasicItem()); + _player.Inventory.TryAdd(ItemDatabase.Instance.PickBasicItem()); } } diff --git a/Zennysoft.Game.Ma/src/items/ItemDatabase.cs b/Zennysoft.Game.Ma/src/items/ItemDatabase.cs index fe3f4b008..19652c0ca 100644 --- a/Zennysoft.Game.Ma/src/items/ItemDatabase.cs +++ b/Zennysoft.Game.Ma/src/items/ItemDatabase.cs @@ -19,32 +19,32 @@ public class ItemDatabase public T PickItem(T itemToExclude = null) where T : InventoryItem { - var itemsToSelectFrom = Items; + var itemsToSelectFrom = Items.OfType(); return PickItemInternal(itemsToSelectFrom, itemToExclude); } public T PickRareItem(T itemToExclude = null) where T : InventoryItem { - var getRareItems = Items.Where(x => x.SpawnRate < 0.1f); + var getRareItems = Items.OfType().Where(x => x.SpawnRate < 0.1f); return PickItemInternal(getRareItems, itemToExclude); } public T PickBasicItem(T itemToExclude = null) where T : InventoryItem { - var getBasicItems = Items.Where(x => x.SpawnRate > 0.5f); + var getBasicItems = Items.OfType().Where(x => x.SpawnRate > 0.5f); return PickItemInternal(getBasicItems, itemToExclude); } - private T PickItemInternal(IEnumerable itemsToSelectFrom, T itemToExclude = null) + private T PickItemInternal(IEnumerable itemsToSelectFrom, T itemToExclude = null) where T : InventoryItem { var rng = new RandomNumberGenerator(); rng.Randomize(); if (itemToExclude is not null) - itemsToSelectFrom = [.. itemsToSelectFrom.OfType().Where(x => x.ItemName != itemToExclude.ItemName)]; + itemsToSelectFrom = [.. itemsToSelectFrom.Where(x => x.ItemName != itemToExclude.ItemName)]; var weights = itemsToSelectFrom.Select(x => x.SpawnRate).ToArray(); var selectedItem = itemsToSelectFrom.ToArray()[rng.RandWeighted(weights)]; @@ -52,7 +52,7 @@ public class ItemDatabase if (selectedItem is ThrowableItem throwableItem) throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount)); - return (T)selectedItem; + return selectedItem; } private ItemDatabase() @@ -64,6 +64,7 @@ public class ItemDatabase var throwableResources = DirAccess.GetFilesAt("res://src/items/throwable/resources/"); var consumableResources = DirAccess.GetFilesAt("res://src/items/consumable/resources/"); var effectResources = DirAccess.GetFilesAt("res://src/items/effect/resources/"); + var boxResources = DirAccess.GetFilesAt("res://src/items/box/resources/"); foreach (var armor in armorResources) { @@ -119,6 +120,15 @@ public class ItemDatabase database.Add(effectItemScene); } + foreach (var boxItem in boxResources) + { + var boxItemInfo = GD.Load($"res://src/items/box/resources/{boxItem}"); + var boxItemScene = ResourceLoader.Load("res://src/items/box/BoxItem.tscn").Instantiate(); + boxItemScene.Stats = boxItemInfo; + if (!database.Contains(boxItemScene)) + database.Add(boxItemScene); + } + Items = [.. database]; } } diff --git a/Zennysoft.Game.Ma/src/items/box/resources/BloodAcquisition.tres b/Zennysoft.Game.Ma/src/items/box/resources/BloodAcquisition.tres new file mode 100644 index 000000000..7d13ca8a6 --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/box/resources/BloodAcquisition.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://deebat2kuxfo3"] + +[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_p2ro7"] +[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_k6pqw"] + +[resource] +script = ExtResource("2_k6pqw") +DamageToPlayer = 0 +Name = "Blood Acquisition" +Description = "Contains a rare item but lowers current HP to 1." +SpawnRate = 0.5 +BonusAttack = 0 +BonusDefense = 0 +BonusLuck = 0.05 +BonusHP = 0 +BonusVT = 0 +AeolicResistance = 0 +TelluricResistance = 0 +HydricResistance = 0 +IgneousResistance = 0 +FerrumResistance = 0 +ThrowSpeed = 12.0 +ThrowDamage = 5 +ItemTag = 10 +Texture = ExtResource("1_p2ro7") +metadata/_custom_type_script = "uid://vuavr681au06" diff --git a/Zennysoft.Game.Ma/src/items/box/resources/ChaoticPrayer.tres b/Zennysoft.Game.Ma/src/items/box/resources/ChaoticPrayer.tres new file mode 100644 index 000000000..3778eedbd --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/box/resources/ChaoticPrayer.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://k0uhsuxvyegw"] + +[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_yf4yo"] +[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_xe8mc"] + +[resource] +script = ExtResource("2_xe8mc") +DamageToPlayer = 0 +Name = "Chaotic Prayer" +Description = "Converts all items into random items." +SpawnRate = 0.5 +BonusAttack = 0 +BonusDefense = 0 +BonusLuck = 0.05 +BonusHP = 0 +BonusVT = 0 +AeolicResistance = 0 +TelluricResistance = 0 +HydricResistance = 0 +IgneousResistance = 0 +FerrumResistance = 0 +ThrowSpeed = 12.0 +ThrowDamage = 5 +ItemTag = 12 +Texture = ExtResource("1_yf4yo") +metadata/_custom_type_script = "uid://vuavr681au06" diff --git a/Zennysoft.Game.Ma/src/items/box/resources/FashionableAcquisition.tres b/Zennysoft.Game.Ma/src/items/box/resources/FashionableAcquisition.tres new file mode 100644 index 000000000..64beff44c --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/box/resources/FashionableAcquisition.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://bit6jsgs4yl7t"] + +[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_85ci2"] +[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_pe0kd"] + +[resource] +script = ExtResource("2_pe0kd") +DamageToPlayer = 0 +Name = "Fashionable Acquisition" +Description = "Contains a random armor." +SpawnRate = 0.5 +BonusAttack = 0 +BonusDefense = 0 +BonusLuck = 0.05 +BonusHP = 0 +BonusVT = 0 +AeolicResistance = 0 +TelluricResistance = 0 +HydricResistance = 0 +IgneousResistance = 0 +FerrumResistance = 0 +ThrowSpeed = 12.0 +ThrowDamage = 5 +ItemTag = 6 +Texture = ExtResource("1_85ci2") +metadata/_custom_type_script = "uid://vuavr681au06" diff --git a/Zennysoft.Game.Ma/src/items/box/resources/FuriousAcquisition.tres b/Zennysoft.Game.Ma/src/items/box/resources/FuriousAcquisition.tres new file mode 100644 index 000000000..9bd8a6c7b --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/box/resources/FuriousAcquisition.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://g3buxgpmjcio"] + +[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_3hy40"] +[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_kb1l2"] + +[resource] +script = ExtResource("2_kb1l2") +DamageToPlayer = 0 +Name = "Furious Acquisition" +Description = "Contains a random weapon." +SpawnRate = 0.5 +BonusAttack = 0 +BonusDefense = 0 +BonusLuck = 0.05 +BonusHP = 0 +BonusVT = 0 +AeolicResistance = 0 +TelluricResistance = 0 +HydricResistance = 0 +IgneousResistance = 0 +FerrumResistance = 0 +ThrowSpeed = 12.0 +ThrowDamage = 5 +ItemTag = 5 +Texture = ExtResource("1_3hy40") +metadata/_custom_type_script = "uid://vuavr681au06" diff --git a/Zennysoft.Game.Ma/src/items/box/resources/HealthyAcquisition.tres b/Zennysoft.Game.Ma/src/items/box/resources/HealthyAcquisition.tres new file mode 100644 index 000000000..4eebb364b --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/box/resources/HealthyAcquisition.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://icdlurnmjryh"] + +[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_svub6"] +[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_iw3ll"] + +[resource] +script = ExtResource("2_iw3ll") +DamageToPlayer = 0 +Name = "Healthy Acquisition" +Description = "Contains a random restorative." +SpawnRate = 0.5 +BonusAttack = 0 +BonusDefense = 0 +BonusLuck = 0.05 +BonusHP = 0 +BonusVT = 0 +AeolicResistance = 0 +TelluricResistance = 0 +HydricResistance = 0 +IgneousResistance = 0 +FerrumResistance = 0 +ThrowSpeed = 12.0 +ThrowDamage = 5 +ItemTag = 4 +Texture = ExtResource("1_svub6") +metadata/_custom_type_script = "uid://vuavr681au06" diff --git a/Zennysoft.Game.Ma/src/items/box/resources/IdentityAcquisition.tres b/Zennysoft.Game.Ma/src/items/box/resources/IdentityAcquisition.tres new file mode 100644 index 000000000..bd4affee7 --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/box/resources/IdentityAcquisition.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://b2buq6ckkam7i"] + +[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_dwyk7"] +[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_pssvy"] + +[resource] +script = ExtResource("2_pssvy") +DamageToPlayer = 0 +Name = "Identity Acquisition" +Description = "Contains a random mask." +SpawnRate = 0.5 +BonusAttack = 0 +BonusDefense = 0 +BonusLuck = 0.05 +BonusHP = 0 +BonusVT = 0 +AeolicResistance = 0 +TelluricResistance = 0 +HydricResistance = 0 +IgneousResistance = 0 +FerrumResistance = 0 +ThrowSpeed = 12.0 +ThrowDamage = 5 +ItemTag = 9 +Texture = ExtResource("1_dwyk7") +metadata/_custom_type_script = "uid://vuavr681au06" diff --git a/Zennysoft.Game.Ma/src/items/box/resources/Malfunction.tres b/Zennysoft.Game.Ma/src/items/box/resources/Malfunction.tres new file mode 100644 index 000000000..5308b1b6f --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/box/resources/Malfunction.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://dsb2gcjeme5yy"] + +[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_3scao"] +[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_vgter"] + +[resource] +script = ExtResource("2_vgter") +DamageToPlayer = 10 +Name = "Malfunction" +Description = "Damages self." +SpawnRate = 0.5 +BonusAttack = 0 +BonusDefense = 0 +BonusLuck = 0.05 +BonusHP = 0 +BonusVT = 0 +AeolicResistance = 0 +TelluricResistance = 0 +HydricResistance = 0 +IgneousResistance = 0 +FerrumResistance = 0 +ThrowSpeed = 12.0 +ThrowDamage = 5 +ItemTag = 3 +Texture = ExtResource("1_3scao") +metadata/_custom_type_script = "uid://vuavr681au06" diff --git a/Zennysoft.Game.Ma/src/items/box/resources/SpeculativeAcquisition.tres b/Zennysoft.Game.Ma/src/items/box/resources/SpeculativeAcquisition.tres new file mode 100644 index 000000000..2be69767e --- /dev/null +++ b/Zennysoft.Game.Ma/src/items/box/resources/SpeculativeAcquisition.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://cf8mf2qguf7q1"] + +[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_1eojb"] +[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_ucc84"] + +[resource] +script = ExtResource("2_ucc84") +DamageToPlayer = 0 +Name = "Speculative Acquisition" +Description = "Contains a random box." +SpawnRate = 0.5 +BonusAttack = 0 +BonusDefense = 0 +BonusLuck = 0.05 +BonusHP = 0 +BonusVT = 0 +AeolicResistance = 0 +TelluricResistance = 0 +HydricResistance = 0 +IgneousResistance = 0 +FerrumResistance = 0 +ThrowSpeed = 12.0 +ThrowDamage = 5 +ItemTag = 7 +Texture = ExtResource("1_1eojb") +metadata/_custom_type_script = "uid://vuavr681au06" diff --git a/Zennysoft.Game.Ma/src/map/dungeon/code/DungeonFloor.cs b/Zennysoft.Game.Ma/src/map/dungeon/code/DungeonFloor.cs index f721d7fb9..205f5c028 100644 --- a/Zennysoft.Game.Ma/src/map/dungeon/code/DungeonFloor.cs +++ b/Zennysoft.Game.Ma/src/map/dungeon/code/DungeonFloor.cs @@ -20,34 +20,34 @@ public partial class DungeonFloor : Node3D, IDungeonFloor public void InitializeDungeon() { - Rooms = []; - Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms); - _playerSpawnPoint = RandomizePlayerSpawnPoint(); + Rooms = []; + Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms); + _playerSpawnPoint = RandomizePlayerSpawnPoint(); } public void SpawnEnemies(DungeonFloorNode floorNode) { - var enemyOdds = new Godot.Collections.Dictionary - { - { EnemyType.Sproingy, floorNode.Sproingy }, - { EnemyType.Michael, floorNode.Michael }, - { EnemyType.FilthEater, floorNode.FilthEater }, - { EnemyType.Sara, floorNode.Sara }, - { EnemyType.Ballos, floorNode.Ballos }, - { EnemyType.Chariot, floorNode.Chariot }, - { EnemyType.Chinthe, floorNode.Chinthe }, - { EnemyType.AmbassadorGreen, floorNode.GreenAmbassador }, - { EnemyType.AmbassadorRed, floorNode.RedAmbassador }, - { EnemyType.AmbassadorSteel, floorNode.SteelAmbassador }, - { EnemyType.AgniDemon, floorNode.AgniDemon }, - { EnemyType.AqueousDemon, floorNode.AqueosDemon }, - { EnemyType.Palan, floorNode.Palan }, - { EnemyType.ShieldOfHeaven, floorNode.ShieldOfHeaven }, - { EnemyType.GoldSproingy, floorNode.GoldSproingy }, - }; - var monsterRooms = Rooms.OfType(); - foreach (var room in monsterRooms) - room.SpawnEnemies(enemyOdds); + var enemyOdds = new Godot.Collections.Dictionary + { + { EnemyType.Sproingy, floorNode.Sproingy }, + { EnemyType.Michael, floorNode.Michael }, + { EnemyType.FilthEater, floorNode.FilthEater }, + { EnemyType.Sara, floorNode.Sara }, + { EnemyType.Ballos, floorNode.Ballos }, + { EnemyType.Chariot, floorNode.Chariot }, + { EnemyType.Chinthe, floorNode.Chinthe }, + { EnemyType.AmbassadorGreen, floorNode.GreenAmbassador }, + { EnemyType.AmbassadorRed, floorNode.RedAmbassador }, + { EnemyType.AmbassadorSteel, floorNode.SteelAmbassador }, + { EnemyType.AgniDemon, floorNode.AgniDemon }, + { EnemyType.AqueousDemon, floorNode.AqueosDemon }, + { EnemyType.Palan, floorNode.Palan }, + { EnemyType.ShieldOfHeaven, floorNode.ShieldOfHeaven }, + { EnemyType.GoldSproingy, floorNode.GoldSproingy }, + }; + var monsterRooms = Rooms.OfType(); + foreach (var room in monsterRooms) + room.SpawnEnemies(enemyOdds); } public (Vector3 Rotation, Vector3 Position) GetPlayerSpawnPoint() { return (_playerSpawnPoint.Rotation, new Vector3(_playerSpawnPoint.GlobalPosition.X, 0, _playerSpawnPoint.GlobalPosition.Z)); } @@ -55,25 +55,25 @@ public partial class DungeonFloor : Node3D, IDungeonFloor private Marker3D RandomizePlayerSpawnPoint() { - var randomSpawnLocations = Rooms - .OfType() - .Select(x => x.PlayerSpawn); - var godotCollection = new Godot.Collections.Array(randomSpawnLocations); - var result = godotCollection.PickRandom(); - return result; + var randomSpawnLocations = Rooms + .OfType() + .Select(x => x.PlayerSpawn); + var godotCollection = new Godot.Collections.Array(randomSpawnLocations); + var result = godotCollection.PickRandom(); + return result; } private static ImmutableList FindAllDungeonRooms(List nodesToSearch, ImmutableList roomsFound) { - if (nodesToSearch.Count == 0) - return roomsFound; + if (nodesToSearch.Count == 0) + return roomsFound; - foreach (var node in nodesToSearch) - { - if (node is IDungeonRoom dungeonRoom) - roomsFound = roomsFound.Add(dungeonRoom); - } + foreach (var node in nodesToSearch) + { + if (node is IDungeonRoom dungeonRoom) + roomsFound = roomsFound.Add(dungeonRoom); + } - return FindAllDungeonRooms([.. nodesToSearch.SelectMany(x => x.GetChildren())], roomsFound); + return FindAllDungeonRooms([.. nodesToSearch.SelectMany(x => x.GetChildren())], roomsFound); } } diff --git a/Zennysoft.Game.Ma/src/map/dungeon/code/DungeonRoom.cs b/Zennysoft.Game.Ma/src/map/dungeon/code/DungeonRoom.cs index 92ec5b86a..3e3e975ff 100644 --- a/Zennysoft.Game.Ma/src/map/dungeon/code/DungeonRoom.cs +++ b/Zennysoft.Game.Ma/src/map/dungeon/code/DungeonRoom.cs @@ -28,47 +28,47 @@ public abstract partial class DungeonRoom : Node3D, IDungeonRoom public void Setup() { - _enemiesInRoom = []; - if (_room != null) - { - _room.BodyEntered += Room_BodyEntered; - _room.BodyExited += Room_BodyExited; - } + _enemiesInRoom = []; + if (_room != null) + { + _room.BodyEntered += Room_BodyEntered; + _room.BodyExited += Room_BodyExited; + } } private void Room_BodyExited(Node3D body) { - if (body is IEnemy enemy) - _enemiesInRoom = _enemiesInRoom.Remove(enemy); - if (body is IPlayer) - _isPlayerInRoom = false; + if (body is IEnemy enemy) + _enemiesInRoom = _enemiesInRoom.Remove(enemy); + if (body is IPlayer) + _isPlayerInRoom = false; } private void Room_BodyEntered(Node3D body) { - if (body is IEnemy enemy) - _enemiesInRoom = _enemiesInRoom.Add(enemy); - if (body is IPlayer) - if (_playerDiscoveredRoom) - _isPlayerInRoom = true; - else - OnPlayerDiscoveringRoom(); + if (body is IEnemy enemy) + _enemiesInRoom = _enemiesInRoom.Add(enemy); + if (body is IPlayer) + if (_playerDiscoveredRoom) + _isPlayerInRoom = true; + else + OnPlayerDiscoveringRoom(); } public ImmutableList GetEnemiesInCurrentRoom() { - return _enemiesInRoom; + return _enemiesInRoom; } private void OnPlayerDiscoveringRoom() { - _isPlayerInRoom = true; - _playerDiscoveredRoom = true; - MinimapShadow.Hide(); + _isPlayerInRoom = true; + _playerDiscoveredRoom = true; + MinimapShadow.Hide(); } public void OnExitTree() { - _room.BodyEntered -= Room_BodyEntered; - _room.BodyExited -= Room_BodyExited; + _room.BodyEntered -= Room_BodyEntered; + _room.BodyExited -= Room_BodyExited; } } diff --git a/Zennysoft.Game.Ma/src/map/dungeon/floors/Special Floors/Overworld.tscn b/Zennysoft.Game.Ma/src/map/dungeon/floors/Special Floors/Overworld.tscn index 7f7750a7a..d139693f4 100644 --- a/Zennysoft.Game.Ma/src/map/dungeon/floors/Special Floors/Overworld.tscn +++ b/Zennysoft.Game.Ma/src/map/dungeon/floors/Special Floors/Overworld.tscn @@ -2,9 +2,9 @@ [ext_resource type="Script" uid="uid://cuhfkyh3d7noa" path="res://src/map/dungeon/code/Overworld.cs" id="1_5hmt3"] [ext_resource type="Texture2D" uid="uid://co6h8vyi11sl2" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_63.png" id="2_g6b7b"] -[ext_resource type="AudioStream" uid="uid://dqmsaok6fyhe7" path="res://src/audio/AMB/amb_perlin.wav" id="2_wbbo3"] -[ext_resource type="AudioStream" uid="uid://dl07vg00se7hd" path="res://src/audio/AMB/amb_white_noise.wav" id="3_c2gp5"] -[ext_resource type="AudioStream" uid="uid://boypvgaweep8a" path="res://src/audio/AMB/amb_beach.wav" id="3_pvi8n"] +[ext_resource type="AudioStream" uid="uid://dv045ax11vybl" path="res://src/audio/AMB/amb_perlin.wav" id="2_wbbo3"] +[ext_resource type="AudioStream" uid="uid://dsc8xu78llst6" path="res://src/audio/AMB/amb_white_noise.wav" id="3_c2gp5"] +[ext_resource type="AudioStream" uid="uid://7hb71ilkd7qh" path="res://src/audio/AMB/amb_beach.wav" id="3_pvi8n"] [ext_resource type="Texture2D" uid="uid://w33fr6exryiy" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_37.png" id="3_uyygh"] [ext_resource type="Texture2D" uid="uid://dv10yaqvp3mub" path="res://src/map/overworld/Models/Overworld_CLOUD_RINGS_INNER_71.png" id="4_r8r3k"] [ext_resource type="Shader" uid="uid://brhf7s3riyag5" path="res://src/map/map shaders/Metal.gdshader" id="5_d1qcb"]