Major Player refactor

This commit is contained in:
2025-02-07 02:29:50 -08:00
parent 0cdae88952
commit fe1a1e61ef
132 changed files with 2554 additions and 2478 deletions

View File

@@ -1,9 +1,8 @@
namespace GameJamDungeon
{
public interface IEquipableItem : IInventoryItem
{
public void Equip();
namespace GameJamDungeon;
public void Unequip();
}
public interface IEquipableItem : IInventoryItem
{
public void Equip();
public void Unequip();
}

View File

@@ -2,7 +2,6 @@
using Chickensoft.GodotNodeInterfaces;
using Godot;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@@ -34,6 +33,8 @@ public interface IInventory : INode
event Inventory.PickedUpItemEventHandler PickedUpItem;
event Inventory.AccessoryUnequippedEventHandler AccessoryUnequipped;
event Inventory.RaiseStatRequestEventHandler RaiseStatRequest;
}
public partial class Inventory : Node, IInventory
@@ -44,7 +45,7 @@ public partial class Inventory : Node, IInventory
[Signal]
public delegate void InventoryAtCapacityEventHandler(string rejectedItemName);
[Signal]
public delegate void AccessoryUnequippedEventHandler(AccessoryStats unequippedAccessory);
public delegate void AccessoryUnequippedEventHandler(Accessory unequippedAccessory);
[Signal]
public delegate void RaiseStatRequestEventHandler(ConsumableItemStats consumableItemStats);
[Signal]
@@ -70,12 +71,12 @@ public partial class Inventory : Node, IInventory
{
if (Items.Count >= _maxInventorySize)
{
EmitSignal(SignalName.InventoryAtCapacity, inventoryItem.Info.Name);
EmitSignal(SignalName.InventoryAtCapacity, inventoryItem.ItemName);
return false;
}
Items.Add(inventoryItem);
EmitSignal(SignalName.PickedUpItem, inventoryItem.Info.Name);
EmitSignal(SignalName.PickedUpItem, inventoryItem.ItemName);
return true;
}
@@ -98,14 +99,14 @@ public partial class Inventory : Node, IInventory
if (equipable is Weapon weapon)
{
_equippedWeapon.OnNext(new Weapon());
if (weapon.WeaponStats.WeaponTags.Contains(WeaponTag.BreaksOnChange))
if (weapon.WeaponTags.Contains(WeaponTag.BreaksOnChange))
Items.Remove(weapon);
}
else if (equipable is Armor armor)
_equippedArmor.OnNext(new Armor());
else if (equipable is Accessory accessory)
{
EmitSignal(SignalName.AccessoryUnequipped, _equippedAccessory.Value.AccessoryStats);
EmitSignal(SignalName.AccessoryUnequipped, _equippedAccessory.Value);
_equippedAccessory.OnNext(new Accessory());
}
else
@@ -146,10 +147,10 @@ public partial class Inventory : Node, IInventory
{
public int Compare(Weapon x, Weapon y)
{
if (x.WeaponStats.Damage == y.WeaponStats.Damage)
return x.WeaponStats.Name.CompareTo(y.WeaponStats.Name);
if (x.Damage == y.Damage)
return x.ItemName.CompareTo(y.ItemName);
return x.WeaponStats.Damage < y.WeaponStats.Damage ? 1 : -1;
return x.Damage < y.Damage ? 1 : -1;
}
}
@@ -157,10 +158,10 @@ public partial class Inventory : Node, IInventory
{
public int Compare(Armor x, Armor y)
{
if (x.ArmorStats.Defense == y.ArmorStats.Defense)
return x.ArmorStats.Name.CompareTo(y.ArmorStats.Name);
if (x.Defense == y.Defense)
return x.ItemName.CompareTo(y.ItemName);
return x.ArmorStats.Defense < y.ArmorStats.Defense ? 1 : -1;
return x.Defense < y.Defense ? 1 : -1;
}
}
@@ -168,7 +169,7 @@ public partial class Inventory : Node, IInventory
{
public int Compare(Accessory x, Accessory y)
{
return x.AccessoryStats.Name.CompareTo(y.AccessoryStats.Name);
return x.ItemName.CompareTo(y.ItemName);
}
}
@@ -176,14 +177,14 @@ public partial class Inventory : Node, IInventory
{
public int Compare(ConsumableItem x, ConsumableItem y)
{
return x.ConsumableItemInfo.Name.CompareTo(y.ConsumableItemInfo.Name);
return x.ItemName.CompareTo(y.ItemName);
}
}
public class ThrowableComparer : IComparer<ThrowableItem>
{
public int Compare(ThrowableItem x, ThrowableItem y)
{
return x.ThrowableItemInfo.Name.CompareTo(y.ThrowableItemInfo.Name);
return x.ItemName.CompareTo(y.ItemName);
}
}
}

View File

@@ -1,17 +1,29 @@
using Chickensoft.GodotNodeInterfaces;
using Godot;
using System;
namespace GameJamDungeon
namespace GameJamDungeon;
public interface IInventoryItem : INode3D
{
public interface IInventoryItem : INode3D
{
public Guid ID { get; }
public Guid ID { get; }
public InventoryItemStats Info { get; }
}
string ItemName { get; }
public interface IUsableItem : IInventoryItem
{
public void Use();
}
string Description { get; }
float SpawnRate { get; }
double ThrowDamage { get; }
float ThrowSpeed { get; }
Texture2D GetTexture();
public void SetItemStats(InventoryItemStats inventoryItemStats);
}
public interface IUsableItem : IInventoryItem
{
public void Use();
}

View File

@@ -1,5 +1,6 @@
using Godot;
namespace GameJamDungeon;
public partial class InventoryItemStats : Resource
{
[Export]

View File

@@ -1,75 +1,74 @@
using Godot;
using System.Collections.Generic;
namespace GameJamDungeon
namespace GameJamDungeon;
public partial class ItemDatabase : Node
{
public partial class ItemDatabase : Node
[Export]
public PackedScene WeaponScene { get; set; }
[Export]
public PackedScene ArmorScene { get; set; }
[Export]
public PackedScene AccessoryScene { get; set; }
[Export]
public PackedScene ThrowableItemScene { get; set; }
[Export]
public PackedScene ConsumableItemScene { get; set; }
public IInventoryItem[] Initialize()
{
[Export]
public PackedScene WeaponScene { get; set; }
var database = new List<IInventoryItem>();
var armorResources = DirAccess.GetFilesAt("res://src/items/armor/resources/");
var weaponResources = DirAccess.GetFilesAt("res://src/items/weapons/resources/");
var accessoryResources = DirAccess.GetFilesAt("res://src/items/accessory/resources/");
var throwableResources = DirAccess.GetFilesAt("res://src/items/throwable/resources/");
var consumableResources = DirAccess.GetFilesAt("res://src/items/consumable/resources/");
[Export]
public PackedScene ArmorScene { get; set; }
[Export]
public PackedScene AccessoryScene { get; set; }
[Export]
public PackedScene ThrowableItemScene { get; set; }
[Export]
public PackedScene ConsumableItemScene { get; set; }
public IInventoryItem[] Initialize()
foreach (var armor in armorResources)
{
var database = new List<IInventoryItem>();
var armorResources = DirAccess.GetFilesAt("res://src/items/armor/resources/");
var weaponResources = DirAccess.GetFilesAt("res://src/items/weapons/resources/");
var accessoryResources = DirAccess.GetFilesAt("res://src/items/accessory/resources/");
var throwableResources = DirAccess.GetFilesAt("res://src/items/throwable/resources/");
var consumableResources = DirAccess.GetFilesAt("res://src/items/consumable/resources/");
foreach (var armor in armorResources)
{
var armorInfo = GD.Load<ArmorStats>($"res://src/items/armor/resources/{armor}");
var armorScene = ArmorScene.Instantiate<Armor>();
armorScene.ArmorStats = armorInfo;
database.Add(armorScene);
}
foreach (var weapon in weaponResources)
{
var weaponInfo = GD.Load<WeaponStats>($"res://src/items/weapons/resources/{weapon}");
var weaponScene = WeaponScene.Instantiate<Weapon>();
weaponScene.WeaponStats = weaponInfo;
database.Add(weaponScene);
}
foreach (var accessory in accessoryResources)
{
var accessoryInfo = GD.Load<AccessoryStats>($"res://src/items/accessory/resources/{accessory}");
var accessoryScene = AccessoryScene.Instantiate<Accessory>();
accessoryScene.AccessoryStats = accessoryInfo;
database.Add(accessoryScene);
}
foreach (var throwable in throwableResources)
{
var throwableItemInfo = GD.Load<ThrowableItemStats>($"res://src/items/throwable/resources/{throwable}");
var throwableItemScene = ThrowableItemScene.Instantiate<ThrowableItem>();
throwableItemScene.ThrowableItemInfo = throwableItemInfo;
database.Add(throwableItemScene);
}
foreach (var consumable in consumableResources)
{
var consumableItemInfo = GD.Load<ConsumableItemStats>($"res://src/items/consumable/resources/{consumable}");
var consumableItemScene = ConsumableItemScene.Instantiate<ConsumableItem>();
consumableItemScene.ConsumableItemInfo = consumableItemInfo;
database.Add(consumableItemScene);
}
return database.ToArray();
var armorInfo = GD.Load<ArmorStats>($"res://src/items/armor/resources/{armor}");
var armorScene = ArmorScene.Instantiate<Armor>();
armorScene.SetItemStats(armorInfo);
database.Add(armorScene);
}
foreach (var weapon in weaponResources)
{
var weaponInfo = GD.Load<WeaponStats>($"res://src/items/weapons/resources/{weapon}");
var weaponScene = WeaponScene.Instantiate<Weapon>();
weaponScene.SetItemStats(weaponInfo);
database.Add(weaponScene);
}
foreach (var accessory in accessoryResources)
{
var accessoryInfo = GD.Load<AccessoryStats>($"res://src/items/accessory/resources/{accessory}");
var accessoryScene = AccessoryScene.Instantiate<Accessory>();
accessoryScene.SetItemStats(accessoryInfo);
database.Add(accessoryScene);
}
foreach (var throwable in throwableResources)
{
var throwableItemInfo = GD.Load<ThrowableItemStats>($"res://src/items/throwable/resources/{throwable}");
var throwableItemScene = ThrowableItemScene.Instantiate<ThrowableItem>();
throwableItemScene.SetItemStats(throwableItemInfo);
database.Add(throwableItemScene);
}
foreach (var consumable in consumableResources)
{
var consumableItemInfo = GD.Load<ConsumableItemStats>($"res://src/items/consumable/resources/{consumable}");
var consumableItemScene = ConsumableItemScene.Instantiate<ConsumableItem>();
consumableItemScene.SetItemStats(consumableItemInfo);
database.Add(consumableItemScene);
}
return database.ToArray();
}
}

View File

@@ -1,8 +1,10 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
using System;
using System.Collections.Immutable;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class Accessory : Node3D, IEquipableItem
@@ -13,21 +15,45 @@ public partial class Accessory : Node3D, IEquipableItem
[Dependency] public IGameEventDepot GameEventDepot => this.DependOn<IGameEventDepot>();
public InventoryItemStats Info => AccessoryStats;
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
[Export]
public AccessoryStats AccessoryStats { get; set; } = new AccessoryStats();
[Export] private AccessoryStats _accessoryStats { get; set; } = new AccessoryStats();
[Node] public Sprite3D Sprite { get; set; } = default!;
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
[Node] public Area3D Pickup { get; set; } = default!;
public Guid ID => Guid.NewGuid();
public string ItemName => _accessoryStats.Name;
public string Description => _accessoryStats.Description;
public float SpawnRate => _accessoryStats.SpawnRate;
public Texture2D GetTexture() => _accessoryStats.Texture;
public double ThrowDamage => _accessoryStats.ThrowDamage;
public float ThrowSpeed => _accessoryStats.ThrowSpeed;
public int MaxHPUp => _accessoryStats.MaxHPUp;
public int MaxVTUp => _accessoryStats.MaxVTUp;
public double LuckUp => _accessoryStats.LuckUp;
public ImmutableList<AccessoryTag> AccessoryTags => [.. _accessoryStats.AccessoryTags];
public void OnReady()
{
Sprite.Texture = AccessoryStats.Texture;
Pickup.BodyEntered += OnEntered;
Sprite.Texture = _accessoryStats.Texture;
}
public void SetItemStats(InventoryItemStats inventoryItemStats)
{
_accessoryStats = (AccessoryStats)inventoryItemStats;
}
public void Equip()
@@ -42,12 +68,12 @@ public partial class Accessory : Node3D, IEquipableItem
public void Throw()
{
GameRepo.PlayerData.Inventory.Remove(this);
Player.Inventory.Remove(this);
}
public void OnEntered(Node3D body)
{
var isAdded = GameRepo.PlayerData.Inventory.TryAdd(this);
var isAdded = Player.Inventory.TryAdd(this);
if (isAdded)
QueueFree();
}

View File

@@ -1,5 +1,4 @@
using Godot;
using System;
namespace GameJamDungeon;
@@ -13,7 +12,7 @@ public partial class AccessoryStats : InventoryItemStats
public int DEFUp { get; set; } = 0;
[Export]
public double LUCKUp { get; set; } = 0;
public double LuckUp { get; set; } = 0;
[Export]
public int MaxHPUp { get; set; } = 0;

View File

@@ -1,33 +1,50 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
using System;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class Armor : Node3D, IEquipableItem
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
[Dependency] public IGameEventDepot GameEventDepot => this.DependOn<IGameEventDepot>();
public InventoryItemStats Info => ArmorStats;
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
[Export]
public ArmorStats ArmorStats { get; set; } = new ArmorStats();
[Export] private ArmorStats _armorStats { get; set; } = new ArmorStats();
[Node] public Sprite3D Sprite { get; set; } = default!;
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
[Node] public Area3D Pickup { get; set; } = default!;
[Node] private Area3D Pickup { get; set; } = default!;
public Guid ID => Guid.NewGuid();
public string ItemName => _armorStats.Name;
public string Description => _armorStats.Description;
public float SpawnRate => _armorStats.SpawnRate;
public Texture2D GetTexture() => _armorStats.Texture;
public double ThrowDamage => _armorStats.ThrowDamage;
public float ThrowSpeed => _armorStats.ThrowSpeed;
public int Defense => _armorStats.Defense;
public void OnReady()
{
Sprite.Texture = ArmorStats.Texture;
Pickup.BodyEntered += OnEntered;
Sprite.Texture = _armorStats.Texture;
}
public void SetItemStats(InventoryItemStats inventoryItemStats)
{
_armorStats = (ArmorStats)inventoryItemStats;
}
public void Equip()
@@ -42,17 +59,17 @@ public partial class Armor : Node3D, IEquipableItem
public void Throw()
{
GameRepo.PlayerData.Inventory.Remove(this);
Player.Inventory.Remove(this);
}
public void Drop()
{
GameRepo.PlayerData.Inventory.Remove(this);
Player.Inventory.Remove(this);
}
public void OnEntered(Node3D body)
{
var isAdded = GameRepo.PlayerData.Inventory.TryAdd(this);
var isAdded = Player.Inventory.TryAdd(this);
if (isAdded)
QueueFree();
}

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=3 format=3 uid="uid://dorr7v1tkeiy0"]
[ext_resource type="Script" path="res://src/items/armor/Armor.cs" id="1_cmjpq"]
[ext_resource type="Script" uid="uid://bxvre2y2caa3h" path="res://src/items/armor/Armor.cs" id="1_cmjpq"]
[sub_resource type="BoxShape3D" id="BoxShape3D_qdeu2"]
size = Vector3(0.778381, 0.929947, 0.731567)

View File

@@ -1,9 +1,10 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
using System;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class ConsumableItem : Node3D, IUsableItem
{
@@ -13,42 +14,57 @@ public partial class ConsumableItem : Node3D, IUsableItem
public delegate void RaiseStatRequestEventHandler(ConsumableItemStats consumableItemStats);
[Dependency] public IGame Game => this.DependOn<IGame>();
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
[Dependency] public IGameEventDepot GameEventDepot => this.DependOn<IGameEventDepot>();
public InventoryItemStats Info => ConsumableItemInfo;
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
[Export]
public ConsumableItemStats ConsumableItemInfo { get; set; }
private ConsumableItemStats _consumableItemStats { get; set; }
[Node] public Sprite3D Sprite { get; set; } = default!;
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
[Node] public Area3D Pickup { get; set; } = default!;
[Node] private Area3D Pickup { get; set; } = default!;
public Guid ID => Guid.NewGuid();
public string ItemName => _consumableItemStats.Name;
public string Description => _consumableItemStats.Description;
public float SpawnRate => _consumableItemStats.SpawnRate;
public Texture2D GetTexture() => _consumableItemStats.Texture;
public double ThrowDamage => _consumableItemStats.ThrowDamage;
public float ThrowSpeed => _consumableItemStats.ThrowSpeed;
public void Use()
{
if (ConsumableItemInfo.RaiseHPAmount > 0)
Game.RaiseHP(ConsumableItemInfo.RaiseHPAmount);
if (ConsumableItemInfo.RaiseVTAmount > 0)
Game.RaiseVT(ConsumableItemInfo.RaiseVTAmount);
if (_consumableItemStats.RaiseHPAmount > 0)
Game.RaiseHP(_consumableItemStats.RaiseHPAmount);
if (_consumableItemStats.RaiseVTAmount > 0)
Game.RaiseVT(_consumableItemStats.RaiseVTAmount);
if (ConsumableItemInfo.HealHPAmount > 0 && GameRepo.PlayerData.CurrentHP.Value != GameRepo.PlayerData.MaximumHP.Value)
Game.HealHP(ConsumableItemInfo.HealHPAmount);
if (ConsumableItemInfo.HealVTAmount > 0 && GameRepo.PlayerData.CurrentVT.Value != GameRepo.PlayerData.MaximumVT.Value)
Game.HealVT(ConsumableItemInfo.HealVTAmount);
if (_consumableItemStats.HealHPAmount > 0 && Player.Stats.CurrentHP.Value != Player.Stats.MaximumHP.Value)
Game.HealHP(_consumableItemStats.HealHPAmount);
if (_consumableItemStats.HealVTAmount > 0 && Player.Stats.CurrentVT.Value != Player.Stats.MaximumVT.Value)
Game.HealVT(_consumableItemStats.HealVTAmount);
}
public void SetItemStats(InventoryItemStats inventoryItemStats)
{
_consumableItemStats = (ConsumableItemStats)inventoryItemStats;
}
public void OnReady()
{
Sprite.Texture = ConsumableItemInfo.Texture;
Pickup.BodyEntered += OnEntered;
Sprite.Texture = _consumableItemStats.Texture;
}
public void OnEntered(Node3D body)
{
var isAdded = GameRepo.PlayerData.Inventory.TryAdd(this);
var isAdded = Player.Inventory.TryAdd(this);
if (isAdded)
QueueFree();
}

View File

@@ -3,86 +3,87 @@ using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
namespace GameJamDungeon
namespace GameJamDungeon;
public interface IDroppedItem : IRigidBody3D
{
public interface IDroppedItem : IRigidBody3D
void RescueItem();
}
[Meta(typeof(IAutoNode))]
public partial class DroppedItem : RigidBody3D, IDroppedItem
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
[Dependency] public IGame Game => this.DependOn<IGame>();
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
[Node] private Sprite2D Sprite { get; set; } = default!;
public IInventoryItem Item { get; set; }
public void OnResolved()
{
void RescueItem();
ContactMonitor = true;
BodyEntered += DroppedItem_BodyEntered;
Sprite.Texture = Item.GetTexture();
}
[Meta(typeof(IAutoNode))]
public partial class DroppedItem : RigidBody3D, IDroppedItem
public async void Drop()
{
public override void _Notification(int what) => this.Notify(what);
AddCollisionExceptionWith((Node)Game.Player);
GlobalPosition = Player.CurrentPosition + Vector3.Up;
ApplyCentralImpulse(-Player.CurrentBasis.Z.Normalized() * 5.0f);
await ToSignal(GetTree().CreateTimer(1.5), "timeout");
RemoveCollisionExceptionWith((Node)Game.Player);
}
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
public void RescueItem()
{
ContactMonitor = false;
PlayRescueAnimation();
Game.RescuedItems.Items.Add(Item);
}
[Dependency] public IGame Game => this.DependOn<IGame>();
private void PlayRescueAnimation()
{
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
var tweener = GetTree().CreateTween();
SetShaderValue(true);
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 0.3f, 2f);
tweener.TweenCallback(Callable.From(QueueFree));
}
[Node] public Sprite2D Sprite { get; set; } = default!;
private void LoadShader(string shaderPath)
{
var shader = GD.Load<Shader>(shaderPath);
Sprite.Material = new ShaderMaterial();
var shaderMaterial = (ShaderMaterial)Sprite.Material;
shaderMaterial.Shader = shader;
}
public IInventoryItem Item { get; set; }
private void SetShaderValue(float shaderValue)
{
var shaderMaterial = (ShaderMaterial)Sprite.Material;
shaderMaterial.SetShaderParameter("progress", shaderValue);
}
public void OnResolved()
private void SetShaderValue(bool shaderValue)
{
var shaderMaterial = (ShaderMaterial)Sprite.Material;
shaderMaterial.SetShaderParameter("reverse", shaderValue);
}
private void DroppedItem_BodyEntered(Node body)
{
if (body is IPlayer player)
{
ContactMonitor = true;
BodyEntered += DroppedItem_BodyEntered;
Sprite.Texture = Item.Info.Texture;
}
public async void Drop()
{
AddCollisionExceptionWith((Node)Game.Player);
GlobalPosition = Game.Player.GlobalPosition + Vector3.Up;
ApplyCentralImpulse(-Game.Player.GlobalBasis.Z.Normalized() * 5.0f);
await ToSignal(GetTree().CreateTimer(1.5), "timeout");
RemoveCollisionExceptionWith((Node)Game.Player);
}
public void RescueItem()
{
ContactMonitor = false;
PlayRescueAnimation();
Game.RescuedItems.Items.Add(Item);
}
private void PlayRescueAnimation()
{
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
var tweener = GetTree().CreateTween();
SetShaderValue(true);
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 0.3f, 2f);
tweener.TweenCallback(Callable.From(QueueFree));
}
private void LoadShader(string shaderPath)
{
var shader = GD.Load<Shader>(shaderPath);
Sprite.Material = new ShaderMaterial();
var shaderMaterial = (ShaderMaterial)Sprite.Material;
shaderMaterial.Shader = shader;
}
private void SetShaderValue(float shaderValue)
{
var shaderMaterial = (ShaderMaterial)Sprite.Material;
shaderMaterial.SetShaderParameter("progress", shaderValue);
}
private void SetShaderValue(bool shaderValue)
{
var shaderMaterial = (ShaderMaterial)Sprite.Material;
shaderMaterial.SetShaderParameter("reverse", shaderValue);
}
private void DroppedItem_BodyEntered(Node body)
{
if (body is IPlayer player)
{
var isAdded = GameRepo.PlayerData.Inventory.TryAdd(Item);
if (isAdded)
QueueFree();
}
var isAdded = Player.Inventory.TryAdd(Item);
if (isAdded)
QueueFree();
}
}
}

View File

@@ -1,8 +1,9 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class Restorative : Node3D
{

View File

@@ -1,8 +1,10 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
using System;
using System.Collections.Immutable;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class ThrowableItem : Node3D, IUsableItem
@@ -11,56 +13,75 @@ public partial class ThrowableItem : Node3D, IUsableItem
[Dependency] public IGame Game => this.DependOn<IGame>();
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
public InventoryItemStats Info => ThrowableItemInfo;
public int Count { get; }
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
public Guid ID => Guid.NewGuid();
public string ItemName => _throwableItemStats.Name;
public string Description => _throwableItemStats.Description;
public float SpawnRate => _throwableItemStats.SpawnRate;
public Texture2D GetTexture() => _throwableItemStats.Texture;
public double ThrowDamage => _throwableItemStats.ThrowDamage;
public float ThrowSpeed => _throwableItemStats.ThrowSpeed;
public ElementType ElementType => _throwableItemStats.ElementType;
public ImmutableList<ThrowableItemTag> ThrowableItemTags => [.. _throwableItemStats.ThrowableItemTags];
public int Count { get; }
public void SetItemStats(InventoryItemStats inventoryItemStats)
{
_throwableItemStats = (ThrowableItemStats)inventoryItemStats;
}
public void OnEntered(Node3D body)
{
var isAdded = Player.Inventory.TryAdd(this);
if (isAdded)
QueueFree();
}
[Export]
public ThrowableItemStats ThrowableItemInfo { get; set; }
private ThrowableItemStats _throwableItemStats { get; set; }
[Node] public Sprite3D Sprite { get; set; } = default!;
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
[Node] public Area3D Pickup { get; set; } = default!;
[Node] private Area3D Pickup { get; set; } = default!;
public void OnResolved()
{
Sprite.Texture = ThrowableItemInfo.Texture;
Pickup.BodyEntered += OnEntered;
Sprite.Texture = _throwableItemStats.Texture;
}
public void Use()
{
if (ThrowableItemInfo.HealHPAmount > 0)
Game.HealHP(ThrowableItemInfo.HealHPAmount);
if (ThrowableItemInfo.HealVTAmount > 0)
Game.HealVT(ThrowableItemInfo.HealVTAmount);
if (_throwableItemStats.HealHPAmount > 0)
Game.HealHP(_throwableItemStats.HealHPAmount);
if (_throwableItemStats.HealVTAmount > 0)
Game.HealVT(_throwableItemStats.HealVTAmount);
if (ThrowableItemInfo.UsableItemTags.Contains(UsableItemTag.DoubleEXP))
if (_throwableItemStats.UsableItemTags.Contains(UsableItemTag.DoubleEXP))
Game.DoubleEXP(TimeSpan.FromSeconds(30));
if (ThrowableItemInfo.ThrowableItemTags.Contains(ThrowableItemTag.CanChangeAffinity))
if (_throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.CanChangeAffinity))
ChangeAffinity();
}
private void ChangeAffinity()
{
var maximumElements = Enum.GetNames(typeof(ElementType)).Length;
ThrowableItemInfo.ElementType = ThrowableItemInfo.ElementType + 1 % maximumElements;
_throwableItemStats.ElementType = _throwableItemStats.ElementType + 1 % maximumElements;
// TODO: Make this an inventory animation to cycle through elements.
ThrowableItemInfo.Description =
$"Inflicts {ThrowableItemInfo.ElementType} damage when thrown." +
_throwableItemStats.Description =
$"Inflicts {_throwableItemStats.ElementType} damage when thrown." +
$"{System.Environment.NewLine}Use item to change Affinity.";
}
public void OnEntered(Node3D body)
{
var isAdded = GameRepo.PlayerData.Inventory.TryAdd(this);
if (isAdded)
QueueFree();
}
}

View File

@@ -1,4 +1,4 @@
using System.ComponentModel;
namespace GameJamDungeon;
public enum ThrowableItemTag
{

View File

@@ -1,53 +1,52 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class ThrownItem : RigidBody3D
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] public IGame Game => this.DependOn<IGame>();
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
public InventoryItemStats ThrownItemStats;
public IInventoryItem ItemThatIsThrown;
[Node] public Sprite3D Sprite { get; set; } = default!;
public void OnResolved()
{
BodyEntered += ThrownItem_BodyEntered;
GlobalPosition = Game.Player.GlobalPosition + new Vector3(0, 0, 0);
Sprite.Texture = ThrownItemStats.Texture;
AddCollisionExceptionWith((Node)Game.Player);
GlobalPosition = Player.CurrentPosition;
Sprite.Texture = ItemThatIsThrown.GetTexture();
AddCollisionExceptionWith((Node)Player);
}
private void ThrownItem_BodyEntered(Node body)
{
if (body is IEnemy enemy)
{
CalculateEffect(enemy);
}
QueueFree();
}
public void Throw()
{
ApplyCentralImpulse(-Game.Player.GlobalBasis.Z.Normalized() * ThrownItemStats.ThrowSpeed);
ApplyCentralImpulse(-Player.CurrentBasis.Z.Normalized() * ItemThatIsThrown.ThrowSpeed);
}
private void CalculateEffect(IEnemy enemy)
{
if (ThrownItemStats is ThrowableItemStats throwableItemStats)
if (ItemThatIsThrown is ThrowableItem throwableItem)
{
if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.LowerTargetTo1HP))
enemy.TakeDamage(enemy.CurrentHP - 1, ElementType.None, false, true, true);
if (throwableItem.ThrowableItemTags.Contains(ThrowableItemTag.LowerTargetTo1HP))
enemy.TakeDamage(enemy.CurrentHP - 1, ignoreDefense: true, ignoreElementalResistance: true);
else
enemy.TakeDamage(throwableItemStats.ThrowDamage, throwableItemStats.ElementType);
enemy.TakeDamage(throwableItem.ThrowDamage, throwableItem.ElementType);
}
else
{
enemy.TakeDamage(ThrownItemStats.ThrowDamage, ElementType.None);
enemy.TakeDamage(ItemThatIsThrown.ThrowDamage);
}
}
}
}

View File

@@ -1,34 +1,65 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using GameJamDungeon;
using Godot;
using System;
using System.Collections.Immutable;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class Weapon : Node3D, IInventoryItem, IEquipableItem
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
public InventoryItemStats Info => WeaponStats;
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
[Signal]
public delegate void EquippedItemEventHandler(Weapon equippedWeapon);
[Export]
public WeaponStats WeaponStats { get; set; } = new WeaponStats();
private WeaponStats _weaponStats { get; set; } = new WeaponStats();
[Node] public Sprite3D Sprite { get; set; } = default!;
[Node] public Sprite3D Sprite { get; set; } = new Sprite3D();
[Node] public Area3D Pickup { get; set; } = default!;
public Texture2D GetTexture() => _weaponStats.Texture;
public Guid ID => Guid.NewGuid();
public string ItemName => _weaponStats.Name;
public string Description => _weaponStats.Description;
public float SpawnRate => _weaponStats.SpawnRate;
public int Damage => _weaponStats.Damage;
public double ThrowDamage => _weaponStats.ThrowDamage;
public float ThrowSpeed => _weaponStats.ThrowSpeed;
public double Luck => _weaponStats.Luck;
public double AttackSpeed => _weaponStats.AttackSpeed;
public ImmutableList<WeaponTag> WeaponTags => [.. _weaponStats.WeaponTags];
public ElementType WeaponElement => _weaponStats.WeaponElement;
public double ElementalDamageBonus => _weaponStats.ElementalDamageBonus;
public void OnReady()
{
Sprite.Texture = WeaponStats.Texture;
Pickup.BodyEntered += OnEntered;
Sprite.Texture = _weaponStats.Texture;
}
public void SetItemStats(InventoryItemStats inventoryItemStats)
{
_weaponStats = (WeaponStats)inventoryItemStats;
var texture = ResourceLoader.Load(inventoryItemStats.Texture.ResourcePath) as Texture2D;
Sprite.Texture = texture;
}
public void Equip()
@@ -43,17 +74,17 @@ public partial class Weapon : Node3D, IInventoryItem, IEquipableItem
public void Throw()
{
GameRepo.PlayerData.Inventory.Remove(this);
Player.Inventory.Remove(this);
}
public void Drop()
{
GameRepo.PlayerData.Inventory.Remove(this);
Player.Inventory.Remove(this);
}
public void OnEntered(Node3D body)
{
var isAdded = GameRepo.PlayerData.Inventory.TryAdd(this);
var isAdded = Player.Inventory.TryAdd(this);
if (isAdded)
QueueFree();
}

View File

@@ -1,6 +1,7 @@
using GameJamDungeon;
using Godot;
namespace GameJamDungeon;
[GlobalClass]
public partial class WeaponStats : InventoryItemStats
{

View File

@@ -1,7 +0,0 @@
using Godot;
using System;
public partial class Rigid : RigidBody3D
{
}