Compare commits
3 Commits
a9cb43b79e
...
e7a48a08ee
| Author | SHA1 | Date | |
|---|---|---|---|
| e7a48a08ee | |||
| 8cc6d85265 | |||
| d35e81a9a8 |
@@ -13,10 +13,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.0" />
|
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.0" />
|
||||||
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.4.0" />
|
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.4.0" />
|
||||||
|
<PackageReference Include="Chickensoft.Introspection" Version="2.2.0" />
|
||||||
<PackageReference Include="Chickensoft.Introspection.Generator" Version="2.2.0" />
|
<PackageReference Include="Chickensoft.Introspection.Generator" Version="2.2.0" />
|
||||||
<PackageReference Include="Chickensoft.LogicBlocks" Version="5.15.0" />
|
<PackageReference Include="Chickensoft.LogicBlocks" Version="5.15.0" />
|
||||||
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.15.0" />
|
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.15.0" />
|
||||||
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
|
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
|
||||||
|
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
|
||||||
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.5.0" />
|
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.5.0" />
|
||||||
<PackageReference Include="SSH.NET" Version="2024.2.0" />
|
<PackageReference Include="SSH.NET" Version="2024.2.0" />
|
||||||
<PackageReference Include="System.IO.Abstractions" Version="21.2.1" />
|
<PackageReference Include="System.IO.Abstractions" Version="21.2.1" />
|
||||||
|
|||||||
9
GlobalSuppressions.cs
Normal file
9
GlobalSuppressions.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// This file is used by Code Analysis to maintain SuppressMessage
|
||||||
|
// attributes that are applied to this project.
|
||||||
|
// Project-level suppressions either have no target or are given
|
||||||
|
// a specific target and scoped to a namespace, type, member, etc.
|
||||||
|
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
[assembly: SuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>", Scope = "member", Target = "~M:GameJamDungeon.Game.OnResolved")]
|
||||||
|
[assembly: SuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>", Scope = "member", Target = "~M:GameJamDungeon.Game.OnResolved")]
|
||||||
1
GlobalSuppressions.cs.uid
Normal file
1
GlobalSuppressions.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dd3so0j48jtyc
|
||||||
@@ -14,6 +14,7 @@ config/name="GameJamDungeon"
|
|||||||
run/main_scene="uid://d1gjaijijd5ot"
|
run/main_scene="uid://d1gjaijijd5ot"
|
||||||
run/print_header=false
|
run/print_header=false
|
||||||
config/features=PackedStringArray("4.4", "C#", "GL Compatibility")
|
config/features=PackedStringArray("4.4", "C#", "GL Compatibility")
|
||||||
|
run/delta_smoothing=false
|
||||||
boot_splash/show_image=false
|
boot_splash/show_image=false
|
||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
@@ -192,6 +193,16 @@ Previous={
|
|||||||
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":true,"script":null)
|
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":true,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Save={
|
||||||
|
"deadzone": 0.2,
|
||||||
|
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":true,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Load={
|
||||||
|
"deadzone": 0.2,
|
||||||
|
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":true,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
[internationalization]
|
[internationalization]
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public partial class InGameAudioLogic
|
|||||||
|
|
||||||
private void OnInventorySorted() => Output(new Output.PlayInventorySortedSound());
|
private void OnInventorySorted() => Output(new Output.PlayInventorySortedSound());
|
||||||
|
|
||||||
private void OnEquippedItem(IEquipableItem equipableItem) => Output(new Output.PlayEquipSound());
|
private void OnEquippedItem(EquipableItem equipableItem) => Output(new Output.PlayEquipSound());
|
||||||
|
|
||||||
private void OnOverworldEntered() => Output(new Output.PlayOverworldMusic());
|
private void OnOverworldEntered() => Output(new Output.PlayOverworldMusic());
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLogic>
|
|||||||
_enemyModelView.PlayHitAnimation();
|
_enemyModelView.PlayHitAnimation();
|
||||||
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
_enemyLogic.Input(new EnemyLogic.Input.Alerted());
|
||||||
|
|
||||||
if (_player.EquippedWeapon.Value.WeaponTags.Contains(WeaponTag.SelfDamage))
|
if (_player.EquippedWeapon.Value.WeaponTag == WeaponTag.SelfDamage)
|
||||||
_player.Stats.SetCurrentHP(_player.Stats.CurrentHP.Value - 5);
|
_player.Stats.SetCurrentHP(_player.Stats.CurrentHP.Value - 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
namespace GameJamDungeon;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
public enum WeaponTag
|
public enum WeaponTag
|
||||||
{
|
{
|
||||||
|
None,
|
||||||
SelfDamage,
|
SelfDamage,
|
||||||
IgnoreAffinity,
|
IgnoreAffinity,
|
||||||
Knockback,
|
Knockback,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(WeaponTag))]
|
||||||
|
public partial class WeaponTagEnumContext : JsonSerializerContext;
|
||||||
|
|
||||||
public enum ItemTag
|
public enum ItemTag
|
||||||
{
|
{
|
||||||
|
None,
|
||||||
BreaksOnChange
|
BreaksOnChange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(ItemTag))]
|
||||||
|
public partial class ItemTagEnumContext : JsonSerializerContext;
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace GameJamDungeon;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
public enum ElementType
|
public enum ElementType
|
||||||
{
|
{
|
||||||
@@ -9,3 +11,6 @@ public enum ElementType
|
|||||||
Igneous,
|
Igneous,
|
||||||
Ferrum
|
Ferrum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(ElementType))]
|
||||||
|
public partial class ElementTypeEnumContext : JsonSerializerContext;
|
||||||
|
|||||||
201
src/game/Game.cs
201
src/game/Game.cs
@@ -2,9 +2,17 @@
|
|||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
|
using Chickensoft.Collections;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.SaveFileBuilder;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using Chickensoft.Serialization.Godot;
|
||||||
|
using GameJamDungeon.src.items;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO.Abstractions;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization.Metadata;
|
||||||
using static GameJamDungeon.GameLogic.State;
|
using static GameJamDungeon.GameLogic.State;
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta(typeof(IAutoNode))]
|
||||||
@@ -53,10 +61,32 @@ public partial class Game : Node3D, IGame
|
|||||||
[Node] private IPlayer Player { get; set; } = default!;
|
[Node] private IPlayer Player { get; set; } = default!;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Save
|
||||||
|
public JsonSerializerOptions JsonOptions { get; set; } = default!;
|
||||||
|
|
||||||
|
public const string SAVE_FILE_NAME = "game.json";
|
||||||
|
|
||||||
|
public IFileSystem FileSystem { get; set; } = default!;
|
||||||
|
|
||||||
|
public string SaveFilePath { get; set; } = default!;
|
||||||
|
|
||||||
|
public ISaveFile<GameData> SaveFile { get; set; } = default!;
|
||||||
|
|
||||||
|
public ISaveChunk<GameData> GameChunk { get; set; } = default!;
|
||||||
|
|
||||||
|
ISaveChunk<GameData> IProvide<ISaveChunk<GameData>>.Value() => GameChunk;
|
||||||
|
#endregion
|
||||||
|
|
||||||
public RescuedItemDatabase RescuedItems { get; set; } = default!;
|
public RescuedItemDatabase RescuedItems { get; set; } = default!;
|
||||||
|
|
||||||
|
private EffectService _effectService;
|
||||||
|
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
|
FileSystem = new FileSystem();
|
||||||
|
|
||||||
|
SaveFilePath = FileSystem.Path.Join(OS.GetUserDataDir(), SAVE_FILE_NAME);
|
||||||
|
|
||||||
GameRepo = new GameRepo();
|
GameRepo = new GameRepo();
|
||||||
GameLogic = new GameLogic();
|
GameLogic = new GameLogic();
|
||||||
GameEventDepot = new GameEventDepot();
|
GameEventDepot = new GameEventDepot();
|
||||||
@@ -66,10 +96,83 @@ public partial class Game : Node3D, IGame
|
|||||||
GameLogic.Set(Player);
|
GameLogic.Set(Player);
|
||||||
Instantiator = new Instantiator(GetTree());
|
Instantiator = new Instantiator(GetTree());
|
||||||
RescuedItems = new RescuedItemDatabase();
|
RescuedItems = new RescuedItemDatabase();
|
||||||
|
|
||||||
|
var resolver = new SerializableTypeResolver();
|
||||||
|
GodotSerialization.Setup();
|
||||||
|
Serializer.AddConverter(new Texture2DConverter());
|
||||||
|
|
||||||
|
var upgradeDependencies = new Blackboard();
|
||||||
|
|
||||||
|
JsonOptions = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
Converters = {
|
||||||
|
new SerializableTypeConverter(upgradeDependencies)
|
||||||
|
},
|
||||||
|
TypeInfoResolver = JsonTypeInfoResolver.Combine(resolver, WeaponTagEnumContext.Default, ItemTagEnumContext.Default, ElementTypeEnumContext.Default, AccessoryTagEnumContext.Default, ThrowableItemTagEnumContext.Default, UsableItemTagEnumContext.Default, BoxItemTagEnumContext.Default),
|
||||||
|
WriteIndented = true
|
||||||
|
};
|
||||||
|
|
||||||
|
GameChunk = new SaveChunk<GameData>(
|
||||||
|
(chunk) =>
|
||||||
|
{
|
||||||
|
var gameData = new GameData()
|
||||||
|
{
|
||||||
|
PlayerData = new PlayerData()
|
||||||
|
{
|
||||||
|
PlayerStats = new PlayerStats()
|
||||||
|
{
|
||||||
|
CurrentHP = Player.Stats.CurrentHP.Value,
|
||||||
|
MaximumHP = Player.Stats.MaximumHP.Value,
|
||||||
|
CurrentVT = Player.Stats.CurrentVT.Value,
|
||||||
|
MaximumVT = Player.Stats.MaximumVT.Value,
|
||||||
|
CurrentAttack = Player.Stats.CurrentAttack.Value,
|
||||||
|
BonusAttack = Player.Stats.BonusAttack.Value,
|
||||||
|
MaxAttack = Player.Stats.MaxAttack.Value,
|
||||||
|
CurrentDefense = Player.Stats.CurrentDefense.Value,
|
||||||
|
BonusDefense = Player.Stats.BonusDefense.Value,
|
||||||
|
MaxDefense = Player.Stats.MaxDefense.Value,
|
||||||
|
CurrentExp = Player.Stats.CurrentExp.Value,
|
||||||
|
CurrentLevel = Player.Stats.CurrentLevel.Value,
|
||||||
|
ExpToNextLevel = Player.Stats.ExpToNextLevel.Value,
|
||||||
|
Luck = Player.Stats.Luck.Value
|
||||||
|
},
|
||||||
|
Inventory = Player.Inventory
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return gameData;
|
||||||
|
},
|
||||||
|
onLoad: (chunk, data) =>
|
||||||
|
{
|
||||||
|
chunk.LoadChunkSaveData(data.PlayerData);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResolved()
|
public void OnResolved()
|
||||||
{
|
{
|
||||||
|
SaveFile = new SaveFile<GameData>(
|
||||||
|
root: GameChunk,
|
||||||
|
onSave: async (GameData data) =>
|
||||||
|
{
|
||||||
|
// Save the game data to disk.
|
||||||
|
var json = JsonSerializer.Serialize(data, JsonOptions);
|
||||||
|
await FileSystem.File.WriteAllTextAsync(SaveFilePath, json);
|
||||||
|
},
|
||||||
|
onLoad: async () =>
|
||||||
|
{
|
||||||
|
// Load the game data from disk.
|
||||||
|
if (!FileSystem.File.Exists(SaveFilePath))
|
||||||
|
{
|
||||||
|
GD.Print("No save file to load");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var json = await FileSystem.File.ReadAllTextAsync(SaveFilePath);
|
||||||
|
return JsonSerializer.Deserialize<GameData>(json, JsonOptions);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
GameBinding = GameLogic.Bind();
|
GameBinding = GameLogic.Bind();
|
||||||
GameBinding
|
GameBinding
|
||||||
.Handle((in GameLogic.Output.StartGame _) =>
|
.Handle((in GameLogic.Output.StartGame _) =>
|
||||||
@@ -127,6 +230,18 @@ public partial class Game : Node3D, IGame
|
|||||||
GameEventDepot.RestorativePickedUp += GameEventDepot_RestorativePickedUp;
|
GameEventDepot.RestorativePickedUp += GameEventDepot_RestorativePickedUp;
|
||||||
|
|
||||||
DoubleEXPTimer.Timeout += DoubleEXPTimer_Timeout;
|
DoubleEXPTimer.Timeout += DoubleEXPTimer_Timeout;
|
||||||
|
|
||||||
|
_effectService = new EffectService(this, Player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
SaveFile.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load()
|
||||||
|
{
|
||||||
|
SaveFile.Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToggleInventory()
|
public void ToggleInventory()
|
||||||
@@ -153,7 +268,81 @@ public partial class Game : Node3D, IGame
|
|||||||
InGameUI.PlayerInfoUI.DisplayMessage($"{pickedUpItemName} picked up.");
|
InGameUI.PlayerInfoUI.DisplayMessage($"{pickedUpItemName} picked up.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DropItem(IInventoryItem item)
|
public void UseItem(InventoryItem item)
|
||||||
|
{
|
||||||
|
if (item is ConsumableItem consumableItem)
|
||||||
|
{
|
||||||
|
if (Player.Stats.CurrentHP == Player.Stats.MaximumHP && consumableItem.RaiseHPAmount > 0)
|
||||||
|
Player.RaiseHP(consumableItem.RaiseHPAmount);
|
||||||
|
if (Player.Stats.CurrentVT == Player.Stats.MaximumVT && consumableItem.RaiseVTAmount > 0)
|
||||||
|
Player.RaiseVT(consumableItem.RaiseVTAmount);
|
||||||
|
|
||||||
|
if (consumableItem.HealHPAmount > 0 && Player.Stats.CurrentHP != Player.Stats.MaximumHP)
|
||||||
|
Player.HealHP(consumableItem.HealHPAmount);
|
||||||
|
if (consumableItem.HealVTAmount > 0 && Player.Stats.CurrentVT != Player.Stats.MaximumVT)
|
||||||
|
Player.HealVT(consumableItem.HealVTAmount);
|
||||||
|
}
|
||||||
|
if (item is EffectItem effectItem)
|
||||||
|
{
|
||||||
|
switch (effectItem.UsableItemTag)
|
||||||
|
{
|
||||||
|
case UsableItemTag.DoubleEXP:
|
||||||
|
DoubleEXP(TimeSpan.FromSeconds(30));
|
||||||
|
break;
|
||||||
|
case UsableItemTag.TeleportAllEnemiesToRoom:
|
||||||
|
_effectService.TeleportEnemiesToCurrentRoom();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.KillHalfEnemiesInRoom:
|
||||||
|
_effectService.KillHalfEnemiesInRoom();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.TurnAllEnemiesIntoHealingItem:
|
||||||
|
_effectService.TurnAllEnemiesInRoomIntoHealingItem();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.HealsAllInRoomToMaxHP:
|
||||||
|
_effectService.HealAllEnemiesAndPlayerInRoomToFull();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.AbsorbHPFromAllEnemiesInRoom:
|
||||||
|
_effectService.AbsorbHPFromAllEnemiesInRoom();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.DealElementalDamageToAllEnemiesInRoom:
|
||||||
|
_effectService.DealElementalDamageToAllEnemiesInRoom(ElementType.Hydric);
|
||||||
|
break;
|
||||||
|
case UsableItemTag.SwapHPAndVT:
|
||||||
|
_effectService.SwapHPandVT();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.RaiseCurrentWeaponAttack:
|
||||||
|
_effectService.RaiseCurrentWeaponAttack();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.RaiseCurrentDefenseArmor:
|
||||||
|
_effectService.RaiseCurrentArmorDefense();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.RaiseLevel:
|
||||||
|
_effectService.RaiseLevel();
|
||||||
|
break;
|
||||||
|
case UsableItemTag.RandomEffect:
|
||||||
|
_effectService.RandomEffect(effectItem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item is ThrowableItem throwableItem)
|
||||||
|
{
|
||||||
|
if (throwableItem.HealHPAmount > 0)
|
||||||
|
Player.HealHP(throwableItem.HealHPAmount);
|
||||||
|
if (throwableItem.HealVTAmount > 0)
|
||||||
|
Player.HealVT(throwableItem.HealVTAmount);
|
||||||
|
|
||||||
|
if (throwableItem.ThrowableItemTag == ThrowableItemTag.TeleportToRandomLocation)
|
||||||
|
_effectService.TeleportToRandomRoom(Player);
|
||||||
|
|
||||||
|
if (throwableItem.ThrowableItemTag == ThrowableItemTag.CanChangeAffinity)
|
||||||
|
_effectService.ChangeAffinity(throwableItem);
|
||||||
|
|
||||||
|
if (throwableItem.ThrowableItemTag == ThrowableItemTag.WarpToExitIfFound)
|
||||||
|
_effectService.WarpToExit(Player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropItem(InventoryItem item)
|
||||||
{
|
{
|
||||||
var droppedScene = GD.Load<PackedScene>("res://src/items/dropped/DroppedItem.tscn");
|
var droppedScene = GD.Load<PackedScene>("res://src/items/dropped/DroppedItem.tscn");
|
||||||
var dropped = droppedScene.Instantiate<DroppedItem>();
|
var dropped = droppedScene.Instantiate<DroppedItem>();
|
||||||
@@ -162,14 +351,14 @@ public partial class Game : Node3D, IGame
|
|||||||
dropped.Drop();
|
dropped.Drop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ThrowItem(IInventoryItem item)
|
public void ThrowItem(InventoryItem item)
|
||||||
{
|
{
|
||||||
var thrownScene = GD.Load<PackedScene>("res://src/items/thrown/ThrownItem.tscn");
|
var thrownScene = GD.Load<PackedScene>("res://src/items/thrown/ThrownItem.tscn");
|
||||||
var thrown = thrownScene.Instantiate<ThrownItem>();
|
var thrown = thrownScene.Instantiate<ThrownItem>();
|
||||||
thrown.ItemThatIsThrown = item;
|
thrown.ItemThatIsThrown = item;
|
||||||
AddChild(thrown);
|
AddChild(thrown);
|
||||||
thrown.Position += new Vector3(0, 1.5f, 0);
|
thrown.Position += new Vector3(0, 1.5f, 0);
|
||||||
thrown.Throw();
|
thrown.Throw(_effectService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AnnounceMessageOnInventoryScreen(string message)
|
public void AnnounceMessageOnInventoryScreen(string message)
|
||||||
@@ -226,11 +415,11 @@ public partial class Game : Node3D, IGame
|
|||||||
private void FloorClearMenu_TransitionCompleted()
|
private void FloorClearMenu_TransitionCompleted()
|
||||||
{
|
{
|
||||||
GameRepo.Resume();
|
GameRepo.Resume();
|
||||||
if (Player.EquippedWeapon.Value.ItemTags.Contains(ItemTag.BreaksOnChange))
|
if (Player.EquippedWeapon.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||||
Player.Unequip(Player.EquippedWeapon.Value);
|
Player.Unequip(Player.EquippedWeapon.Value);
|
||||||
if (Player.EquippedArmor.Value.ItemTags.Contains(ItemTag.BreaksOnChange))
|
if (Player.EquippedArmor.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||||
Player.Unequip(Player.EquippedArmor.Value);
|
Player.Unequip(Player.EquippedArmor.Value);
|
||||||
if (Player.EquippedAccessory.Value.ItemTags.Contains(ItemTag.BreaksOnChange))
|
if (Player.EquippedAccessory.Value.ItemTag == ItemTag.BreaksOnChange)
|
||||||
Player.Unequip(Player.EquippedAccessory.Value);
|
Player.Unequip(Player.EquippedAccessory.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
[gd_scene load_steps=14 format=3 uid="uid://33ek675mfb5n"]
|
[gd_scene load_steps=13 format=3 uid="uid://33ek675mfb5n"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://chftlu4proh3d" path="res://src/game/Game.cs" id="1_ytcii"]
|
[ext_resource type="Script" uid="uid://chftlu4proh3d" path="res://src/game/Game.cs" id="1_ytcii"]
|
||||||
[ext_resource type="Shader" uid="uid://dmjxo4k2rx1an" path="res://src/app/App.gdshader" id="2_6ifxs"]
|
[ext_resource type="Shader" uid="uid://dmjxo4k2rx1an" path="res://src/app/App.gdshader" id="2_6ifxs"]
|
||||||
[ext_resource type="PackedScene" uid="uid://by67pn7fdsg1m" path="res://src/map/Map.tscn" id="3_d8awv"]
|
[ext_resource type="PackedScene" uid="uid://by67pn7fdsg1m" path="res://src/map/Map.tscn" id="3_d8awv"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="3_kk6ly"]
|
[ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="3_kk6ly"]
|
||||||
[ext_resource type="Resource" uid="uid://bpdbuf0k0exb5" path="res://src/items/weapons/resources/Sword Sword Odette.tres" id="4_6pp6l"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://b1muxus5qdbeu" path="res://src/ui/in_game_ui/InGameUI.tscn" id="5_lxtnp"]
|
[ext_resource type="PackedScene" uid="uid://b1muxus5qdbeu" path="res://src/ui/in_game_ui/InGameUI.tscn" id="5_lxtnp"]
|
||||||
[ext_resource type="PackedScene" uid="uid://b16ejcwanod72" path="res://src/audio/InGameAudio.tscn" id="6_qc71l"]
|
[ext_resource type="PackedScene" uid="uid://b16ejcwanod72" path="res://src/audio/InGameAudio.tscn" id="6_qc71l"]
|
||||||
[ext_resource type="Script" uid="uid://daphxl6vvsbjm" path="res://src/game/DialogueController.cs" id="10_58pbt"]
|
[ext_resource type="Script" uid="uid://daphxl6vvsbjm" path="res://src/game/DialogueController.cs" id="10_58pbt"]
|
||||||
@@ -49,8 +48,7 @@ process_mode = 1
|
|||||||
[node name="Player" parent="SubViewportContainer/SubViewport/PauseContainer" instance=ExtResource("3_kk6ly")]
|
[node name="Player" parent="SubViewportContainer/SubViewport/PauseContainer" instance=ExtResource("3_kk6ly")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
process_mode = 1
|
process_mode = 1
|
||||||
transform = Transform3D(0.0141716, 0, 0.9999, 0, 1, 0, -0.9999, 0, 0.0141716, 0, -2.25339, -6.18796)
|
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, -3, 0)
|
||||||
_defaultWeapon = ExtResource("4_6pp6l")
|
|
||||||
|
|
||||||
[node name="Map" parent="SubViewportContainer/SubViewport/PauseContainer" instance=ExtResource("3_d8awv")]
|
[node name="Map" parent="SubViewportContainer/SubViewport/PauseContainer" instance=ExtResource("3_d8awv")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ namespace GameJamDungeon;
|
|||||||
public partial record GameData
|
public partial record GameData
|
||||||
{
|
{
|
||||||
[Save("player_data")]
|
[Save("player_data")]
|
||||||
public required PlayerStats PlayerData { get; init; }
|
public required PlayerData PlayerData { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ namespace GameJamDungeon;
|
|||||||
|
|
||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.GodotNodeInterfaces;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
|
using Chickensoft.SaveFileBuilder;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvide<IGame>, IProvide<IPlayer>, INode3D
|
public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvide<IGame>, IProvide<IPlayer>, IProvide<ISaveChunk<GameData>>, INode3D
|
||||||
{
|
{
|
||||||
event Game.StatRaisedAlertEventHandler StatRaisedAlert;
|
event Game.StatRaisedAlertEventHandler StatRaisedAlert;
|
||||||
|
|
||||||
@@ -14,9 +15,11 @@ public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvid
|
|||||||
|
|
||||||
public IDungeonFloor CurrentFloor { get; }
|
public IDungeonFloor CurrentFloor { get; }
|
||||||
|
|
||||||
public void DropItem(IInventoryItem item);
|
public void UseItem(InventoryItem item);
|
||||||
|
|
||||||
public void ThrowItem(IInventoryItem item);
|
public void DropItem(InventoryItem item);
|
||||||
|
|
||||||
|
public void ThrowItem(InventoryItem item);
|
||||||
|
|
||||||
public void DoubleEXP(TimeSpan lengthOfEffect);
|
public void DoubleEXP(TimeSpan lengthOfEffect);
|
||||||
|
|
||||||
@@ -33,4 +36,8 @@ public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvid
|
|||||||
public void NextFloorLoaded();
|
public void NextFloorLoaded();
|
||||||
|
|
||||||
public void EnemyDefeated(Vector3 defeatedLocation, EnemyStatResource enemyStatResource);
|
public void EnemyDefeated(Vector3 defeatedLocation, EnemyStatResource enemyStatResource);
|
||||||
|
|
||||||
|
public void Save();
|
||||||
|
|
||||||
|
public void Load();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
|
|
||||||
var currentItem = ItemSlots.ElementAt(_currentIndex).Item;
|
var currentItem = ItemSlots.ElementAt(_currentIndex).Item;
|
||||||
|
|
||||||
if (currentItem is IEquipableItem equipable)
|
if (currentItem is EquipableItem equipable)
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
UseButton.Text = equipable.IsEquipped ? "Unequip" : "Equip";
|
UseButton.Text = equipable.IsEquipped ? "Unequip" : "Equip";
|
||||||
@@ -339,14 +339,14 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
itemSlot.Item = item;
|
itemSlot.Item = item;
|
||||||
ItemsPage.AddChildEx(itemSlot);
|
ItemsPage.AddChildEx(itemSlot);
|
||||||
|
|
||||||
if (itemSlot.Item is IEquipableItem equipable && equipable.IsEquipped)
|
if (itemSlot.Item is EquipableItem equipable && equipable.IsEquipped)
|
||||||
itemSlot.SetEquippedItemStyle();
|
itemSlot.SetEquippedItemStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ItemSlots.Any())
|
if (ItemSlots.Any())
|
||||||
{
|
{
|
||||||
ItemSlots.ElementAt(_currentIndex).SetSelectedItemStyle();
|
ItemSlots.ElementAt(_currentIndex).SetSelectedItemStyle();
|
||||||
if (ItemSlots.ElementAt(_currentIndex).Item is IEquipableItem equipable && equipable.IsEquipped)
|
if (ItemSlots.ElementAt(_currentIndex).Item is EquipableItem equipable && equipable.IsEquipped)
|
||||||
ItemSlots.ElementAt(_currentIndex).SetEquippedSelectedItemStyle();
|
ItemSlots.ElementAt(_currentIndex).SetEquippedSelectedItemStyle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,7 +355,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
{
|
{
|
||||||
await ToSignal(GetTree().CreateTimer(0.1f), "timeout");
|
await ToSignal(GetTree().CreateTimer(0.1f), "timeout");
|
||||||
itemSlot.SetItemStyle();
|
itemSlot.SetItemStyle();
|
||||||
if (itemSlot.Item is IEquipableItem equipable && equipable.IsEquipped)
|
if (itemSlot.Item is EquipableItem equipable && equipable.IsEquipped)
|
||||||
itemSlot.SetEquippedItemStyle();
|
itemSlot.SetEquippedItemStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +370,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
private async Task EquipOrUnequipItem()
|
private async Task EquipOrUnequipItem()
|
||||||
{
|
{
|
||||||
var itemSlot = ItemSlots[_currentIndex];
|
var itemSlot = ItemSlots[_currentIndex];
|
||||||
if (itemSlot.Item is IEquipableItem equipableItem)
|
if (itemSlot.Item is EquipableItem equipableItem)
|
||||||
{
|
{
|
||||||
if (equipableItem.IsEquipped)
|
if (equipableItem.IsEquipped)
|
||||||
{
|
{
|
||||||
@@ -392,21 +392,21 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
private async void UseButtonPressed()
|
private async void UseButtonPressed()
|
||||||
{
|
{
|
||||||
var currentItem = ItemSlots[_currentIndex].Item;
|
var currentItem = ItemSlots[_currentIndex].Item;
|
||||||
if (currentItem is IEquipableItem)
|
if (currentItem is EquipableItem)
|
||||||
await EquipOrUnequipItem();
|
await EquipOrUnequipItem();
|
||||||
else if (currentItem is IUsableItem usableItem)
|
else
|
||||||
{
|
{
|
||||||
usableItem.Use();
|
Game.UseItem(currentItem);
|
||||||
DestroyItem(usableItem);
|
DestroyItem(currentItem);
|
||||||
EmitSignal(SignalName.ClosedMenu);
|
EmitSignal(SignalName.ClosedMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefreshUIAfterUserSelection();
|
RefreshUIAfterUserSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void DestroyItem(IUsableItem usableItem)
|
private async void DestroyItem(InventoryItem item)
|
||||||
{
|
{
|
||||||
Player.Inventory.Remove(usableItem);
|
Player.Inventory.Remove(item);
|
||||||
if (_currentIndex >= ItemSlots.Length - 1)
|
if (_currentIndex >= ItemSlots.Length - 1)
|
||||||
_currentIndex--;
|
_currentIndex--;
|
||||||
if (_currentIndex <= 0)
|
if (_currentIndex <= 0)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace GameJamDungeon;
|
|||||||
|
|
||||||
public interface IItemSlot : IHBoxContainer
|
public interface IItemSlot : IHBoxContainer
|
||||||
{
|
{
|
||||||
public IInventoryItem Item { get; set; }
|
public InventoryItem Item { get; set; }
|
||||||
|
|
||||||
public void SetItemStyle();
|
public void SetItemStyle();
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ public partial class ItemSlot : HBoxContainer, IItemSlot
|
|||||||
{
|
{
|
||||||
ItemName.Text = Item.ItemName;
|
ItemName.Text = Item.ItemName;
|
||||||
//EquipBonus.Text = "...";
|
//EquipBonus.Text = "...";
|
||||||
ItemTexture.Texture = Item.GetTexture();
|
ItemTexture.Texture = Item.ItemStats.Texture;
|
||||||
Player.EquippedWeapon.Sync += EquippedWeapon_Sync;
|
Player.EquippedWeapon.Sync += EquippedWeapon_Sync;
|
||||||
Player.EquippedArmor.Sync += EquippedArmor_Sync;
|
Player.EquippedArmor.Sync += EquippedArmor_Sync;
|
||||||
Player.EquippedAccessory.Sync += EquippedAccessory_Sync;
|
Player.EquippedAccessory.Sync += EquippedAccessory_Sync;
|
||||||
@@ -90,7 +90,7 @@ public partial class ItemSlot : HBoxContainer, IItemSlot
|
|||||||
}
|
}
|
||||||
public void SetSelectedItemStyle()
|
public void SetSelectedItemStyle()
|
||||||
{
|
{
|
||||||
if (Item is IEquipableItem equipableItem && equipableItem.IsEquipped)
|
if (Item is EquipableItem equipableItem && equipableItem.IsEquipped)
|
||||||
{
|
{
|
||||||
ItemName.LabelSettings = SelectedEquippedItemFont;
|
ItemName.LabelSettings = SelectedEquippedItemFont;
|
||||||
//EquipBonus.LabelSettings = EquippedItemFont;
|
//EquipBonus.LabelSettings = EquippedItemFont;
|
||||||
@@ -113,5 +113,5 @@ public partial class ItemSlot : HBoxContainer, IItemSlot
|
|||||||
//EquipBonus.LabelSettings = EquippedItemFont;
|
//EquipBonus.LabelSettings = EquippedItemFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IInventoryItem Item { get; set; } = default!;
|
public InventoryItem Item { get; set; } = default!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ namespace GameJamDungeon;
|
|||||||
|
|
||||||
public class RescuedItemDatabase
|
public class RescuedItemDatabase
|
||||||
{
|
{
|
||||||
public List<IInventoryItem> Items;
|
public List<InventoryItem> Items;
|
||||||
|
|
||||||
public RescuedItemDatabase()
|
public RescuedItemDatabase()
|
||||||
{
|
{
|
||||||
Items = new List<IInventoryItem>();
|
Items = new List<InventoryItem>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
219
src/items/EffectService.cs
Normal file
219
src/items/EffectService.cs
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
using Godot;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GameJamDungeon.src.items
|
||||||
|
{
|
||||||
|
public class EffectService
|
||||||
|
{
|
||||||
|
private readonly IGame _game;
|
||||||
|
private readonly IPlayer _player;
|
||||||
|
|
||||||
|
public EffectService(IGame game, IPlayer player)
|
||||||
|
{
|
||||||
|
_game = game;
|
||||||
|
_player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TeleportEnemiesToCurrentRoom()
|
||||||
|
{
|
||||||
|
var currentFloor = _game.CurrentFloor;
|
||||||
|
var rooms = currentFloor.Rooms;
|
||||||
|
var currentRoom = _player.GetCurrentRoom();
|
||||||
|
|
||||||
|
if (currentRoom is not MonsterRoom)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||||
|
if (currentRoom is MonsterRoom monsterRoom)
|
||||||
|
validRooms.Remove(monsterRoom);
|
||||||
|
|
||||||
|
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
||||||
|
|
||||||
|
var enemyList = validRooms.SelectMany(x => x.GetEnemiesInCurrentRoom());
|
||||||
|
|
||||||
|
foreach (var enemy in enemyList)
|
||||||
|
{
|
||||||
|
var spawnPoints = currentMonsterRoom.EnemySpawnPoints.GetChildren().OfType<Marker3D>().ToList();
|
||||||
|
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
|
||||||
|
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
|
||||||
|
enemy.SetEnemyGlobalPosition(randomSpawnPoint.GlobalPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void KillHalfEnemiesInRoom()
|
||||||
|
{
|
||||||
|
var currentRoom = _player.GetCurrentRoom();
|
||||||
|
if (currentRoom is not MonsterRoom)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
||||||
|
var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().ToList();
|
||||||
|
var enemiesToKill = enemyList.Count / 2;
|
||||||
|
for (var i = 0; i < enemiesToKill; i++)
|
||||||
|
enemyList[i].Die();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TurnAllEnemiesInRoomIntoHealingItem()
|
||||||
|
{
|
||||||
|
var currentRoom = _player.GetCurrentRoom();
|
||||||
|
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||||
|
foreach (var enemy in currentEnemies)
|
||||||
|
{
|
||||||
|
enemy.Die();
|
||||||
|
DropHealingItem(enemy.GetEnemyGlobalPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropHealingItem(Vector3 vector)
|
||||||
|
{
|
||||||
|
var consumableFolder = "res://src/items/consumable";
|
||||||
|
var restorativeScene = GD.Load<PackedScene>($"{consumableFolder}/ConsumableItem.tscn");
|
||||||
|
var consumable = restorativeScene.Instantiate<ConsumableItem>();
|
||||||
|
var resourceFiles = DirAccess.GetFilesAt($"{consumableFolder}/resources");
|
||||||
|
var rng = new RandomNumberGenerator();
|
||||||
|
rng.Randomize();
|
||||||
|
var randomResource = resourceFiles[rng.RandiRange(0, resourceFiles.Length - 1)];
|
||||||
|
var randomFile = ResourceLoader.Load<ConsumableItemStats>($"{consumableFolder}/resources/{randomResource}");
|
||||||
|
consumable.ItemStats = randomFile;
|
||||||
|
_game.AddChild(consumable);
|
||||||
|
consumable.GlobalPosition = vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HealAllEnemiesAndPlayerInRoomToFull()
|
||||||
|
{
|
||||||
|
var currentRoom = _player.GetCurrentRoom();
|
||||||
|
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||||
|
foreach (var enemy in currentEnemies)
|
||||||
|
enemy.SetCurrentHP(enemy.GetMaximumHP());
|
||||||
|
_player.Stats.SetCurrentHP(_player.Stats.MaximumHP.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AbsorbHPFromAllEnemiesInRoom()
|
||||||
|
{
|
||||||
|
var currentRoom = _player.GetCurrentRoom();
|
||||||
|
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||||
|
var hpToAbsorb = 0.0;
|
||||||
|
foreach (var enemy in currentEnemies)
|
||||||
|
hpToAbsorb += enemy.CurrentHP * 0.05;
|
||||||
|
_player.Stats.SetCurrentHP(_player.Stats.CurrentHP.Value + (int)hpToAbsorb);
|
||||||
|
GD.Print("HP to absorb: " + hpToAbsorb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DealElementalDamageToAllEnemiesInRoom(ElementType elementType)
|
||||||
|
{
|
||||||
|
var currentRoom = _player.GetCurrentRoom();
|
||||||
|
var currentEnemies = currentRoom.EnemiesInRoom;
|
||||||
|
foreach (var enemy in currentEnemies)
|
||||||
|
enemy.TakeDamage(20, elementType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SwapHPandVT()
|
||||||
|
{
|
||||||
|
var oldHp = _player.Stats.CurrentHP.Value;
|
||||||
|
var oldVt = _player.Stats.CurrentVT.Value;
|
||||||
|
|
||||||
|
_player.Stats.SetCurrentHP(oldVt);
|
||||||
|
_player.Stats.SetCurrentVT(oldHp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RandomEffect(EffectItem item)
|
||||||
|
{
|
||||||
|
var itemEffects = Enum.GetValues<UsableItemTag>().ToList();
|
||||||
|
itemEffects.Remove(UsableItemTag.RandomEffect);
|
||||||
|
itemEffects.Remove(UsableItemTag.None);
|
||||||
|
var randomEffect = new Godot.Collections.Array<UsableItemTag>(itemEffects).PickRandom();
|
||||||
|
item.SetEffectTag(randomEffect);
|
||||||
|
_game.UseItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RaiseCurrentWeaponAttack()
|
||||||
|
{
|
||||||
|
if (_player.EquippedWeapon.Value.ItemName == string.Empty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentWeapon = _player.EquippedWeapon.Value;
|
||||||
|
currentWeapon.IncreaseWeaponAttack(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RaiseCurrentArmorDefense()
|
||||||
|
{
|
||||||
|
if (_player.EquippedArmor.Value.ItemName == string.Empty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentArmor = _player.EquippedArmor.Value;
|
||||||
|
currentArmor.IncreaseArmorDefense(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RaiseLevel()
|
||||||
|
{
|
||||||
|
_player.LevelUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TeleportToRandomRoom(IEnemy enemy)
|
||||||
|
{
|
||||||
|
var currentFloor = _game.CurrentFloor;
|
||||||
|
var rooms = currentFloor.Rooms;
|
||||||
|
var currentRoom = enemy.GetCurrentRoom();
|
||||||
|
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||||
|
if (currentRoom is MonsterRoom currentMonsterRoom)
|
||||||
|
validRooms.Remove(currentMonsterRoom);
|
||||||
|
|
||||||
|
if (validRooms.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
||||||
|
var randomRoom = roomsGodotCollection.PickRandom();
|
||||||
|
var spawnPoints = randomRoom.EnemySpawnPoints.GetChildren().OfType<Marker3D>().ToList();
|
||||||
|
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
|
||||||
|
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
|
||||||
|
|
||||||
|
enemy.SetEnemyGlobalPosition(randomSpawnPoint.GlobalPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TeleportToRandomRoom(IPlayer player)
|
||||||
|
{
|
||||||
|
var currentFloor = _game.CurrentFloor;
|
||||||
|
var rooms = currentFloor.Rooms;
|
||||||
|
|
||||||
|
var currentRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom);
|
||||||
|
|
||||||
|
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
||||||
|
if (currentRoom is MonsterRoom currentMonsterRoom)
|
||||||
|
validRooms.Remove(currentMonsterRoom);
|
||||||
|
|
||||||
|
if (validRooms.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
||||||
|
var randomRoom = roomsGodotCollection.PickRandom();
|
||||||
|
var spawnPoint = randomRoom.PlayerSpawn;
|
||||||
|
_game.ToggleInventory();
|
||||||
|
player.TeleportPlayer(spawnPoint.GlobalPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ChangeAffinity(ThrowableItem throwableItem)
|
||||||
|
{
|
||||||
|
var maximumElements = Enum.GetNames(typeof(ElementType)).Length;
|
||||||
|
throwableItem.SetElementType(throwableItem.ElementType + 1 % maximumElements);
|
||||||
|
|
||||||
|
// 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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WarpToExit(IPlayer player)
|
||||||
|
{
|
||||||
|
var exitRoom = _game.CurrentFloor.Rooms.OfType<ExitRoom>().Single();
|
||||||
|
if (exitRoom.PlayerDiscoveredRoom)
|
||||||
|
player.TeleportPlayer(exitRoom.PlayerSpawn.GlobalPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WarpToExit(IEnemy enemy)
|
||||||
|
{
|
||||||
|
var exitRoom = _game.CurrentFloor.Rooms.OfType<ExitRoom>().Single();
|
||||||
|
enemy.SetEnemyGlobalPosition(exitRoom.PlayerSpawn.GlobalPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/items/EffectService.cs.uid
Normal file
1
src/items/EffectService.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cnvyubmj6u7qw
|
||||||
13
src/items/EquipableItem.cs
Normal file
13
src/items/EquipableItem.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
|
||||||
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
|
[Meta]
|
||||||
|
public abstract partial class EquipableItem : InventoryItem
|
||||||
|
{
|
||||||
|
public abstract ItemTag ItemTag { get; }
|
||||||
|
|
||||||
|
[Save("equipable_item_is_equipped")]
|
||||||
|
public bool IsEquipped { get; set; }
|
||||||
|
}
|
||||||
1
src/items/EquipableItem.cs.uid
Normal file
1
src/items/EquipableItem.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cw8s4mjrde4no
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using System.Collections.Immutable;
|
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
|
||||||
|
|
||||||
public interface IEquipableItem : IInventoryItem
|
|
||||||
{
|
|
||||||
public ImmutableList<ItemTag> ItemTags { get; }
|
|
||||||
|
|
||||||
public bool IsEquipped { get; }
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.GodotNodeInterfaces;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -8,11 +10,11 @@ namespace GameJamDungeon;
|
|||||||
|
|
||||||
public interface IInventory : INode
|
public interface IInventory : INode
|
||||||
{
|
{
|
||||||
public List<IInventoryItem> Items { get; }
|
public List<InventoryItem> Items { get; }
|
||||||
|
|
||||||
public bool TryAdd(IInventoryItem inventoryItem);
|
public bool TryAdd(InventoryItem inventoryItem);
|
||||||
|
|
||||||
public void Remove(IInventoryItem inventoryItem);
|
public void Remove(InventoryItem inventoryItem);
|
||||||
|
|
||||||
public void Sort();
|
public void Sort();
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ public interface IInventory : INode
|
|||||||
event Inventory.PickedUpItemEventHandler PickedUpItem;
|
event Inventory.PickedUpItemEventHandler PickedUpItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Meta, Id("inventory")]
|
||||||
public partial class Inventory : Node, IInventory
|
public partial class Inventory : Node, IInventory
|
||||||
{
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
public override void _Notification(int what) => this.Notify(what);
|
||||||
@@ -38,9 +41,10 @@ public partial class Inventory : Node, IInventory
|
|||||||
Items = [];
|
Items = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IInventoryItem> Items { get; private set; }
|
[Save("inventory_items")]
|
||||||
|
public List<InventoryItem> Items { get; private set; }
|
||||||
|
|
||||||
public bool TryAdd(IInventoryItem inventoryItem)
|
public bool TryAdd(InventoryItem inventoryItem)
|
||||||
{
|
{
|
||||||
if (Items.Count >= _maxInventorySize)
|
if (Items.Count >= _maxInventorySize)
|
||||||
{
|
{
|
||||||
@@ -53,7 +57,7 @@ public partial class Inventory : Node, IInventory
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(IInventoryItem inventoryItem) => Items.Remove(inventoryItem);
|
public void Remove(InventoryItem inventoryItem) => Items.Remove(inventoryItem);
|
||||||
|
|
||||||
|
|
||||||
public void Sort()
|
public void Sort()
|
||||||
@@ -61,7 +65,7 @@ public partial class Inventory : Node, IInventory
|
|||||||
var equippedWeapon = Items.OfType<Weapon>().Where(x => x.IsEquipped);
|
var equippedWeapon = Items.OfType<Weapon>().Where(x => x.IsEquipped);
|
||||||
var equippedArmor = Items.OfType<Armor>().Where(x => x.IsEquipped);
|
var equippedArmor = Items.OfType<Armor>().Where(x => x.IsEquipped);
|
||||||
var equippedAccessory = Items.OfType<Accessory>().Where(x => x.IsEquipped);
|
var equippedAccessory = Items.OfType<Accessory>().Where(x => x.IsEquipped);
|
||||||
var equippedItems = new List<IInventoryItem>();
|
var equippedItems = new List<InventoryItem>();
|
||||||
equippedItems.AddRange(equippedWeapon);
|
equippedItems.AddRange(equippedWeapon);
|
||||||
equippedItems.AddRange(equippedArmor);
|
equippedItems.AddRange(equippedArmor);
|
||||||
equippedItems.AddRange(equippedAccessory);
|
equippedItems.AddRange(equippedAccessory);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Chickensoft.GodotNodeInterfaces;
|
using Chickensoft.GodotNodeInterfaces;
|
||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@@ -17,13 +19,24 @@ public interface IInventoryItem : INode3D
|
|||||||
double ThrowDamage { get; }
|
double ThrowDamage { get; }
|
||||||
|
|
||||||
float ThrowSpeed { get; }
|
float ThrowSpeed { get; }
|
||||||
|
|
||||||
Texture2D GetTexture();
|
|
||||||
|
|
||||||
public void SetItemStats(InventoryItemStats inventoryItemStats);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IUsableItem : IInventoryItem
|
[Meta]
|
||||||
|
public abstract partial class InventoryItem : Node3D, IInventoryItem
|
||||||
{
|
{
|
||||||
public void Use();
|
[Save("inventory_item_id")]
|
||||||
|
public Guid ID => Guid.NewGuid();
|
||||||
|
public abstract string ItemName { get; }
|
||||||
|
public abstract string Description { get; }
|
||||||
|
[Save("inventory_item_spawn_rate")]
|
||||||
|
public abstract float SpawnRate { get; }
|
||||||
|
[Save("inventory_item_throw_damage")]
|
||||||
|
public abstract double ThrowDamage { get; }
|
||||||
|
[Save("inventory_item_throw_speed")]
|
||||||
|
public abstract float ThrowSpeed { get; }
|
||||||
|
|
||||||
|
[Save("inventory_item_stats")]
|
||||||
|
public abstract InventoryItemStats ItemStats { get; set; }
|
||||||
|
|
||||||
|
public Sprite3D Sprite { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
|
[Meta, Id("inventory_item_stats")]
|
||||||
public partial class InventoryItemStats : Resource
|
public partial class InventoryItemStats : Resource
|
||||||
{
|
{
|
||||||
[Export]
|
[Export]
|
||||||
public string Name = string.Empty;
|
[Save("inventory_item_name")]
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Export(PropertyHint.MultilineText)]
|
[Export(PropertyHint.MultilineText)]
|
||||||
public string Description = string.Empty;
|
[Save("inventory_item_description")]
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Export]
|
[Save("inventory_item_texture")]
|
||||||
public Texture2D Texture { get; set; }
|
[Export] public Texture2D Texture { get; set; } = default!;
|
||||||
|
|
||||||
[Export(PropertyHint.Range, "0, 1, 0.01")]
|
[Export(PropertyHint.Range, "0, 1, 0.01")]
|
||||||
public float SpawnRate { get; set; } = 0.5f;
|
public float SpawnRate { get; set; } = 0.5f;
|
||||||
@@ -28,5 +34,5 @@ public partial class InventoryItemStats : Resource
|
|||||||
public int ThrowDamage { get; set; } = 5;
|
public int ThrowDamage { get; set; } = 5;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public Godot.Collections.Array<ItemTag> ItemTags { get; set; } = new Godot.Collections.Array<ItemTag>();
|
public ItemTag ItemTag { get; set; } = ItemTag.None;
|
||||||
}
|
}
|
||||||
67
src/items/InventoryItemTextureExtensions.cs
Normal file
67
src/items/InventoryItemTextureExtensions.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using Godot;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
using System.Text.Json;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>Basis JSON converter.</summary>
|
||||||
|
public class Texture2DConverter : JsonConverter<Texture2D>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool CanConvert(Type typeToConvert) =>
|
||||||
|
typeToConvert == typeof(Texture2D);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Texture2D Read(
|
||||||
|
ref Utf8JsonReader reader,
|
||||||
|
Type typeToConvert,
|
||||||
|
JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var texture2D = new Texture2D();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
|
return texture2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyName = reader.GetString();
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
switch (propertyName)
|
||||||
|
{
|
||||||
|
case "resource_path":
|
||||||
|
var resourcePath = JsonSerializer.Deserialize<string>(ref reader, options);
|
||||||
|
texture2D = GD.Load<Texture2D>(resourcePath);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new JsonException("Unexpected end when reading Texture2D.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(
|
||||||
|
Utf8JsonWriter writer,
|
||||||
|
Texture2D value,
|
||||||
|
JsonSerializerOptions options
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var resolver = options.TypeInfoResolver;
|
||||||
|
var resourcePathType = resolver!.GetTypeInfo(typeof(string), options)!;
|
||||||
|
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WritePropertyName("resource_path");
|
||||||
|
JsonSerializer.Serialize(writer, value.ResourcePath, resourcePathType);
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/items/InventoryItemTextureExtensions.cs.uid
Normal file
1
src/items/InventoryItemTextureExtensions.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bdc3xwj2b1oog
|
||||||
@@ -33,7 +33,9 @@ public partial class ItemDatabase : Node
|
|||||||
{
|
{
|
||||||
var armorInfo = GD.Load<ArmorStats>($"res://src/items/armor/resources/{armor}");
|
var armorInfo = GD.Load<ArmorStats>($"res://src/items/armor/resources/{armor}");
|
||||||
var armorScene = ArmorScene.Instantiate<Armor>();
|
var armorScene = ArmorScene.Instantiate<Armor>();
|
||||||
armorScene.SetItemStats(armorInfo);
|
armorScene.ItemStats = armorInfo;
|
||||||
|
armorScene.Sprite = armorScene.GetNode<Sprite3D>("%Sprite");
|
||||||
|
armorScene.Sprite.Texture = armorInfo.Texture;
|
||||||
database.Add(armorScene);
|
database.Add(armorScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +43,9 @@ public partial class ItemDatabase : Node
|
|||||||
{
|
{
|
||||||
var weaponInfo = GD.Load<WeaponStats>($"res://src/items/weapons/resources/{weapon}");
|
var weaponInfo = GD.Load<WeaponStats>($"res://src/items/weapons/resources/{weapon}");
|
||||||
var weaponScene = WeaponScene.Instantiate<Weapon>();
|
var weaponScene = WeaponScene.Instantiate<Weapon>();
|
||||||
weaponScene.SetItemStats(weaponInfo);
|
weaponScene.ItemStats = weaponInfo;
|
||||||
|
weaponScene.Sprite = weaponScene.GetNode<Sprite3D>("%Sprite");
|
||||||
|
weaponScene.Sprite.Texture = weaponInfo.Texture;
|
||||||
database.Add(weaponScene);
|
database.Add(weaponScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +53,9 @@ public partial class ItemDatabase : Node
|
|||||||
{
|
{
|
||||||
var accessoryInfo = GD.Load<AccessoryStats>($"res://src/items/accessory/resources/{accessory}");
|
var accessoryInfo = GD.Load<AccessoryStats>($"res://src/items/accessory/resources/{accessory}");
|
||||||
var accessoryScene = AccessoryScene.Instantiate<Accessory>();
|
var accessoryScene = AccessoryScene.Instantiate<Accessory>();
|
||||||
accessoryScene.SetItemStats(accessoryInfo);
|
accessoryScene.ItemStats = accessoryInfo;
|
||||||
|
accessoryScene.Sprite = accessoryScene.GetNode<Sprite3D>("%Sprite");
|
||||||
|
accessoryScene.Sprite.Texture = accessoryInfo.Texture;
|
||||||
database.Add(accessoryScene);
|
database.Add(accessoryScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +63,9 @@ public partial class ItemDatabase : Node
|
|||||||
{
|
{
|
||||||
var throwableItemInfo = GD.Load<ThrowableItemStats>($"res://src/items/throwable/resources/{throwable}");
|
var throwableItemInfo = GD.Load<ThrowableItemStats>($"res://src/items/throwable/resources/{throwable}");
|
||||||
var throwableItemScene = ThrowableItemScene.Instantiate<ThrowableItem>();
|
var throwableItemScene = ThrowableItemScene.Instantiate<ThrowableItem>();
|
||||||
throwableItemScene.SetItemStats(throwableItemInfo);
|
throwableItemScene.ItemStats = throwableItemInfo;
|
||||||
|
throwableItemScene.Sprite = throwableItemScene.GetNode<Sprite3D>("%Sprite");
|
||||||
|
throwableItemScene.Sprite.Texture = throwableItemInfo.Texture;
|
||||||
database.Add(throwableItemScene);
|
database.Add(throwableItemScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,10 +73,12 @@ public partial class ItemDatabase : Node
|
|||||||
{
|
{
|
||||||
var consumableItemInfo = GD.Load<ConsumableItemStats>($"res://src/items/consumable/resources/{consumable}");
|
var consumableItemInfo = GD.Load<ConsumableItemStats>($"res://src/items/consumable/resources/{consumable}");
|
||||||
var consumableItemScene = ConsumableItemScene.Instantiate<ConsumableItem>();
|
var consumableItemScene = ConsumableItemScene.Instantiate<ConsumableItem>();
|
||||||
consumableItemScene.SetItemStats(consumableItemInfo);
|
consumableItemScene.ItemStats = consumableItemInfo;
|
||||||
|
consumableItemScene.Sprite = consumableItemScene.GetNode<Sprite3D>("%Sprite");
|
||||||
|
consumableItemScene.Sprite.Texture = consumableItemInfo.Texture;
|
||||||
database.Add(consumableItemScene);
|
database.Add(consumableItemScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
return database.ToArray();
|
return [.. database];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,22 @@
|
|||||||
using Chickensoft.AutoInject;
|
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta, Id("accessory")]
|
||||||
public partial class Accessory : Node3D, IEquipableItem
|
public partial class Accessory : EquipableItem
|
||||||
{
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
|
||||||
|
|
||||||
[Dependency] public IGameEventDepot GameEventDepot => this.DependOn<IGameEventDepot>();
|
|
||||||
|
|
||||||
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
|
||||||
|
|
||||||
[Export] private AccessoryStats _accessoryStats { get; set; } = new AccessoryStats();
|
[Export] private AccessoryStats _accessoryStats { get; set; } = new AccessoryStats();
|
||||||
|
|
||||||
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
|
public override string ItemName => _accessoryStats.Name;
|
||||||
|
|
||||||
[Node] public Area3D Pickup { get; set; } = default!;
|
public override string Description => _accessoryStats.Description;
|
||||||
|
|
||||||
public Guid ID => Guid.NewGuid();
|
public override float SpawnRate => _accessoryStats.SpawnRate;
|
||||||
|
|
||||||
public string ItemName => _accessoryStats.Name;
|
public override double ThrowDamage => _accessoryStats.ThrowDamage;
|
||||||
|
|
||||||
public string Description => _accessoryStats.Description;
|
public override float ThrowSpeed => _accessoryStats.ThrowSpeed;
|
||||||
|
|
||||||
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 MaxHPUp => _accessoryStats.MaxHPUp;
|
||||||
|
|
||||||
@@ -45,32 +28,9 @@ public partial class Accessory : Node3D, IEquipableItem
|
|||||||
|
|
||||||
public int DEFUp => _accessoryStats.DEFUp;
|
public int DEFUp => _accessoryStats.DEFUp;
|
||||||
|
|
||||||
public ImmutableList<AccessoryTag> AccessoryTags => [.. _accessoryStats.AccessoryTags];
|
public AccessoryTag AccessoryTag => _accessoryStats.AccessoryTag;
|
||||||
|
|
||||||
public ImmutableList<ItemTag> ItemTags => [.. _accessoryStats.ItemTags];
|
public override ItemTag ItemTag => _accessoryStats.ItemTag;
|
||||||
|
|
||||||
public bool IsEquipped { get; set; }
|
public override InventoryItemStats ItemStats { get => _accessoryStats; set => _accessoryStats = (AccessoryStats)value; }
|
||||||
|
|
||||||
public void OnReady()
|
|
||||||
{
|
|
||||||
Pickup.BodyEntered += OnEntered;
|
|
||||||
Sprite.Texture = _accessoryStats.Texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetItemStats(InventoryItemStats inventoryItemStats)
|
|
||||||
{
|
|
||||||
_accessoryStats = (AccessoryStats)inventoryItemStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Throw()
|
|
||||||
{
|
|
||||||
Player.Inventory.Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnEntered(Node3D body)
|
|
||||||
{
|
|
||||||
var isAdded = Player.Inventory.TryAdd(this);
|
|
||||||
if (isAdded)
|
|
||||||
QueueFree();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
radius = 0.470016
|
radius = 0.470016
|
||||||
|
|
||||||
[node name="Accessory" type="Node3D"]
|
[node name="Accessory" type="Node3D"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.75, 0)
|
|
||||||
script = ExtResource("1_ikyk2")
|
script = ExtResource("1_ikyk2")
|
||||||
|
|
||||||
[node name="Pickup" type="Area3D" parent="."]
|
[node name="Pickup" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
collision_layer = 0
|
collision_layer = 4
|
||||||
collision_mask = 4
|
collision_mask = 0
|
||||||
|
|
||||||
[node name="Sprite" type="Sprite3D" parent="Pickup"]
|
[node name="Sprite" type="Sprite3D" parent="Pickup"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|||||||
@@ -1,31 +1,44 @@
|
|||||||
using Godot;
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using Godot;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
|
[Meta, Id("accessory_stat_type")]
|
||||||
public partial class AccessoryStats : InventoryItemStats
|
public partial class AccessoryStats : InventoryItemStats
|
||||||
{
|
{
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("accessory_atk_up")]
|
||||||
public int ATKUp { get; set; } = 0;
|
public int ATKUp { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("accessory_def_up")]
|
||||||
public int DEFUp { get; set; } = 0;
|
public int DEFUp { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("accessory_luck_up")]
|
||||||
public double LuckUp { get; set; } = 0;
|
public double LuckUp { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("accessory_max_hp_up")]
|
||||||
public int MaxHPUp { get; set; } = 0;
|
public int MaxHPUp { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("accessory_max_vt_up")]
|
||||||
public int MaxVTUp { get; set; } = 0;
|
public int MaxVTUp { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public Godot.Collections.Array<AccessoryTag> AccessoryTags { get; set; } = new Godot.Collections.Array<AccessoryTag>();
|
[Save("accessory_tag")]
|
||||||
|
public AccessoryTag AccessoryTag { get; set; } = AccessoryTag.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AccessoryTag
|
public enum AccessoryTag
|
||||||
{
|
{
|
||||||
|
None,
|
||||||
HalfVTConsumption,
|
HalfVTConsumption,
|
||||||
StatusEffectImmunity
|
StatusEffectImmunity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(AccessoryTag))]
|
||||||
|
public partial class AccessoryTagEnumContext : JsonSerializerContext;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ DEFUp = 0
|
|||||||
LuckUp = 0.1
|
LuckUp = 0.1
|
||||||
MaxHPUp = 0
|
MaxHPUp = 0
|
||||||
MaxVTUp = 0
|
MaxVTUp = 0
|
||||||
AccessoryTags = Array[int]([])
|
AccessoryTag = 0
|
||||||
Name = "Mask of the Goddess of Avarice"
|
Name = "Mask of the Goddess of Avarice"
|
||||||
Description = "Raises Luck"
|
Description = "Raises Luck"
|
||||||
Texture = ExtResource("1_q42cv")
|
Texture = ExtResource("1_q42cv")
|
||||||
@@ -19,4 +19,4 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
[gd_resource type="Resource" script_class="AccessoryStats" load_steps=3 format=3 uid="uid://c3v6r8s8yruag"]
|
[gd_resource type="Resource" script_class="AccessoryStats" load_steps=3 format=3 uid="uid://c3v6r8s8yruag"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/items/accessory/AccessoryStats.cs" id="1_co7sc"]
|
[ext_resource type="Script" uid="uid://b8arlmivk68b" path="res://src/items/accessory/AccessoryStats.cs" id="1_co7sc"]
|
||||||
[ext_resource type="Texture2D" uid="uid://db7i7iy5gagae" path="res://src/items/accessory/textures/MASK 02.PNG" id="1_uwbei"]
|
[ext_resource type="Texture2D" uid="uid://db7i7iy5gagae" path="res://src/items/accessory/textures/MASK 02.PNG" id="1_uwbei"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_co7sc")
|
script = ExtResource("1_co7sc")
|
||||||
ATKUp = 0
|
ATKUp = 0
|
||||||
DEFUp = 0
|
DEFUp = 0
|
||||||
LUCKUp = 0.0
|
LuckUp = 0.0
|
||||||
MaxHPUp = 0
|
MaxHPUp = 0
|
||||||
MaxVTUp = 0
|
MaxVTUp = 0
|
||||||
AccessoryTags = [1]
|
AccessoryTag = 2
|
||||||
Name = "Mask of the Shunned Goddess"
|
Name = "Mask of the Shunned Goddess"
|
||||||
Description = "Status Effect Immunity"
|
Description = "Status Effect Immunity"
|
||||||
Texture = ExtResource("1_uwbei")
|
Texture = ExtResource("1_uwbei")
|
||||||
SpawnRate = 0.1
|
SpawnRate = 0.1
|
||||||
|
ThrowSpeed = 12.0
|
||||||
|
HealHPAmount = 0
|
||||||
|
HealVTAmount = 0
|
||||||
|
ThrowDamage = 5
|
||||||
|
ItemTags = Array[int]([])
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
[gd_resource type="Resource" script_class="AccessoryStats" load_steps=3 format=3 uid="uid://ct8iply3dwssv"]
|
[gd_resource type="Resource" script_class="AccessoryStats" load_steps=3 format=3 uid="uid://ct8iply3dwssv"]
|
||||||
|
|
||||||
[ext_resource type="Texture2D" uid="uid://db7i7iy5gagae" path="res://src/items/accessory/textures/MASK 02.PNG" id="1_t16cd"]
|
[ext_resource type="Texture2D" uid="uid://db7i7iy5gagae" path="res://src/items/accessory/textures/MASK 02.PNG" id="1_t16cd"]
|
||||||
[ext_resource type="Script" path="res://src/items/accessory/AccessoryStats.cs" id="1_vdb56"]
|
[ext_resource type="Script" uid="uid://b8arlmivk68b" path="res://src/items/accessory/AccessoryStats.cs" id="1_vdb56"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_vdb56")
|
script = ExtResource("1_vdb56")
|
||||||
ATKUp = 0
|
ATKUp = 0
|
||||||
DEFUp = 0
|
DEFUp = 0
|
||||||
LUCKUp = 0.0
|
LuckUp = 0.0
|
||||||
MaxHPUp = 0
|
MaxHPUp = 0
|
||||||
MaxVTUp = 0
|
MaxVTUp = 0
|
||||||
AccessoryTags = [0]
|
AccessoryTag = 1
|
||||||
Name = "Mask of the Goddess of Sloth"
|
Name = "Mask of the Goddess of Sloth"
|
||||||
Description = "Halves VT Depletion Rate"
|
Description = "Halves VT Depletion Rate"
|
||||||
Texture = ExtResource("1_t16cd")
|
Texture = ExtResource("1_t16cd")
|
||||||
SpawnRate = 0.1
|
SpawnRate = 0.1
|
||||||
|
ThrowSpeed = 12.0
|
||||||
|
HealHPAmount = 0
|
||||||
|
HealVTAmount = 0
|
||||||
|
ThrowDamage = 5
|
||||||
|
ItemTags = Array[int]([])
|
||||||
|
|||||||
@@ -1,72 +1,28 @@
|
|||||||
using Chickensoft.AutoInject;
|
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta, Id("armor")]
|
||||||
public partial class Armor : Node3D, IEquipableItem
|
public partial class Armor : EquipableItem
|
||||||
{
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
public override InventoryItemStats ItemStats { get => _armorStats; set => _armorStats = (ArmorStats)value; }
|
||||||
|
|
||||||
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
private ArmorStats _armorStats { get; set; } = new ArmorStats();
|
||||||
|
|
||||||
[Export] private ArmorStats _armorStats { get; set; } = new ArmorStats();
|
public override string ItemName => _armorStats.Name;
|
||||||
|
|
||||||
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
|
public override string Description => _armorStats.Description;
|
||||||
|
|
||||||
[Node] private Area3D Pickup { get; set; } = default!;
|
public override float SpawnRate => _armorStats.SpawnRate;
|
||||||
|
|
||||||
public Guid ID => Guid.NewGuid();
|
public override double ThrowDamage => _armorStats.ThrowDamage;
|
||||||
|
|
||||||
public string ItemName => _armorStats.Name;
|
public override float ThrowSpeed => _armorStats.ThrowSpeed;
|
||||||
|
|
||||||
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 int Defense => _armorStats.Defense;
|
||||||
|
|
||||||
public void IncreaseArmorDefense(int bonus) => _armorStats.Defense += bonus;
|
public void IncreaseArmorDefense(int bonus) => _armorStats.Defense += bonus;
|
||||||
|
|
||||||
|
public override ItemTag ItemTag => _armorStats.ItemTag;
|
||||||
public ImmutableList<ItemTag> ItemTags => [.. _armorStats.ItemTags];
|
|
||||||
|
|
||||||
public bool IsEquipped { get; set; }
|
|
||||||
|
|
||||||
public void OnReady()
|
|
||||||
{
|
|
||||||
Pickup.BodyEntered += OnEntered;
|
|
||||||
Sprite.Texture = _armorStats.Texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetItemStats(InventoryItemStats inventoryItemStats)
|
|
||||||
{
|
|
||||||
_armorStats = (ArmorStats)inventoryItemStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Throw()
|
|
||||||
{
|
|
||||||
Player.Inventory.Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Drop()
|
|
||||||
{
|
|
||||||
Player.Inventory.Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnEntered(Node3D body)
|
|
||||||
{
|
|
||||||
var isAdded = Player.Inventory.TryAdd(this);
|
|
||||||
if (isAdded)
|
|
||||||
QueueFree();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
size = Vector3(0.778381, 0.929947, 0.731567)
|
size = Vector3(0.778381, 0.929947, 0.731567)
|
||||||
|
|
||||||
[node name="Armor" type="Node3D"]
|
[node name="Armor" type="Node3D"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.75, 0)
|
|
||||||
script = ExtResource("1_cmjpq")
|
script = ExtResource("1_cmjpq")
|
||||||
|
|
||||||
[node name="Pickup" type="Area3D" parent="."]
|
[node name="Pickup" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
collision_layer = 0
|
collision_layer = 4
|
||||||
collision_mask = 4
|
collision_mask = 0
|
||||||
|
|
||||||
[node name="Sprite" type="Sprite3D" parent="Pickup"]
|
[node name="Sprite" type="Sprite3D" parent="Pickup"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|||||||
@@ -1,25 +1,34 @@
|
|||||||
using Godot;
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
|
[Meta, Id("armor_stats")]
|
||||||
public partial class ArmorStats : InventoryItemStats
|
public partial class ArmorStats : InventoryItemStats
|
||||||
{
|
{
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("armor_defense")]
|
||||||
public int Defense { get; set; } = 0;
|
public int Defense { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("armor_telluric_resistance")]
|
||||||
public double TelluricResistance { get; set; } = 0;
|
public double TelluricResistance { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("armor_aeolic_resistance")]
|
||||||
public double AeolicResistance { get; set; } = 0;
|
public double AeolicResistance { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("armor_hydric_resistance")]
|
||||||
public double HydricResistance { get; set; } = 0;
|
public double HydricResistance { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("armor_igneous_resistance")]
|
||||||
public double IgneousResistance { get; set; } = 0;
|
public double IgneousResistance { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("armor_ferrum_resistance")]
|
||||||
public double FerrumResistance { get; set; } = 0;
|
public double FerrumResistance { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[gd_resource type="Resource" script_class="ArmorStats" load_steps=3 format=3 uid="uid://ce2vfa2t3io67"]
|
[gd_resource type="Resource" script_class="ArmorStats" load_steps=3 format=3 uid="uid://ce2vfa2t3io67"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/items/armor/ArmorStats.cs" id="1_6r2bl"]
|
[ext_resource type="Script" uid="uid://dqtp6ewvttoyu" path="res://src/items/armor/ArmorStats.cs" id="1_6r2bl"]
|
||||||
[ext_resource type="Texture2D" uid="uid://ckcn67d64mgke" path="res://src/items/armor/textures/atoners adornment.PNG" id="1_588l8"]
|
[ext_resource type="Texture2D" uid="uid://ckcn67d64mgke" path="res://src/items/armor/textures/atoners adornment.PNG" id="1_588l8"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
@@ -15,3 +15,8 @@ Name = "Atoner's Adornments"
|
|||||||
Description = "+1 DEF"
|
Description = "+1 DEF"
|
||||||
Texture = ExtResource("1_588l8")
|
Texture = ExtResource("1_588l8")
|
||||||
SpawnRate = 0.25
|
SpawnRate = 0.25
|
||||||
|
ThrowSpeed = 12.0
|
||||||
|
HealHPAmount = 0
|
||||||
|
HealVTAmount = 0
|
||||||
|
ThrowDamage = 5
|
||||||
|
ItemTag = 0
|
||||||
|
|||||||
@@ -1,68 +1,31 @@
|
|||||||
using Chickensoft.AutoInject;
|
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta, Id("consumable_item")]
|
||||||
public partial class ConsumableItem : Node3D, IUsableItem
|
public partial class ConsumableItem : InventoryItem
|
||||||
{
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
|
||||||
|
|
||||||
[Dependency] public IGame Game => this.DependOn<IGame>();
|
|
||||||
|
|
||||||
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
private ConsumableItemStats _consumableItemStats { get; set; }
|
private ConsumableItemStats _consumableItemStats { get; set; } = new ConsumableItemStats();
|
||||||
|
|
||||||
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
|
public override string ItemName => _consumableItemStats.Name;
|
||||||
|
|
||||||
[Node] private Area3D Pickup { get; set; } = default!;
|
public override string Description => _consumableItemStats.Description;
|
||||||
|
|
||||||
public Guid ID => Guid.NewGuid();
|
public override float SpawnRate => _consumableItemStats.SpawnRate;
|
||||||
|
|
||||||
public string ItemName => _consumableItemStats.Name;
|
public override double ThrowDamage => _consumableItemStats.ThrowDamage;
|
||||||
|
|
||||||
public string Description => _consumableItemStats.Description;
|
public override float ThrowSpeed => _consumableItemStats.ThrowSpeed;
|
||||||
|
|
||||||
public float SpawnRate => _consumableItemStats.SpawnRate;
|
public int HealHPAmount => _consumableItemStats.HealHPAmount;
|
||||||
|
|
||||||
public Texture2D GetTexture() => _consumableItemStats.Texture;
|
public int HealVTAmount => _consumableItemStats.HealVTAmount;
|
||||||
|
|
||||||
public double ThrowDamage => _consumableItemStats.ThrowDamage;
|
public int RaiseHPAmount => _consumableItemStats.RaiseHPAmount;
|
||||||
|
|
||||||
public float ThrowSpeed => _consumableItemStats.ThrowSpeed;
|
public int RaiseVTAmount => _consumableItemStats.RaiseVTAmount;
|
||||||
|
|
||||||
public void Use()
|
public override InventoryItemStats ItemStats { get => _consumableItemStats; set => _consumableItemStats = (ConsumableItemStats)value; }
|
||||||
{
|
|
||||||
if (Player.Stats.CurrentHP.Value == Player.Stats.MaximumHP.Value && _consumableItemStats.RaiseHPAmount > 0)
|
|
||||||
Player.RaiseHP(_consumableItemStats.RaiseHPAmount);
|
|
||||||
if (Player.Stats.CurrentVT.Value == Player.Stats.MaximumVT.Value && _consumableItemStats.RaiseVTAmount > 0)
|
|
||||||
Player.RaiseVT(_consumableItemStats.RaiseVTAmount);
|
|
||||||
|
|
||||||
if (_consumableItemStats.HealHPAmount > 0 && Player.Stats.CurrentHP.Value != Player.Stats.MaximumHP.Value)
|
|
||||||
Player.HealHP(_consumableItemStats.HealHPAmount);
|
|
||||||
if (_consumableItemStats.HealVTAmount > 0 && Player.Stats.CurrentVT.Value != Player.Stats.MaximumVT.Value)
|
|
||||||
Player.HealVT(_consumableItemStats.HealVTAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetItemStats(InventoryItemStats inventoryItemStats)
|
|
||||||
{
|
|
||||||
_consumableItemStats = (ConsumableItemStats)inventoryItemStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnReady()
|
|
||||||
{
|
|
||||||
Pickup.BodyEntered += OnEntered;
|
|
||||||
Sprite.Texture = _consumableItemStats.Texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnEntered(Node3D body)
|
|
||||||
{
|
|
||||||
var isAdded = Player.Inventory.TryAdd(this);
|
|
||||||
if (isAdded)
|
|
||||||
QueueFree();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ script = ExtResource("1_26bad")
|
|||||||
|
|
||||||
[node name="Pickup" type="Area3D" parent="."]
|
[node name="Pickup" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
collision_layer = 0
|
collision_layer = 4
|
||||||
collision_mask = 4
|
collision_mask = 0
|
||||||
|
|
||||||
[node name="Sprite" type="Sprite3D" parent="Pickup"]
|
[node name="Sprite" type="Sprite3D" parent="Pickup"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
using Godot;
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
|
[Meta, Id("consumable_item_stats")]
|
||||||
public partial class ConsumableItemStats : InventoryItemStats
|
public partial class ConsumableItemStats : InventoryItemStats
|
||||||
{
|
{
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("consumable_item_raise_hp")]
|
||||||
public int RaiseHPAmount { get; set; } = 0;
|
public int RaiseHPAmount { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("consumable_item_raise_vt")]
|
||||||
public int RaiseVTAmount { get; set; } = 0;
|
public int RaiseVTAmount { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ public partial class DroppedItem : RigidBody3D, IDroppedItem
|
|||||||
|
|
||||||
[Node] private Sprite2D Sprite { get; set; } = default!;
|
[Node] private Sprite2D Sprite { get; set; } = default!;
|
||||||
|
|
||||||
public IInventoryItem Item { get; set; }
|
public InventoryItem Item { get; set; }
|
||||||
|
|
||||||
public void OnResolved()
|
public void OnResolved()
|
||||||
{
|
{
|
||||||
ContactMonitor = true;
|
ContactMonitor = true;
|
||||||
BodyEntered += DroppedItem_BodyEntered;
|
BodyEntered += DroppedItem_BodyEntered;
|
||||||
Sprite.Texture = Item.GetTexture();
|
Sprite.Texture = Item.ItemStats.Texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Drop()
|
public async void Drop()
|
||||||
|
|||||||
@@ -1,221 +1,27 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Introspection;
|
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta, Id("effect_item")]
|
||||||
public partial class EffectItem : Node3D, IUsableItem
|
public partial class EffectItem : InventoryItem
|
||||||
{
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
|
||||||
|
|
||||||
[Dependency] public IGame Game => this.DependOn<IGame>();
|
|
||||||
|
|
||||||
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
private EffectItemStats _effectItemStats { get; set; }
|
private EffectItemStats _effectItemStats { get; set; } = new EffectItemStats();
|
||||||
|
|
||||||
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
|
public override string ItemName => _effectItemStats.Name;
|
||||||
|
|
||||||
[Node] private Area3D Pickup { get; set; } = default!;
|
public override string Description => _effectItemStats.Description;
|
||||||
|
|
||||||
public Guid ID => Guid.NewGuid();
|
public override float SpawnRate => _effectItemStats.SpawnRate;
|
||||||
|
|
||||||
public string ItemName => _effectItemStats.Name;
|
public override double ThrowDamage => _effectItemStats.ThrowDamage;
|
||||||
|
|
||||||
public string Description => _effectItemStats.Description;
|
public override float ThrowSpeed => _effectItemStats.ThrowSpeed;
|
||||||
|
|
||||||
public float SpawnRate => _effectItemStats.SpawnRate;
|
public UsableItemTag UsableItemTag => _effectItemStats.UsableItemTag;
|
||||||
|
|
||||||
public Texture2D GetTexture() => _effectItemStats.Texture;
|
public void SetEffectTag(UsableItemTag effect) => _effectItemStats.UsableItemTag = effect;
|
||||||
|
|
||||||
public double ThrowDamage => _effectItemStats.ThrowDamage;
|
public override InventoryItemStats ItemStats { get => _effectItemStats; set => _effectItemStats = (EffectItemStats)value; }
|
||||||
|
|
||||||
public float ThrowSpeed => _effectItemStats.ThrowSpeed;
|
|
||||||
|
|
||||||
public void Use()
|
|
||||||
{
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.DoubleEXP))
|
|
||||||
Game.DoubleEXP(TimeSpan.FromSeconds(30));
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.TeleportAllEnemiesToRoom))
|
|
||||||
TeleportEnemiesToCurrentRoom();
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.KillHalfEnemiesInRoom))
|
|
||||||
KillHalfEnemiesInRoom();
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.TurnAllEnemiesIntoHealingItem))
|
|
||||||
TurnAllEnemiesInRoomIntoHealingItem();
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.HealsAllInRoomToMaxHP))
|
|
||||||
HealAllEnemiesAndPlayerInRoomToFull();
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.AbsorbHPFromAllEnemiesInRoom))
|
|
||||||
AbsorbHPFromAllEnemiesInRoom();
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.DealElementalDamageToAllEnemiesInRoom))
|
|
||||||
DealElementalDamageToAllEnemiesInRoom(ElementType.Hydric);
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.SwapHPAndVT))
|
|
||||||
SwapHPandVT();
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.RaiseCurrentWeaponAttack))
|
|
||||||
RaiseCurrentWeaponAttack();
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.RaiseCurrentDefenseArmor))
|
|
||||||
RaiseCurrentArmorDefense();
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.RaiseLevel))
|
|
||||||
RaiseLevel();
|
|
||||||
|
|
||||||
if (_effectItemStats.UsableItemTags.Contains(UsableItemTag.RandomEffect))
|
|
||||||
RandomEffect();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetItemStats(InventoryItemStats inventoryItemStats)
|
|
||||||
{
|
|
||||||
_effectItemStats = (EffectItemStats)inventoryItemStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnReady()
|
|
||||||
{
|
|
||||||
Pickup.BodyEntered += OnEntered;
|
|
||||||
Sprite.Texture = _effectItemStats.Texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnEntered(Node3D body)
|
|
||||||
{
|
|
||||||
var isAdded = Player.Inventory.TryAdd(this);
|
|
||||||
if (isAdded)
|
|
||||||
QueueFree();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TeleportEnemiesToCurrentRoom()
|
|
||||||
{
|
|
||||||
var currentFloor = Game.CurrentFloor;
|
|
||||||
var rooms = currentFloor.Rooms;
|
|
||||||
var currentRoom = Player.GetCurrentRoom();
|
|
||||||
|
|
||||||
if (currentRoom is not MonsterRoom)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
|
||||||
if (currentRoom is MonsterRoom monsterRoom)
|
|
||||||
validRooms.Remove(monsterRoom);
|
|
||||||
|
|
||||||
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
|
||||||
|
|
||||||
var enemyList = validRooms.SelectMany(x => x.GetEnemiesInCurrentRoom());
|
|
||||||
|
|
||||||
foreach (var enemy in enemyList)
|
|
||||||
{
|
|
||||||
var spawnPoints = currentMonsterRoom.EnemySpawnPoints.GetChildren().OfType<Marker3D>().ToList();
|
|
||||||
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
|
|
||||||
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
|
|
||||||
enemy.SetEnemyGlobalPosition(randomSpawnPoint.GlobalPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void KillHalfEnemiesInRoom()
|
|
||||||
{
|
|
||||||
var currentRoom = Player.GetCurrentRoom();
|
|
||||||
if (currentRoom is not MonsterRoom)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var currentMonsterRoom = (MonsterRoom)currentRoom;
|
|
||||||
var enemyList = currentMonsterRoom.GetEnemiesInCurrentRoom().ToList();
|
|
||||||
var enemiesToKill = enemyList.Count / 2;
|
|
||||||
for (var i = 0; i < enemiesToKill; i++)
|
|
||||||
enemyList[i].Die();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TurnAllEnemiesInRoomIntoHealingItem()
|
|
||||||
{
|
|
||||||
var currentRoom = Player.GetCurrentRoom();
|
|
||||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
|
||||||
foreach (var enemy in currentEnemies)
|
|
||||||
{
|
|
||||||
enemy.Die();
|
|
||||||
DropHealingItem(enemy.GetEnemyGlobalPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DropHealingItem(Vector3 vector)
|
|
||||||
{
|
|
||||||
var consumableFolder = "res://src/items/consumable";
|
|
||||||
var restorativeScene = GD.Load<PackedScene>($"{consumableFolder}/ConsumableItem.tscn");
|
|
||||||
var consumable = restorativeScene.Instantiate<ConsumableItem>();
|
|
||||||
var resourceFiles = DirAccess.GetFilesAt($"{consumableFolder}/resources");
|
|
||||||
var rng = new RandomNumberGenerator();
|
|
||||||
rng.Randomize();
|
|
||||||
var randomResource = resourceFiles[rng.RandiRange(0, resourceFiles.Length - 1)];
|
|
||||||
var randomFile = ResourceLoader.Load<ConsumableItemStats>($"{consumableFolder}/resources/{randomResource}");
|
|
||||||
consumable.SetItemStats(randomFile);
|
|
||||||
Game.AddChild(consumable);
|
|
||||||
consumable.GlobalPosition = vector;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HealAllEnemiesAndPlayerInRoomToFull()
|
|
||||||
{
|
|
||||||
var currentRoom = Player.GetCurrentRoom();
|
|
||||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
|
||||||
foreach (var enemy in currentEnemies)
|
|
||||||
enemy.SetCurrentHP(enemy.GetMaximumHP());
|
|
||||||
Player.Stats.SetCurrentHP(Player.Stats.MaximumHP.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AbsorbHPFromAllEnemiesInRoom()
|
|
||||||
{
|
|
||||||
var currentRoom = Player.GetCurrentRoom();
|
|
||||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
|
||||||
var hpToAbsorb = 0.0;
|
|
||||||
foreach (var enemy in currentEnemies)
|
|
||||||
hpToAbsorb += enemy.CurrentHP * 0.05;
|
|
||||||
Player.Stats.SetCurrentHP(Player.Stats.CurrentHP.Value + (int)hpToAbsorb);
|
|
||||||
GD.Print("HP to absorb: " + hpToAbsorb);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DealElementalDamageToAllEnemiesInRoom(ElementType elementType)
|
|
||||||
{
|
|
||||||
var currentRoom = Player.GetCurrentRoom();
|
|
||||||
var currentEnemies = currentRoom.EnemiesInRoom;
|
|
||||||
foreach (var enemy in currentEnemies)
|
|
||||||
enemy.TakeDamage(20, elementType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SwapHPandVT()
|
|
||||||
{
|
|
||||||
var oldHp = Player.Stats.CurrentHP.Value;
|
|
||||||
var oldVt = Player.Stats.CurrentVT.Value;
|
|
||||||
|
|
||||||
Player.Stats.SetCurrentHP(oldVt);
|
|
||||||
Player.Stats.SetCurrentVT(oldHp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RandomEffect()
|
|
||||||
{
|
|
||||||
var itemEffects = Enum.GetValues<UsableItemTag>().ToList();
|
|
||||||
itemEffects.Remove(UsableItemTag.RandomEffect);
|
|
||||||
var randomEffect = new Godot.Collections.Array<UsableItemTag>(itemEffects).PickRandom();
|
|
||||||
_effectItemStats.UsableItemTags.Clear();
|
|
||||||
_effectItemStats.UsableItemTags.Add(randomEffect);
|
|
||||||
Use();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RaiseCurrentWeaponAttack()
|
|
||||||
{
|
|
||||||
if (Player.EquippedWeapon.Value.ItemName == string.Empty)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var currentWeapon = Player.EquippedWeapon.Value;
|
|
||||||
currentWeapon.IncreaseWeaponAttack(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RaiseCurrentArmorDefense()
|
|
||||||
{
|
|
||||||
if (Player.EquippedArmor.Value.ItemName == string.Empty)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var currentArmor = Player.EquippedArmor.Value;
|
|
||||||
currentArmor.IncreaseArmorDefense(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RaiseLevel()
|
|
||||||
{
|
|
||||||
Player.LevelUp();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ script = ExtResource("1_yw2rj")
|
|||||||
|
|
||||||
[node name="Pickup" type="Area3D" parent="."]
|
[node name="Pickup" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
collision_layer = 0
|
collision_layer = 4
|
||||||
collision_mask = 4
|
collision_mask = 0
|
||||||
|
|
||||||
[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.0600509, 0.26725, 0.180481)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0600509, 0.26725, 0.180481)
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
using Godot;
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
|
[Meta, Id("effect_item_stats")]
|
||||||
public partial class EffectItemStats : InventoryItemStats
|
public partial class EffectItemStats : InventoryItemStats
|
||||||
{
|
{
|
||||||
[Export]
|
[Export]
|
||||||
public Godot.Collections.Array<UsableItemTag> UsableItemTags { get; set; } = new Godot.Collections.Array<UsableItemTag>();
|
[Save("effect_item_tag")]
|
||||||
|
public UsableItemTag UsableItemTag { get; set; } = UsableItemTag.None;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("effect_item_element")]
|
||||||
public ElementType ElementalDamageType { get; set; }
|
public ElementType ElementalDamageType { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_yytis")
|
script = ExtResource("2_yytis")
|
||||||
UsableItemTags = Array[int]([9])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 1
|
ElementalDamageType = 1
|
||||||
Name = "Aeolic Caster"
|
Name = "Aeolic Caster"
|
||||||
Description = "Deal Aeolic Damage to all enemies in the room."
|
Description = "Deal Aeolic Damage to all enemies in the room."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_53wiy")
|
script = ExtResource("2_53wiy")
|
||||||
UsableItemTags = Array[int]([11])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 0
|
ElementalDamageType = 0
|
||||||
Name = "Cloth Resolution"
|
Name = "Cloth Resolution"
|
||||||
Description = "Raises currently equipped armor's defense by 1."
|
Description = "Raises currently equipped armor's defense by 1."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_n1557")
|
script = ExtResource("2_n1557")
|
||||||
UsableItemTags = Array[int]([12])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 0
|
ElementalDamageType = 0
|
||||||
Name = "Cosmos"
|
Name = "Cosmos"
|
||||||
Description = "Raises current Level by 1."
|
Description = "Raises current Level by 1."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_50lqu")
|
script = ExtResource("1_50lqu")
|
||||||
UsableItemTags = Array[int]([6])
|
UsableItemTag = 0
|
||||||
|
ElementalDamageType = 0
|
||||||
Name = "Devic Balance"
|
Name = "Devic Balance"
|
||||||
Description = "Kill half of all enemies in current room."
|
Description = "Kill half of all enemies in current room."
|
||||||
Texture = ExtResource("1_j7j7j")
|
Texture = ExtResource("1_j7j7j")
|
||||||
@@ -14,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_0uaie")
|
script = ExtResource("1_0uaie")
|
||||||
UsableItemTags = Array[int]([4])
|
UsableItemTag = 0
|
||||||
|
ElementalDamageType = 0
|
||||||
Name = "Devic Recall"
|
Name = "Devic Recall"
|
||||||
Description = "Teleports all enemies to current room."
|
Description = "Teleports all enemies to current room."
|
||||||
Texture = ExtResource("1_j462p")
|
Texture = ExtResource("1_j462p")
|
||||||
@@ -14,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_3l06v")
|
script = ExtResource("1_3l06v")
|
||||||
UsableItemTags = Array[int]([10])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 0
|
ElementalDamageType = 0
|
||||||
Name = "Entropic Seal"
|
Name = "Entropic Seal"
|
||||||
Description = "Random effect."
|
Description = "Random effect."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_uojwo")
|
script = ExtResource("1_uojwo")
|
||||||
UsableItemTags = Array[int]([10])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 0
|
ElementalDamageType = 0
|
||||||
Name = "Ferrous Resolution"
|
Name = "Ferrous Resolution"
|
||||||
Description = "Raises currently equipped weapon's attack by 1."
|
Description = "Raises currently equipped weapon's attack by 1."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_i4na1")
|
script = ExtResource("2_i4na1")
|
||||||
UsableItemTags = Array[int]([9])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 5
|
ElementalDamageType = 5
|
||||||
Name = "Ferrum Caster"
|
Name = "Ferrum Caster"
|
||||||
Description = "Deal Ferrum Damage to all enemies in the room."
|
Description = "Deal Ferrum Damage to all enemies in the room."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_drp30")
|
script = ExtResource("1_drp30")
|
||||||
UsableItemTags = Array[int]([8])
|
UsableItemTag = 0
|
||||||
|
ElementalDamageType = 0
|
||||||
Name = "Heaven's Rebellion"
|
Name = "Heaven's Rebellion"
|
||||||
Description = "Heals self and all enemies in current room to maximum HP."
|
Description = "Heals self and all enemies in current room to maximum HP."
|
||||||
Texture = ExtResource("1_g0a3x")
|
Texture = ExtResource("1_g0a3x")
|
||||||
@@ -14,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_mj844")
|
script = ExtResource("1_mj844")
|
||||||
UsableItemTags = Array[int]([9])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 3
|
ElementalDamageType = 3
|
||||||
Name = "Hydric Caster"
|
Name = "Hydric Caster"
|
||||||
Description = "Deal Hydric Damage to all enemies in the room."
|
Description = "Deal Hydric Damage to all enemies in the room."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_cl8lc")
|
script = ExtResource("2_cl8lc")
|
||||||
UsableItemTags = Array[int]([9])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 4
|
ElementalDamageType = 4
|
||||||
Name = "Igneous Caster"
|
Name = "Igneous Caster"
|
||||||
Description = "Deal Igneous Damage to all enemies in the room."
|
Description = "Deal Igneous Damage to all enemies in the room."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_lq0bc")
|
script = ExtResource("1_lq0bc")
|
||||||
UsableItemTags = Array[int]([3])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 0
|
ElementalDamageType = 0
|
||||||
Name = "Perspective"
|
Name = "Perspective"
|
||||||
Description = "Swap current HP and VT."
|
Description = "Swap current HP and VT."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_ksb1c")
|
script = ExtResource("1_ksb1c")
|
||||||
UsableItemTags = Array[int]([5])
|
UsableItemTag = 0
|
||||||
|
ElementalDamageType = 0
|
||||||
Name = "Sine Morphization"
|
Name = "Sine Morphization"
|
||||||
Description = "Turns all enemies in room to healing item."
|
Description = "Turns all enemies in room to healing item."
|
||||||
Texture = ExtResource("1_vqhky")
|
Texture = ExtResource("1_vqhky")
|
||||||
@@ -14,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_38yjb")
|
script = ExtResource("2_38yjb")
|
||||||
UsableItemTags = Array[int]([9])
|
UsableItemTag = 0
|
||||||
ElementalDamageType = 2
|
ElementalDamageType = 2
|
||||||
Name = "Telluric Caster"
|
Name = "Telluric Caster"
|
||||||
Description = "Deal Telluric Damage to all enemies in the room."
|
Description = "Deal Telluric Damage to all enemies in the room."
|
||||||
@@ -15,5 +15,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
metadata/_custom_type_script = "uid://b5w4iw4iqmxtn"
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ texture = ExtResource("1_1rwq6")
|
|||||||
[node name="Pickup" type="Area3D" parent="."]
|
[node name="Pickup" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
collision_layer = 4
|
collision_layer = 4
|
||||||
collision_mask = 4
|
collision_mask = 0
|
||||||
|
|
||||||
[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, 0.348749, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.348749, 0)
|
||||||
|
|||||||
@@ -1,146 +1,37 @@
|
|||||||
using Chickensoft.AutoInject;
|
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta, Id("throwable_item")]
|
||||||
public partial class ThrowableItem : Node3D, IUsableItem
|
public partial class ThrowableItem : InventoryItem
|
||||||
{
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
|
||||||
|
|
||||||
[Dependency] public IGame Game => this.DependOn<IGame>();
|
|
||||||
|
|
||||||
[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]
|
[Export]
|
||||||
private ThrowableItemStats _throwableItemStats { get; set; }
|
private ThrowableItemStats _throwableItemStats { get; set; }
|
||||||
|
|
||||||
[Node] private Sprite3D Sprite { get; set; } = new Sprite3D();
|
public override string ItemName => _throwableItemStats.Name;
|
||||||
|
|
||||||
[Node] private Area3D Pickup { get; set; } = default!;
|
public override string Description => _throwableItemStats.Description;
|
||||||
|
|
||||||
public void OnResolved()
|
public override float SpawnRate => _throwableItemStats.SpawnRate;
|
||||||
{
|
|
||||||
Pickup.BodyEntered += OnEntered;
|
|
||||||
Sprite.Texture = _throwableItemStats.Texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Use()
|
public override double ThrowDamage => _throwableItemStats.ThrowDamage;
|
||||||
{
|
|
||||||
if (_throwableItemStats.HealHPAmount > 0)
|
|
||||||
Player.HealHP(_throwableItemStats.HealHPAmount);
|
|
||||||
if (_throwableItemStats.HealVTAmount > 0)
|
|
||||||
Player.HealVT(_throwableItemStats.HealVTAmount);
|
|
||||||
|
|
||||||
if (_throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.TeleportToRandomLocation))
|
public override float ThrowSpeed => _throwableItemStats.ThrowSpeed;
|
||||||
TeleportToRandomRoom(Player);
|
|
||||||
|
|
||||||
if (_throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.CanChangeAffinity))
|
public ElementType ElementType => _throwableItemStats.ElementType;
|
||||||
ChangeAffinity();
|
|
||||||
|
|
||||||
if (_throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.WarpToExitIfFound))
|
public ThrowableItemTag ThrowableItemTag => _throwableItemStats.ThrowableItemTag;
|
||||||
WarpToExit(Player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TeleportToRandomRoom(IEnemy enemy)
|
public int HealHPAmount => _throwableItemStats.HealHPAmount;
|
||||||
{
|
|
||||||
var currentFloor = Game.CurrentFloor;
|
|
||||||
var rooms = currentFloor.Rooms;
|
|
||||||
var currentRoom = enemy.GetCurrentRoom();
|
|
||||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
|
||||||
if (currentRoom is MonsterRoom currentMonsterRoom)
|
|
||||||
validRooms.Remove(currentMonsterRoom);
|
|
||||||
|
|
||||||
if (validRooms.Count == 0)
|
public int HealVTAmount => _throwableItemStats.HealVTAmount;
|
||||||
return;
|
|
||||||
|
|
||||||
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
public void SetElementType(ElementType elementType) => _throwableItemStats.ElementType = elementType;
|
||||||
var randomRoom = roomsGodotCollection.PickRandom();
|
|
||||||
var spawnPoints = randomRoom.EnemySpawnPoints.GetChildren().OfType<Marker3D>().ToList();
|
|
||||||
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
|
|
||||||
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
|
|
||||||
|
|
||||||
enemy.SetEnemyGlobalPosition(randomSpawnPoint.GlobalPosition);
|
public void SetDescription(string description) => _throwableItemStats.Description = description;
|
||||||
}
|
|
||||||
|
|
||||||
private void TeleportToRandomRoom(IPlayer player)
|
public int Count { get; }
|
||||||
{
|
|
||||||
var currentFloor = Game.CurrentFloor;
|
|
||||||
var rooms = currentFloor.Rooms;
|
|
||||||
|
|
||||||
var currentRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom);
|
public override InventoryItemStats ItemStats { get => _throwableItemStats; set => _throwableItemStats = (ThrowableItemStats)value; }
|
||||||
|
|
||||||
var validRooms = rooms.OfType<MonsterRoom>().ToList();
|
|
||||||
if (currentRoom is MonsterRoom currentMonsterRoom)
|
|
||||||
validRooms.Remove(currentMonsterRoom);
|
|
||||||
|
|
||||||
if (validRooms.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var roomsGodotCollection = new Godot.Collections.Array<MonsterRoom>(validRooms);
|
|
||||||
var randomRoom = roomsGodotCollection.PickRandom();
|
|
||||||
var spawnPoint = randomRoom.PlayerSpawn;
|
|
||||||
Game.ToggleInventory();
|
|
||||||
player.TeleportPlayer(spawnPoint.GlobalPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ChangeAffinity()
|
|
||||||
{
|
|
||||||
var maximumElements = Enum.GetNames(typeof(ElementType)).Length;
|
|
||||||
_throwableItemStats.ElementType = _throwableItemStats.ElementType + 1 % maximumElements;
|
|
||||||
|
|
||||||
// TODO: Make this an inventory animation to cycle through elements.
|
|
||||||
_throwableItemStats.Description =
|
|
||||||
$"Inflicts {_throwableItemStats.ElementType} damage when thrown." +
|
|
||||||
$"{System.Environment.NewLine}Use item to change Affinity.";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WarpToExit(IPlayer player)
|
|
||||||
{
|
|
||||||
var exitRoom = Game.CurrentFloor.Rooms.OfType<ExitRoom>().Single();
|
|
||||||
if (exitRoom.PlayerDiscoveredRoom)
|
|
||||||
player.TeleportPlayer(exitRoom.PlayerSpawn.GlobalPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WarpToExit(IEnemy enemy)
|
|
||||||
{
|
|
||||||
var exitRoom = Game.CurrentFloor.Rooms.OfType<ExitRoom>().Single();
|
|
||||||
enemy.SetEnemyGlobalPosition(exitRoom.PlayerSpawn.GlobalPosition);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ script = ExtResource("1_nac2l")
|
|||||||
|
|
||||||
[node name="Pickup" type="Area3D" parent="."]
|
[node name="Pickup" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
collision_layer = 0
|
collision_layer = 4
|
||||||
collision_mask = 4
|
collision_mask = 0
|
||||||
|
|
||||||
[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.0600509, 0.26725, 0.180481)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0600509, 0.26725, 0.180481)
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
using Godot;
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
|
[Meta, Id("throwable_item_stats")]
|
||||||
public partial class ThrowableItemStats : InventoryItemStats
|
public partial class ThrowableItemStats : InventoryItemStats
|
||||||
{
|
{
|
||||||
[Export]
|
[Export]
|
||||||
public Godot.Collections.Array<ThrowableItemTag> ThrowableItemTags { get; set; } = new Godot.Collections.Array<ThrowableItemTag>();
|
[Save("throwable_item_tag")]
|
||||||
|
public ThrowableItemTag ThrowableItemTag { get; set; } = ThrowableItemTag.None;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("throwable_item_element")]
|
||||||
public ElementType ElementType { get; set; } = ElementType.None;
|
public ElementType ElementType { get; set; } = ElementType.None;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public Godot.Collections.Array<UsableItemTag> UsableItemTags { get; set; } = new Godot.Collections.Array<UsableItemTag>();
|
[Save("throwable_item_usable_tag")]
|
||||||
|
public UsableItemTag UsableItemTag { get; set; } = UsableItemTag.None;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
namespace GameJamDungeon;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
public enum ThrowableItemTag
|
public enum ThrowableItemTag
|
||||||
{
|
{
|
||||||
|
None,
|
||||||
LowerTargetTo1HP,
|
LowerTargetTo1HP,
|
||||||
CanChangeAffinity,
|
CanChangeAffinity,
|
||||||
TeleportToRandomLocation,
|
TeleportToRandomLocation,
|
||||||
WarpToExitIfFound
|
WarpToExitIfFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(ThrowableItemTag))]
|
||||||
|
public partial class ThrowableItemTagEnumContext : JsonSerializerContext;
|
||||||
|
|
||||||
public enum UsableItemTag
|
public enum UsableItemTag
|
||||||
{
|
{
|
||||||
|
None,
|
||||||
DoubleEXP,
|
DoubleEXP,
|
||||||
IdentifyAllItemsCostHP,
|
IdentifyAllItemsCostHP,
|
||||||
BriefImmunity,
|
BriefImmunity,
|
||||||
@@ -26,14 +33,13 @@ public enum UsableItemTag
|
|||||||
RandomEffect,
|
RandomEffect,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum EnhancingItemTag
|
[JsonSerializable(typeof(UsableItemTag))]
|
||||||
{
|
public partial class UsableItemTagEnumContext : JsonSerializerContext;
|
||||||
Add1ATK,
|
|
||||||
Add1DEF,
|
|
||||||
RaiseLevelBy1,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum BoxItemTag
|
public enum BoxItemTag
|
||||||
{
|
{
|
||||||
RandomNewItem,
|
RandomNewItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(BoxItemTag))]
|
||||||
|
public partial class BoxItemTagEnumContext : JsonSerializerContext;
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_m680r")
|
script = ExtResource("2_m680r")
|
||||||
ThrowableItemTags = Array[int]([2])
|
ThrowableItemTag = 0
|
||||||
ElementType = 0
|
ElementType = 0
|
||||||
UsableItemTags = Array[int]([])
|
UsableItemTag = 0
|
||||||
Name = "Gospel of Dimension"
|
Name = "Gospel of Dimension"
|
||||||
Description = "Teleports target to a random location."
|
Description = "Teleports target to a random location."
|
||||||
Texture = ExtResource("1_xt2mp")
|
Texture = ExtResource("1_xt2mp")
|
||||||
@@ -16,4 +16,4 @@ ThrowSpeed = 20.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 20
|
ThrowDamage = 20
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_pn8sr")
|
script = ExtResource("1_pn8sr")
|
||||||
ThrowableItemTags = Array[int]([3])
|
ThrowableItemTag = 0
|
||||||
ElementType = 0
|
ElementType = 0
|
||||||
UsableItemTags = Array[int]([])
|
UsableItemTag = 0
|
||||||
Name = "Gospel of Escape"
|
Name = "Gospel of Escape"
|
||||||
Description = "Warps target to the exit. No effect on player if exit has not been found."
|
Description = "Warps target to the exit. No effect on player if exit has not been found."
|
||||||
Texture = ExtResource("1_26kno")
|
Texture = ExtResource("1_26kno")
|
||||||
@@ -16,5 +16,5 @@ ThrowSpeed = 12.0
|
|||||||
HealHPAmount = 0
|
HealHPAmount = 0
|
||||||
HealVTAmount = 0
|
HealVTAmount = 0
|
||||||
ThrowDamage = 5
|
ThrowDamage = 5
|
||||||
ItemTags = Array[int]([])
|
ItemTag = 0
|
||||||
metadata/_custom_type_script = "uid://d3wlunkcuv2w2"
|
metadata/_custom_type_script = "uid://d3wlunkcuv2w2"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
|
using GameJamDungeon.src.items;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
@@ -14,7 +14,9 @@ public partial class ThrownItem : RigidBody3D
|
|||||||
|
|
||||||
[Dependency] public IGame Game => this.DependOn<IGame>();
|
[Dependency] public IGame Game => this.DependOn<IGame>();
|
||||||
|
|
||||||
public IInventoryItem ItemThatIsThrown;
|
public InventoryItem ItemThatIsThrown;
|
||||||
|
|
||||||
|
private EffectService _effectService;
|
||||||
|
|
||||||
[Node] public Sprite2D Sprite { get; set; } = default!;
|
[Node] public Sprite2D Sprite { get; set; } = default!;
|
||||||
|
|
||||||
@@ -22,7 +24,7 @@ public partial class ThrownItem : RigidBody3D
|
|||||||
{
|
{
|
||||||
BodyEntered += ThrownItem_BodyEntered;
|
BodyEntered += ThrownItem_BodyEntered;
|
||||||
GlobalPosition = Player.CurrentPosition;
|
GlobalPosition = Player.CurrentPosition;
|
||||||
Sprite.Texture = ItemThatIsThrown.GetTexture();
|
Sprite.Texture = ItemThatIsThrown.ItemStats.Texture;
|
||||||
AddCollisionExceptionWith((Node)Player);
|
AddCollisionExceptionWith((Node)Player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,8 +35,9 @@ public partial class ThrownItem : RigidBody3D
|
|||||||
QueueFree();
|
QueueFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Throw()
|
public void Throw(EffectService effectService)
|
||||||
{
|
{
|
||||||
|
_effectService = effectService;
|
||||||
ApplyCentralImpulse(-Player.CurrentBasis.Z.Normalized() * ItemThatIsThrown.ThrowSpeed);
|
ApplyCentralImpulse(-Player.CurrentBasis.Z.Normalized() * ItemThatIsThrown.ThrowSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,16 +82,16 @@ public partial class ThrownItem : RigidBody3D
|
|||||||
{
|
{
|
||||||
if (ItemThatIsThrown is ThrowableItem throwableItem)
|
if (ItemThatIsThrown is ThrowableItem throwableItem)
|
||||||
{
|
{
|
||||||
switch (throwableItem.ThrowableItemTags.Single())
|
switch (throwableItem.ThrowableItemTag)
|
||||||
{
|
{
|
||||||
case ThrowableItemTag.LowerTargetTo1HP:
|
case ThrowableItemTag.LowerTargetTo1HP:
|
||||||
enemy.TakeDamage(enemy.CurrentHP - 1, ignoreDefense: true, ignoreElementalResistance: true);
|
enemy.TakeDamage(enemy.CurrentHP - 1, ignoreDefense: true, ignoreElementalResistance: true);
|
||||||
break;
|
break;
|
||||||
case ThrowableItemTag.TeleportToRandomLocation:
|
case ThrowableItemTag.TeleportToRandomLocation:
|
||||||
throwableItem.TeleportToRandomRoom(enemy);
|
_effectService.TeleportToRandomRoom(enemy);
|
||||||
break;
|
break;
|
||||||
case ThrowableItemTag.WarpToExitIfFound:
|
case ThrowableItemTag.WarpToExitIfFound:
|
||||||
throwableItem.WarpToExit(enemy);
|
_effectService.WarpToExit(enemy);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
enemy.TakeDamage(throwableItem.ThrowDamage, throwableItem.ElementType);
|
enemy.TakeDamage(throwableItem.ThrowDamage, throwableItem.ElementType);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
[gd_scene load_steps=6 format=3 uid="uid://b1twcuneob5kt"]
|
[gd_scene load_steps=5 format=3 uid="uid://b1twcuneob5kt"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://bx1k4yff3m82m" path="res://src/items/thrown/ThrownItem.cs" id="1_wlplc"]
|
[ext_resource type="Script" uid="uid://bx1k4yff3m82m" path="res://src/items/thrown/ThrownItem.cs" id="1_wlplc"]
|
||||||
[ext_resource type="Texture2D" uid="uid://mi70lolgtf3n" path="res://src/items/throwable/textures/GEOMANCER-DICE.png" id="2_alcjn"]
|
|
||||||
[ext_resource type="Material" uid="uid://x2bv1q51mcjq" path="res://src/enemy/PixelMelt.tres" id="2_qjpqg"]
|
[ext_resource type="Material" uid="uid://x2bv1q51mcjq" path="res://src/enemy/PixelMelt.tres" id="2_qjpqg"]
|
||||||
|
|
||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_s4ym5"]
|
[sub_resource type="BoxShape3D" id="BoxShape3D_s4ym5"]
|
||||||
@@ -13,7 +12,8 @@ viewport_path = NodePath("Sprite3D/SubViewportContainer/SubViewport")
|
|||||||
[node name="Hitbox" type="RigidBody3D"]
|
[node name="Hitbox" type="RigidBody3D"]
|
||||||
collision_layer = 1040
|
collision_layer = 1040
|
||||||
collision_mask = 25
|
collision_mask = 25
|
||||||
gravity_scale = 0.25
|
mass = 0.1
|
||||||
|
gravity_scale = 0.01
|
||||||
contact_monitor = true
|
contact_monitor = true
|
||||||
max_contacts_reported = 50
|
max_contacts_reported = 50
|
||||||
script = ExtResource("1_wlplc")
|
script = ExtResource("1_wlplc")
|
||||||
@@ -54,5 +54,4 @@ render_target_update_mode = 4
|
|||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
material = ExtResource("2_qjpqg")
|
material = ExtResource("2_qjpqg")
|
||||||
scale = Vector2(0.1, 0.1)
|
scale = Vector2(0.1, 0.1)
|
||||||
texture = ExtResource("2_alcjn")
|
|
||||||
centered = false
|
centered = false
|
||||||
|
|||||||
@@ -1,51 +1,33 @@
|
|||||||
using Chickensoft.AutoInject;
|
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta, Id("weapon")]
|
||||||
public partial class Weapon : Node3D, IInventoryItem, IEquipableItem
|
public partial class Weapon : EquipableItem
|
||||||
{
|
{
|
||||||
public override void _Notification(int what) => this.Notify(what);
|
|
||||||
|
|
||||||
[Dependency] public IPlayer Player => this.DependOn<IPlayer>();
|
|
||||||
|
|
||||||
[Signal]
|
|
||||||
public delegate void EquippedItemEventHandler(Weapon equippedWeapon);
|
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
private WeaponStats _weaponStats { get; set; } = new WeaponStats();
|
private WeaponStats _weaponStats { get; set; } = new WeaponStats();
|
||||||
|
|
||||||
[Node] public Sprite3D Sprite { get; set; } = new Sprite3D();
|
public override string ItemName => _weaponStats.Name;
|
||||||
|
|
||||||
[Node] public Area3D Pickup { get; set; } = default!;
|
public override string Description => _weaponStats.Description;
|
||||||
|
|
||||||
public Texture2D GetTexture() => _weaponStats.Texture;
|
public override float SpawnRate => _weaponStats.SpawnRate;
|
||||||
|
|
||||||
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 int Damage => _weaponStats.Damage;
|
||||||
|
|
||||||
public double ThrowDamage => _weaponStats.ThrowDamage;
|
public override double ThrowDamage => _weaponStats.ThrowDamage;
|
||||||
|
|
||||||
public float ThrowSpeed => _weaponStats.ThrowSpeed;
|
public override float ThrowSpeed => _weaponStats.ThrowSpeed;
|
||||||
|
|
||||||
public double Luck => _weaponStats.Luck;
|
public double Luck => _weaponStats.Luck;
|
||||||
|
|
||||||
public double AttackSpeed => _weaponStats.AttackSpeed;
|
public double AttackSpeed => _weaponStats.AttackSpeed;
|
||||||
|
|
||||||
public ImmutableList<WeaponTag> WeaponTags => [.. _weaponStats.WeaponTags];
|
public WeaponTag WeaponTag => _weaponStats.WeaponTag;
|
||||||
|
|
||||||
public ImmutableList<ItemTag> ItemTags => [.. _weaponStats.ItemTags];
|
public override ItemTag ItemTag => _weaponStats.ItemTag;
|
||||||
|
|
||||||
public ElementType WeaponElement => _weaponStats.WeaponElement;
|
public ElementType WeaponElement => _weaponStats.WeaponElement;
|
||||||
|
|
||||||
@@ -53,38 +35,5 @@ public partial class Weapon : Node3D, IInventoryItem, IEquipableItem
|
|||||||
|
|
||||||
public void IncreaseWeaponAttack(int bonus) => _weaponStats.Damage += bonus;
|
public void IncreaseWeaponAttack(int bonus) => _weaponStats.Damage += bonus;
|
||||||
|
|
||||||
public bool IsEquipped { get; set; }
|
public override InventoryItemStats ItemStats { get => _weaponStats; set => _weaponStats = (WeaponStats)value; }
|
||||||
|
|
||||||
public void OnReady()
|
|
||||||
{
|
|
||||||
Pickup.BodyEntered += OnEntered;
|
|
||||||
Sprite.Texture = _weaponStats.Texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetItemStats(InventoryItemStats inventoryItemStats)
|
|
||||||
{
|
|
||||||
_weaponStats = (WeaponStats)inventoryItemStats;
|
|
||||||
if (inventoryItemStats.Texture != null)
|
|
||||||
{
|
|
||||||
var texture = ResourceLoader.Load(inventoryItemStats.Texture.ResourcePath) as Texture2D;
|
|
||||||
Sprite.Texture = texture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Throw()
|
|
||||||
{
|
|
||||||
Player.Inventory.Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Drop()
|
|
||||||
{
|
|
||||||
Player.Inventory.Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnEntered(Node3D body)
|
|
||||||
{
|
|
||||||
var isAdded = Player.Inventory.TryAdd(this);
|
|
||||||
if (isAdded)
|
|
||||||
QueueFree();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
radius = 0.470016
|
radius = 0.470016
|
||||||
|
|
||||||
[node name="Weapon" type="Node3D"]
|
[node name="Weapon" type="Node3D"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.75, 0)
|
|
||||||
script = ExtResource("1_7pkyf")
|
script = ExtResource("1_7pkyf")
|
||||||
|
|
||||||
[node name="Pickup" type="Area3D" parent="."]
|
[node name="Pickup" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
collision_layer = 4
|
collision_layer = 4
|
||||||
collision_mask = 4
|
collision_mask = 0
|
||||||
|
|
||||||
[node name="Sprite" type="Sprite3D" parent="Pickup"]
|
[node name="Sprite" type="Sprite3D" parent="Pickup"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|||||||
@@ -1,25 +1,34 @@
|
|||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
|
[Meta, Id("weapon_stat_type")]
|
||||||
public partial class WeaponStats : InventoryItemStats
|
public partial class WeaponStats : InventoryItemStats
|
||||||
{
|
{
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("weapon_damage")]
|
||||||
public int Damage { get; set; } = 0;
|
public int Damage { get; set; } = 0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("weapon_luck")]
|
||||||
public double Luck { get; set; } = 0.05;
|
public double Luck { get; set; } = 0.05;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("weapon_atk_speed")]
|
||||||
public double AttackSpeed { get; set; } = 1;
|
public double AttackSpeed { get; set; } = 1;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("weapon_element")]
|
||||||
public ElementType WeaponElement { get; set; } = ElementType.None;
|
public ElementType WeaponElement { get; set; } = ElementType.None;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
|
[Save("weapon_elemental_damage_bonus")]
|
||||||
public double ElementalDamageBonus { get; set; } = 1.0;
|
public double ElementalDamageBonus { get; set; } = 1.0;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public Godot.Collections.Array<WeaponTag> WeaponTags { get; set; } = new Godot.Collections.Array<WeaponTag>();
|
[Save("weapon_tag")]
|
||||||
|
public WeaponTag WeaponTag { get; set; } = WeaponTag.None;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=42 format=4 uid="uid://bn4gslp2gk8ds"]
|
[gd_scene load_steps=43 format=4 uid="uid://bn4gslp2gk8ds"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://fk3jis6rsipv" path="res://src/map/dungeon/code/corridor.gd" id="1_lepkf"]
|
[ext_resource type="Script" uid="uid://fk3jis6rsipv" path="res://src/map/dungeon/code/corridor.gd" id="1_lepkf"]
|
||||||
[ext_resource type="Texture2D" uid="uid://crsw35eypj6ry" path="res://src/map/dungeon/models/Set A/18. Corridor A/18_A1_CORRIDOR_A_WALL TILE 1.jpg" id="2_jmyyj"]
|
[ext_resource type="Texture2D" uid="uid://crsw35eypj6ry" path="res://src/map/dungeon/models/Set A/18. Corridor A/18_A1_CORRIDOR_A_WALL TILE 1.jpg" id="2_jmyyj"]
|
||||||
@@ -433,6 +433,9 @@ shadow_mesh = SubResource("ArrayMesh_etli6")
|
|||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_d16dk"]
|
[sub_resource type="BoxShape3D" id="BoxShape3D_d16dk"]
|
||||||
size = Vector3(0.236, 5.538, 0.149)
|
size = Vector3(0.236, 5.538, 0.149)
|
||||||
|
|
||||||
|
[sub_resource type="BoxShape3D" id="BoxShape3D_xywry"]
|
||||||
|
size = Vector3(4, 0.557617, 4)
|
||||||
|
|
||||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2qrwe"]
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2qrwe"]
|
||||||
transparency = 1
|
transparency = 1
|
||||||
shading_mode = 0
|
shading_mode = 0
|
||||||
@@ -741,6 +744,10 @@ shape = SubResource("BoxShape3D_d16dk")
|
|||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -11.637, 2.14158, 2.73139)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -11.637, 2.14158, 2.73139)
|
||||||
shape = SubResource("BoxShape3D_d16dk")
|
shape = SubResource("BoxShape3D_d16dk")
|
||||||
|
|
||||||
|
[node name="CollisionShape3D5" type="CollisionShape3D" parent="Collision/StaticBody3D"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -9.88863, -0.243546, 0.997182)
|
||||||
|
shape = SubResource("BoxShape3D_xywry")
|
||||||
|
|
||||||
[node name="Doors" type="Node3D" parent="."]
|
[node name="Doors" type="Node3D" parent="."]
|
||||||
|
|
||||||
[node name="DOOR?_F_CUT" type="CSGBox3D" parent="Doors"]
|
[node name="DOOR?_F_CUT" type="CSGBox3D" parent="Doors"]
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.AutoInject;
|
||||||
|
using Chickensoft.Collections;
|
||||||
|
using Chickensoft.SaveFileBuilder;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
public interface IPlayer : IKillable
|
public interface IPlayer : IKillable, IProvide<ISaveChunk<PlayerData>>
|
||||||
{
|
{
|
||||||
public void Attack();
|
public void Attack();
|
||||||
|
|
||||||
@@ -45,9 +47,9 @@ public interface IPlayer : IKillable
|
|||||||
|
|
||||||
public void ModifyBonusLuck(double amount);
|
public void ModifyBonusLuck(double amount);
|
||||||
|
|
||||||
public IInventory Inventory { get; }
|
public Inventory Inventory { get; }
|
||||||
|
|
||||||
public PlayerStats Stats { get; }
|
public PlayerStatController Stats { get; }
|
||||||
|
|
||||||
public Vector3 CurrentPosition { get; }
|
public Vector3 CurrentPosition { get; }
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ public interface IPlayer : IKillable
|
|||||||
|
|
||||||
public IAutoProp<Accessory> EquippedAccessory { get; }
|
public IAutoProp<Accessory> EquippedAccessory { get; }
|
||||||
|
|
||||||
public void Equip(IEquipableItem equipable);
|
public void Equip(EquipableItem equipable);
|
||||||
|
|
||||||
public void Unequip(IEquipableItem equipable);
|
public void Unequip(EquipableItem equipable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,18 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
private PlayerLogic.IBinding PlayerBinding { get; set; } = default!;
|
private PlayerLogic.IBinding PlayerBinding { get; set; } = default!;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Save
|
||||||
|
public ISaveChunk<PlayerData> PlayerChunk { get; set; } = default!;
|
||||||
|
#endregion
|
||||||
|
|
||||||
public double CurrentHP => Stats.CurrentHP.Value;
|
public double CurrentHP => Stats.CurrentHP.Value;
|
||||||
|
|
||||||
public Vector3 CurrentPosition => GlobalPosition;
|
public Vector3 CurrentPosition => GlobalPosition;
|
||||||
|
|
||||||
public Basis CurrentBasis => Transform.Basis;
|
public Basis CurrentBasis => Transform.Basis;
|
||||||
public PlayerStats Stats { get; set; } = default!;
|
public PlayerStatController Stats { get; set; } = default!;
|
||||||
|
|
||||||
public IInventory Inventory { get; private set; } = default!;
|
public Inventory Inventory { get; private set; } = default!;
|
||||||
|
|
||||||
public IAutoProp<Weapon> EquippedWeapon => _equippedWeapon;
|
public IAutoProp<Weapon> EquippedWeapon => _equippedWeapon;
|
||||||
private AutoProp<Weapon> _equippedWeapon { get; set; } = new AutoProp<Weapon>(new Weapon());
|
private AutoProp<Weapon> _equippedWeapon { get; set; } = new AutoProp<Weapon>(new Weapon());
|
||||||
@@ -48,6 +52,8 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
|
|
||||||
[Dependency]
|
[Dependency]
|
||||||
public ISaveChunk<GameData> GameChunk => this.DependOn<ISaveChunk<GameData>>();
|
public ISaveChunk<GameData> GameChunk => this.DependOn<ISaveChunk<GameData>>();
|
||||||
|
|
||||||
|
ISaveChunk<PlayerData> IProvide<ISaveChunk<PlayerData>>.Value() => PlayerChunk;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Event Signals
|
#region Event Signals
|
||||||
@@ -76,6 +82,8 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
|
|
||||||
[Node] private IHitbox Hitbox { get; set; } = default!;
|
[Node] private IHitbox Hitbox { get; set; } = default!;
|
||||||
|
|
||||||
|
[Node] private Area3D CollisionDetector { get; set; } = default!;
|
||||||
|
|
||||||
[Node] private Timer HealthTimer { get; set; } = default!;
|
[Node] private Timer HealthTimer { get; set; } = default!;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -110,34 +118,37 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Settings = new PlayerLogic.Settings() { RotationSpeed = PlayerStatResource.RotationSpeed, MoveSpeed = PlayerStatResource.MoveSpeed, Acceleration = PlayerStatResource.Acceleration };
|
Settings = new PlayerLogic.Settings() { RotationSpeed = PlayerStatResource.RotationSpeed, MoveSpeed = PlayerStatResource.MoveSpeed, Acceleration = PlayerStatResource.Acceleration };
|
||||||
|
Stats = new PlayerStatController();
|
||||||
|
Stats.Init(
|
||||||
|
new PlayerStats
|
||||||
|
{
|
||||||
|
CurrentHP = PlayerStatResource.CurrentHP,
|
||||||
|
MaximumHP = PlayerStatResource.MaximumHP,
|
||||||
|
CurrentVT = PlayerStatResource.CurrentVT,
|
||||||
|
MaximumVT = PlayerStatResource.MaximumVT,
|
||||||
|
CurrentAttack = PlayerStatResource.CurrentAttack,
|
||||||
|
BonusAttack = PlayerStatResource.BonusAttack,
|
||||||
|
MaxAttack = PlayerStatResource.MaxAttack,
|
||||||
|
CurrentDefense = PlayerStatResource.CurrentDefense,
|
||||||
|
BonusDefense = PlayerStatResource.BonusDefense,
|
||||||
|
MaxDefense = PlayerStatResource.MaxDefense,
|
||||||
|
CurrentExp = PlayerStatResource.CurrentExp,
|
||||||
|
CurrentLevel = PlayerStatResource.CurrentLevel,
|
||||||
|
ExpToNextLevel = PlayerStatResource.ExpToNextLevel,
|
||||||
|
Luck = PlayerStatResource.Luck
|
||||||
|
});
|
||||||
|
|
||||||
Stats = new PlayerStats();
|
|
||||||
Inventory = new Inventory();
|
Inventory = new Inventory();
|
||||||
|
|
||||||
Stats.SetCurrentHP(PlayerStatResource.CurrentHP);
|
|
||||||
Stats.SetMaximumHP(PlayerStatResource.MaximumHP);
|
|
||||||
Stats.SetCurrentVT(PlayerStatResource.CurrentVT);
|
|
||||||
Stats.SetMaximumVT(PlayerStatResource.MaximumVT);
|
|
||||||
Stats.SetCurrentAttack(PlayerStatResource.CurrentAttack);
|
|
||||||
Stats.SetBonusAttack(PlayerStatResource.BonusAttack);
|
|
||||||
Stats.SetMaxAttack(PlayerStatResource.MaxAttack);
|
|
||||||
Stats.SetCurrentDefense(PlayerStatResource.CurrentDefense);
|
|
||||||
Stats.SetBonusDefense(PlayerStatResource.BonusDefense);
|
|
||||||
Stats.SetMaxDefense(PlayerStatResource.MaxDefense);
|
|
||||||
Stats.SetCurrentExp(PlayerStatResource.CurrentExp);
|
|
||||||
Stats.SetCurrentLevel(PlayerStatResource.CurrentLevel);
|
|
||||||
Stats.SetExpToNextLevel(PlayerStatResource.ExpToNextLevel);
|
|
||||||
Stats.SetLuck(PlayerStatResource.Luck);
|
|
||||||
|
|
||||||
PlayerLogic = new PlayerLogic();
|
PlayerLogic = new PlayerLogic();
|
||||||
PlayerLogic.Set(this as IPlayer);
|
PlayerLogic.Set(this as IPlayer);
|
||||||
PlayerLogic.Set(Settings);
|
PlayerLogic.Set(Settings);
|
||||||
PlayerLogic.Set(Stats);
|
PlayerLogic.Set(Stats);
|
||||||
|
|
||||||
var defaultWeapon = new Weapon();
|
var defaultWeapon = new Weapon();
|
||||||
defaultWeapon.SetItemStats(_defaultWeapon);
|
defaultWeapon.ItemStats = _defaultWeapon;
|
||||||
var defaultArmor = new Armor();
|
var defaultArmor = new Armor();
|
||||||
defaultArmor.SetItemStats(_defaultArmor);
|
defaultArmor.ItemStats = _defaultArmor;
|
||||||
Inventory.TryAdd(defaultWeapon);
|
Inventory.TryAdd(defaultWeapon);
|
||||||
Inventory.TryAdd(defaultArmor);
|
Inventory.TryAdd(defaultArmor);
|
||||||
|
|
||||||
@@ -155,6 +166,35 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
|
|
||||||
public void OnResolved()
|
public void OnResolved()
|
||||||
{
|
{
|
||||||
|
PlayerChunk = new SaveChunk<PlayerData>(
|
||||||
|
onSave: (chunk) => new PlayerData()
|
||||||
|
{
|
||||||
|
PlayerStats = new PlayerStats()
|
||||||
|
{
|
||||||
|
CurrentHP = Stats.CurrentHP.Value,
|
||||||
|
MaximumHP = Stats.MaximumHP.Value,
|
||||||
|
CurrentVT = Stats.CurrentVT.Value,
|
||||||
|
MaximumVT = Stats.MaximumVT.Value,
|
||||||
|
CurrentAttack = Stats.CurrentAttack.Value,
|
||||||
|
BonusAttack = Stats.BonusAttack.Value,
|
||||||
|
MaxAttack = Stats.MaxAttack.Value,
|
||||||
|
CurrentDefense = Stats.CurrentDefense.Value,
|
||||||
|
BonusDefense = Stats.BonusDefense.Value,
|
||||||
|
MaxDefense = Stats.MaxDefense.Value,
|
||||||
|
CurrentExp = Stats.CurrentExp.Value,
|
||||||
|
CurrentLevel = Stats.CurrentLevel.Value,
|
||||||
|
ExpToNextLevel = Stats.ExpToNextLevel.Value,
|
||||||
|
Luck = Stats.Luck.Value
|
||||||
|
},
|
||||||
|
Inventory = Inventory
|
||||||
|
},
|
||||||
|
onLoad: (chunk, data) =>
|
||||||
|
{
|
||||||
|
Stats.Init(data.PlayerStats);
|
||||||
|
Inventory = data.Inventory;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
PlayerBinding = PlayerLogic.Bind();
|
PlayerBinding = PlayerLogic.Bind();
|
||||||
|
|
||||||
PlayerBinding
|
PlayerBinding
|
||||||
@@ -169,10 +209,23 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
{
|
{
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Provide();
|
GameChunk.AddChunk(PlayerChunk);
|
||||||
|
|
||||||
PlayerLogic.Start();
|
PlayerLogic.Start();
|
||||||
|
this.Provide();
|
||||||
HealthTimer.Timeout += OnHealthTimerTimeout;
|
HealthTimer.Timeout += OnHealthTimerTimeout;
|
||||||
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
Hitbox.AreaEntered += Hitbox_AreaEntered;
|
||||||
|
CollisionDetector.AreaEntered += CollisionDetector_AreaEntered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CollisionDetector_AreaEntered(Area3D area)
|
||||||
|
{
|
||||||
|
if (area.GetParent() is InventoryItem inventoryItem)
|
||||||
|
{
|
||||||
|
var isAdded = Inventory.TryAdd(inventoryItem);
|
||||||
|
if (isAdded)
|
||||||
|
inventoryItem.QueueFree();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnReady()
|
public void OnReady()
|
||||||
@@ -225,7 +278,7 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
|
|
||||||
public void RaiseVT(int amountToRaise)
|
public void RaiseVT(int amountToRaise)
|
||||||
{
|
{
|
||||||
if (Stats.CurrentVT.Value == Stats.MaximumVT.Value)
|
if (Stats.CurrentVT == Stats.MaximumVT)
|
||||||
{
|
{
|
||||||
Stats.SetMaximumVT(Stats.MaximumVT.Value + amountToRaise);
|
Stats.SetMaximumVT(Stats.MaximumVT.Value + amountToRaise);
|
||||||
Stats.SetCurrentVT(Stats.MaximumVT.Value);
|
Stats.SetCurrentVT(Stats.MaximumVT.Value);
|
||||||
@@ -333,6 +386,12 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
|
|
||||||
if (@event.IsActionPressed(GameInputs.Attack))
|
if (@event.IsActionPressed(GameInputs.Attack))
|
||||||
Attack();
|
Attack();
|
||||||
|
|
||||||
|
if (@event.IsActionPressed(GameInputs.Save))
|
||||||
|
Game.Save();
|
||||||
|
|
||||||
|
if (@event.IsActionPressed(GameInputs.Load))
|
||||||
|
Game.Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnPhysicsProcess(double delta)
|
public void OnPhysicsProcess(double delta)
|
||||||
@@ -341,7 +400,7 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
|
PlayerLogic.Input(new PlayerLogic.Input.Moved(GlobalPosition, GlobalTransform));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Equip(IEquipableItem equipable)
|
public void Equip(EquipableItem equipable)
|
||||||
{
|
{
|
||||||
if (equipable is Weapon weapon)
|
if (equipable is Weapon weapon)
|
||||||
{
|
{
|
||||||
@@ -365,7 +424,7 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
throw new NotImplementedException("Item type is not supported.");
|
throw new NotImplementedException("Item type is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unequip(IEquipableItem equipable)
|
public void Unequip(EquipableItem equipable)
|
||||||
{
|
{
|
||||||
if (equipable is Weapon weapon)
|
if (equipable is Weapon weapon)
|
||||||
{
|
{
|
||||||
@@ -392,7 +451,7 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
else
|
else
|
||||||
throw new NotImplementedException("Item type is not supported.");
|
throw new NotImplementedException("Item type is not supported.");
|
||||||
|
|
||||||
if (equipable.ItemTags.Contains(ItemTag.BreaksOnChange))
|
if (equipable.ItemTag == ItemTag.BreaksOnChange)
|
||||||
Inventory.Remove(equipable);
|
Inventory.Remove(equipable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,7 +516,7 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
|
|
||||||
if (Stats.CurrentVT.Value > 0)
|
if (Stats.CurrentVT.Value > 0)
|
||||||
{
|
{
|
||||||
if (EquippedAccessory.Value.AccessoryTags.Contains(AccessoryTag.HalfVTConsumption))
|
if (EquippedAccessory.Value.AccessoryTag == AccessoryTag.HalfVTConsumption)
|
||||||
{
|
{
|
||||||
reduceOnTick = !reduceOnTick;
|
reduceOnTick = !reduceOnTick;
|
||||||
}
|
}
|
||||||
@@ -515,7 +574,7 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
private void HitEnemy(IEnemy enemy)
|
private void HitEnemy(IEnemy enemy)
|
||||||
{
|
{
|
||||||
var attackValue = Stats.CurrentAttack.Value + Stats.BonusAttack.Value;
|
var attackValue = Stats.CurrentAttack.Value + Stats.BonusAttack.Value;
|
||||||
var ignoreElementalResistance = EquippedWeapon.Value.WeaponTags.Contains(WeaponTag.IgnoreAffinity);
|
var ignoreElementalResistance = EquippedWeapon.Value.WeaponTag == WeaponTag.IgnoreAffinity;
|
||||||
var isCriticalHit = BattleExtensions.IsCriticalHit(Stats.Luck.Value);
|
var isCriticalHit = BattleExtensions.IsCriticalHit(Stats.Luck.Value);
|
||||||
var element = EquippedWeapon.Value.WeaponElement;
|
var element = EquippedWeapon.Value.WeaponElement;
|
||||||
|
|
||||||
@@ -526,7 +585,7 @@ public partial class Player : CharacterBody3D, IPlayer
|
|||||||
false,
|
false,
|
||||||
ignoreElementalResistance);
|
ignoreElementalResistance);
|
||||||
|
|
||||||
if (EquippedWeapon.Value.WeaponTags.Contains(WeaponTag.Knockback))
|
if (EquippedWeapon.Value.WeaponTag == WeaponTag.Knockback)
|
||||||
enemy.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
enemy.Knockback(0.3f, -CurrentBasis.Z.Normalized());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[ext_resource type="Script" uid="uid://yxmiqy7i0t7r" path="res://src/player/Player.cs" id="1_xcol5"]
|
[ext_resource type="Script" uid="uid://yxmiqy7i0t7r" path="res://src/player/Player.cs" id="1_xcol5"]
|
||||||
[ext_resource type="Script" uid="uid://6edayafleq8y" path="res://src/hitbox/Hitbox.cs" id="2_lb3qc"]
|
[ext_resource type="Script" uid="uid://6edayafleq8y" path="res://src/hitbox/Hitbox.cs" id="2_lb3qc"]
|
||||||
[ext_resource type="Script" uid="uid://s6ku2kyc4rbk" path="res://src/player/PlayerStatResource.cs" id="2_xq68d"]
|
[ext_resource type="Script" uid="uid://s6ku2kyc4rbk" path="res://src/player/PlayerStatResource.cs" id="2_xq68d"]
|
||||||
[ext_resource type="Resource" uid="uid://b7xr0l4a8g1gk" path="res://src/items/weapons/resources/SealingRod.tres" id="3_ebyyx"]
|
[ext_resource type="Resource" uid="uid://bpdbuf0k0exb5" path="res://src/items/weapons/resources/Swan Sword Odette.tres" id="3_es4xk"]
|
||||||
[ext_resource type="Resource" uid="uid://ce2vfa2t3io67" path="res://src/items/armor/resources/AtonersAdornments.tres" id="4_bj1ma"]
|
[ext_resource type="Resource" uid="uid://ce2vfa2t3io67" path="res://src/items/armor/resources/AtonersAdornments.tres" id="4_bj1ma"]
|
||||||
[ext_resource type="Texture2D" uid="uid://c6r3dhnkuw22w" path="res://src/vfx/hit_effects/FIRE_STRIKE_1.0.png" id="5_wr6lo"]
|
[ext_resource type="Texture2D" uid="uid://c6r3dhnkuw22w" path="res://src/vfx/hit_effects/FIRE_STRIKE_1.0.png" id="5_wr6lo"]
|
||||||
[ext_resource type="Texture2D" uid="uid://m6xsyhnt67sh" path="res://src/player/dont_look_in_here/tendomaya_body0_tex00.png" id="6_es4xk"]
|
[ext_resource type="Texture2D" uid="uid://m6xsyhnt67sh" path="res://src/player/dont_look_in_here/tendomaya_body0_tex00.png" id="6_es4xk"]
|
||||||
@@ -32,13 +32,13 @@ BonusDefense = 0
|
|||||||
MaxDefense = 12
|
MaxDefense = 12
|
||||||
Luck = 0.05
|
Luck = 0.05
|
||||||
|
|
||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_wedu3"]
|
|
||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dw45s"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dw45s"]
|
||||||
radius = 1.0
|
radius = 1.0
|
||||||
|
|
||||||
|
[sub_resource type="BoxShape3D" id="BoxShape3D_wedu3"]
|
||||||
|
|
||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_hs4wf"]
|
[sub_resource type="BoxShape3D" id="BoxShape3D_hs4wf"]
|
||||||
size = Vector3(1.94531, 2.43945, 2.35425)
|
size = Vector3(1.94531, 3.38623, 2.35425)
|
||||||
|
|
||||||
[sub_resource type="Animation" id="Animation_hcjph"]
|
[sub_resource type="Animation" id="Animation_hcjph"]
|
||||||
length = 0.001
|
length = 0.001
|
||||||
@@ -470,9 +470,13 @@ collision_layer = 806
|
|||||||
collision_mask = 775
|
collision_mask = 775
|
||||||
script = ExtResource("1_xcol5")
|
script = ExtResource("1_xcol5")
|
||||||
PlayerStatResource = SubResource("Resource_btp2w")
|
PlayerStatResource = SubResource("Resource_btp2w")
|
||||||
_defaultWeapon = ExtResource("3_ebyyx")
|
_defaultWeapon = ExtResource("3_es4xk")
|
||||||
_defaultArmor = ExtResource("4_bj1ma")
|
_defaultArmor = ExtResource("4_bj1ma")
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.06447, 0)
|
||||||
|
shape = SubResource("CapsuleShape3D_dw45s")
|
||||||
|
|
||||||
[node name="Hitbox" type="Area3D" parent="."]
|
[node name="Hitbox" type="Area3D" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.12691, -1)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.12691, -1)
|
||||||
@@ -484,18 +488,14 @@ script = ExtResource("2_lb3qc")
|
|||||||
shape = SubResource("BoxShape3D_wedu3")
|
shape = SubResource("BoxShape3D_wedu3")
|
||||||
disabled = true
|
disabled = true
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
[node name="CollisionDetector" type="Area3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.06447, 0)
|
|
||||||
shape = SubResource("CapsuleShape3D_dw45s")
|
|
||||||
|
|
||||||
[node name="CollisionDetector" type="Area3D" parent="CollisionShape3D"]
|
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.937567, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.126903, 0)
|
||||||
collision_layer = 452
|
collision_layer = 452
|
||||||
collision_mask = 452
|
collision_mask = 452
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="CollisionShape3D/CollisionDetector"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="CollisionDetector"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0479561, 0.982638, -0.675098)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0479561, 0.509249, -0.675098)
|
||||||
shape = SubResource("BoxShape3D_hs4wf")
|
shape = SubResource("BoxShape3D_hs4wf")
|
||||||
|
|
||||||
[node name="Camera3D" type="Camera3D" parent="."]
|
[node name="Camera3D" type="Camera3D" parent="."]
|
||||||
|
|||||||
14
src/player/PlayerData.cs
Normal file
14
src/player/PlayerData.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
|
||||||
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
|
[Meta, Id("player_data")]
|
||||||
|
public partial record PlayerData
|
||||||
|
{
|
||||||
|
[Save("player_stats")]
|
||||||
|
public required PlayerStats PlayerStats { get; init; }
|
||||||
|
|
||||||
|
[Save("player_inventory")]
|
||||||
|
public required Inventory Inventory { get; init; }
|
||||||
|
}
|
||||||
@@ -1,38 +1,76 @@
|
|||||||
using Chickensoft.Collections;
|
using Chickensoft.Collections;
|
||||||
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Serialization;
|
using Chickensoft.Serialization;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace GameJamDungeon;
|
namespace GameJamDungeon;
|
||||||
|
|
||||||
|
[Meta, Id("player_stats")]
|
||||||
public partial record PlayerStats
|
public partial record PlayerStats
|
||||||
{
|
{
|
||||||
[Save("currentHP")]
|
[Save("currentHP")]
|
||||||
public IAutoProp<int> CurrentHP => _currentHP;
|
public int CurrentHP { get; init; }
|
||||||
[Save("maximumHP")]
|
[Save("maximumHP")]
|
||||||
public IAutoProp<int> MaximumHP => _maximumHP;
|
public int MaximumHP { get; init; }
|
||||||
[Save("currentVT")]
|
[Save("currentVT")]
|
||||||
public IAutoProp<int> CurrentVT => _currentVT;
|
public int CurrentVT { get; init; }
|
||||||
[Save("maximumVT")]
|
[Save("maximumVT")]
|
||||||
public IAutoProp<int> MaximumVT => _maximumVT;
|
public int MaximumVT { get; init; }
|
||||||
[Save("currentExp")]
|
[Save("currentExp")]
|
||||||
public IAutoProp<int> CurrentExp => _currentExp;
|
public int CurrentExp { get; init; }
|
||||||
[Save("currentLevel")]
|
[Save("currentLevel")]
|
||||||
public IAutoProp<int> CurrentLevel => _currentLevel;
|
public int CurrentLevel { get; init; }
|
||||||
[Save("currentAttack")]
|
[Save("currentAttack")]
|
||||||
public IAutoProp<int> CurrentAttack => _currentAttack;
|
public int CurrentAttack { get; init; }
|
||||||
[Save("bonusAttack")]
|
[Save("bonusAttack")]
|
||||||
public IAutoProp<int> BonusAttack => _bonusAttack;
|
public int BonusAttack { get; init; }
|
||||||
[Save("maxAttack")]
|
[Save("maxAttack")]
|
||||||
public IAutoProp<int> MaxAttack => _maxAttack;
|
public int MaxAttack { get; init; }
|
||||||
[Save("currentDefense")]
|
[Save("currentDefense")]
|
||||||
public IAutoProp<int> CurrentDefense => _currentDefense;
|
public int CurrentDefense { get; init; }
|
||||||
[Save("bonusDefense")]
|
[Save("bonusDefense")]
|
||||||
public IAutoProp<int> BonusDefense => _bonusDefense;
|
public int BonusDefense { get; init; }
|
||||||
[Save("maxDefense")]
|
[Save("maxDefense")]
|
||||||
public IAutoProp<int> MaxDefense => _maxDefense;
|
public int MaxDefense { get; init; }
|
||||||
[Save("expToNextLevel")]
|
[Save("expToNextLevel")]
|
||||||
public IAutoProp<int> ExpToNextLevel => _expToNextLevel;
|
public int ExpToNextLevel { get; init; }
|
||||||
[Save("luck")]
|
[Save("luck")]
|
||||||
|
public double Luck { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlayerStatController
|
||||||
|
{
|
||||||
|
public void Init(PlayerStats playerStats)
|
||||||
|
{
|
||||||
|
_currentHP.OnNext(playerStats.CurrentHP);
|
||||||
|
_maximumHP.OnNext(playerStats.MaximumHP);
|
||||||
|
_currentVT.OnNext(playerStats.CurrentVT);
|
||||||
|
_maximumVT.OnNext(playerStats.MaximumVT);
|
||||||
|
_currentExp.OnNext(playerStats.CurrentExp);
|
||||||
|
_currentLevel.OnNext(playerStats.CurrentLevel);
|
||||||
|
_currentAttack.OnNext(playerStats.CurrentAttack);
|
||||||
|
_bonusAttack.OnNext(playerStats.BonusAttack);
|
||||||
|
_maxAttack.OnNext(playerStats.MaxAttack);
|
||||||
|
_currentDefense.OnNext(playerStats.CurrentDefense);
|
||||||
|
_bonusDefense.OnNext(playerStats.BonusDefense);
|
||||||
|
_maxDefense.OnNext(playerStats.MaxDefense);
|
||||||
|
_expToNextLevel.OnNext(playerStats.ExpToNextLevel);
|
||||||
|
_luck.OnNext(playerStats.Luck);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAutoProp<int> CurrentHP => _currentHP;
|
||||||
|
public IAutoProp<int> MaximumHP => _maximumHP;
|
||||||
|
public IAutoProp<int> CurrentVT => _currentVT;
|
||||||
|
public IAutoProp<int> MaximumVT => _maximumVT;
|
||||||
|
public IAutoProp<int> CurrentAttack => _currentAttack;
|
||||||
|
public IAutoProp<int> MaxAttack => _maxAttack;
|
||||||
|
public IAutoProp<int> BonusAttack => _bonusAttack;
|
||||||
|
public IAutoProp<int> CurrentDefense => _currentDefense;
|
||||||
|
public IAutoProp<int> MaxDefense => _maxDefense;
|
||||||
|
public IAutoProp<int> BonusDefense => _bonusDefense;
|
||||||
|
public IAutoProp<int> CurrentExp => _currentExp;
|
||||||
|
public IAutoProp<int> ExpToNextLevel => _expToNextLevel;
|
||||||
|
public IAutoProp<int> CurrentLevel => _currentLevel;
|
||||||
public IAutoProp<double> Luck => _luck;
|
public IAutoProp<double> Luck => _luck;
|
||||||
|
|
||||||
public void SetCurrentHP(int newValue)
|
public void SetCurrentHP(int newValue)
|
||||||
@@ -97,18 +135,18 @@ public partial record PlayerStats
|
|||||||
_luck.OnNext(clampedValue);
|
_luck.OnNext(clampedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly AutoProp<int> _currentHP = new(int.MaxValue);
|
private readonly AutoProp<int> _currentHP = new(-1);
|
||||||
private readonly AutoProp<int> _maximumHP = new(int.MaxValue);
|
private readonly AutoProp<int> _maximumHP = new(-1);
|
||||||
private readonly AutoProp<int> _currentVT = new(int.MaxValue);
|
private readonly AutoProp<int> _currentVT = new(-1);
|
||||||
private readonly AutoProp<int> _maximumVT = new(int.MaxValue);
|
private readonly AutoProp<int> _maximumVT = new(-1);
|
||||||
private readonly AutoProp<int> _currentExp = new(int.MaxValue);
|
private readonly AutoProp<int> _currentExp = new(-1);
|
||||||
private readonly AutoProp<int> _currentLevel = new(int.MaxValue);
|
private readonly AutoProp<int> _currentLevel = new(-1);
|
||||||
private readonly AutoProp<int> _currentAttack = new(int.MaxValue);
|
private readonly AutoProp<int> _currentAttack = new(-1);
|
||||||
private readonly AutoProp<int> _bonusAttack = new(int.MaxValue);
|
private readonly AutoProp<int> _bonusAttack = new(-1);
|
||||||
private readonly AutoProp<int> _maxAttack = new(int.MaxValue);
|
private readonly AutoProp<int> _maxAttack = new(-1);
|
||||||
private readonly AutoProp<int> _currentDefense = new(int.MaxValue);
|
private readonly AutoProp<int> _currentDefense = new(-1);
|
||||||
private readonly AutoProp<int> _bonusDefense = new(int.MaxValue);
|
private readonly AutoProp<int> _bonusDefense = new(-1);
|
||||||
private readonly AutoProp<int> _maxDefense = new(int.MaxValue);
|
private readonly AutoProp<int> _maxDefense = new(-1);
|
||||||
private readonly AutoProp<int> _expToNextLevel = new(int.MaxValue);
|
private readonly AutoProp<int> _expToNextLevel = new(-1);
|
||||||
private readonly AutoProp<double> _luck = new(double.MaxValue);
|
private readonly AutoProp<double> _luck = new(-1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user