Compare commits

...

3 Commits

Author SHA1 Message Date
8a99771491 Add more boxes, implement weapon that gets stronger on lower HP 2026-02-04 23:51:07 -08:00
d45bc67722 Partially implementation of box items 2026-02-04 22:30:10 -08:00
13ebe54474 Fix some control issues 2026-02-04 02:34:23 -08:00
26 changed files with 662 additions and 262 deletions

View File

@@ -7,4 +7,5 @@ public enum WeaponTag
IgnoreAffinity, IgnoreAffinity,
IgnoreDefense, IgnoreDefense,
Knockback, Knockback,
InverseHPAttackPower,
} }

View File

@@ -435,6 +435,43 @@ public partial class Game : Node3D, IGame
{ {
case ItemTag.DamagesPlayer: case ItemTag.DamagesPlayer:
_effectService.DamagesPlayer(boxItem.Stats.DamageToPlayer); _effectService.DamagesPlayer(boxItem.Stats.DamageToPlayer);
GameRepo.CloseInventory();
break;
case ItemTag.ContainsAccessory:
_player.Inventory.TryAdd(_effectService.GetRandomItemOfType<Accessory>());
break;
case ItemTag.ContainsArmor:
_player.Inventory.TryAdd(_effectService.GetRandomItemOfType<Armor>());
break;
case ItemTag.ContainsWeapon:
_player.Inventory.TryAdd(_effectService.GetRandomItemOfType<Weapon>());
break;
case ItemTag.ContainsBox:
_player.Inventory.TryAdd(_effectService.GetRandomItemOfType<BoxItem>());
break;
case ItemTag.ContainsRestorative:
_player.Inventory.TryAdd(_effectService.GetRandomItemOfType<ConsumableItem>());
break;
case ItemTag.DropTo1HPAndGainRareItem:
_effectService.DropTo1HPAndGainRareItem<InventoryItem>();
break;
case ItemTag.TradeAllRandomItems:
var newInventory = _effectService.TradeAllRandomItems<InventoryItem>(boxItem);
_player.Inventory.Items.Clear();
_player.Inventory.TryAdd(boxItem);
foreach (var item in newInventory)
_player.Inventory.TryAdd(item);
break;
case ItemTag.ContainsUnobtainedItem:
_effectService.GetUnobtainedItem();
break;
case ItemTag.ContainsBasicItem:
_effectService.GetBasicItem<InventoryItem>();
break;
case ItemTag.UnequipAllItems:
_player.EquipmentComponent.Unequip(_player.EquipmentComponent.EquippedWeapon.Value);
_player.EquipmentComponent.Unequip(_player.EquipmentComponent.EquippedArmor.Value);
_player.EquipmentComponent.Unequip(_player.EquipmentComponent.EquippedAccessory.Value);
break; break;
} }
} }

View File

@@ -1,8 +1,9 @@
using Godot; using Godot;
using System.Linq; using System.Linq;
using System; using System;
using Zennysoft.Ma.Adapter; using Zennysoft.Ma.Adapter;
using Zennysoft.Ma.Adapter.Entity; using Zennysoft.Ma.Adapter.Entity;
using System.Collections.Generic;
namespace Zennysoft.Game.Ma; namespace Zennysoft.Game.Ma;
@@ -14,302 +15,301 @@ public class EffectService
public EffectService(IGame game, IPlayer player, IMap map) public EffectService(IGame game, IPlayer player, IMap map)
{ {
_game = game; _game = game;
_player = player; _player = player;
_map = map; _map = map;
} }
public void TeleportEnemiesToCurrentRoom() public void TeleportEnemiesToCurrentRoom()
{ {
var currentFloor = _game.CurrentFloor; var currentFloor = _game.CurrentFloor;
var rooms = currentFloor.Rooms; var rooms = currentFloor.Rooms;
var currentRoom = _map.GetPlayersCurrentRoom(); var currentRoom = _map.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom) if (currentRoom is not MonsterRoom)
return; return;
var validRooms = rooms.OfType<MonsterRoom>().ToList(); var validRooms = rooms.OfType<MonsterRoom>().ToList();
if (currentRoom is MonsterRoom monsterRoom) if (currentRoom is MonsterRoom monsterRoom)
validRooms.Remove(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) foreach (var enemy in enemyList)
enemy.MoveEnemyToNewRoom(currentMonsterRoom); enemy.MoveEnemyToNewRoom(currentMonsterRoom);
} }
public void KillHalfEnemiesInRoom() public void KillHalfEnemiesInRoom()
{ {
var currentRoom = _map.GetPlayersCurrentRoom(); var currentRoom = _map.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom) if (currentRoom is not MonsterRoom)
return; return;
var currentMonsterRoom = (MonsterRoom)currentRoom; var currentMonsterRoom = (MonsterRoom)currentRoom;
var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().OfType<Enemy>().ToList(); var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().OfType<Enemy>().ToList();
var enemiesToKill = enemyList.Count / 2; var enemiesToKill = enemyList.Count / 2;
for (var i = 0; i < enemiesToKill; i++) for (var i = 0; i < enemiesToKill; i++)
enemyList[i].Die(); enemyList[i].Die();
} }
public void TurnAllEnemiesInRoomIntoHealingItem() public void TurnAllEnemiesInRoomIntoHealingItem()
{ {
var currentRoom = _map.GetPlayersCurrentRoom(); var currentRoom = _map.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom) if (currentRoom is not MonsterRoom)
return; return;
var currentEnemies = currentRoom.EnemiesInRoom.OfType<Enemy>().ToList(); var currentEnemies = currentRoom.EnemiesInRoom.OfType<Enemy>().ToList();
foreach (var enemy in currentEnemies) foreach (var enemy in currentEnemies)
{ {
enemy.OnMorph(); enemy.OnMorph();
DropHealingItem(enemy.GlobalPosition); DropHealingItem(enemy.GlobalPosition);
} }
if (currentEnemies.Any()) if (currentEnemies.Any())
SfxDatabase.Instance.Play(SoundEffect.TurnAllEnemiesIntoHealingItems); SfxDatabase.Instance.Play(SoundEffect.TurnAllEnemiesIntoHealingItems);
} }
public void DropHealingItem(Vector3 vector) public void DropHealingItem(Vector3 vector)
{ {
var consumableFolder = "res://src/items/consumable"; var consumableFolder = "res://src/items/consumable";
var restorativeScene = GD.Load<PackedScene>($"{consumableFolder}/ConsumableItem.tscn"); var restorativeScene = GD.Load<PackedScene>($"{consumableFolder}/ConsumableItem.tscn");
var consumable = restorativeScene.Instantiate<ConsumableItem>(); var consumable = restorativeScene.Instantiate<ConsumableItem>();
var resourceFiles = DirAccess.GetFilesAt($"{consumableFolder}/resources"); var resourceFiles = DirAccess.GetFilesAt($"{consumableFolder}/resources");
var rng = new RandomNumberGenerator(); var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
var randomResource = resourceFiles[rng.RandiRange(0, resourceFiles.Length - 1)]; var randomResource = resourceFiles[rng.RandiRange(0, resourceFiles.Length - 1)];
var randomFile = ResourceLoader.Load<ConsumableItemStats>($"{consumableFolder}/resources/{randomResource}"); var randomFile = ResourceLoader.Load<ConsumableItemStats>($"{consumableFolder}/resources/{randomResource}");
consumable.Stats = randomFile; consumable.Stats = randomFile;
_game.AddChild(consumable); _game.AddChild(consumable);
consumable.GlobalPosition = vector; consumable.GlobalPosition = vector;
} }
public void HealAllEnemiesAndPlayerInRoomToFull() public void HealAllEnemiesAndPlayerInRoomToFull()
{ {
var currentRoom = _map.GetPlayersCurrentRoom(); var currentRoom = _map.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom) if (currentRoom is not MonsterRoom)
return; return;
currentRoom.EnemiesInRoom.ForEach(e => e.HealthComponent.SetCurrentHealth(e.HealthComponent.MaximumHP.Value)); currentRoom.EnemiesInRoom.ForEach(e => e.HealthComponent.SetCurrentHealth(e.HealthComponent.MaximumHP.Value));
_player.HealthComponent.SetCurrentHealth(_player.HealthComponent.MaximumHP.Value); _player.HealthComponent.SetCurrentHealth(_player.HealthComponent.MaximumHP.Value);
} }
public void AbsorbHPFromAllEnemiesInRoom() public void AbsorbHPFromAllEnemiesInRoom()
{ {
var currentRoom = _map.GetPlayersCurrentRoom(); var currentRoom = _map.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom) if (currentRoom is not MonsterRoom)
return; return;
var currentEnemies = currentRoom.EnemiesInRoom; var currentEnemies = currentRoom.EnemiesInRoom;
var hpToAbsorb = 0.0; var hpToAbsorb = 0.0;
foreach (var enemy in currentEnemies) foreach (var enemy in currentEnemies)
{ {
var absorbAmount = enemy.HealthComponent.MaximumHP.Value * 0.05; var absorbAmount = enemy.HealthComponent.MaximumHP.Value * 0.05;
enemy.HealthComponent.Damage((int)absorbAmount); enemy.HealthComponent.Damage((int)absorbAmount);
hpToAbsorb += absorbAmount; hpToAbsorb += absorbAmount;
enemy.OnAbsorb(); enemy.OnAbsorb();
} }
_player.HealthComponent.Heal((int)hpToAbsorb); _player.HealthComponent.Heal((int)hpToAbsorb);
GD.Print("HP to absorb: " + hpToAbsorb); GD.Print("HP to absorb: " + hpToAbsorb);
} }
public void DealElementalDamageToAllEnemiesInRoom(ElementType elementType) public void DealElementalDamageToAllEnemiesInRoom(ElementType elementType)
{ {
var currentRoom = _map.GetPlayersCurrentRoom(); var currentRoom = _map.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom) if (currentRoom is not MonsterRoom)
return; return;
var currentEnemies = currentRoom.EnemiesInRoom; var currentEnemies = currentRoom.EnemiesInRoom;
foreach (var enemy in currentEnemies) foreach (var enemy in currentEnemies)
{ {
var damageDealt = DamageCalculator.CalculateDamage(new AttackData(20, elementType), 10, enemy.ElementalResistanceSet); var damageDealt = DamageCalculator.CalculateDamage(new AttackData(20, elementType), 10, enemy.ElementalResistanceSet);
enemy.HealthComponent.Damage(damageDealt); enemy.HealthComponent.Damage(damageDealt);
} }
} }
public void SwapHPandVT() public void SwapHPandVT()
{ {
var oldHp = _player.HealthComponent.CurrentHP.Value; var oldHp = _player.HealthComponent.CurrentHP.Value;
var oldVt = _player.VTComponent.CurrentVT.Value; var oldVt = _player.VTComponent.CurrentVT.Value;
_player.HealthComponent.SetCurrentHealth(oldVt); _player.HealthComponent.SetCurrentHealth(oldVt);
_player.VTComponent.SetVT(oldHp); _player.VTComponent.SetVT(oldHp);
SfxDatabase.Instance.Play(SoundEffect.SwapHPAndVT); SfxDatabase.Instance.Play(SoundEffect.SwapHPAndVT);
} }
public void RandomEffect(EffectItem item) public void RandomEffect(EffectItem item)
{ {
var itemEffects = Enum.GetValues<UsableItemTag>().ToList(); var itemEffects = Enum.GetValues<UsableItemTag>().ToList();
itemEffects.Remove(UsableItemTag.RandomEffect); itemEffects.Remove(UsableItemTag.RandomEffect);
itemEffects.Remove(UsableItemTag.None); itemEffects.Remove(UsableItemTag.None);
var randomEffect = new Godot.Collections.Array<UsableItemTag>(itemEffects).PickRandom(); var randomEffect = new Godot.Collections.Array<UsableItemTag>(itemEffects).PickRandom();
item.SetEffectTag(randomEffect); item.SetEffectTag(randomEffect);
_game.UseItem(item); _game.UseItem(item);
} }
public void RaiseCurrentWeaponAttack() public void RaiseCurrentWeaponAttack()
{ {
if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedWeapon.Value.ItemName)) if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedWeapon.Value.ItemName))
return; return;
var currentWeapon = (Weapon)_player.EquipmentComponent.EquippedWeapon.Value; var currentWeapon = (Weapon)_player.EquipmentComponent.EquippedWeapon.Value;
currentWeapon.IncreaseWeaponAttack(1); currentWeapon.IncreaseWeaponAttack(1);
SfxDatabase.Instance.Play(SoundEffect.IncreaseStat); SfxDatabase.Instance.Play(SoundEffect.IncreaseStat);
} }
public void RaiseCurrentArmorDefense() public void RaiseCurrentArmorDefense()
{ {
if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedArmor.Value.ItemName)) if (string.IsNullOrEmpty(_player.EquipmentComponent.EquippedArmor.Value.ItemName))
return; return;
var currentArmor = (Armor)_player.EquipmentComponent.EquippedArmor.Value; var currentArmor = (Armor)_player.EquipmentComponent.EquippedArmor.Value;
currentArmor.IncreaseArmorDefense(1); currentArmor.IncreaseArmorDefense(1);
SfxDatabase.Instance.Play(SoundEffect.IncreaseStat); SfxDatabase.Instance.Play(SoundEffect.IncreaseStat);
} }
public void RaiseLevel() => _player.LevelUp(); public void RaiseLevel() => _player.LevelUp();
public void TeleportToRandomRoom(IEnemy enemy) public void TeleportToRandomRoom(IEnemy enemy)
{ {
var currentFloor = _game.CurrentFloor; var currentFloor = _game.CurrentFloor;
var rooms = currentFloor.Rooms; var rooms = currentFloor.Rooms;
var currentRoom = enemy.GetCurrentRoom(rooms); var currentRoom = enemy.GetCurrentRoom(rooms);
var validRooms = rooms.OfType<MonsterRoom>().ToList(); var validRooms = rooms.OfType<MonsterRoom>().ToList();
if (currentRoom is MonsterRoom currentMonsterRoom) if (currentRoom is MonsterRoom currentMonsterRoom)
validRooms.Remove(currentMonsterRoom); validRooms.Remove(currentMonsterRoom);
if (validRooms.Count == 0) if (validRooms.Count == 0)
return; return;
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms); var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
var randomRoom = roomsGodotCollection.PickRandom(); var randomRoom = roomsGodotCollection.PickRandom();
enemy.MoveEnemyToNewRoom(randomRoom); enemy.MoveEnemyToNewRoom(randomRoom);
} }
public void TeleportToRandomRoom(IPlayer player) public void TeleportToRandomRoom(IPlayer player)
{ {
var currentFloor = _game.CurrentFloor; var currentFloor = _game.CurrentFloor;
var rooms = currentFloor.Rooms; var rooms = currentFloor.Rooms;
var currentRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom); var currentRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom);
var validRooms = rooms.OfType<MonsterRoom>().ToList(); var validRooms = rooms.OfType<MonsterRoom>().ToList();
if (currentRoom is MonsterRoom currentMonsterRoom) if (currentRoom is MonsterRoom currentMonsterRoom)
validRooms.Remove(currentMonsterRoom); validRooms.Remove(currentMonsterRoom);
if (validRooms.Count == 0) if (validRooms.Count == 0)
return; return;
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms); var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
var randomRoom = roomsGodotCollection.PickRandom(); var randomRoom = roomsGodotCollection.PickRandom();
var spawnPoint = randomRoom.PlayerSpawn; var spawnPoint = randomRoom.PlayerSpawn;
player.TeleportPlayer((spawnPoint.Rotation, spawnPoint.Position)); player.TeleportPlayer((spawnPoint.Rotation, spawnPoint.Position));
SfxDatabase.Instance.Play(SoundEffect.TeleportToRandomRoom); SfxDatabase.Instance.Play(SoundEffect.TeleportToRandomRoom);
} }
public void ChangeAffinity(ThrowableItem throwableItem) public void ChangeAffinity(ThrowableItem throwableItem)
{ {
var maximumElements = Enum.GetNames(typeof(ElementType)).Length; var maximumElements = Enum.GetNames(typeof(ElementType)).Length;
var newElement = ((int)throwableItem.ElementType + 1) % maximumElements; var newElement = ((int)throwableItem.ElementType + 1) % maximumElements;
throwableItem.SetElementType((ElementType)newElement); throwableItem.SetElementType((ElementType)newElement);
// TODO: Make this an inventory animation to cycle through elements. // TODO: Make this an inventory animation to cycle through elements.
throwableItem.SetDescription( throwableItem.SetDescription(
$"Inflicts {throwableItem.ElementType} damage when thrown." + $"Inflicts {throwableItem.ElementType} damage when thrown." +
$"{System.Environment.NewLine}Use item to change Affinity."); $"{System.Environment.NewLine}Use item to change Affinity.");
throwableItem.SetCount(throwableItem.Count + 1); throwableItem.SetCount(throwableItem.Count + 1);
} }
public void WarpToExit() public void WarpToExit()
{ {
var exitRoom = _game.CurrentFloor.Rooms.OfType<ExitRoom>().Single(); var exitRoom = _game.CurrentFloor.Rooms.OfType<ExitRoom>().Single();
if (exitRoom.PlayerDiscoveredRoom) if (exitRoom.PlayerDiscoveredRoom)
{ {
SfxDatabase.Instance.Play(SoundEffect.TeleportToExit); SfxDatabase.Instance.Play(SoundEffect.TeleportToExit);
_player.TeleportPlayer((exitRoom.PlayerSpawn.Rotation, exitRoom.PlayerSpawn.Position)); _player.TeleportPlayer((exitRoom.PlayerSpawn.Rotation, exitRoom.PlayerSpawn.Position));
} }
} }
public void DamagesPlayer(int damage) 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) public void RerollItem(InventoryItem itemToReroll)
{ {
var itemReroller = new ItemReroller(ItemDatabase.Instance); var itemReroller = new ItemReroller(ItemDatabase.Instance);
itemReroller.RerollItem(itemToReroll, _player.Inventory); itemReroller.RerollItem(itemToReroll, _player.Inventory);
} }
public void GetRandomItemOfType<T>(T itemToExclude = null) public T GetRandomItemOfType<T>(T itemToExclude = null)
where T : InventoryItem where T : InventoryItem => ItemDatabase.Instance.PickItem(itemToExclude);
{
_player.Inventory.TryAdd(ItemDatabase.Instance.PickItem(itemToExclude));
}
public void RandomSpell() public void RandomSpell()
{ {
throw new NotImplementedException("Spells not implemented yet."); throw new NotImplementedException("Spells not implemented yet.");
} }
public void DropTo1HPAndGainRareItem<T>() public void DropTo1HPAndGainRareItem<T>()
where T : InventoryItem where T : InventoryItem
{ {
_player.HealthComponent.SetCurrentHealth(1); _player.HealthComponent.SetCurrentHealth(1);
_player.Inventory.TryAdd(ItemDatabase.Instance.PickRareItem<T>()); _player.Inventory.TryAdd(ItemDatabase.Instance.PickRareItem<T>());
} }
public void TradeRandomItem(BoxItem box) public void TradeRandomItem<T>(BoxItem box)
where T : InventoryItem
{ {
if (_player.Inventory.Items.Count == 1) var tradableItems = _player.Inventory.Items.OfType<T>().Where(x => x != box).ToList();
return;
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(); GetRandomItemOfType<T>();
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<InventoryItem>(box);
} }
public void TradeAllRandomItems(BoxItem box) public IEnumerable<InventoryItem> TradeAllRandomItems<T>(BoxItem box)
where T : InventoryItem
{ {
var tradableItems = _player.Inventory.Items.Where(x => x != box); var newInventory = new List<InventoryItem>();
foreach (var item in tradableItems) var items = _player.Inventory.Items.OfType<T>().Where(x => x != box).ToList();
TradeRandomItem(box); foreach (var item in items)
newInventory.Add(GetRandomItemOfType<T>());
return newInventory;
} }
public void GetUnobtainedItem() public void GetUnobtainedItem()
{ {
var pickableItems = ItemDatabase.Instance.Items.Except(_player.Inventory.Items).ToList(); var pickableItems = ItemDatabase.Instance.Items.Except(_player.Inventory.Items).ToList();
var rng = new RandomNumberGenerator(); var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
var randomIndex = rng.RandiRange(0, pickableItems.Count - 1); var randomIndex = rng.RandiRange(0, pickableItems.Count - 1);
var selectedItem = pickableItems[randomIndex]; var selectedItem = pickableItems[randomIndex];
if (selectedItem is ThrowableItem throwableItem) if (selectedItem is ThrowableItem throwableItem)
throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount)); throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount));
_player.Inventory.TryAdd(selectedItem); _player.Inventory.TryAdd(selectedItem);
} }
public void GetBasicItem<T>() public void GetBasicItem<T>()
where T : InventoryItem where T : InventoryItem
{ {
_player.Inventory.TryAdd(ItemDatabase.Instance.PickBasicItem<T>()); _player.Inventory.TryAdd(ItemDatabase.Instance.PickBasicItem<T>());
} }
} }

View File

@@ -19,32 +19,32 @@ public class ItemDatabase
public T PickItem<T>(T itemToExclude = null) public T PickItem<T>(T itemToExclude = null)
where T : InventoryItem where T : InventoryItem
{ {
var itemsToSelectFrom = Items; var itemsToSelectFrom = Items.OfType<T>();
return PickItemInternal(itemsToSelectFrom, itemToExclude); return PickItemInternal(itemsToSelectFrom, itemToExclude);
} }
public T PickRareItem<T>(T itemToExclude = null) public T PickRareItem<T>(T itemToExclude = null)
where T : InventoryItem where T : InventoryItem
{ {
var getRareItems = Items.Where(x => x.SpawnRate < 0.1f); var getRareItems = Items.OfType<T>().Where(x => x.SpawnRate < 0.1f);
return PickItemInternal(getRareItems, itemToExclude); return PickItemInternal(getRareItems, itemToExclude);
} }
public T PickBasicItem<T>(T itemToExclude = null) public T PickBasicItem<T>(T itemToExclude = null)
where T : InventoryItem where T : InventoryItem
{ {
var getBasicItems = Items.Where(x => x.SpawnRate > 0.5f); var getBasicItems = Items.OfType<T>().Where(x => x.SpawnRate > 0.5f);
return PickItemInternal(getBasicItems, itemToExclude); return PickItemInternal(getBasicItems, itemToExclude);
} }
private T PickItemInternal<T>(IEnumerable<InventoryItem> itemsToSelectFrom, T itemToExclude = null) private T PickItemInternal<T>(IEnumerable<T> itemsToSelectFrom, T itemToExclude = null)
where T : InventoryItem where T : InventoryItem
{ {
var rng = new RandomNumberGenerator(); var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
if (itemToExclude is not null) if (itemToExclude is not null)
itemsToSelectFrom = [.. itemsToSelectFrom.OfType<T>().Where(x => x.ItemName != itemToExclude.ItemName)]; itemsToSelectFrom = [.. itemsToSelectFrom.Where(x => x.ItemName != itemToExclude.ItemName)];
var weights = itemsToSelectFrom.Select(x => x.SpawnRate).ToArray(); var weights = itemsToSelectFrom.Select(x => x.SpawnRate).ToArray();
var selectedItem = itemsToSelectFrom.ToArray()[rng.RandWeighted(weights)]; var selectedItem = itemsToSelectFrom.ToArray()[rng.RandWeighted(weights)];
@@ -52,7 +52,7 @@ public class ItemDatabase
if (selectedItem is ThrowableItem throwableItem) if (selectedItem is ThrowableItem throwableItem)
throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount)); throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount));
return (T)selectedItem; return selectedItem;
} }
private ItemDatabase() private ItemDatabase()
@@ -64,6 +64,7 @@ public class ItemDatabase
var throwableResources = DirAccess.GetFilesAt("res://src/items/throwable/resources/"); var throwableResources = DirAccess.GetFilesAt("res://src/items/throwable/resources/");
var consumableResources = DirAccess.GetFilesAt("res://src/items/consumable/resources/"); var consumableResources = DirAccess.GetFilesAt("res://src/items/consumable/resources/");
var effectResources = DirAccess.GetFilesAt("res://src/items/effect/resources/"); var effectResources = DirAccess.GetFilesAt("res://src/items/effect/resources/");
var boxResources = DirAccess.GetFilesAt("res://src/items/box/resources/");
foreach (var armor in armorResources) foreach (var armor in armorResources)
{ {
@@ -119,6 +120,15 @@ public class ItemDatabase
database.Add(effectItemScene); database.Add(effectItemScene);
} }
foreach (var boxItem in boxResources)
{
var boxItemInfo = GD.Load<BoxItemStats>($"res://src/items/box/resources/{boxItem}");
var boxItemScene = ResourceLoader.Load<PackedScene>("res://src/items/box/BoxItem.tscn").Instantiate<BoxItem>();
boxItemScene.Stats = boxItemInfo;
if (!database.Contains(boxItemScene))
database.Add(boxItemScene);
}
Items = [.. database]; Items = [.. database];
} }
} }

View File

@@ -6,7 +6,7 @@
height = 0.725098 height = 0.725098
[sub_resource type="BoxShape3D" id="BoxShape3D_qdeu2"] [sub_resource type="BoxShape3D" id="BoxShape3D_qdeu2"]
size = Vector3(0.778381, 0.929947, 0.731567) size = Vector3(0.898941, 2.34974, 0.86676)
[node name="Armor" type="RigidBody3D"] [node name="Armor" type="RigidBody3D"]
collision_layer = 0 collision_layer = 0
@@ -36,4 +36,5 @@ texture_filter = 0
render_priority = 100 render_priority = 100
[node name="CollisionShape3D" type="CollisionShape3D" parent="Pickup"] [node name="CollisionShape3D" type="CollisionShape3D" parent="Pickup"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00804907, 0.709896, 0.0675965)
shape = SubResource("BoxShape3D_qdeu2") shape = SubResource("BoxShape3D_qdeu2")

View File

@@ -0,0 +1,26 @@
[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://ds7s722m5y7m4"]
[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_dgx1x"]
[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_ncstm"]
[resource]
script = ExtResource("2_ncstm")
DamageToPlayer = 0
Name = "Alluring Acquisition"
Description = "Grants you a basic item."
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 = 14
Texture = ExtResource("1_dgx1x")
metadata/_custom_type_script = "uid://vuavr681au06"

View File

@@ -0,0 +1,26 @@
[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://6c0t45setc82"]
[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_wwmaf"]
[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_6h66g"]
[resource]
script = ExtResource("2_6h66g")
DamageToPlayer = 0
Name = "Asceticism"
Description = "Forcibly unequips all of your 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 = 16
Texture = ExtResource("1_wwmaf")
metadata/_custom_type_script = "uid://vuavr681au06"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -0,0 +1,26 @@
[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://bb44i0nb2ov3i"]
[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_kqlme"]
[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_w23fa"]
[resource]
script = ExtResource("2_w23fa")
DamageToPlayer = 0
Name = "Glue Jar"
Description = "Makes you unable to unequip any 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 = 15
Texture = ExtResource("1_kqlme")
metadata/_custom_type_script = "uid://vuavr681au06"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -0,0 +1,26 @@
[gd_resource type="Resource" script_class="BoxItemStats" load_steps=3 format=3 uid="uid://ba1ihsi6culef"]
[ext_resource type="Texture2D" uid="uid://bg47n2tmintm0" path="res://src/items/consumable/textures/past self remnant.PNG" id="1_a6ha2"]
[ext_resource type="Script" uid="uid://vuavr681au06" path="res://src/items/accessory/BoxItemStats.cs" id="2_tbg32"]
[resource]
script = ExtResource("2_tbg32")
DamageToPlayer = 0
Name = "Scripture Sign; Curiosity"
Description = "Grants you an item you do not currently have."
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 = 13
Texture = ExtResource("1_a6ha2")
metadata/_custom_type_script = "uid://vuavr681au06"

View File

@@ -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"

View File

@@ -6,7 +6,7 @@
height = 0.725098 height = 0.725098
[sub_resource type="BoxShape3D" id="BoxShape3D_7mh0f"] [sub_resource type="BoxShape3D" id="BoxShape3D_7mh0f"]
size = Vector3(0.778381, 0.929947, 0.731567) size = Vector3(0.778381, 3.19556, 0.731567)
[node name="ConsumableItem" type="RigidBody3D"] [node name="ConsumableItem" type="RigidBody3D"]
collision_layer = 0 collision_layer = 0
@@ -38,4 +38,5 @@ texture_filter = 0
render_priority = 100 render_priority = 100
[node name="CollisionShape3D" type="CollisionShape3D" parent="Pickup"] [node name="CollisionShape3D" type="CollisionShape3D" parent="Pickup"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.13281, 0)
shape = SubResource("BoxShape3D_7mh0f") shape = SubResource("BoxShape3D_7mh0f")

View File

@@ -2,6 +2,7 @@ using Chickensoft.AutoInject;
using Chickensoft.Introspection; using Chickensoft.Introspection;
using Chickensoft.Serialization; using Chickensoft.Serialization;
using Godot; using Godot;
using System;
using Zennysoft.Ma.Adapter; using Zennysoft.Ma.Adapter;
using Zennysoft.Ma.Adapter.Entity; using Zennysoft.Ma.Adapter.Entity;
@@ -44,6 +45,8 @@ public partial class Weapon : EquipableItem
public void IncreaseWeaponAttack(int bonus) => _bonusDamage += bonus; public void IncreaseWeaponAttack(int bonus) => _bonusDamage += bonus;
public void SetWeaponAttack(int newBonus) => _bonusDamage = newBonus;
public override int BonusAttack { get => Stats.BonusAttack + _bonusDamage; } public override int BonusAttack { get => Stats.BonusAttack + _bonusDamage; }
[Save("weapon_bonus_damage")] [Save("weapon_bonus_damage")]

View File

@@ -0,0 +1,30 @@
[gd_resource type="Resource" script_class="WeaponStats" load_steps=4 format=3 uid="uid://c5d1lx0m53d5i"]
[ext_resource type="AudioStream" uid="uid://ilf2s8ct2stt" path="res://src/audio/sfx/PLAYER_slower_slash.ogg" id="1_wkueq"]
[ext_resource type="Texture2D" uid="uid://cil3xe3jq82r6" path="res://src/items/weapons/textures/JIBLETT.PNG" id="2_13kat"]
[ext_resource type="Script" uid="uid://cc7byqeolw5y4" path="res://src/items/weapons/WeaponStats.cs" id="3_34krx"]
[resource]
script = ExtResource("3_34krx")
AttackSpeed = 1.0
WeaponElement = 0
WeaponTag = 5
SoundEffect = 4
Name = "Hope's Edge"
Description = "Sword that strikes harder the lower HP you have."
SpawnRate = 0.1
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 = 0
Texture = ExtResource("2_13kat")
AudioStream = ExtResource("1_wkueq")

View File

@@ -20,34 +20,34 @@ 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 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)); }
@@ -55,25 +55,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

@@ -28,47 +28,47 @@ public abstract partial class DungeonRoom : Node3D, IDungeonRoom
public void Setup() public void Setup()
{ {
_enemiesInRoom = []; _enemiesInRoom = [];
if (_room != null) if (_room != null)
{ {
_room.BodyEntered += Room_BodyEntered; _room.BodyEntered += Room_BodyEntered;
_room.BodyExited += Room_BodyExited; _room.BodyExited += Room_BodyExited;
} }
} }
private void Room_BodyExited(Node3D body) private void Room_BodyExited(Node3D body)
{ {
if (body is IEnemy enemy) if (body is IEnemy enemy)
_enemiesInRoom = _enemiesInRoom.Remove(enemy); _enemiesInRoom = _enemiesInRoom.Remove(enemy);
if (body is IPlayer) if (body is IPlayer)
_isPlayerInRoom = false; _isPlayerInRoom = false;
} }
private void Room_BodyEntered(Node3D body) private void Room_BodyEntered(Node3D body)
{ {
if (body is IEnemy enemy) if (body is IEnemy enemy)
_enemiesInRoom = _enemiesInRoom.Add(enemy); _enemiesInRoom = _enemiesInRoom.Add(enemy);
if (body is IPlayer) if (body is IPlayer)
if (_playerDiscoveredRoom) if (_playerDiscoveredRoom)
_isPlayerInRoom = true; _isPlayerInRoom = true;
else else
OnPlayerDiscoveringRoom(); OnPlayerDiscoveringRoom();
} }
public ImmutableList<IEnemy> GetEnemiesInCurrentRoom() public ImmutableList<IEnemy> GetEnemiesInCurrentRoom()
{ {
return _enemiesInRoom; return _enemiesInRoom;
} }
private void OnPlayerDiscoveringRoom() private void OnPlayerDiscoveringRoom()
{ {
_isPlayerInRoom = true; _isPlayerInRoom = true;
_playerDiscoveredRoom = true; _playerDiscoveredRoom = true;
MinimapShadow.Hide(); MinimapShadow.Hide();
} }
public void OnExitTree() public void OnExitTree()
{ {
_room.BodyEntered -= Room_BodyEntered; _room.BodyEntered -= Room_BodyEntered;
_room.BodyExited -= Room_BodyExited; _room.BodyExited -= Room_BodyExited;
} }
} }

View File

@@ -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="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="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://dv045ax11vybl" 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://dsc8xu78llst6" 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://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://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="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"] [ext_resource type="Shader" uid="uid://brhf7s3riyag5" path="res://src/map/map shaders/Metal.gdshader" id="5_d1qcb"]

View File

@@ -102,6 +102,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
private bool _healthTimerActive = true; private bool _healthTimerActive = true;
private bool _debugSprint = false;
private float _knockbackStrength = 0.0f; private float _knockbackStrength = 0.0f;
private Vector3 _knockbackDirection = Vector3.Zero; private Vector3 _knockbackDirection = Vector3.Zero;
@@ -167,6 +169,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
{ {
Hitbox.AreaEntered += Hitbox_AreaEntered; Hitbox.AreaEntered += Hitbox_AreaEntered;
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered; CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
HealthComponent.CurrentHP.Changed += InverseHPToAttackPowerSync;
HealthComponent.HealthReachedZero += Die; HealthComponent.HealthReachedZero += Die;
PlayerFXAnimations.AnimationFinished += PlayerFXAnimations_AnimationFinished; PlayerFXAnimations.AnimationFinished += PlayerFXAnimations_AnimationFinished;
HealthTimer.WaitTime = _healthTimerWaitTime; HealthTimer.WaitTime = _healthTimerWaitTime;
@@ -242,9 +245,9 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
if (@event.IsActionPressed(GameInputs.Attack)) if (@event.IsActionPressed(GameInputs.Attack))
Attack(); Attack();
if (@event.IsActionPressed(GameInputs.Sprint)) if (@event.IsActionPressed(GameInputs.Sprint))
Settings.MoveSpeed *= 2; _debugSprint = true;
if (@event.IsActionReleased(GameInputs.Sprint)) else if (@event.IsActionReleased(GameInputs.Sprint))
Settings.MoveSpeed /= 2; _debugSprint = false;
} }
public void PlayTestAnimation() public void PlayTestAnimation()
@@ -330,6 +333,17 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
PlayerDied?.Invoke(); PlayerDied?.Invoke();
} }
private void InverseHPToAttackPowerSync(int obj)
{
var weapon = (Weapon)EquipmentComponent.EquippedWeapon.Value;
if (weapon.WeaponTag == WeaponTag.InverseHPAttackPower)
{
var healthPercentage = (HealthComponent.CurrentHP.Value * 10) / HealthComponent.MaximumHP.Value;
weapon.SetWeaponAttack(10 - healthPercentage);
EquipmentComponent.Equip(weapon);
}
}
private void OnExitTree() private void OnExitTree()
{ {
PlayerLogic.Stop(); PlayerLogic.Stop();
@@ -350,6 +364,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
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)
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);

View File

@@ -60,12 +60,6 @@ public partial class InventoryMenu : Control, IInventoryMenu
private IItemSlot _currentlySelectedItem = null; private IItemSlot _currentlySelectedItem = null;
private bool _enableMenuSound = false; private bool _enableMenuSound = false;
public override void _EnterTree()
{
SetProcessInput(false);
SetProcessUnhandledInput(false);
}
public void OnResolved() public void OnResolved()
{ {
ItemSlots = [ItemSlot1, ItemSlot2, ItemSlot3, ItemSlot4, ItemSlot5, ItemSlot6, ItemSlot7, ItemSlot8, ItemSlot9, ItemSlot10, ItemSlot11, ItemSlot12, ItemSlot13, ItemSlot14, ItemSlot15, ItemSlot16, ItemSlot17, ItemSlot18, ItemSlot19, ItemSlot20]; ItemSlots = [ItemSlot1, ItemSlot2, ItemSlot3, ItemSlot4, ItemSlot5, ItemSlot6, ItemSlot7, ItemSlot8, ItemSlot9, ItemSlot10, ItemSlot11, ItemSlot12, ItemSlot13, ItemSlot14, ItemSlot15, ItemSlot16, ItemSlot17, ItemSlot18, ItemSlot19, ItemSlot20];
@@ -93,6 +87,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
DropButton.FocusEntered += ActionButtonFocusChanged; DropButton.FocusEntered += ActionButtonFocusChanged;
VisibilityChanged += InventoryMenu_VisibilityChanged; VisibilityChanged += InventoryMenu_VisibilityChanged;
SetProcessUnhandledInput(false);
} }
private void ActionButtonFocusChanged() private void ActionButtonFocusChanged()

View File

@@ -62,12 +62,6 @@ public partial class LoadNextLevel : Control, IFloorClearMenu
ExitButton.Pressed += ExitButton_Pressed; ExitButton.Pressed += ExitButton_Pressed;
} }
public override void _Input(InputEvent @event)
{
if (_fadingIn)
GetViewport().SetInputAsHandled();
}
private void CurrentFloorNumber_Sync(int _) => FloorNumber.Text = _map.CurrentFloorNumber.Value.ToString("D2"); private void CurrentFloorNumber_Sync(int _) => FloorNumber.Text = _map.CurrentFloorNumber.Value.ToString("D2");
private void EquipmentComponent_EquipmentChanged(EquipableItem obj) private void EquipmentComponent_EquipmentChanged(EquipableItem obj)