Throwable item rework, increase health on timer timeout, add boss 1 model

This commit is contained in:
2024-09-22 23:05:33 -07:00
parent f490a390aa
commit 59390c04bf
44 changed files with 3373 additions and 101 deletions

View File

@@ -113,13 +113,13 @@ public partial class Enemy : RigidBody3D, IEnemy, IProvide<IEnemyLogic>
var roll = rng.Randf(); var roll = rng.Randf();
if (roll <= EnemyStatResource.Luck) if (roll <= EnemyStatResource.Luck)
isCriticalHit = true; isCriticalHit = true;
var damage = DamageCalculator.CalculateEnemyDamage( var damage = DamageCalculator.CalculateEnemyAttackDamage(
GameRepo.PlayerData.CurrentDefense.Value + GameRepo.PlayerData.BonusDefense, GameRepo.PlayerData.CurrentDefense.Value + GameRepo.PlayerData.BonusDefense,
EnemyStatResource, EnemyStatResource,
GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats, GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats,
isCriticalHit); isCriticalHit);
GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - Mathf.RoundToInt(damage)); GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - Mathf.RoundToInt(damage));
GD.Print($"Player hit for {Mathf.Abs(damage)} damage."); GD.Print($"Player hit for {damage} damage.");
} }
} }
@@ -215,7 +215,7 @@ public partial class Enemy : RigidBody3D, IEnemy, IProvide<IEnemyLogic>
var roll = rng.Randf(); var roll = rng.Randf();
if (roll <= GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.Luck) if (roll <= GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.Luck)
isCriticalHit = true; isCriticalHit = true;
var damage = DamageCalculator.CalculatePlayerDamage(GameRepo.PlayerData.CurrentAttack.Value + GameRepo.PlayerData.BonusAttack, EnemyStatResource, GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats, isCriticalHit); var damage = DamageCalculator.CalculateWeaponAttackDamage(GameRepo.PlayerData.CurrentAttack.Value + GameRepo.PlayerData.BonusAttack, EnemyStatResource, GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats, isCriticalHit);
GD.Print($"Enemy Hit for {damage} damage."); GD.Print($"Enemy Hit for {damage} damage.");
EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(damage)); EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(damage));
} }

View File

@@ -0,0 +1,36 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://bamlwgrtgygso"
path="res://.godot/imported/horse head attacks.glb-dcab1d965104e14cbd195cba15abf21b.scn"
[deps]
source_file="res://src/enemy/enemy_types/horse_head/horse head attacks.glb"
dest_files=["res://.godot/imported/horse head attacks.glb-dcab1d965104e14cbd195cba15abf21b.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://uwtl4o2wwqop"
path="res://.godot/imported/horse head attacks_Metal054C_1K-JPG_Color.jpg-81ed1056b036ba0c8f4f3ae2c23e2d32.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "a736e2bfd0819e969c4fbfc879bc7b02"
}
[deps]
source_file="res://src/enemy/enemy_types/horse_head/horse head attacks_Metal054C_1K-JPG_Color.jpg"
dest_files=["res://.godot/imported/horse head attacks_Metal054C_1K-JPG_Color.jpg-81ed1056b036ba0c8f4f3ae2c23e2d32.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cvxu5y3mjekav"
path="res://.godot/imported/horse head attacks_Metal054C_1K-JPG_Displacement.jpg-17a0c7fc80435a64564a9d490002bc28.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "ebbb46c4f552a8b17e6801dc6b95714a"
}
[deps]
source_file="res://src/enemy/enemy_types/horse_head/horse head attacks_Metal054C_1K-JPG_Displacement.jpg"
dest_files=["res://.godot/imported/horse head attacks_Metal054C_1K-JPG_Displacement.jpg-17a0c7fc80435a64564a9d490002bc28.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://src/enemy/enemy_types/horse_head/horse head attacks_Metal054C_1K-JPG_Displacement.jpg"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@@ -0,0 +1,36 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://hmpprwcxrg33"
path="res://.godot/imported/horse head walking.glb-b2312d1734249989e72a119030aaad46.scn"
[deps]
source_file="res://src/enemy/enemy_types/horse_head/horse head walking.glb"
dest_files=["res://.godot/imported/horse head walking.glb-b2312d1734249989e72a119030aaad46.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c3ex6glkhqjo4"
path="res://.godot/imported/horse head walking_Metal054C_1K-JPG_Color.jpg-d93af1df2a02d1bbdb524e4ae77d9857.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "a736e2bfd0819e969c4fbfc879bc7b02"
}
[deps]
source_file="res://src/enemy/enemy_types/horse_head/horse head walking_Metal054C_1K-JPG_Color.jpg"
dest_files=["res://.godot/imported/horse head walking_Metal054C_1K-JPG_Color.jpg-d93af1df2a02d1bbdb524e4ae77d9857.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://vid8c7jc38iv"
path="res://.godot/imported/horse head walking_Metal054C_1K-JPG_Displacement.jpg-4b12d030c2ad62e11e4222398953eec4.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "ebbb46c4f552a8b17e6801dc6b95714a"
}
[deps]
source_file="res://src/enemy/enemy_types/horse_head/horse head walking_Metal054C_1K-JPG_Displacement.jpg"
dest_files=["res://.godot/imported/horse head walking_Metal054C_1K-JPG_Displacement.jpg-4b12d030c2ad62e11e4222398953eec4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://src/enemy/enemy_types/horse_head/horse head walking_Metal054C_1K-JPG_Displacement.jpg"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1,36 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cdq4rvhqft640"
path="res://.godot/imported/OX FACE.glb-b27382349eff512c89ebca6e162115f7.scn"
[deps]
source_file="res://src/enemy/enemy_types/ox_face/models/OX FACE.glb"
dest_files=["res://.godot/imported/OX FACE.glb-b27382349eff512c89ebca6e162115f7.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dp6hwvuhfkji8"
path="res://.godot/imported/OX FACE_Metal054C_1K-JPG_Color.jpg-8bddebd2df83eb42a2ee74051fa85f33.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "a736e2bfd0819e969c4fbfc879bc7b02"
}
[deps]
source_file="res://src/enemy/enemy_types/ox_face/models/OX FACE_Metal054C_1K-JPG_Color.jpg"
dest_files=["res://.godot/imported/OX FACE_Metal054C_1K-JPG_Color.jpg-8bddebd2df83eb42a2ee74051fa85f33.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cqmo71mabu36n"
path="res://.godot/imported/OX FACE_Metal054C_1K-JPG_Displacement.jpg-2ec0133b274445c2689ea63d31ffc6fb.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "ebbb46c4f552a8b17e6801dc6b95714a"
}
[deps]
source_file="res://src/enemy/enemy_types/ox_face/models/OX FACE_Metal054C_1K-JPG_Displacement.jpg"
dest_files=["res://.godot/imported/OX FACE_Metal054C_1K-JPG_Displacement.jpg-2ec0133b274445c2689ea63d31ffc6fb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://src/enemy/enemy_types/ox_face/models/OX FACE_Metal054C_1K-JPG_Displacement.jpg"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@@ -0,0 +1,36 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cf867ubrd5pg8"
path="res://.godot/imported/OX FACE_STATUE.glb-9f5768fc43d629e96ce935b81706de73.scn"
[deps]
source_file="res://src/enemy/enemy_types/ox_face/models/OX FACE_STATUE.glb"
dest_files=["res://.godot/imported/OX FACE_STATUE.glb-9f5768fc43d629e96ce935b81706de73.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bk1x0b0drkucu"
path="res://.godot/imported/OX FACE_STATUE_Metal054C_1K-JPG_Color.jpg-db1c37803655e45a527c8ac19fd5b348.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "a736e2bfd0819e969c4fbfc879bc7b02"
}
[deps]
source_file="res://src/enemy/enemy_types/ox_face/models/OX FACE_STATUE_Metal054C_1K-JPG_Color.jpg"
dest_files=["res://.godot/imported/OX FACE_STATUE_Metal054C_1K-JPG_Color.jpg-db1c37803655e45a527c8ac19fd5b348.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ctr67j567n5an"
path="res://.godot/imported/OX FACE_STATUE_Metal054C_1K-JPG_Displacement.jpg-9be59a0cfb6bfcbc26f3d1553dd90281.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "ebbb46c4f552a8b17e6801dc6b95714a"
}
[deps]
source_file="res://src/enemy/enemy_types/ox_face/models/OX FACE_STATUE_Metal054C_1K-JPG_Displacement.jpg"
dest_files=["res://.godot/imported/OX FACE_STATUE_Metal054C_1K-JPG_Displacement.jpg-9be59a0cfb6bfcbc26f3d1553dd90281.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://src/enemy/enemy_types/ox_face/models/OX FACE_STATUE_Metal054C_1K-JPG_Displacement.jpg"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

File diff suppressed because one or more lines are too long

View File

@@ -25,7 +25,7 @@ public partial class EnemyLogic
var lookAtPosition = new Vector3(lookAtDir.X, enemy.GlobalPosition.Y, lookAtDir.Z); var lookAtPosition = new Vector3(lookAtDir.X, enemy.GlobalPosition.Y, lookAtDir.Z);
if (!velocity.IsEqualApprox(Vector3.Zero) && !enemy.GlobalPosition.IsEqualApprox(lookAtPosition)) if (!velocity.IsEqualApprox(Vector3.Zero) && !enemy.GlobalPosition.IsEqualApprox(lookAtPosition))
enemy.LookAt(new Vector3(lookAtDir.X, enemy.GlobalPosition.Y, lookAtDir.Z)); enemy.LookAt(lookAtPosition);
Output(new Output.MovementComputed(velocity)); Output(new Output.MovementComputed(velocity));
return ToSelf(); return ToSelf();

View File

@@ -15,6 +15,12 @@ public interface IGame : IProvide<IGameRepo>, IProvide<IGameEventDepot>, IProvid
public void DropItem(IInventoryItem item); public void DropItem(IInventoryItem item);
public void ThrowItem(IInventoryItem item); public void ThrowItem(IInventoryItem item);
public void HealHP(int amountToRaise);
public void RaiseHP(int amountToRaise);
public void HealVT(int amountToRaise);
public void RaiseVT(int amountToRaise);
} }
[Meta(typeof(IAutoNode))] [Meta(typeof(IAutoNode))]
@@ -220,22 +226,26 @@ public partial class Game : Node3D, IGame
private void GameEventDepot_RestorativePickedUp(Restorative obj) => GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.CurrentVT.Value + obj.VTRestoreAmount); private void GameEventDepot_RestorativePickedUp(Restorative obj) => GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.CurrentVT.Value + obj.VTRestoreAmount);
private void Inventory_RaiseStatRequest(ConsumableItemStats consumableItemStats) private void Inventory_RaiseStatRequest(InventoryItemStats itemStats)
{ {
if (consumableItemStats.RaiseHPAmount > 0 && GameRepo.PlayerData.CurrentHP.Value.Equals(GameRepo.PlayerData.MaximumHP.Value)) //if (itemStats.RaiseHPAmount > 0 && GameRepo.PlayerData.CurrentHP.Value.Equals(GameRepo.PlayerData.MaximumHP.Value))
RaiseHP(consumableItemStats.RaiseHPAmount); // RaiseHP(itemStats.RaiseHPAmount);
else if (consumableItemStats.HealHPAmount > 0) //else if (itemStats.HealHPAmount > 0)
HealHP(consumableItemStats.HealHPAmount); HealHP(itemStats.HealHPAmount);
HealVT(itemStats.HealVTAmount);
if (consumableItemStats.RaiseVTAmount > 0 && GameRepo.PlayerData.CurrentVT.Value.Equals(GameRepo.PlayerData.MaximumVT.Value)) //if (itemStats.RaiseVTAmount > 0 && GameRepo.PlayerData.CurrentVT.Value.Equals(GameRepo.PlayerData.MaximumVT.Value))
RaiseVT(consumableItemStats.RaiseVTAmount); // RaiseVT(itemStats.RaiseVTAmount);
else if (consumableItemStats.HealVTAmount > 0) //else if (itemStats.HealVTAmount > 0)
HealVT(consumableItemStats.HealVTAmount);
GameEventDepot.OnHealingItemConsumed(consumableItemStats);
} }
private void RaiseHP(int amountToRaise) private void SetPauseMode(bool isPaused)
{
if (GetTree() != null)
GetTree().Paused = isPaused;
}
public void RaiseHP(int amountToRaise)
{ {
if (GameRepo.PlayerData.CurrentHP.Value == GameRepo.PlayerData.MaximumHP.Value) if (GameRepo.PlayerData.CurrentHP.Value == GameRepo.PlayerData.MaximumHP.Value)
{ {
@@ -245,20 +255,14 @@ public partial class Game : Node3D, IGame
} }
} }
private void SetPauseMode(bool isPaused) public void HealHP(int amountToRaise)
{
if (GetTree() != null)
GetTree().Paused = isPaused;
}
private void HealHP(int amountToRaise)
{ {
GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value + amountToRaise); GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value + amountToRaise);
var raiseString = amountToRaise == 1000 ? "MAX" : $"{amountToRaise}"; var raiseString = amountToRaise == 1000 ? "MAX" : $"{amountToRaise}";
EmitSignal(SignalName.StatRaisedAlert, $"{raiseString}HP Restored."); EmitSignal(SignalName.StatRaisedAlert, $"{raiseString}HP Restored.");
} }
private void RaiseVT(int amountToRaise) public void RaiseVT(int amountToRaise)
{ {
if (GameRepo.PlayerData.CurrentVT.Value == GameRepo.PlayerData.MaximumVT.Value) if (GameRepo.PlayerData.CurrentVT.Value == GameRepo.PlayerData.MaximumVT.Value)
{ {
@@ -268,7 +272,7 @@ public partial class Game : Node3D, IGame
} }
} }
private void HealVT(int amountToRaise) public void HealVT(int amountToRaise)
{ {
GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.CurrentVT.Value + amountToRaise); GameRepo.PlayerData.SetCurrentVT(GameRepo.PlayerData.CurrentVT.Value + amountToRaise);
var raiseString = amountToRaise == 1000 ? "MAX" : $"{amountToRaise}"; var raiseString = amountToRaise == 1000 ? "MAX" : $"{amountToRaise}";

View File

@@ -397,9 +397,9 @@ public partial class InventoryMenu : Control, IInventoryMenu
var currentItem = ItemSlots[_currentIndex].Item; var currentItem = ItemSlots[_currentIndex].Item;
if (currentItem is IEquipableItem) if (currentItem is IEquipableItem)
await EquipOrUnequipItem(); await EquipOrUnequipItem();
else if (currentItem is IUsableItem usable) else if (currentItem is IUsableItem usableItem)
{ {
usable.Use(); usableItem.Use();
if (_currentIndex >= ItemSlots.Length - 1) if (_currentIndex >= ItemSlots.Length - 1)
_currentIndex--; _currentIndex--;
if (_currentIndex <= 0) if (_currentIndex <= 0)

View File

@@ -32,8 +32,6 @@ public interface IInventory : INode
event Inventory.InventoryAtCapacityEventHandler InventoryAtCapacity; event Inventory.InventoryAtCapacityEventHandler InventoryAtCapacity;
event Inventory.AccessoryUnequippedEventHandler AccessoryUnequipped; event Inventory.AccessoryUnequippedEventHandler AccessoryUnequipped;
event Inventory.RaiseStatRequestEventHandler RaiseStatRequest;
} }
public partial class Inventory : Node, IInventory public partial class Inventory : Node, IInventory

View File

@@ -14,5 +14,15 @@ public partial class InventoryItemStats : Resource
[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;
public float ThrowSpeed { get; set; } = 7.0f; [Export(PropertyHint.Range, "0, 25, 0.1")]
public float ThrowSpeed { get; set; } = 12.0f;
[Export(PropertyHint.Range, "0, 999, 1")]
public int HealHPAmount { get; set; }
[Export(PropertyHint.Range, "0, 999, 1")]
public int HealVTAmount { get; set; }
[Export(PropertyHint.Range, "0, 999, 1")]
public int ThrowDamage { get; set; } = 5;
} }

View File

@@ -9,6 +9,9 @@ public partial class ConsumableItem : Node3D, IUsableItem
{ {
public override void _Notification(int what) => this.Notify(what); public override void _Notification(int what) => this.Notify(what);
[Signal]
public delegate void RaiseStatRequestEventHandler(ConsumableItemStats consumableItemStats);
[Dependency] public IGame Game => this.DependOn<IGame>(); [Dependency] public IGame Game => this.DependOn<IGame>();
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>(); [Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
[Dependency] public IGameEventDepot GameEventDepot => this.DependOn<IGameEventDepot>(); [Dependency] public IGameEventDepot GameEventDepot => this.DependOn<IGameEventDepot>();
@@ -26,17 +29,15 @@ public partial class ConsumableItem : Node3D, IUsableItem
public void Use() public void Use()
{ {
GameEventDepot.OnHealingItemConsumed(ConsumableItemInfo); if (ConsumableItemInfo.RaiseHPAmount > 0)
} Game.RaiseHP(ConsumableItemInfo.RaiseHPAmount);
if (ConsumableItemInfo.RaiseVTAmount > 0)
Game.RaiseVT(ConsumableItemInfo.RaiseVTAmount);
public void Throw() if (ConsumableItemInfo.HealHPAmount > 0)
{ Game.HealHP(ConsumableItemInfo.HealHPAmount);
var throwableScene = GD.Load<PackedScene>("res://src/items/thrown/ThrownItem.tscn"); if (ConsumableItemInfo.HealVTAmount > 0)
var throwable = throwableScene.Instantiate<ThrownItem>(); Game.HealVT(ConsumableItemInfo.HealVTAmount);
throwable.ThrownItemStats = ConsumableItemInfo;
Game.AddChild(throwable);
throwable.Throw();
GameRepo.PlayerData.Inventory.Remove(this);
} }
public void OnReady() public void OnReady()

View File

@@ -5,15 +5,9 @@ namespace GameJamDungeon;
[GlobalClass] [GlobalClass]
public partial class ConsumableItemStats : InventoryItemStats public partial class ConsumableItemStats : InventoryItemStats
{ {
[Export]
public int HealHPAmount { get; set; } = 0;
[Export] [Export]
public int RaiseHPAmount { get; set; } = 0; public int RaiseHPAmount { get; set; } = 0;
[Export]
public int HealVTAmount { get; set; } = 0;
[Export] [Export]
public int RaiseVTAmount { get; set; } = 0; public int RaiseVTAmount { get; set; } = 0;
} }

View File

@@ -5,7 +5,7 @@ using Godot;
using System; using System;
[Meta(typeof(IAutoNode))] [Meta(typeof(IAutoNode))]
public partial class ThrowableItem : Node3D, IInventoryItem public partial class ThrowableItem : Node3D, IUsableItem
{ {
public override void _Notification(int what) => this.Notify(what); public override void _Notification(int what) => this.Notify(what);
@@ -32,6 +32,14 @@ public partial class ThrowableItem : Node3D, IInventoryItem
Pickup.BodyEntered += OnEntered; Pickup.BodyEntered += OnEntered;
} }
public void Use()
{
if (ThrowableItemInfo.HealHPAmount > 0)
Game.HealHP(ThrowableItemInfo.HealHPAmount);
if (ThrowableItemInfo.HealVTAmount > 0)
Game.HealVT(ThrowableItemInfo.HealVTAmount);
}
public void OnEntered(Node3D body) public void OnEntered(Node3D body)
{ {
var isAdded = GameRepo.PlayerData.Inventory.TryAdd(this); var isAdded = GameRepo.PlayerData.Inventory.TryAdd(this);

View File

@@ -5,9 +5,6 @@ namespace GameJamDungeon;
[GlobalClass] [GlobalClass]
public partial class ThrowableItemStats : InventoryItemStats public partial class ThrowableItemStats : InventoryItemStats
{ {
[Export]
public int Damage { get; set; } = 0;
[Export] [Export]
public Godot.Collections.Array<ThrowableItemTag> ThrowableItemTags { get; set; } = new Godot.Collections.Array<ThrowableItemTag>(); public Godot.Collections.Array<ThrowableItemTag> ThrowableItemTags { get; set; } = new Godot.Collections.Array<ThrowableItemTag>();
} }

View File

@@ -5,13 +5,27 @@
InflictHydricDamage, InflictHydricDamage,
InflictIgneousDamage, InflictIgneousDamage,
InflictFerrumDamage, InflictFerrumDamage,
LowerTargetTo1HP,
}
public enum UsableItemTag
{
DoubleEXP, DoubleEXP,
RandomWarp, RandomWarp,
LowerTargetTo1HP,
IdentifyAllItemsCostHP, IdentifyAllItemsCostHP,
BriefImmunity,
WarpToExitIfFound, WarpToExitIfFound,
RandomNewItem, }
BasicItem,
public enum EnhancingItemTag
{
Add1ATK,
Add1DEF,
RaiseLevelBy1,
}
public enum EffectorItemTag
{
SwapHPandVTWithEntitiesInRoom, SwapHPandVTWithEntitiesInRoom,
TeleportAllEnemiesToRoom, TeleportAllEnemiesToRoom,
TurnAllEnemiesIntoHealingItem, TurnAllEnemiesIntoHealingItem,
@@ -19,8 +33,9 @@
AbsorbHPFromAllEnemiesInRoom, AbsorbHPFromAllEnemiesInRoom,
HealsAllInRoomToMaxHP, HealsAllInRoomToMaxHP,
RandomEffect, RandomEffect,
Add1ATK, }
Add1DEF,
RaiseLevelBy1, public enum BoxItemTag
BriefImmunity {
RandomNewItem,
} }

View File

@@ -5,9 +5,12 @@
[resource] [resource]
script = ExtResource("1_ewck5") script = ExtResource("1_ewck5")
Damage = 0
ThrowableItemTags = [] ThrowableItemTags = []
Name = "Geomantic Dice" Name = "Geomantic Dice"
Description = "Inflicts Affinity damage when thrown." Description = "Inflicts Affinity damage when thrown."
Texture = ExtResource("1_jhits") Texture = ExtResource("1_jhits")
SpawnRate = 0.1 SpawnRate = 0.1
ThrowSpeed = 20.0
HealHPAmount = 0
HealVTAmount = 0
ThrowDamage = 20

View File

@@ -17,7 +17,7 @@ public partial class ThrownItem : RigidBody3D
public void OnResolved() public void OnResolved()
{ {
BodyEntered += ThrownItem_BodyEntered; BodyEntered += ThrownItem_BodyEntered;
GlobalPosition = Game.Player.GlobalPosition + new Vector3(0, 1f, 0); GlobalPosition = Game.Player.GlobalPosition + new Vector3(0, 1.5f, 0);
Sprite.Texture = ThrownItemStats.Texture; Sprite.Texture = ThrownItemStats.Texture;
AddCollisionExceptionWith((Node)Game.Player); AddCollisionExceptionWith((Node)Game.Player);
} }
@@ -26,39 +26,26 @@ public partial class ThrownItem : RigidBody3D
{ {
if (body is IEnemy enemy) if (body is IEnemy enemy)
{ {
if (ThrownItemStats is ThrowableItemStats throwableItemStats) CalculateEffect(enemy);
enemy.EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(throwableItemStats.Damage));
} }
QueueFree(); QueueFree();
} }
public void Throw() public void Throw()
{ {
ThrowInternal((dynamic)ThrownItemStats); ApplyCentralImpulse(-Game.Player.GlobalBasis.Z.Normalized() * ThrownItemStats.ThrowSpeed);
} }
private void ThrowInternal(WeaponStats weaponStats) private void CalculateEffect(IEnemy enemy)
{ {
ApplyCentralImpulse(-Game.Player.GlobalBasis.Z.Normalized() * 12.0f); enemy.EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(ThrownItemStats.ThrowDamage));
}
private void ThrowInternal(ArmorStats armorStats) if (ThrownItemStats is ThrowableItemStats throwableItemStats)
{ {
ApplyCentralImpulse(-Game.Player.GlobalBasis.Z.Normalized() * 12.0f); if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.LowerTargetTo1HP))
} enemy.EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(enemy.CurrentHP.Value - 1));
enemy.EnemyLogic.Input(new EnemyLogic.Input.HitByPlayer(DamageCalculator.CalculateThrownItemDamage(throwableItemStats.ThrowDamage, enemy.EnemyStatResource, throwableItemStats)));
private void ThrowInternal(AccessoryStats accessoryStats) }
{
ApplyCentralImpulse(-Game.Player.GlobalBasis.Z.Normalized() * 12.0f);
}
private void ThrowInternal(ConsumableItemStats consumableItemStats)
{
ApplyCentralImpulse(-Game.Player.GlobalBasis.Z.Normalized() * 12.0f);
}
private void ThrowInternal(ThrowableItemStats throwableItemStats)
{
ApplyCentralImpulse(-Game.Player.GlobalBasis.Z.Normalized() * 20.0f);
} }
} }

View File

@@ -4,7 +4,7 @@
[ext_resource type="Texture2D" uid="uid://mi70lolgtf3n" path="res://src/items/throwable/textures/GEOMANCER-DICE.png" id="2_alcjn"] [ext_resource type="Texture2D" uid="uid://mi70lolgtf3n" path="res://src/items/throwable/textures/GEOMANCER-DICE.png" id="2_alcjn"]
[sub_resource type="BoxShape3D" id="BoxShape3D_s4ym5"] [sub_resource type="BoxShape3D" id="BoxShape3D_s4ym5"]
size = Vector3(0.884321, 0.999205, 1.52861) size = Vector3(0.46632, 0.507293, 0.586082)
[node name="Hitbox" type="RigidBody3D"] [node name="Hitbox" type="RigidBody3D"]
collision_layer = 16 collision_layer = 16
@@ -15,7 +15,7 @@ max_contacts_reported = 50
script = ExtResource("1_wlplc") script = ExtResource("1_wlplc")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."] [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0347672, 0.152068, 0.118644) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.129255, 0.162556, 0.00695503)
shape = SubResource("BoxShape3D_s4ym5") shape = SubResource("BoxShape3D_s4ym5")
[node name="Sprite" type="Sprite3D" parent="."] [node name="Sprite" type="Sprite3D" parent="."]

View File

@@ -244,7 +244,10 @@ namespace GameJamDungeon
private void OnHealthTimerTimeout() private void OnHealthTimerTimeout()
{ {
if (PlayerData.CurrentVT.Value > 0) if (PlayerData.CurrentVT.Value > 0)
{
PlayerData.SetCurrentVT(PlayerData.CurrentVT.Value - 1); PlayerData.SetCurrentVT(PlayerData.CurrentVT.Value - 1);
PlayerData.SetCurrentHP(PlayerData.CurrentHP.Value + 1);
}
else else
PlayerData.SetCurrentHP(PlayerData.CurrentHP.Value - 1); PlayerData.SetCurrentHP(PlayerData.CurrentHP.Value - 1);
} }
@@ -278,7 +281,7 @@ namespace GameJamDungeon
var roll = rng.Randf(); var roll = rng.Randf();
if (roll <= enemy.EnemyStatResource.Luck) if (roll <= enemy.EnemyStatResource.Luck)
isCriticalHit = true; isCriticalHit = true;
var damage = DamageCalculator.CalculateEnemyDamage(PlayerData.CurrentDefense.Value + PlayerData.BonusDefense, enemy.EnemyStatResource, GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats, isCriticalHit); var damage = DamageCalculator.CalculateEnemyAttackDamage(PlayerData.CurrentDefense.Value + PlayerData.BonusDefense, enemy.EnemyStatResource, GameRepo.PlayerData.Inventory.EquippedArmor.Value.ArmorStats, isCriticalHit);
PlayerData.SetCurrentHP(PlayerData.CurrentHP.Value - Mathf.RoundToInt(damage)); PlayerData.SetCurrentHP(PlayerData.CurrentHP.Value - Mathf.RoundToInt(damage));
GD.Print($"Player hit for {damage} damage."); GD.Print($"Player hit for {damage} damage.");
} }

View File

@@ -4,13 +4,13 @@ namespace GameJamDungeon
{ {
public static class DamageCalculator public static class DamageCalculator
{ {
public static double CalculatePlayerDamage(int totalAttack, EnemyStatResource enemyStatInfo, WeaponStats weapon, bool isCriticalHit) public static double CalculateWeaponAttackDamage(int totalAttack, EnemyStatResource enemyStatResource, WeaponStats weapon, bool isCriticalHit)
{ {
var hydricResistance = enemyStatInfo.HydricResistance; var hydricResistance = enemyStatResource.HydricResistance;
var igneousResistance = enemyStatInfo.IgneousResistance; var igneousResistance = enemyStatResource.IgneousResistance;
var telluricResistance = enemyStatInfo.TelluricResistance; var telluricResistance = enemyStatResource.TelluricResistance;
var aeolicResistance = enemyStatInfo.AeolicResistance; var aeolicResistance = enemyStatResource.AeolicResistance;
var ferrumResistance = enemyStatInfo.FerrumResistance; var ferrumResistance = enemyStatResource.FerrumResistance;
if (weapon.WeaponTags.Contains(WeaponTag.IgnoreAffinity)) if (weapon.WeaponTags.Contains(WeaponTag.IgnoreAffinity))
{ {
@@ -27,29 +27,45 @@ namespace GameJamDungeon
var elementDDamage = (weapon.AeolicDamageBonus > 0 ? weapon.AeolicDamageBonus - aeolicResistance : 0) / 100; var elementDDamage = (weapon.AeolicDamageBonus > 0 ? weapon.AeolicDamageBonus - aeolicResistance : 0) / 100;
var elementEDamage = (weapon.FerrumDamageBonus > 0 ? weapon.FerrumDamageBonus - ferrumResistance : 0) / 100; var elementEDamage = (weapon.FerrumDamageBonus > 0 ? weapon.FerrumDamageBonus - ferrumResistance : 0) / 100;
var elementalBonusDamage = totalAttack + (totalAttack * elementADamage) + (totalAttack * elementBDamage) + (totalAttack * elementCDamage) + (totalAttack * elementDDamage) + (totalAttack * elementEDamage); var elementalBonusDamage = totalAttack + (totalAttack * elementADamage) + (totalAttack * elementBDamage) + (totalAttack * elementCDamage) + (totalAttack * elementDDamage) + (totalAttack * elementEDamage);
var calculatedDamage = elementalBonusDamage - enemyStatInfo.CurrentDefense; var calculatedDamage = elementalBonusDamage - enemyStatResource.CurrentDefense;
if (isCriticalHit) if (isCriticalHit)
calculatedDamage *= 2; calculatedDamage *= 2;
return calculatedDamage; return Mathf.Max(calculatedDamage, 0.0);
} }
public static double CalculateEnemyDamage(int playerTotalDefense, EnemyStatResource enemyStatInfo, ArmorStats armor, bool isCriticalHit) public static double CalculateEnemyAttackDamage(int playerTotalDefense, EnemyStatResource enemyStatResource, ArmorStats armor, bool isCriticalHit)
{ {
var totalAttack = enemyStatInfo.CurrentAttack; var totalAttack = enemyStatResource.CurrentAttack;
var elementADamage = (enemyStatInfo.BaseHydricDamageBonus > 0 ? enemyStatInfo.BaseHydricDamageBonus - armor.HydricResistance : 0) / 100; var elementADamage = (enemyStatResource.BaseHydricDamageBonus > 0 ? enemyStatResource.BaseHydricDamageBonus - armor.HydricResistance : 0) / 100;
var elementBDamage = (enemyStatInfo.IgneousDamageBonus > 0 ? enemyStatInfo.IgneousDamageBonus - armor.IgneousResistance : 0) / 100; var elementBDamage = (enemyStatResource.IgneousDamageBonus > 0 ? enemyStatResource.IgneousDamageBonus - armor.IgneousResistance : 0) / 100;
var elementCDamage = (enemyStatInfo.TelluricDamageBonus > 0 ? enemyStatInfo.TelluricDamageBonus - armor.TelluricResistance : 0) / 100; var elementCDamage = (enemyStatResource.TelluricDamageBonus > 0 ? enemyStatResource.TelluricDamageBonus - armor.TelluricResistance : 0) / 100;
var elementDDamage = (enemyStatInfo.AeolicDamageBonus > 0 ? enemyStatInfo.AeolicDamageBonus - armor.AeolicResistance : 0) / 100; var elementDDamage = (enemyStatResource.AeolicDamageBonus > 0 ? enemyStatResource.AeolicDamageBonus - armor.AeolicResistance : 0) / 100;
var elementEDamage = (enemyStatInfo.FerrumDamageBonus > 0 ? enemyStatInfo.FerrumDamageBonus - armor.FerrumResistance : 0) / 100; var elementEDamage = (enemyStatResource.FerrumDamageBonus > 0 ? enemyStatResource.FerrumDamageBonus - armor.FerrumResistance : 0) / 100;
var elementalBonusDamage = totalAttack + (totalAttack * elementADamage) + (totalAttack * elementBDamage) + (totalAttack * elementCDamage) + (totalAttack * elementDDamage) + (totalAttack * elementEDamage); var elementalBonusDamage = totalAttack + (totalAttack * elementADamage) + (totalAttack * elementBDamage) + (totalAttack * elementCDamage) + (totalAttack * elementDDamage) + (totalAttack * elementEDamage);
var calculatedDamage = elementalBonusDamage - playerTotalDefense - (armor != null ? armor.Defense : 0); var calculatedDamage = elementalBonusDamage - playerTotalDefense - (armor != null ? armor.Defense : 0);
if (isCriticalHit) if (isCriticalHit)
calculatedDamage *= 2; calculatedDamage *= 2;
return calculatedDamage; return Mathf.Max(calculatedDamage, 0.0);
}
public static double CalculateThrownItemDamage(int baseThrowDamage, EnemyStatResource enemyStatResource, ThrowableItemStats throwableItemStats)
{
if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictAeolicDamage))
return Mathf.Max(baseThrowDamage * enemyStatResource.AeolicResistance, 0.0);
if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictFerrumDamage))
return Mathf.Max(baseThrowDamage * enemyStatResource.FerrumResistance, 0.0);
if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictHydricDamage))
return Mathf.Max(baseThrowDamage * enemyStatResource.HydricResistance, 0.0);
if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictIgneousDamage))
return Mathf.Max(baseThrowDamage * enemyStatResource.IgneousResistance, 0.0);
if (throwableItemStats.ThrowableItemTags.Contains(ThrowableItemTag.InflictTelluricDamage))
return Mathf.Max(baseThrowDamage * enemyStatResource.TelluricResistance, 0.0);
return Mathf.Max(baseThrowDamage, 0.0);
} }
} }
} }