Compare commits

..

109 Commits

Author SHA1 Message Date
34c125e6bb no message 2026-02-15 01:14:09 -08:00
66905c9b53 Overhaul 2026-02-15 01:06:46 -08:00
Pal
a1f4a29eb3 Mask of Zeal, Mask Placeholder, Health Item Placeholder, VT pickup animation added. Temp Environment added to Final Floor. 2026-02-15 00:57:19 -08:00
a6ea1b1873 laptop 2026-02-14 19:26:33 -08:00
Pal
47ceb2f613 Remove E, fix UI, Altar scale better 2026-02-14 16:49:16 -08:00
bf6b0d50c3 Additional in progress changes 2026-02-13 23:39:49 -08:00
c7603a163f Revert "update"
This reverts commit fe0241ac88.
2026-02-13 16:33:44 -08:00
a20c80d922 Remaining changes 2026-02-13 16:33:30 -08:00
e14007b7f4 Merge branch 'main' into item_changes 2026-02-13 16:24:40 -08:00
b17c134c9a Add debug info folder that got filtered by git 2026-02-13 16:12:34 -08:00
fe0241ac88 update 2026-02-13 16:11:38 -08:00
0ab6ef1343 In progress item changes 2026-02-13 15:59:10 -08:00
Pal
638946d23a UI Mockup Ver.2 With Correct Transparencies 2026-02-13 15:48:04 -08:00
Pal
b56668dcbe 3D Render Icons Wave 1 Added 2026-02-13 14:44:03 -08:00
d6faf8642a Fix up debug info overlay 2026-02-13 10:14:42 -08:00
68b1455c53 Fix restorative 2026-02-12 23:28:51 -08:00
9615e1e251 Audio fade 2026-02-12 22:42:18 -08:00
c755485855 Add sample Stele to overworld 2026-02-12 21:39:10 -08:00
d503413140 Fix up effect items
Fix up minimap
Add some debug info
2026-02-12 20:49:09 -08:00
Pal
ac31c3ae65 Deleted a bunch of unused files.
Added environment to A2 exit, deleted environment from other A2 rooms.
2026-02-12 20:43:52 -08:00
Pal
549040c339 Gaps Fixed, Overworld Visual Fixes, Some lighting and additions to block rooms, may have accidentally moved a folder but cant find which. 2026-02-12 20:17:13 -08:00
c246d8d654 Fix crit calculation and bonus attack/def/luck 2026-02-12 02:58:30 -08:00
b475df6f68 Implement most jewels 2026-02-12 02:36:25 -08:00
230b47061d Add item spawn menu
Fix game over bug
Start adding more implementation for jewels
2026-02-11 15:25:20 -08:00
8ce38c3c13 Redesign and reimplement inventory menu
Add jewels but no implementation yet (needed redesign of inventory menu to function correctly)
2026-02-11 04:08:42 -08:00
5451f0b31f Persuader 2026-02-10 18:42:46 -08:00
92b4e8662f Add projectiles 2026-02-10 18:03:53 -08:00
2f377d2d7a Add curse element, increase throw speed/damage of Ciello 2026-02-10 15:37:12 -08:00
363ee1cd33 Turn more HQs on 2026-02-10 15:02:55 -08:00
97198afe18 Fix dropped/thrown item behavior 2026-02-10 14:57:41 -08:00
Pal
fdc4a6f2c1 Small Map Fixes 2026-02-10 01:55:56 -08:00
Pal
843a100218 Small Changes 2026-02-10 01:21:47 -08:00
Pal
8001556f37 Item Icons Wave 2 2026-02-10 00:49:15 -08:00
90d054a3c6 Clean up events, add weapon tag for weaker on swing 2026-02-09 23:50:15 -08:00
aba325ff2b Implement plasma sword instakill 2026-02-09 23:01:52 -08:00
bfaa324e6a Fix references and start more weapon tag implementation 2026-02-09 22:16:49 -08:00
f08c69fa10 Add weapons 2026-02-09 21:37:40 -08:00
9d6aa6d88d Update item icons 2026-02-09 21:05:45 -08:00
654e368a65 Fix exported project not loading issue 2026-02-09 20:24:48 -08:00
ce727b523a Change import settings for textures 2026-02-09 18:52:31 -08:00
Pal
6a474576f0 wave 1 of item icons
(cherry picked from commit 6355ffb26d)
2026-02-09 17:20:39 -08:00
8dd194a202 Fix level up, fix gallery room height, fix enemy heights, fix gospel of dimension spawn height, put minimap on right visual layer for some floors, add script to floor scene file 2026-02-06 03:24:34 -08:00
70a33d68cf Add navigation regions to all floors
Actually fix the annoying LookAt bug for real this time I hope
2026-02-06 00:00:22 -08:00
da8c4209d7 Fix annoying issue with LookAt
Add jump scare
2026-02-05 20:10:41 -08:00
c6fbc9f553 Rework dimmable audio stream 2026-02-05 14:45:28 -08:00
36b851254e Add collisions to A2 corridors
Start implementation of fading ambient audio in/out on level load
2026-02-05 14:17:45 -08:00
147f04d2ff Modify palm of heaven, remove random box item in altar 2026-02-05 10:52:13 -08:00
8ea881edb3 Item holy and all element implementation, still need to work out some of the math for it
Fix bonus defense for weapons
2026-02-05 10:48:24 -08:00
8a99771491 Add more boxes, implement weapon that gets stronger on lower HP 2026-02-04 23:51:07 -08:00
d45bc67722 Partially implementation of box items 2026-02-04 22:30:10 -08:00
13ebe54474 Fix some control issues 2026-02-04 02:34:23 -08:00
b9a1888bfc Add implementation for box item 2026-02-04 02:11:00 -08:00
5ae556cb4b Fix some broken stuff (player spawn, disabled input after loading next floor) 2026-02-04 02:04:04 -08:00
52dc8fb9e4 Box item implementation 2026-02-04 01:49:17 -08:00
affa5e1f79 Player step SFX pitch change 2026-02-03 22:15:02 -08:00
Pal
35a625f636 merge 2026-02-03 21:06:28 -08:00
Pal
d5de5f7379 player anim changes 2026-02-03 21:05:20 -08:00
3e6e21977e Fix Altar scaling 2026-02-03 20:52:14 -08:00
Pal
4a2d131276 Boss floor changes minor 2026-02-03 19:54:05 -08:00
Pal
d9c2ba7ed1 Added Memorial Steles, boss A floor visual polish, re-enabled overworld distance scenery 2026-02-03 04:18:25 -08:00
051ffbbcb1 Fix bug with Boss A (hit box didn't get scaled correctly)
Fix reset of death animation
2026-02-03 02:24:54 -08:00
9747d7d2c5 Revert boss floor environment lighting change 2026-02-03 02:04:21 -08:00
34dce8c5a2 Loading screen fixes, transition screen UI fixes 2026-02-03 01:47:42 -08:00
51010c4f7d Fix overworld collisions 2026-02-03 00:34:19 -08:00
fd96eb2dc9 Fix minimap height
Rework boss code to separate boss A concerns from demon wall
2026-02-02 23:24:48 -08:00
51c8f26e50 Minor fixes for NPC dialogue stuff
Add collisions for overworld
2026-02-02 22:39:33 -08:00
4c90eb6f07 Fix additional collisions 2026-02-02 21:59:48 -08:00
30f0a078a9 Boss A fixes 2026-02-02 20:01:54 -08:00
6e4a4d605c Partially fix boss room A, only one guy moves though 2026-02-02 00:27:11 -08:00
Pal
836b9eb26d idk merghhe 2026-02-01 16:48:25 -08:00
Pal
cb2df83079 idk 2026-02-01 16:48:02 -08:00
0282ef68f3 Collisions again 2026-02-01 16:00:44 -08:00
Pal
1678d79bbd Added E symbol to Exit floors 2026-02-01 14:02:52 -08:00
Pal
20d2890b37 Pit A, Dismantled, Puer texture fixes 2026-02-01 13:46:14 -08:00
Pal
e85c8d51f1 1A fix 2026-02-01 05:07:13 -08:00
Pal
3e178257aa merger 2026-02-01 05:03:10 -08:00
Pal
25b6d53ec4 Minimap added to all floors, all minimaps added and refined.
Less overlap neccessary for revealer cubes
2026-02-01 05:02:15 -08:00
a9ed8fda10 Add minimap shadows 2026-01-31 18:31:50 -08:00
Pal
4801d7d9b3 Special Collision Maps Added 2026-01-31 14:15:43 -08:00
Pal
f08817a586 Merging 2026-01-30 20:35:10 -08:00
Pal
4b23c2ca6f Floor Maps and room updates 2026-01-30 20:34:07 -08:00
39b2bc631d Collisions for floor set B 2026-01-29 01:12:44 -08:00
f346f0f529 Fix up Set A room collisions more and organize node structure 2026-01-28 00:53:35 -08:00
4ffe04fcff Exploding wall implementation 2026-01-26 02:15:03 -08:00
2ef838f270 Forgot a bit 2026-01-26 01:43:40 -08:00
e63a94210c Looking into room collisions we need; set up plastique behavior 2026-01-25 19:40:59 -08:00
865934399d Boss fixes, various changes 2026-01-25 19:01:34 -08:00
2622ed4423 Fix maze floor 2026-01-25 16:56:05 -08:00
79dd6eb33a Fix player height 2026-01-25 16:06:20 -08:00
Pal
bba0bb5ecd Minimap Reveal system tscns added, floor adjustments, collisions added for mazefloor 2026-01-25 02:19:11 -08:00
Pal
d6b20ce4c2 Merge branch 'main' of https://git.zenny.quest/zenayi/GameJamDungeon 2026-01-24 18:55:38 -08:00
Pal
60d8c55c7d Finished All Basic Floor layouts 2026-01-24 18:55:35 -08:00
d3a3c18d13 Fix doors 2026-01-24 15:13:27 -08:00
Pal
12993bced0 Floors 1ABC and 2ABC complete 2026-01-23 18:02:20 -08:00
Pal
8fd7a5133d A1 Floor Progress 2026-01-22 17:54:12 -08:00
Pal
97472f2a61 Deleted old unused Corridor tscns, B set (Floors 9-15) complete 2026-01-22 16:14:58 -08:00
5284a7c00d Some geometry fixes, fix spawn height for overworld 2026-01-22 01:08:25 -08:00
Pal
92b39c1ee9 Lighting for new rooms etc 2026-01-21 14:46:48 -08:00
faf3288061 Script types for block rooms 2026-01-21 01:59:12 -08:00
b715d6b459 Add collisions to block rooms 2026-01-21 01:25:28 -08:00
9897acffac Unlockable door implementation (currently opens with regular attack) 2026-01-21 00:50:21 -08:00
aa9e14c498 Make overworld doors be of unlockable type, add behavior later 2026-01-20 23:33:28 -08:00
945c5e14bb Licking all the room files 2026-01-20 22:01:22 -08:00
a1f67c3d71 Fix dying loop, add death counter, add die button to debug 2026-01-20 21:18:10 -08:00
Pal
670f8baabf Added/Fixed Rooms 2026-01-20 18:29:21 -08:00
Pal
6a62d3d943 Room fixes, started mapping floors 2026-01-17 00:00:37 -08:00
3fe45cb3e7 First floor set collisions 2026-01-15 01:37:57 -08:00
Pal
db218f26e7 Merge branch 'main' of https://git.zenny.quest/zenayi/GameJamDungeon 2026-01-14 00:46:57 -08:00
Pal
eb4e901c8a Boss 1 death animation animations added, wall explosion animation added. 2026-01-14 00:46:15 -08:00
8355 changed files with 120082 additions and 65087 deletions

View File

@@ -1,8 +0,0 @@
namespace Zennysoft.Game.Abstractions;
public interface IStackable
{
int Count { get; }
void SetCount(int count);
}

View File

@@ -2,5 +2,5 @@
public interface IHealthPack
{
public double RestoreAmount { get; }
public int RestoreAmount { get; }
}

View File

@@ -0,0 +1,54 @@
namespace Zennysoft.Game.Implementation;
using Chickensoft.GodotNodeInterfaces;
using Godot;
using Zennysoft.Game.Abstractions;
public partial class DimmableAudioStreamPlayer3D : AudioStreamPlayer3D, IDimmableAudioStreamPlayer
{
#region Constants
// -60 to -80 is considered inaudible for decibels.
public const float VOLUME_DB_INAUDIBLE = -80f;
public const double FADE_DURATION = 3d; // seconds
#endregion Constants
public ITween? FadeTween { get; set; }
public float InitialVolumeDb;
public override void _Ready()
{
InitialVolumeDb = VolumeDb;
VolumeDb = VOLUME_DB_INAUDIBLE;
}
public void FadeIn()
{
SetupFade(InitialVolumeDb, Tween.EaseType.Out);
Play();
}
public void FadeOut()
{
SetupFade(VOLUME_DB_INAUDIBLE, Tween.EaseType.In);
FadeTween!.TweenCallback(Callable.From(Stop));
}
public void SetupFade(float volumeDb, Tween.EaseType ease)
{
FadeTween?.Kill();
FadeTween = GodotInterfaces.Adapt<ITween>(CreateTween());
FadeTween.TweenProperty(
this,
"volume_db",
volumeDb,
FADE_DURATION
).SetTrans(Tween.TransitionType.Circ).SetEase(ease);
}
public override void _EnterTree() => FadeIn();
public override void _ExitTree() => FadeOut();
}

View File

@@ -0,0 +1,10 @@
using Chickensoft.Collections;
namespace Zennysoft.Game.Implementation;
public interface IStackable
{
AutoProp<int> Count { get; }
void SetCount(int count);
}

View File

@@ -13,7 +13,7 @@
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zennysoft.Game.Abstractions\Zennysoft.Game.Abstractions.csproj" />

View File

@@ -12,7 +12,6 @@ namespace Zennysoft.Ma.Adapter
calculatedDamage = CalculateDefenseResistance(calculatedDamage, defense);
if (!damage.IgnoreElementalResistance)
calculatedDamage = CalculateElementalResistance(calculatedDamage, elementalResistanceSet.ElementalResistance[damage.ElementType]);
return Mathf.Max(1, calculatedDamage);
}
@@ -26,7 +25,7 @@ namespace Zennysoft.Ma.Adapter
int incomingDamage,
double elementalResistance)
{
var result = incomingDamage - (int)(incomingDamage * elementalResistance);
var result = incomingDamage - (int)(incomingDamage * (elementalResistance / 100));
return result;
}
}

View File

@@ -7,5 +7,8 @@ public enum ElementType
Telluric,
Hydric,
Igneous,
Ferrum
Ferrum,
Holy,
Curse,
All
}

View File

@@ -5,17 +5,23 @@ using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Ma.Adapter;
public interface IEquipmentComponent : IEntityComponent
{
public IAutoProp<EquipableItem> EquippedWeapon { get; }
public IAutoProp<IWeapon> EquippedWeapon { get; }
public IAutoProp<EquipableItem> EquippedArmor { get; }
public IAutoProp<IArmor> EquippedArmor { get; }
public IAutoProp<EquipableItem> EquippedAccessory { get; }
public IAutoProp<IAccessory> EquippedAccessory { get; }
public void Equip(EquipableItem equipable);
public IAutoProp<IEquipableItem> EquippedAmmo { get; }
public void Unequip(EquipableItem equipable);
public void Equip(IEquipableItem equipable);
public bool IsItemEquipped(InventoryItem item);
public void Unequip(IEquipableItem equipable);
public bool IsItemEquipped(IEquipableItem item);
public void UpdateEquipment(IEquipableItem equipable);
public bool AugmentableEquipmentExists();
public int BonusAttack { get; }
@@ -29,5 +35,5 @@ public interface IEquipmentComponent : IEntityComponent
public ElementalResistanceSet ElementalResistance { get; }
public event Action<EquipableItem> EquipmentChanged;
public event Action<IEquipableItem> EquipmentChanged;
}

View File

@@ -12,7 +12,13 @@ public interface IExperiencePointsComponent : IEntityComponent
public IAutoProp<int> Level { get; }
public void ModifyExpGainRate(double newRate);
public void Gain(int baseExpGain);
public void GainUnmodified(int flateRateExpGain);
public void LevelUp();
public event Action PlayerLevelUp;
}

View File

@@ -7,9 +7,9 @@ namespace Zennysoft.Ma.Adapter.Entity
[Save("elemental_resist_set")]
public Dictionary<ElementType, double> ElementalResistance { get; }
public static ElementalResistanceSet None => new ElementalResistanceSet(0, 0, 0, 0, 0);
public static ElementalResistanceSet None => new ElementalResistanceSet(0, 0, 0, 0, 0, 0, 0);
public ElementalResistanceSet(double aeolicResistance, double hydricResistance, double igneousResistance, double ferrumResistance, double telluricResistance)
public ElementalResistanceSet(double aeolicResistance, double hydricResistance, double igneousResistance, double ferrumResistance, double telluricResistance, double holyResistance, double curseResistance)
{
ElementalResistance = new Dictionary<ElementType, double>
{
@@ -19,6 +19,9 @@ namespace Zennysoft.Ma.Adapter.Entity
{ ElementType.Igneous, igneousResistance },
{ ElementType.Ferrum, ferrumResistance },
{ ElementType.Telluric, telluricResistance },
{ ElementType.Holy, holyResistance },
{ ElementType.Curse, curseResistance },
{ ElementType.All, aeolicResistance + hydricResistance + igneousResistance + ferrumResistance + telluricResistance + holyResistance + curseResistance },
};
}
@@ -29,7 +32,9 @@ namespace Zennysoft.Ma.Adapter.Entity
left.ElementalResistance[ElementType.Hydric] + right.ElementalResistance[ElementType.Hydric],
left.ElementalResistance[ElementType.Igneous] + right.ElementalResistance[ElementType.Igneous],
left.ElementalResistance[ElementType.Ferrum] + right.ElementalResistance[ElementType.Ferrum],
left.ElementalResistance[ElementType.Telluric] + right.ElementalResistance[ElementType.Telluric]);
left.ElementalResistance[ElementType.Telluric] + right.ElementalResistance[ElementType.Telluric],
left.ElementalResistance[ElementType.Holy] + right.ElementalResistance[ElementType.Holy],
left.ElementalResistance[ElementType.Curse] + right.ElementalResistance[ElementType.Curse]);
}
}
}

View File

@@ -0,0 +1,167 @@
using Zennysoft.Ma.Adapter;
public class Augment
{
public JewelTags AugmentTag;
public Augment(JewelTags tag, IAugmentType augment)
{
AugmentTag = tag;
AugmentType = augment;
}
public IAugmentType AugmentType { get; set; }
}
public class HPRecoverySpeedAugment : IAugmentType
{
private readonly IPlayer _player;
public HPRecoverySpeedAugment(IPlayer player)
{
_player = player;
}
public void Apply() => _player.HealthTimerHPRate += 2;
public void Remove() => _player.HealthTimerHPRate -= 2;
}
public class BasicAugment : IAugmentType
{
public void Apply()
{
// do nothing
}
public void Remove()
{
// do nothing
}
}
public class HastenVTAugment : IAugmentType
{
private readonly IPlayer _player;
public HastenVTAugment(IPlayer player)
{
_player = player;
}
public void Apply() => _player.ModifyHealthTimerSpeed(_player.HealthTimerSpeedModifier + 0.25f);
public void Remove() => _player.ModifyHealthTimerSpeed(_player.HealthTimerSpeedModifier - 0.25f);
}
public class SlowVTReductionAugment : IAugmentType
{
private readonly IPlayer _player;
public SlowVTReductionAugment(IPlayer player)
{
_player = player;
}
public void Apply() => _player.ModifyHealthTimerSpeed(_player.HealthTimerSpeedModifier - 0.25f);
public void Remove() => _player.ModifyHealthTimerSpeed(_player.HealthTimerSpeedModifier + 0.25f);
}
public class IncreaseEXPRateAugment : IAugmentType
{
private readonly IPlayer _player;
public IncreaseEXPRateAugment(IPlayer player)
{
_player = player;
}
public void Apply() => _player.ExperiencePointsComponent.ModifyExpGainRate(_player.ExperiencePointsComponent.ExpGainRate.Value + 0.25f);
public void Remove() => _player.ExperiencePointsComponent.ModifyExpGainRate(_player.ExperiencePointsComponent.ExpGainRate.Value - 0.25f);
}
public class LowerEXPRateAugment : IAugmentType
{
private readonly IPlayer _player;
public LowerEXPRateAugment(IPlayer player)
{
_player = player;
}
public void Apply() => _player.ExperiencePointsComponent.ModifyExpGainRate(_player.ExperiencePointsComponent.ExpGainRate.Value - 0.25f);
public void Remove() => _player.ExperiencePointsComponent.ModifyExpGainRate(_player.ExperiencePointsComponent.ExpGainRate.Value + 0.25f);
}
public class LowerHPRecoveryAugment : IAugmentType
{
private readonly IPlayer _player;
public LowerHPRecoveryAugment(IPlayer player)
{
_player = player;
}
public void Apply() => _player.HealthTimerHPRate -= 1;
public void Remove() => _player.HealthTimerHPRate += 1;
}
public class IdentifyAllItemsAugment : IAugmentType
{
private readonly IPlayer _player;
public IdentifyAllItemsAugment(IPlayer player)
{
_player = player;
}
public void Apply()
{
_player.AutoIdentifyItems = true;
foreach (var item in _player.Inventory.Items.ToList())
{
if (item.ItemTag == ItemTag.MysteryItem)
_player.IdentifyItem(item);
}
}
public void Remove()
{
var weaponAugment = _player.EquipmentComponent.EquippedWeapon.Value.Augment;
var armorAugment = _player.EquipmentComponent.EquippedArmor.Value.Augment;
var accessoryAugment = _player.EquipmentComponent.EquippedAccessory.Value.Augment;
var augments = new List<Augment?>() { weaponAugment, armorAugment, accessoryAugment };
if (augments.Count(x => x != null && x.AugmentTag == JewelTags.AutoIdentifyAllItems) > 1)
return;
else
_player.AutoIdentifyItems = false;
}
}
public class RevivePlayerAugment : IAugmentType
{
private readonly IPlayer _player;
public RevivePlayerAugment(IPlayer player)
{
_player = player;
}
public void Apply()
{
_player.AutoRevive = true;
}
public void Remove()
{
var weaponAugment = _player.EquipmentComponent.EquippedWeapon.Value.Augment;
var armorAugment = _player.EquipmentComponent.EquippedArmor.Value.Augment;
var accessoryAugment = _player.EquipmentComponent.EquippedAccessory.Value.Augment;
var augments = new List<Augment?>() { weaponAugment, armorAugment, accessoryAugment };
if (augments.Count(x => x != null && x.AugmentTag == JewelTags.ReviveUserOnce) > 1)
return;
else
_player.AutoRevive = false;
}
}

View File

@@ -1,22 +0,0 @@
using Chickensoft.Introspection;
using Chickensoft.Serialization;
using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Ma.Adapter;
[Meta, Id("equipable_item")]
public abstract partial class EquipableItem : InventoryItem
{
[Save("bonus_attack_stats")]
public virtual int BonusAttack { get; }
[Save("bonus_defense_stats")]
public virtual int BonusDefense { get; }
[Save("bonus_hp_stats")]
public virtual int BonusHP { get; }
[Save("bonus_vt_stats")]
public virtual int BonusVT { get; }
[Save("bonus_luck_stats")]
public virtual int BonusLuck { get; }
[Save("bonus_elemental_resist_stats")]
public virtual ElementalResistanceSet ElementalResistance { get; } = new ElementalResistanceSet(0, 0, 0, 0, 0);
}

View File

@@ -0,0 +1,6 @@
public interface IAugmentType
{
void Apply();
void Remove();
}

View File

@@ -1,26 +0,0 @@
using Chickensoft.Introspection;
using Chickensoft.Serialization;
using Godot;
namespace Zennysoft.Ma.Adapter;
[Meta, Id("inventory_item")]
public abstract partial class InventoryItem : Node3D
{
[Save("inventory_item_id")]
public Guid ID => Guid.NewGuid();
[Save("inventory_item_name")]
public abstract string ItemName { get; }
[Save("inventory_item_description")]
public abstract string Description { get; }
[Save("inventory_item_spawn_rate")]
public abstract float SpawnRate { get; }
[Save("inventory_item_throw_damage")]
public abstract int ThrowDamage { get; }
[Save("inventory_item_throw_speed")]
public abstract float ThrowSpeed { get; }
[Save("inventory_item_tag")]
public abstract ItemTag ItemTag { get; }
public abstract Texture2D GetTexture();
}

View File

@@ -4,5 +4,21 @@ public enum ItemTag
{
None,
BreaksOnChange,
MysteryItem
}
MysteryItem,
DamagesPlayer,
ContainsRestorative,
ContainsWeapon,
ContainsArmor,
ContainsBox,
RandomSpell,
ContainsAccessory,
DropTo1HPAndGainRareItem,
TradeOneRandomItem,
TradeAllRandomItems,
ContainsUnobtainedItem,
ContainsBasicItem,
RestrictUnequip,
UnequipAllItems,
EjectAllItems,
UseAllItems
}

View File

@@ -0,0 +1,21 @@
public enum JewelTags
{
None,
AeolicElement,
IncreaseHPRecovery,
HastenVT,
LowerEXPGain,
Glue,
ItemRescue,
HydricElement,
IgneousElement,
IncreaseEXPGain,
LowerHPRecovery,
SlowVTReduction,
AutoIdentifyAllItems,
ReviveUserOnce,
TelluricElement,
IncreaseAtkDefLuck,
IncreaseLuck
}

View File

@@ -1,11 +0,0 @@
namespace Zennysoft.Ma.Adapter;
public enum ThrowableItemTag
{
None,
DoubleExp,
LowerTargetTo1HP,
CanChangeAffinity,
TeleportToRandomLocation,
WarpToExitIfFound
}

View File

@@ -16,4 +16,9 @@ public enum UsableItemTag
RaiseCurrentDefenseArmor,
RaiseLevel,
RandomEffect,
DoubleExp,
LowerTargetTo1HP,
CanChangeAffinity,
TeleportToRandomLocation,
WarpToExitIfFound
}

View File

@@ -7,4 +7,12 @@ public enum WeaponTag
IgnoreAffinity,
IgnoreDefense,
Knockback,
InverseHPAttackPower,
RustChanceSelfAndEnemy,
Instakill,
DegradeOnSwing,
DoubleAttack,
TripleAttack,
ElementalProjectile,
KineticProjectile
}

View File

@@ -2,6 +2,7 @@
using Godot;
using Zennysoft.Game.Abstractions;
using Zennysoft.Game.Implementation;
using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Ma.Adapter;
@@ -19,7 +20,7 @@ public interface IGameRepo : IDisposable
event Action? DoubleExpTimeEnd;
event Action<InventoryItem>? RemoveItemFromInventoryEvent;
event Action<IBaseInventoryItem>? RemoveItemFromInventoryEvent;
event Action? PlayerAttack;
@@ -27,11 +28,11 @@ public interface IGameRepo : IDisposable
event Action? PlayerAttackedEnemy;
event Action<EquipableItem>? EquippedItem;
event Action<IEquipableItem>? EquippedItem;
event Action<EquipableItem>? UnequippedItem;
event Action<IEquipableItem>? UnequippedItem;
event Action<IHealthPack>? RestorativePickedUp;
event Action<IEnemy>? EnemyDied;
void Pause();
@@ -47,21 +48,21 @@ public interface IGameRepo : IDisposable
public void AnnounceMessageInInventory(string message);
public void RemoveItemFromInventory(InventoryItem item);
public void RemoveItemFromInventory(IBaseInventoryItem item);
public void OnPlayerAttack();
public void OnPlayerAttackedWall();
public void OnRestorativePickedUp(IHealthPack restorative);
public void CloseInventory();
public void GameEnded();
public void OnEquippedItem(EquipableItem item);
public void OnEquippedItem(IEquipableItem item);
public void OnUnequippedItem(EquipableItem item);
public void OnUnequippedItem(IEquipableItem item);
public void OnEnemyDied(IEnemy enemy);
public double ExpRate { get; }
}
@@ -74,13 +75,13 @@ public class GameRepo : IGameRepo
public event Action<string>? AnnounceMessageInInventoryEvent;
public event Action<int>? DoubleExpTimeStart;
public event Action? DoubleExpTimeEnd;
public event Action<InventoryItem>? RemoveItemFromInventoryEvent;
public event Action<IBaseInventoryItem>? RemoveItemFromInventoryEvent;
public event Action? PlayerAttack;
public event Action? PlayerAttackedWall;
public event Action? PlayerAttackedEnemy;
public event Action<EquipableItem>? EquippedItem;
public event Action<EquipableItem>? UnequippedItem;
public event Action<IHealthPack>? RestorativePickedUp;
public event Action<IEquipableItem>? EquippedItem;
public event Action<IEquipableItem>? UnequippedItem;
public event Action<IEnemy>? EnemyDied;
public IAutoProp<bool> IsPaused => _isPaused;
private readonly AutoProp<bool> _isPaused;
@@ -110,14 +111,14 @@ public class GameRepo : IGameRepo
{
AnnounceMessageInInventory("Experience points temporarily doubled.");
DoubleExpTimeStart?.Invoke(lengthOfEffect.Seconds);
ExpRate = 2;
ExpRate *= 2;
}
public void EndDoubleExp()
{
AnnounceMessageOnMainScreen("Experience points effect wore off.");
DoubleExpTimeEnd?.Invoke();
ExpRate = 1;
ExpRate /= 2;
}
public void AnnounceMessageOnMainScreen(string message)
@@ -130,7 +131,7 @@ public class GameRepo : IGameRepo
AnnounceMessageInInventoryEvent?.Invoke(message);
}
public void RemoveItemFromInventory(InventoryItem item)
public void RemoveItemFromInventory(IBaseInventoryItem item)
{
RemoveItemFromInventoryEvent?.Invoke(item);
}
@@ -145,19 +146,16 @@ public class GameRepo : IGameRepo
PlayerAttackedWall?.Invoke();
}
public void OnRestorativePickedUp(IHealthPack restorative)
{
RestorativePickedUp?.Invoke(restorative);
}
public void CloseInventory()
{
CloseInventoryEvent?.Invoke();
}
public void OnEquippedItem(EquipableItem item) => EquippedItem?.Invoke(item);
public void OnEquippedItem(IEquipableItem item) => EquippedItem?.Invoke(item);
public void OnUnequippedItem(EquipableItem item) => UnequippedItem?.Invoke(item);
public void OnUnequippedItem(IEquipableItem item) => UnequippedItem?.Invoke(item);
public void OnEnemyDied(IEnemy enemy) => EnemyDied?.Invoke(enemy);
public void GameEnded()
{

View File

@@ -8,7 +8,7 @@ public partial class GameState
public partial record State
{
[Meta, LogicBlock(typeof(State), Diagram = true)]
public partial record DebugMenu : State, IGet<Input.DebugButtonPressed>
public partial record DebugMenu : InGame, IGet<Input.DebugButtonPressed>
{
public Transition On(in Input.DebugButtonPressed input)
{

View File

@@ -8,13 +8,20 @@ public partial class GameState
public partial record State
{
[Meta, LogicBlock(typeof(State), Diagram = true)]
public partial record GameOver : State, IGet<Input.NewGame>
public partial record GameOver : InGame, IGet<Input.NewGame>, IGet<Input.ExitGame>
{
public Transition On(in Input.NewGame input)
{
Output(new Output.InitializeGame());
return To<InGame>();
}
public Transition On(in Input.ExitGame input)
{
Output(new Output.ClosePauseScreen());
Output(new Output.ExitGame());
return To<State>();
}
}
}
}

View File

@@ -0,0 +1,5 @@
using Zennysoft.Ma.Adapter;
public interface IAccessory : IEquipableItem, IAugmentableItem
{
}

View File

@@ -0,0 +1,5 @@
using Zennysoft.Ma.Adapter;
public interface IArmor : IEquipableItem, IAugmentableItem
{
}

View File

@@ -0,0 +1,5 @@
public interface IAugmentItem : IBaseInventoryItem
{
public IAugmentType Augment { get; }
}

View File

@@ -0,0 +1,7 @@
namespace Zennysoft.Ma.Adapter
{
public interface IAugmentableItem
{
public Augment? Augment { get; }
}
}

View File

@@ -0,0 +1,15 @@
using Godot;
using Zennysoft.Ma.Adapter;
public interface IBaseInventoryItem
{
public string ItemName { get; }
public string Description { get; }
public float SpawnRate { get; }
public int ThrowDamage { get; }
public float ThrowSpeed { get; }
public ItemTag ItemTag { get; }
public abstract Texture2D GetTexture();
}

View File

@@ -4,6 +4,6 @@
{
void RescueItem();
public InventoryItem Item { get; }
public IBaseInventoryItem Item { get; }
}
}

View File

@@ -0,0 +1,14 @@
using Zennysoft.Ma.Adapter.Entity;
public interface IEquipableItem : IBaseInventoryItem
{
public int BonusAttack { get; }
public int BonusDefense { get; }
public int BonusHP { get; }
public int BonusVT { get; }
public int BonusLuck { get; }
public bool Glued { get; set; }
public ElementalResistanceSet ElementalResistance { get; }
}

View File

@@ -2,17 +2,19 @@
public interface IInventory
{
public bool PickUpItem(InventoryItem item);
public bool PickUpItem(IBaseInventoryItem item);
public List<InventoryItem> Items { get; }
public List<IBaseInventoryItem> Items { get; }
public bool TryAdd(InventoryItem inventoryItem);
public bool TryAdd(IBaseInventoryItem inventoryItem);
public bool TryInsert(InventoryItem inventoryItem, int index);
public bool TryInsert(IBaseInventoryItem inventoryItem, int index);
public void Remove(InventoryItem inventoryItem);
public void Remove(IBaseInventoryItem inventoryItem);
public bool Sort(EquipableItem currentWeapon, EquipableItem currentArmor, EquipableItem currentAccessory);
public bool Sort(IWeapon currentWeapon, IArmor currentArmor, IAccessory currentAccessory, IEquipableItem ammo);
public bool AtCapacity();
public event Action<string> BroadcastMessage;
public event Action InventoryChanged;

View File

@@ -2,5 +2,5 @@
public interface IThrownItem
{
public InventoryItem ItemThatIsThrown { get; set; }
public IBaseInventoryItem ItemThatIsThrown { get; set; }
}

View File

@@ -0,0 +1,5 @@
using Zennysoft.Ma.Adapter;
public interface IWeapon : IEquipableItem, IAugmentableItem
{
}

View File

@@ -7,10 +7,10 @@ namespace Zennysoft.Ma.Adapter;
public partial class RescuedItemDatabase
{
[Save("rescued_item_list")]
public List<InventoryItem> Items { get; init; }
public List<IBaseInventoryItem> Items { get; init; }
public RescuedItemDatabase()
{
Items = new List<InventoryItem>();
Items = new List<IBaseInventoryItem>();
}
}

View File

@@ -11,9 +11,6 @@ public partial class ItemTagEnumContext : JsonSerializerContext;
[JsonSerializable(typeof(AccessoryTag))]
public partial class AccessoryTagEnumContext : JsonSerializerContext;
[JsonSerializable(typeof(ThrowableItemTag))]
public partial class ThrowableItemTagEnumContext : JsonSerializerContext;
[JsonSerializable(typeof(UsableItemTag))]
public partial class UsableItemTagEnumContext : JsonSerializerContext;

View File

@@ -7,9 +7,11 @@ public interface IDungeonFloor : INode3D
{
void InitializeDungeon();
public Transform3D GetPlayerSpawnPoint();
public abstract (Vector3 Rotation, Vector3 Position) GetPlayerSpawnPoint();
public ImmutableList<IDungeonRoom> Rooms { get; }
public void FadeOutAudio();
public bool FloorIsLoaded { get; set; }
}

View File

@@ -18,15 +18,17 @@ public interface IPlayer : IKillable, ICharacterBody3D
public void LevelUp();
public void LookUp();
public void TeleportPlayer((Vector3 Rotation, Vector3 Position) newTransform);
public void TeleportPlayer(Transform3D newTransform);
public void Equip(IEquipableItem equipable);
public void Equip(EquipableItem equipable);
public void Unequip(IEquipableItem equipable);
public void Unequip(EquipableItem equipable);
public void PlayJumpScareAnimation();
public void Reset();
public void ApplyNewAugment(IAugmentItem jewel, IAugmentableItem equipableItem);
public void IdentifyItem(IBaseInventoryItem unidentifiedItem);
public IInventory Inventory { get; }
@@ -44,12 +46,22 @@ public interface IPlayer : IKillable, ICharacterBody3D
public IEquipmentComponent EquipmentComponent { get; }
public void PlayTestAnimation();
public void SetHealthTimerStatus(bool isActive);
public event Action PlayerDied;
public delegate InventoryItem RerollItem(InventoryItem item);
public void ModifyHealthTimerSpeed(float newModifier);
public event Action PointUpFinished;
public bool AutoRevive { get; set; }
public int TotalAttack { get; }
public int TotalDefense { get; }
public int TotalLuck { get; }
public int HealthTimerHPRate { get; set; }
public float HealthTimerSpeedModifier { get; }
public bool AutoIdentifyItems { get; set; }
public event Action PlayerDied;
public delegate IBaseInventoryItem RerollItem(IBaseInventoryItem item);
}

View File

@@ -8,8 +8,6 @@ public partial class PlayerLogic
{
public readonly record struct PhysicsTick(double Delta);
public readonly record struct Moved(Vector3 GlobalPosition, Transform3D GlobalTransform);
public readonly record struct Enable;
public readonly record struct Attack;

View File

@@ -6,6 +6,9 @@ namespace Zennysoft.Ma.Adapter;
[Meta, Id("quest_data")]
public partial record QuestData
{
[Save("death_count")]
public int DeathCount { get; set; } = 0;
[Save("quest_data_1")]
public bool QuestMarker1 { get; set; } = false;
}

View File

@@ -19,7 +19,7 @@ public sealed class MaSaveFileManager : IMaSaveFileManager
public MaSaveFileManager(ISaveFileManager saveFileManager)
{
_saveFileManager = saveFileManager;
_converters = [WeaponTagEnumContext.Default, ItemTagEnumContext.Default, ElementTypeEnumContext.Default, AccessoryTagEnumContext.Default, ThrowableItemTagEnumContext.Default, UsableItemTagEnumContext.Default, BoxItemTagEnumContext.Default];
_converters = [WeaponTagEnumContext.Default, ItemTagEnumContext.Default, ElementTypeEnumContext.Default, AccessoryTagEnumContext.Default, UsableItemTagEnumContext.Default, BoxItemTagEnumContext.Default];
}
public async Task Save<T>(T gameData)

View File

@@ -38,7 +38,7 @@ public partial class InGameUILogic
Output(new Output.AnnounceMessageInInventory(message));
}
private void OnRemoveItemFromInventory(InventoryItem item) => Output(new Output.RemoveItemFromInventory(item));
private void OnRemoveItemFromInventory(IBaseInventoryItem item) => Output(new Output.RemoveItemFromInventory(item));
}
}

View File

@@ -8,7 +8,7 @@ public partial class InGameUILogic
{
public readonly record struct AnnounceMessageOnMainScreen(string Message);
public readonly record struct AnnounceMessageInInventory(string Message);
public readonly record struct RemoveItemFromInventory(InventoryItem Item);
public readonly record struct RemoveItemFromInventory(IBaseInventoryItem Item);
public readonly record struct ShowInventory;
public readonly record struct HideInventory;
}

View File

@@ -1,51 +0,0 @@
<Project Sdk="Godot.NET.Sdk/4.4.0">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<!-- Use NativeAOT. -->
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<Compile Remove="src\items\weapons\models\**" />
<EmbeddedResource Remove="src\items\weapons\models\**" />
</ItemGroup>
<ItemGroup>
<!-- Root the assemblies to avoid trimming. -->
<TrimmerRootAssembly Include="GodotSharp" />
<TrimmerRootAssembly Include="$(TargetName)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.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.LogicBlocks" Version="5.16.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.16.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0-250131-2115.Release" />
<PackageReference Include="SimpleInjector" Version="5.5.0" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.11" />
<PackageReference Include="Zeroconf" Version="3.7.16" />
</ItemGroup>
<ItemGroup>
<Folder Include="src\ui\dialogue\" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zennysoft.Game.Godot.Implementation\Zennysoft.Game.Implementation.csproj" />
<ProjectReference Include="..\Zennysoft.Game.Ma.Implementation\Zennysoft.Ma.Adapter.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Godot.SourceGenerators" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharp" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharpEditor" Version="4.4.0-dev.2" />
</ItemGroup>
</Project>

View File

@@ -1,38 +0,0 @@
<Project Sdk="Godot.NET.Sdk/4.4.0">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<WarningsAsErrors>CS9057</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.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.LogicBlocks" Version="5.16.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.16.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0-250131-2115.Release" />
<PackageReference Include="SimpleInjector" Version="5.5.0" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.11" />
<PackageReference Include="Zeroconf" Version="3.7.16" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zennysoft.Game.Godot.Implementation\Zennysoft.Game.Implementation.csproj" />
<ProjectReference Include="..\Zennysoft.Game.Ma.Implementation\Zennysoft.Ma.Adapter.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Godot.SourceGenerators" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharp" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharpEditor" Version="4.4.0-dev.2" />
</ItemGroup>
</Project>

View File

@@ -1,38 +0,0 @@
<Project Sdk="Godot.NET.Sdk/4.4.0">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<WarningsAsErrors>CS9057</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.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.LogicBlocks" Version="5.16.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.16.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0-250131-2115.Release" />
<PackageReference Include="SimpleInjector" Version="5.5.0" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.11" />
<PackageReference Include="Zeroconf" Version="3.7.16" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zennysoft.Game.Godot.Implementation\Zennysoft.Game.Implementation.csproj" />
<ProjectReference Include="..\Zennysoft.Game.Ma.Implementation\Zennysoft.Ma.Adapter.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Godot.SourceGenerators" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharp" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharpEditor" Version="4.4.0-dev.2" />
</ItemGroup>
</Project>

View File

@@ -1,38 +0,0 @@
<Project Sdk="Godot.NET.Sdk/4.4.1">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<WarningsAsErrors>CS9057</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.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.LogicBlocks" Version="5.16.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.16.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0-250131-2115.Release" />
<PackageReference Include="SimpleInjector" Version="5.5.0" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.11" />
<PackageReference Include="Zeroconf" Version="3.7.16" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zennysoft.Game.Godot.Implementation\Zennysoft.Game.Implementation.csproj" />
<ProjectReference Include="..\Zennysoft.Game.Ma.Implementation\Zennysoft.Ma.Adapter.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Godot.SourceGenerators" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharp" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharpEditor" Version="4.4.0-dev.2" />
</ItemGroup>
</Project>

View File

@@ -1,38 +0,0 @@
<Project Sdk="Godot.NET.Sdk/4.4.0">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<WarningsAsErrors>CS9057</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.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.LogicBlocks" Version="5.16.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.16.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0-250131-2115.Release" />
<PackageReference Include="SimpleInjector" Version="5.5.0" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.11" />
<PackageReference Include="Zeroconf" Version="3.7.16" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zennysoft.Game.Godot.Implementation\Zennysoft.Game.Implementation.csproj" />
<ProjectReference Include="..\Zennysoft.Game.Ma.Implementation\Zennysoft.Ma.Adapter.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Godot.SourceGenerators" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharp" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharpEditor" Version="4.4.0-dev.2" />
</ItemGroup>
</Project>

View File

@@ -1,38 +0,0 @@
<Project Sdk="Godot.NET.Sdk/4.4.0">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<WarningsAsErrors>CS9057</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.5.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.LogicBlocks" Version="5.16.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.16.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.7.6" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0-250131-2115.Release" />
<PackageReference Include="SimpleInjector" Version="5.5.0" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.0.11" />
<PackageReference Include="Zeroconf" Version="3.7.16" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zennysoft.Game.Godot.Implementation\Zennysoft.Game.Implementation.csproj" />
<ProjectReference Include="..\Zennysoft.Game.Ma.Implementation\Zennysoft.Ma.Adapter.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Godot.SourceGenerators" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharp" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharpEditor" Version="4.4.0-dev.2" />
</ItemGroup>
</Project>

View File

@@ -1,23 +1,22 @@
[preset.0]
name="Steamdeck"
platform="Linux"
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
advanced_options=false
advanced_options=true
dedicated_server=false
custom_features=""
export_filter="exclude"
export_files=PackedStringArray()
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path=""
export_path="Export/Ma.exe"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
script_export_mode=1
[preset.0.options]
@@ -28,51 +27,6 @@ binary_format/embed_pck=false
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
export DISPLAY=:0
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
\"{temp_dir}/{exe_name}\" {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""
dotnet/include_scripts_content=false
dotnet/include_debug_symbols=true
dotnet/embed_build_outputs=false
[preset.1]
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
advanced_options=false
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="Output/Ma.zip"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.1.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=0
binary_format/embed_pck=true
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
binary_format/architecture="x86_64"
codesign/enable=false
codesign/timestamp=true
codesign/timestamp_server_url=""
@@ -111,5 +65,5 @@ ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debu
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"
dotnet/include_scripts_content=false
dotnet/include_debug_symbols=false
dotnet/include_debug_symbols=true
dotnet/embed_build_outputs=false

View File

@@ -12,9 +12,8 @@ config_version=5
config/name="Ma"
run/main_scene="uid://d1gjaijijd5ot"
run/print_header=false
config/features=PackedStringArray("4.4", "C#", "GL Compatibility")
run/delta_smoothing=false
run/max_fps=60
boot_splash/show_image=false
[autoload]
@@ -42,6 +41,10 @@ window/stretch/mode="canvas_items"
project/assembly_name="Ma"
[editor]
export/convert_text_resources_to_binary=false
[editor_plugins]
enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg", "res://addons/input_helper/plugin.cfg")
@@ -54,6 +57,20 @@ folder_colors={
"res://src/game/": "orange",
"res://src/items/": "teal",
"res://src/map/": "gray",
"res://src/map/dungeon/floors/Floor01/": "red",
"res://src/map/dungeon/floors/Floor02/": "red",
"res://src/map/dungeon/floors/Floor03/": "red",
"res://src/map/dungeon/floors/Floor04/": "red",
"res://src/map/dungeon/floors/Floor05/": "red",
"res://src/map/dungeon/floors/Floor06/": "red",
"res://src/map/dungeon/floors/Floor07/": "red",
"res://src/map/dungeon/floors/Floor09/": "teal",
"res://src/map/dungeon/floors/Floor10/": "teal",
"res://src/map/dungeon/floors/Floor11/": "teal",
"res://src/map/dungeon/floors/Floor12/": "teal",
"res://src/map/dungeon/floors/Floor13/": "teal",
"res://src/map/dungeon/floors/Floor14/": "teal",
"res://src/map/dungeon/floors/Floor15/": "teal",
"res://src/player/": "blue",
"res://src/ui/inventory_menu/": "green"
}
@@ -62,10 +79,16 @@ folder_colors={
import/blender/enabled=false
[global_group]
DimmableAudio=""
[importer_defaults]
texture={
"detect_3d/compress_to": 0
&"compress/high_quality": true,
&"compress/mode": 2,
&"detect_3d/compress_to": 0
}
[input]
@@ -251,7 +274,7 @@ EnemyViewerWalk={
[internationalization]
locale/translations_pot_files=PackedStringArray("res://src/dialog/Dialogue.dialogue", "res://src/npc/Ran/ran.dialogue", "res://src/npc/Rat/ratdialogue.dialogue", "res://src/dialog/Altar.dialogue")
locale/translations_pot_files=PackedStringArray("res://src/dialog/Dialogue.dialogue", "res://src/npc/Ran/ran.dialogue", "res://src/npc/Rat/ratdialogue.dialogue", "res://src/dialog/Altar.dialogue", "res://stone.dialogue", "res://src/npc/Proscenium/JumpScare.dialogue", "res://tutorialstone.dialogue")
[layer_names]
@@ -267,6 +290,8 @@ locale/translations_pot_files=PackedStringArray("res://src/dialog/Dialogue.dialo
3d_physics/layer_10="Minimap"
3d_physics/layer_11="ItemRescue"
3d_physics/layer_12="EnemyHitbox"
3d_physics/layer_13="UnlockableDoor"
3d_physics/layer_14="ExplodableWall"
3d_physics/layer_32="Navigation"
[navigation]
@@ -277,6 +302,7 @@ locale/translations_pot_files=PackedStringArray("res://src/dialog/Dialogue.dialo
3d/run_on_separate_thread=true
common/physics_ticks_per_second=144
jolt_physics_3d/simulation/areas_detect_static_bodies=true
[rendering]

View File

@@ -0,0 +1 @@
uid://bevfcpew3kket

View File

@@ -1,5 +1,4 @@
using Chickensoft.Collections;
using Godot;
using System;
using Zennysoft.Ma.Adapter;
using Zennysoft.Ma.Adapter.Entity;
@@ -7,19 +6,23 @@ using Zennysoft.Ma.Adapter.Entity;
namespace Zennysoft.Game.Ma;
public class EquipmentComponent : IEquipmentComponent
{
public IAutoProp<EquipableItem> EquippedWeapon => _equippedWeapon;
public IAutoProp<IWeapon> EquippedWeapon => _equippedWeapon;
public IAutoProp<EquipableItem> EquippedArmor => _equippedArmor;
public IAutoProp<IArmor> EquippedArmor => _equippedArmor;
public IAutoProp<EquipableItem> EquippedAccessory => _equippedAccessory;
public IAutoProp<IAccessory> EquippedAccessory => _equippedAccessory;
public AutoProp<EquipableItem> _equippedWeapon;
public IAutoProp<IEquipableItem> EquippedAmmo => _equippedAmmo;
public AutoProp<EquipableItem> _equippedArmor;
public AutoProp<IWeapon> _equippedWeapon;
public AutoProp<EquipableItem> _equippedAccessory;
public AutoProp<IArmor> _equippedArmor;
public event Action<EquipableItem> EquipmentChanged;
public AutoProp<IAccessory> _equippedAccessory;
public AutoProp<IEquipableItem> _equippedAmmo;
public event Action<IEquipableItem> EquipmentChanged;
public int BonusAttack => _equippedWeapon.Value.BonusAttack + _equippedArmor.Value.BonusAttack + _equippedAccessory.Value.BonusAttack;
@@ -35,9 +38,10 @@ public class EquipmentComponent : IEquipmentComponent
public EquipmentComponent()
{
_equippedWeapon = new AutoProp<EquipableItem>(new Weapon());
_equippedArmor = new AutoProp<EquipableItem>(new Armor());
_equippedAccessory = new AutoProp<EquipableItem>(new Accessory());
_equippedWeapon = new AutoProp<IWeapon>(new Weapon());
_equippedArmor = new AutoProp<IArmor>(new Armor());
_equippedAccessory = new AutoProp<IAccessory>(new Accessory());
_equippedAmmo = new AutoProp<IEquipableItem>(new Ammo());
}
public void Reset()
@@ -45,9 +49,10 @@ public class EquipmentComponent : IEquipmentComponent
_equippedWeapon.OnNext(new Weapon());
_equippedArmor.OnNext(new Armor());
_equippedAccessory.OnNext(new Accessory());
_equippedAmmo.OnNext(new Ammo());
}
public void Equip(EquipableItem equipable)
public void Equip(IEquipableItem equipable)
{
if (equipable is Weapon weapon)
_equippedWeapon.OnNext(weapon);
@@ -55,10 +60,12 @@ public class EquipmentComponent : IEquipmentComponent
_equippedArmor.OnNext(armor);
if (equipable is Accessory accessory)
_equippedAccessory.OnNext(accessory);
if (equipable is Ammo ammo)
_equippedAmmo.OnNext(ammo);
EquipmentChanged?.Invoke(equipable);
}
public void Unequip(EquipableItem equipable)
public void Unequip(IEquipableItem equipable)
{
if (equipable is Weapon weapon)
_equippedWeapon.OnNext(new Weapon());
@@ -66,14 +73,20 @@ public class EquipmentComponent : IEquipmentComponent
_equippedArmor.OnNext(new Armor());
if (equipable is Accessory accessory)
_equippedAccessory.OnNext(new Accessory());
if (equipable is Ammo ammo)
_equippedAmmo.OnNext(new Ammo());
EquipmentChanged?.Invoke(equipable);
}
public bool IsItemEquipped(InventoryItem item)
public bool IsItemEquipped(IEquipableItem item)
{
if (item is not EquipableItem)
return false;
return item == _equippedWeapon.Value || item == _equippedArmor.Value || item == _equippedAccessory.Value || item == _equippedAmmo.Value;
}
return item == _equippedWeapon.Value || item == _equippedArmor.Value || item == _equippedAccessory.Value;
public void UpdateEquipment(IEquipableItem equipable) => EquipmentChanged?.Invoke(equipable);
public bool AugmentableEquipmentExists()
{
return (_equippedWeapon.Value.ItemName != null && _equippedWeapon.Value.Augment == null) || (_equippedArmor.Value.ItemName != null && _equippedArmor.Value.Augment == null) || (_equippedAccessory.Value.ItemName != null && _equippedAccessory.Value.Augment == null);
}
}

View File

@@ -22,6 +22,8 @@ public class ExperiencePointsComponent : IExperiencePointsComponent
private readonly AutoProp<int> _level;
public event Action PlayerLevelUp;
public ExperiencePointsComponent()
{
var firstLevelExpRequirement = ExpToNextLevelCalculation(1);
@@ -50,6 +52,17 @@ public class ExperiencePointsComponent : IExperiencePointsComponent
_currentExp.OnNext(cappedAmount);
}
public void GainUnmodified(int flatRateExp)
{
var newCurrentExpTotal = flatRateExp + _currentExp.Value;
while (flatRateExp + _currentExp.Value >= _expToNextLevel.Value)
LevelUp();
var cappedAmount = Math.Min(flatRateExp + _currentExp.Value, _expToNextLevel.Value);
_currentExp.OnNext(cappedAmount);
}
public void ModifyExpGainRate(double newRate) => _expGainRate.OnNext(newRate);
public void LevelUp()
{
SfxDatabase.Instance.Play(SoundEffect.LevelUp);
@@ -57,6 +70,7 @@ public class ExperiencePointsComponent : IExperiencePointsComponent
var expToNextLevel = ExpToNextLevelCalculation(_level.Value);
_currentExp.OnNext(_currentExp.Value - _expToNextLevel.Value);
_expToNextLevel.OnNext(expToNextLevel);
PlayerLevelUp?.Invoke();
}
private int ExpToNextLevelCalculation(int nextLevel)

View File

@@ -31,8 +31,6 @@ public partial class App : Node, IApp
[Node] private GalleryMenu GalleryMenu { get; set; }
[Node] private VideoStreamPlayer VideoStreamPlayer { get; set; }
IAppRepo IProvide<IAppRepo>.Value() => AppRepo;
public IAppRepo AppRepo { get; set; } = default!;
@@ -55,144 +53,142 @@ public partial class App : Node, IApp
public void Initialize()
{
_container = new SimpleInjector.Container();
_container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
_container.RegisterSingleton<IAppRepo, AppRepo>();
_container.RegisterSingleton<IAppLogic, AppLogic>();
_container.RegisterSingleton<IFileSystem, FileSystem>();
_container.RegisterSingleton<ISaveFileManager, SaveFileManager>();
_container = new SimpleInjector.Container();
_container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
_container.RegisterSingleton<IAppRepo, AppRepo>();
_container.RegisterSingleton<IAppLogic, AppLogic>();
_container.RegisterSingleton<IFileSystem, FileSystem>();
_container.RegisterSingleton<ISaveFileManager, SaveFileManager>();
_saveFileManager = _container.GetInstance<ISaveFileManager>();
_optionsSavePath = $"{OS.GetUserDataDir()}/options.json";
_controllerSavePath = $"{OS.GetUserDataDir()}/controls.json";
_saveFileManager = _container.GetInstance<ISaveFileManager>();
_optionsSavePath = $"{OS.GetUserDataDir()}/options.json";
_controllerSavePath = $"{OS.GetUserDataDir()}/controls.json";
MainMenu.StartGame += OnStartGame;
MainMenu.EnemyViewer += OnEnemyViewer;
MainMenu.Gallery += OnGallery;
MainMenu.Options += OnOptions;
MainMenu.Quit += OnQuit;
MainMenu.StartGame += OnStartGame;
MainMenu.EnemyViewer += OnEnemyViewer;
MainMenu.Gallery += OnGallery;
MainMenu.Options += OnOptions;
MainMenu.Quit += OnQuit;
GalleryMenu.GalleryExited += GalleryExited;
GalleryMenu.GalleryExited += GalleryExited;
OptionsMenu.OptionsMenuExited += OptionsMenu_OptionsMenuExited;
OptionsMenu.DeleteSaveData += DeleteSaveData;
AppRepo = _container.GetInstance<IAppRepo>();
AppLogic = _container.GetInstance<IAppLogic>();
OptionsMenu.OptionsMenuExited += OptionsMenu_OptionsMenuExited;
OptionsMenu.DeleteSaveData += DeleteSaveData;
AppRepo = _container.GetInstance<IAppRepo>();
AppLogic = _container.GetInstance<IAppLogic>();
Task.Run(() => _saveFileManager.ReadFromFile<string>(_controllerSavePath).ContinueWith((data) =>
{
if (data.IsCompletedSuccessfully)
OptionsMenu.Controller.CallDeferred(nameof(OptionsMenu.Controller.LoadControllerInput), data.Result);
}));
Task.Run(() => _saveFileManager.ReadFromFile<string>(_controllerSavePath).ContinueWith((data) =>
{
if (data.IsCompletedSuccessfully)
OptionsMenu.Controller.CallDeferred(nameof(OptionsMenu.Controller.LoadControllerInput), data.Result);
}));
AppLogic.Set(AppRepo);
AppLogic.Set(new AppLogic.Data());
AppLogic.Set(AppRepo);
AppLogic.Set(new AppLogic.Data());
AppRepo.DataViewerExited += DataViewerExited;
AppRepo.DataViewerExited += DataViewerExited;
Input.MouseMode = Input.MouseModeEnum.Visible;
_progress = [];
this.Provide();
Input.MouseMode = Input.MouseModeEnum.Visible;
_progress = [];
this.Provide();
}
private void GameExitRequested()
{
AppLogic.Input(new AppLogic.Input.QuitGame());
AppLogic.Input(new AppLogic.Input.QuitGame());
}
private void DeleteSaveData()
{
var saveFileManager = _container.GetInstance<ISaveFileManager>();
saveFileManager.DeleteSaveData();
var saveFileManager = _container.GetInstance<ISaveFileManager>();
saveFileManager.DeleteSaveData();
}
private void DataViewerExited()
{
AppLogic.Input(new AppLogic.Input.EnemyViewerExited());
AppLogic.Input(new AppLogic.Input.EnemyViewerExited());
}
private async void OptionsMenu_OptionsMenuExited()
{
var saveFileManager = _container.GetInstance<ISaveFileManager>();
await saveFileManager.WriteToFile(OptionsMenu.OptionsData, _optionsSavePath);
var controllerOutput = InputHelper.SerializeInputsForActions();
await saveFileManager.WriteToFile(controllerOutput, _controllerSavePath);
OptionsMenu.Hide();
MainMenu.OptionsButton.GrabFocus();
var saveFileManager = _container.GetInstance<ISaveFileManager>();
await saveFileManager.WriteToFile(OptionsMenu.OptionsData, _optionsSavePath);
var controllerOutput = InputHelper.SerializeInputsForActions();
await saveFileManager.WriteToFile(controllerOutput, _controllerSavePath);
OptionsMenu.Hide();
MainMenu.OptionsButton.GrabFocus();
}
private void GalleryExited()
{
GalleryMenu.Hide();
MainMenu.GalleryButton.GrabFocus();
GalleryMenu.Hide();
MainMenu.GalleryButton.GrabFocus();
}
public void OnReady()
{
AppBinding = AppLogic.Bind();
AppBinding = AppLogic.Bind();
AppBinding
.Handle((in AppLogic.Output.Initialize _) =>
{
Task.Run(() => _saveFileManager.ReadFromFile<string>(_optionsSavePath).ContinueWith((data) =>
{
AppLogic.Input(new AppLogic.Input.SaveFileLoaded());
}));
})
.Handle((in AppLogic.Output.ShowSplashScreen _) =>
{
AppLogic.Input(new AppLogic.Input.FadeOutFinished());
})
.Handle((in AppLogic.Output.HideSplashScreen _) =>
{
})
.Handle((in AppLogic.Output.SetupGameScene _) =>
{
LoadingScreen.Show();
LoadGame(GAME_SCENE_PATH);
})
.Handle((in AppLogic.Output.ShowMainMenu _) =>
{
MainMenu.CallDeferred(MainMenu.MethodName.FadeIn);
})
.Handle((in AppLogic.Output.CloseGame _) =>
{
LoadingScreen.Hide();
_game.GameExitRequested -= GameExitRequested;
MainMenu.StartGameButton.GrabFocus();
_game.CallDeferred(MethodName.QueueFree, []);
GetTree().Paused = false;
})
.Handle((in AppLogic.Output.StartLoadingSaveFile _) =>
{
})
.Handle((in AppLogic.Output.EnemyViewerOpened _) =>
{
LoadingScreen.Show();
LoadEnemyViewer(ENEMY_VIEWER_PATH);
})
.Handle((in AppLogic.Output.EnemyViewerExited _) =>
{
LoadingScreen.Hide();
if (_enemyViewer != null && _enemyViewer is DataViewer enemyViewer)
enemyViewer.CallDeferred(MethodName.QueueFree);
MainMenu.Show();
MainMenu.EnemyViewerButton.GrabFocus();
})
.Handle((in AppLogic.Output.ExitGame _) =>
{
GetTree().Quit();
});
AppBinding
.Handle((in AppLogic.Output.Initialize _) =>
{
Task.Run(() => _saveFileManager.ReadFromFile<string>(_optionsSavePath).ContinueWith((data) =>
{
AppLogic.Input(new AppLogic.Input.SaveFileLoaded());
}));
})
.Handle((in AppLogic.Output.ShowSplashScreen _) =>
{
AppLogic.Input(new AppLogic.Input.FadeOutFinished());
})
.Handle((in AppLogic.Output.HideSplashScreen _) =>
{
})
.Handle((in AppLogic.Output.SetupGameScene _) =>
{
LoadingScreen.ShowLoadingScreen();
LoadGame(GAME_SCENE_PATH);
})
.Handle((in AppLogic.Output.ShowMainMenu _) =>
{
MainMenu.CallDeferred(MainMenu.MethodName.FadeIn);
})
.Handle((in AppLogic.Output.CloseGame _) =>
{
LoadingScreen.HideLoadingScreen();
_game.GameExitRequested -= GameExitRequested;
MainMenu.StartGameButton.GrabFocus();
_game.CallDeferred(MethodName.QueueFree, []);
GetTree().Paused = false;
})
.Handle((in AppLogic.Output.StartLoadingSaveFile _) =>
{
})
.Handle((in AppLogic.Output.EnemyViewerOpened _) =>
{
LoadingScreen.ShowLoadingScreen();
MainMenu.Hide();
LoadEnemyViewer(ENEMY_VIEWER_PATH);
})
.Handle((in AppLogic.Output.EnemyViewerExited _) =>
{
LoadingScreen.HideLoadingScreen();
if (_enemyViewer != null && _enemyViewer is DataViewer enemyViewer)
enemyViewer.CallDeferred(MethodName.QueueFree);
MainMenu.Show();
MainMenu.EnemyViewerButton.GrabFocus();
})
.Handle((in AppLogic.Output.ExitGame _) =>
{
GetTree().Quit();
});
AppLogic.Start();
AppLogic.Start();
}
public override void _Process(double delta)
{
if (_reportedProgress < 1)
LoadingScreen.ProgressBar.Value = Mathf.RoundToInt(Mathf.Lerp(LoadingScreen.ProgressBar.Value, _reportedProgress * 100, (float)delta * 2));
else
LoadingScreen.ProgressBar.Value = Mathf.RoundToInt(Mathf.Lerp(LoadingScreen.ProgressBar.Value, 200, (float)delta * 5));
LoadingScreen.ProgressBar.Value = Mathf.RoundToInt(Mathf.Lerp(LoadingScreen.ProgressBar.Value, _reportedProgress * 100, (float)delta * 2));
}
public void OnStartGame() => AppLogic.Input(new AppLogic.Input.NewGame());
@@ -203,64 +199,73 @@ public partial class App : Node, IApp
private async void LoadGame(string sceneName)
{
var scene = await LoadSceneInternal(sceneName);
_game = scene as IGame;
_game.GameExitRequested += GameExitRequested;
await ToSignal(GetTree().CreateTimer(0.8f), "timeout");
CallDeferred(MethodName.AddChild, scene);
var scene = await LoadSceneInternal(sceneName);
_game = scene as IGame;
_game.GameLoaded += OnGameLoaded;
_game.GameExitRequested += GameExitRequested;
CallDeferred(MethodName.AddChild, scene);
}
private void OnGameLoaded() => LoadingScreen.HideLoadingScreen();
private async void LoadEnemyViewer(string sceneName)
{
var scene = await LoadSceneInternal(sceneName);
_enemyViewer = scene as IDataViewer;
await ToSignal(GetTree().CreateTimer(0.8f), "timeout");
CallDeferred(MethodName.AddChild, scene);
var scene = await LoadSceneInternal(sceneName);
_enemyViewer = scene as IDataViewer;
CallDeferred(MethodName.AddChild, scene);
LoadingScreen.HideLoadingScreen();
}
private async Task<Node> LoadSceneInternal(string sceneName)
{
LoadingScreen.Show();
LoadingScreen.ProgressBar.Value = 0;
var sceneLoader = new SceneLoader();
CallDeferred(MethodName.AddChild, sceneLoader);
sceneLoader.LoadSceneRequest(sceneName);
sceneLoader.SceneReportedProgress += SceneLoader_SceneReportedProgress;
await ToSignal(sceneLoader, SceneLoader.SignalName.SceneLoaded);
var result = sceneLoader.LoadedScene;
sceneLoader.QueueFree();
return result;
LoadingScreen.ShowLoadingScreen();
LoadingScreen.ProgressBar.Value = 0;
var sceneLoader = new SceneLoader();
CallDeferred(MethodName.AddChild, sceneLoader);
sceneLoader.LoadSceneRequest(sceneName);
sceneLoader.SceneReportedProgress += SceneLoader_SceneReportedProgress;
await ToSignal(sceneLoader, SceneLoader.SignalName.SceneLoaded);
var result = sceneLoader.LoadedScene;
sceneLoader.QueueFree();
return result;
}
private void SceneLoader_SceneReportedProgress(double progress) => _reportedProgress = progress;
private async void OnOptions()
{
OptionsMenu.Show();
OptionsMenu.GameTab.GrabFocus();
OptionsMenu.Show();
OptionsMenu.GameTab.GrabFocus();
}
private async void OnGallery()
{
GalleryMenu.Show();
GalleryMenu.ItemButton1.GrabFocus();
GalleryMenu.Show();
GalleryMenu.ItemButton1.GrabFocus();
}
public void OnQuit() => AppLogic.Input(new AppLogic.Input.QuitGame());
public void OnSaveFileLoaded()
{
AppLogic.Input(new AppLogic.Input.SaveFileLoaded());
AppLogic.Input(new AppLogic.Input.SaveFileLoaded());
}
public void OnExitTree()
{
AppLogic.Stop();
AppBinding.Dispose();
AppRepo.Dispose();
AppLogic.Stop();
AppBinding.Dispose();
AppRepo.Dispose();
MainMenu.StartGame -= OnStartGame;
MainMenu.EnemyViewer -= OnEnemyViewer;
MainMenu.Quit -= OnQuit;
MainMenu.StartGame -= OnStartGame;
MainMenu.EnemyViewer -= OnEnemyViewer;
MainMenu.Gallery -= OnGallery;
MainMenu.Options -= OnOptions;
MainMenu.Quit -= OnQuit;
GalleryMenu.GalleryExited -= GalleryExited;
OptionsMenu.OptionsMenuExited -= OptionsMenu_OptionsMenuExited;
OptionsMenu.DeleteSaveData -= DeleteSaveData;
}
}

View File

@@ -10,13 +10,16 @@
process_mode = 3
script = ExtResource("1_rt73h")
[node name="ColorRect" type="ColorRect" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 1)
[node name="MainMenu" parent="." instance=ExtResource("2_1uiag")]
unique_name_in_owner = true
visible = false
[node name="LoadingScreen" parent="." instance=ExtResource("3_3st5l")]
unique_name_in_owner = true
visible = false
[node name="OptionsMenu" parent="." instance=ExtResource("2_v0mgf")]
unique_name_in_owner = true
@@ -26,8 +29,8 @@ visible = false
unique_name_in_owner = true
visible = false
[node name="VideoStreamPlayer" type="VideoStreamPlayer" parent="."]
[node name="LoadingScreen" parent="." instance=ExtResource("3_3st5l")]
unique_name_in_owner = true
visible = false
offset_right = 40.0
offset_bottom = 40.0
top_level = true
z_index = 999

View File

@@ -0,0 +1,6 @@
using Zennysoft.Game.Implementation;
public partial class AmbientSFXPlayer : DimmableAudioStreamPlayer
{
public override void _EnterTree() => FadeIn();
}

View File

@@ -0,0 +1 @@
uid://cstc8tdapyrst

View File

@@ -0,0 +1,6 @@
using Zennysoft.Game.Implementation;
public partial class AmbientSFXPlayer3D : DimmableAudioStreamPlayer3D
{
public override void _EnterTree() => FadeIn();
}

View File

@@ -0,0 +1 @@
uid://b83kye8yinfxs

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=25 format=3 uid="uid://brgi35xj3b4ud"]
[gd_scene load_steps=26 format=3 uid="uid://brgi35xj3b4ud"]
[ext_resource type="Script" uid="uid://cw100tox0ufsy" path="res://src/audio/SfxDatabase.cs" id="1_ojkqd"]
[ext_resource type="AudioStream" uid="uid://cye8wlqbx66h4" path="res://src/audio/sfx/player_heal.ogg" id="2_158j8"]
@@ -11,6 +11,7 @@
[ext_resource type="AudioStream" uid="uid://doeefxilh0luj" path="res://src/audio/sfx/ITEM_SORT.ogg" id="9_l6w22"]
[ext_resource type="AudioStream" uid="uid://4mk4hlse81if" path="res://src/audio/sfx/player_losehealth.ogg" id="10_kac56"]
[ext_resource type="AudioStream" uid="uid://dwp3ep3jddvrr" path="res://src/audio/sfx/UI_SELECT.ogg" id="10_nerso"]
[ext_resource type="AudioStream" uid="uid://ilf2s8ct2stt" path="res://src/audio/sfx/PLAYER_slower_slash.ogg" id="10_vyvit"]
[ext_resource type="AudioStream" uid="uid://oslvh60ec5gc" path="res://src/audio/sfx/UI_CANCEL_BACK.ogg" id="11_rloay"]
[ext_resource type="AudioStream" uid="uid://bo2u1ceci6k1i" path="res://src/audio/sfx/PLAYER_quicker_slash.ogg" id="13_fa8i8"]
[ext_resource type="AudioStream" uid="uid://na0lxb1lib11" path="res://src/audio/sfx/player_crit.ogg" id="14_p5cio"]
@@ -38,6 +39,7 @@ bus = &"SFX"
[node name="MoveSound" type="AudioStreamPlayer" parent="UI"]
unique_name_in_owner = true
stream = ExtResource("6_r16t0")
max_polyphony = 5
bus = &"SFX"
[node name="SelectSound" type="AudioStreamPlayer" parent="UI"]
@@ -67,11 +69,16 @@ unique_name_in_owner = true
stream = ExtResource("3_kac56")
bus = &"SFX"
[node name="WeaponSwingSound" type="AudioStreamPlayer" parent="Player"]
[node name="WeaponQuickSlashSound" type="AudioStreamPlayer" parent="Player"]
unique_name_in_owner = true
stream = ExtResource("13_fa8i8")
bus = &"SFX"
[node name="WeaponSlowSlashSound" type="AudioStreamPlayer" parent="Player"]
unique_name_in_owner = true
stream = ExtResource("10_vyvit")
bus = &"SFX"
[node name="CritSound" type="AudioStreamPlayer" parent="Player"]
unique_name_in_owner = true
stream = ExtResource("14_p5cio")

View File

@@ -24,7 +24,6 @@ public partial class SfxDatabase : Node
{SoundEffect.TakeDamage, TakeDamageSound },
{SoundEffect.HealVT, HealVTSound },
{SoundEffect.IncreaseStat, IncreaseStatSound },
{SoundEffect.WeaponSwing, WeaponSwingSound },
{SoundEffect.Crit, CritSound },
{SoundEffect.PickupItem, PickupItemSound },
{SoundEffect.OpenInventory, OpenInventorySound },
@@ -42,6 +41,8 @@ public partial class SfxDatabase : Node
{SoundEffect.TeleportToExit, TeleportToExitSound},
{SoundEffect.AbsorbHPFromAllEnemies, AbsorbHPFromAllEnemiesSound},
{SoundEffect.TurnAllEnemiesIntoHealingItems, TurnAllEnemiesIntoHealingItemsSound},
{SoundEffect.WeaponQuickSlash, WeaponQuickSlashSound },
{SoundEffect.WeaponSlowSlash, WeaponSlowSlashSound },
};
}
@@ -49,7 +50,8 @@ public partial class SfxDatabase : Node
[Node] private AudioStreamPlayer TakeDamageSound { get; set; } = default!;
[Node] private AudioStreamPlayer HealVTSound { get; set; } = default!;
[Node] private AudioStreamPlayer IncreaseStatSound { get; set; } = default!;
[Node] private AudioStreamPlayer WeaponSwingSound { get; set; } = default!;
[Node] private AudioStreamPlayer WeaponQuickSlashSound { get; set; } = default!;
[Node] private AudioStreamPlayer WeaponSlowSlashSound { get; set; } = default!;
[Node] private AudioStreamPlayer CritSound { get; set; } = default!;
[Node] private AudioStreamPlayer PickupItemSound { get; set; } = default!;
[Node] private AudioStreamPlayer OpenInventorySound { get; set; }
@@ -85,7 +87,6 @@ public enum SoundEffect
TakeDamage,
HealVT,
IncreaseStat,
WeaponSwing,
Crit,
PickupItem,
OpenInventory,
@@ -104,5 +105,7 @@ public enum SoundEffect
AbsorbHPFromAllEnemies,
SwapHPAndVT,
TurnAllEnemiesIntoHealingItems,
WeaponQuickSlash,
WeaponSlowSlash,
}

View File

@@ -54,111 +54,118 @@ public partial class DataViewer : Control, IDataViewer
public void OnReady()
{
BackButton.Pressed += BackButton_Pressed;
_enemies = [.. ModelPivot.GetChildren().Cast<EnemyModelView>()];
_currentModel = _enemies.First();
DisplayEnemy();
BackButton.Pressed += BackButton_Pressed;
_enemies = [.. ModelPivot.GetChildren().Cast<EnemyModelView>()];
_currentModel = _enemies.First();
DisplayEnemy();
}
public void OnEnterTree() => GetTree().Paused = false;
public void OnEnterTree()
{
GetTree().Paused = false;
}
public void OnExitTree() => GetTree().Paused = false;
public void OnExitTree()
{
GetTree().Paused = false;
BackButton.Pressed -= BackButton_Pressed;
}
private void BackButton_Pressed() => AppRepo.OnDataViewerExited();
public override void _Input(InputEvent @event)
{
if (BackButton.HasFocus() && @event.IsActionPressed(GameInputs.Interact))
{
GetTree().Paused = false;
BackButton.ReleaseFocus();
return;
}
if (BackButton.HasFocus() && @event.IsActionPressed(GameInputs.Interact))
{
GetTree().Paused = false;
BackButton.ReleaseFocus();
return;
}
if (_currentModel == null || BackButton.HasFocus())
return;
if (_currentModel == null || BackButton.HasFocus())
return;
if (@event.IsActionPressed(GameInputs.Attack))
_currentModel.PlayPrimaryAttackAnimation();
if (@event.IsActionPressed(GameInputs.InventorySort))
_currentModel.PlaySecondaryAttackAnimation();
if (Input.IsActionJustPressed(GameInputs.Inventory))
_currentModel.PlayActivateAnimation();
if (@event.IsActionPressed(GameInputs.EnemyViewerWalk))
_currentModel.PlayWalkAnimation();
if (@event.IsActionReleased(GameInputs.EnemyViewerWalk))
_currentModel.PlayIdleAnimation();
if (@event.IsActionPressed(GameInputs.Attack))
_currentModel.PlayPrimaryAttackAnimation();
if (@event.IsActionPressed(GameInputs.InventorySort))
_currentModel.PlaySecondaryAttackAnimation();
if (Input.IsActionJustPressed(GameInputs.Inventory))
_currentModel.PlayActivateAnimation();
if (@event.IsActionPressed(GameInputs.EnemyViewerWalk))
_currentModel.PlayWalkAnimation();
if (@event.IsActionReleased(GameInputs.EnemyViewerWalk))
_currentModel.PlayIdleAnimation();
if (@event.IsActionPressed(GameInputs.Interact))
{
GetTree().Paused = true;
BackButton.GrabFocus();
}
if (@event.IsActionPressed(GameInputs.Interact))
{
GetTree().Paused = true;
BackButton.GrabFocus();
}
if (@event.IsActionPressed(GameInputs.StrafeRight))
{
// Load next model
_enemies[_currentIndex].Hide();
if (_currentIndex == _enemies.Count - 1)
_currentIndex = 0;
else
_currentIndex++;
DisplayEnemy();
}
if (@event.IsActionPressed(GameInputs.StrafeLeft))
{
_enemies[_currentIndex].Hide();
// Load previous model
if (_currentIndex == 0)
_currentIndex = _enemies.Count - 1;
else
_currentIndex--;
DisplayEnemy();
}
if (@event.IsActionPressed(GameInputs.StrafeRight))
{
// Load next model
_enemies[_currentIndex].Hide();
if (_currentIndex == _enemies.Count - 1)
_currentIndex = 0;
else
_currentIndex++;
DisplayEnemy();
}
if (@event.IsActionPressed(GameInputs.StrafeLeft))
{
_enemies[_currentIndex].Hide();
// Load previous model
if (_currentIndex == 0)
_currentIndex = _enemies.Count - 1;
else
_currentIndex--;
DisplayEnemy();
}
}
public override void _Process(double delta)
{
if (_currentModel == null || BackButton.HasFocus())
return;
if (_currentModel == null || BackButton.HasFocus())
return;
var forwardStrength = Input.GetActionStrength(GameInputs.CameraForward);
Camera3D.Position = Camera3D.Position.MoveToward(CameraPivot.Position, _cameraSpeed * forwardStrength * (_cameraStartingPoint / 10));
var backStrength = Input.GetActionStrength(GameInputs.CameraBack);
Camera3D.Position = Camera3D.Position.MoveToward(CameraPivot.Position, -_cameraSpeed * backStrength * (_cameraStartingPoint / 10));
var leftStrength = Input.GetActionStrength(GameInputs.MoveLeft);
CameraPivot.RotateY(_cameraSpeed * leftStrength);
var rightStrength = Input.GetActionStrength(GameInputs.MoveRight);
CameraPivot.RotateY(-_cameraSpeed * rightStrength);
var forwardStrength = Input.GetActionStrength(GameInputs.CameraForward);
Camera3D.Position = Camera3D.Position.MoveToward(CameraPivot.Position, _cameraSpeed * forwardStrength * (_cameraStartingPoint / 10));
var backStrength = Input.GetActionStrength(GameInputs.CameraBack);
Camera3D.Position = Camera3D.Position.MoveToward(CameraPivot.Position, -_cameraSpeed * backStrength * (_cameraStartingPoint / 10));
var leftStrength = Input.GetActionStrength(GameInputs.MoveLeft);
CameraPivot.RotateY(_cameraSpeed * leftStrength);
var rightStrength = Input.GetActionStrength(GameInputs.MoveRight);
CameraPivot.RotateY(-_cameraSpeed * rightStrength);
Camera3D.Position = Camera3D.Position.Clamp(new Vector3(0, 0, _cameraStartingPoint / 2), new Vector3(0, 0, _cameraStartingPoint));
ModelPivot.Rotation = ModelPivot.Rotation.Clamp(Mathf.DegToRad(-60), Mathf.DegToRad(60));
Camera3D.Position = Camera3D.Position.Clamp(new Vector3(0, 0, _cameraStartingPoint / 2), new Vector3(0, 0, _cameraStartingPoint));
ModelPivot.Rotation = ModelPivot.Rotation.Clamp(Mathf.DegToRad(-60), Mathf.DegToRad(60));
if (_currentModel is EnemyModelView2D enemyModelView2D)
enemyModelView2D.SetCurrentDirection(_currentModel.GlobalBasis, -CameraPivot.Basis.Z);
if (_currentModel is EnemyModelView2D enemyModelView2D)
enemyModelView2D.SetCurrentDirection(_currentModel.GlobalBasis, -CameraPivot.Basis.Z);
}
private void DisplayEnemy()
{
_currentModel = _enemies[_currentIndex];
_currentModel = _enemies[_currentIndex];
var size = _currentModel.GetSize();
if (_currentModel is EnemyModelView2D)
_cameraStartingPoint = size.X / 50;
else
_cameraStartingPoint = size.X * 2;
var size = _currentModel.GetSize();
if (_currentModel is EnemyModelView2D)
_cameraStartingPoint = size.X / 50;
else
_cameraStartingPoint = size.X * 2;
Camera3D.Position = new Vector3(Camera3D.Position.X, Camera3D.Position.Y, _cameraStartingPoint);
EnemyName.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Name : "Placeholder Text";
Description.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Description : "Placeholder Text";
HPValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.MaximumHP : "Placeholder Text";
ATKValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.ATK : "Placeholder Text";
DEFValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.DEF : "Placeholder Text";
Drop1Value.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Drop1 : "Placeholder Text";
Drop2Value.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Drop2 : "Placeholder Text";
AffinityValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Affinity : "Placeholder Text";
WeaknessValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Weakness : "Placeholder Text";
Camera3D.Position = new Vector3(Camera3D.Position.X, Camera3D.Position.Y, _cameraStartingPoint);
EnemyName.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Name : "Placeholder Text";
Description.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Description : "Placeholder Text";
HPValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.MaximumHP : "Placeholder Text";
ATKValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.ATK : "Placeholder Text";
DEFValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.DEF : "Placeholder Text";
Drop1Value.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Drop1 : "Placeholder Text";
Drop2Value.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Drop2 : "Placeholder Text";
AffinityValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Affinity : "Placeholder Text";
WeaknessValue.Text = _currentModel.EnemyLoreInfo != null ? _currentModel.EnemyLoreInfo.Weakness : "Placeholder Text";
_enemies[_currentIndex].Show();
_enemies[_currentIndex].Show();
}
}

View File

@@ -0,0 +1,40 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using System.Linq;
using Zennysoft.Game.Ma;
using Zennysoft.Ma.Adapter;
using Zennysoft.Ma.Adapter.Entity;
[Meta(typeof(IAutoNode)), Id("debug")]
public partial class DebugInfo : Control
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] private IGame _game => this.DependOn<IGame>();
[Dependency] private IGameRepo _gameRepo => this.DependOn<IGameRepo>();
[Dependency] private IMap _map => this.DependOn<IMap>();
[Dependency] private IPlayer _player => this.DependOn<IPlayer>();
[Node] public Label MapName { get; set; }
[Node] public Label EnemyCount { get; set; }
[Node] public Label DeathCount { get; set; }
public void OnResolved()
{
_map.FloorLoaded += _map_FloorLoaded;
_gameRepo.EnemyDied += _gameRepo_EnemyDied;
_player.PlayerDied += _player_PlayerDied;
DeathCount.Text = _game.QuestData.DeathCount.ToString();
}
private void _gameRepo_EnemyDied(IEnemy obj) => EnemyCount.Text = (EnemyCount.Text.ToInt() - 1).ToString();
private void _map_FloorLoaded()
{
MapName.Text = _map.CurrentFloor.SceneFilePath.GetFile().TrimSuffix(".tscn");
EnemyCount.Text = _map.CurrentFloor.GetChild(0).GetChildren().OfType<IDungeonRoom>().Select(x => x.GetChildren().OfType<IEnemy>()).Count().ToString();
}
private void _player_PlayerDied() => DeathCount.Text = _game.QuestData.DeathCount.ToString();
}

View File

@@ -0,0 +1 @@
uid://c4g3frcpt0h36

View File

@@ -0,0 +1,82 @@
[gd_scene load_steps=4 format=3 uid="uid://t22s2y1t8ktc"]
[ext_resource type="Script" uid="uid://c4g3frcpt0h36" path="res://src/debug_info/DebugInfo.cs" id="1_6tk84"]
[ext_resource type="LabelSettings" uid="uid://b6f8ggy3ulonb" path="res://src/ui/label_settings/GeorgiaItalic.tres" id="1_i766g"]
[ext_resource type="Script" uid="uid://3fpuxsgdl8xe" path="res://src/utils/FpsCounter.cs" id="3_rco7p"]
[node name="DebugInfo" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_6tk84")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 20
theme_override_constants/margin_top = 20
theme_override_constants/margin_right = 20
theme_override_constants/margin_bottom = 20
[node name="VFlowContainer" type="VFlowContainer" parent="MarginContainer"]
layout_mode = 2
alignment = 2
[node name="FPS" type="HBoxContainer" parent="MarginContainer/VFlowContainer"]
layout_mode = 2
[node name="FPSLabel" type="Label" parent="MarginContainer/VFlowContainer/FPS"]
layout_mode = 2
text = "FPS:"
label_settings = ExtResource("1_i766g")
[node name="FPSCounter" type="Label" parent="MarginContainer/VFlowContainer/FPS"]
layout_mode = 2
label_settings = ExtResource("1_i766g")
script = ExtResource("3_rco7p")
[node name="MapInfo" type="HBoxContainer" parent="MarginContainer/VFlowContainer"]
layout_mode = 2
[node name="Map Name Label" type="Label" parent="MarginContainer/VFlowContainer/MapInfo"]
layout_mode = 2
text = "Map Name:"
label_settings = ExtResource("1_i766g")
[node name="MapName" type="Label" parent="MarginContainer/VFlowContainer/MapInfo"]
unique_name_in_owner = true
layout_mode = 2
label_settings = ExtResource("1_i766g")
[node name="EnemyInfo" type="HBoxContainer" parent="MarginContainer/VFlowContainer"]
layout_mode = 2
[node name="Enemy Count Label" type="Label" parent="MarginContainer/VFlowContainer/EnemyInfo"]
layout_mode = 2
text = "Number of enemies:"
label_settings = ExtResource("1_i766g")
[node name="EnemyCount" type="Label" parent="MarginContainer/VFlowContainer/EnemyInfo"]
unique_name_in_owner = true
layout_mode = 2
label_settings = ExtResource("1_i766g")
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VFlowContainer"]
layout_mode = 2
[node name="DeathCountLabel" type="Label" parent="MarginContainer/VFlowContainer/HBoxContainer"]
layout_mode = 2
text = "Player Death Count:"
label_settings = ExtResource("1_i766g")
[node name="DeathCount" type="Label" parent="MarginContainer/VFlowContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
label_settings = ExtResource("1_i766g")

View File

@@ -1,3 +1,3 @@
~ no_exit
Altar: This is the text that shows when you try to leave
Altar: There exists only one way forward.
=> END

View File

@@ -0,0 +1,48 @@
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
namespace Zennysoft.Game.Ma;
[Meta(typeof(IAutoNode))]
public partial class BossAModelView : EnemyModelView3D, INode3D
{
public override void _Notification(int what) => this.Notify(what);
[Node] public Node3D Armature { get; set; } = default!;
[Node] public Area3D Hitbox { get; set; } = default!;
[Node] public Node3D ExplodingModel { get; set; } = default!;
[Node] public AnimationPlayer DeathAnimation { get; set; } = default!;
[Signal] public delegate void OnDeathAnimationCompletedEventHandler();
public void Setup()
{
Hitbox.AreaEntered += Hitbox_AreaEntered;
DeathAnimation.AnimationFinished += DeathAnimation_AnimationFinished;
}
private void Hitbox_AreaEntered(Area3D area) => OnPlayerHit(new AttackEventArgs(AttackData));
private void DeathAnimation_AnimationFinished(StringName animName)
{
EmitSignal(SignalName.OnDeathAnimationCompleted);
}
public override void PlayDeathAnimation()
{
Armature.Hide();
ExplodingModel.Show();
DeathAnimation.Play("Animation");
}
public void OnExitTree()
{
Hitbox.AreaEntered -= Hitbox_AreaEntered;
DeathAnimation.AnimationFinished -= DeathAnimation_AnimationFinished;
}
}

View File

@@ -0,0 +1 @@
uid://cycffa0wn7sks

View File

@@ -0,0 +1 @@
uid://brnlf1ybd4mu

View File

@@ -1,8 +1,9 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma;
@@ -37,17 +38,30 @@ public partial class BossTypeA : Enemy, IHaveEngagePlayerBehavior, IHaveFollowBe
[Node] public Area3D PlayerDetector { get; set; } = default!;
private float _movementSpeed = 2.0f;
[Node] public Label BossHP { get; set; } = default!;
public void OnReady()
private Vector3 _previousPosition = Vector3.Zero;
public void OnResolved()
{
FollowBehavior.Init(NavigationAgent);
FollowBehavior.OnVelocityComputed += OnVelocityComputed;
EngagePlayerBehavior.TakeAction += PerformAction;
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
PlayerDetector.BodyExited += PlayerDetector_BodyExited;
_enemyLogic.Input(new EnemyLogic.Input.Idle());
SetPhysicsProcess(true);
var enemyModelView3D = EnemyModelView as BossAModelView;
enemyModelView3D.OnDeathAnimationCompleted += EnemyModelView3D_OnDeathAnimationCompleted;
}
public override void _Process(double delta)
{
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer || _enemyLogic.Value is EnemyLogic.State.Patrolling)
{
var velocity = (GlobalPosition - _previousPosition) / (float)delta;
if (velocity.IsZeroApprox())
_enemyLogic.Input(new EnemyLogic.Input.Idle());
else
_enemyLogic.Input(new EnemyLogic.Input.Move());
_previousPosition = GlobalPosition;
}
BossHP.Text = HealthComponent.CurrentHP.Value + "/" + HealthComponent.MaximumHP.Value;
}
public void OnPhysicsProcess(double delta)
@@ -66,10 +80,8 @@ public partial class BossTypeA : Enemy, IHaveEngagePlayerBehavior, IHaveFollowBe
protected void OnVelocityComputed(Vector3 safeVelocity)
{
Velocity = safeVelocity;
if (Velocity > Vector3.Zero)
_enemyLogic.Input(new EnemyLogic.Input.Move());
else
_enemyLogic.Input(new EnemyLogic.Input.Idle());
if (!Velocity.IsZeroApprox())
LookAtTarget(safeVelocity);
MoveAndSlide();
}
@@ -106,11 +118,34 @@ public partial class BossTypeA : Enemy, IHaveEngagePlayerBehavior, IHaveFollowBe
public override void Activate()
{
FollowBehavior.OnVelocityComputed += OnVelocityComputed;
EngagePlayerBehavior.TakeAction += PerformAction;
PlayerDetector.BodyEntered += PlayerDetector_BodyEntered;
PlayerDetector.BodyExited += PlayerDetector_BodyExited;
SetProcess(true);
SetPhysicsProcess(true);
Show();
EnemyHitbox.SetDeferred(CollisionShape3D.PropertyName.Disabled, false);
_enemyLogic.Input(new EnemyLogic.Input.Activate());
}
public override void Die()
{
SetProcess(false);
SetPhysicsProcess(false);
_enemyLogic.Input(new EnemyLogic.Input.Defeated());
_collisionShape.SetDeferred(CollisionShape3D.PropertyName.Disabled, true);
EnemyHitbox.SetDeferred(CollisionShape3D.PropertyName.Disabled, true);
_player.ExperiencePointsComponent.Gain(ExpGiven);
EnemyModelView.PlayDeathAnimation();
}
private void EnemyModelView3D_OnDeathAnimationCompleted()
{
CallDeferred(MethodName.QueueFree);
}
public override void Die() => QueueFree();
public void RotateToPlayer(float rotationAngle)
{
@@ -146,5 +181,6 @@ public partial class BossTypeA : Enemy, IHaveEngagePlayerBehavior, IHaveFollowBe
EngagePlayerBehavior.TakeAction -= PerformAction;
PlayerDetector.BodyEntered -= PlayerDetector_BodyEntered;
PlayerDetector.BodyExited -= PlayerDetector_BodyExited;
(EnemyModelView as BossAModelView).OnDeathAnimationCompleted -= EnemyModelView3D_OnDeathAnimationCompleted;
}
}

View File

@@ -1,7 +1,6 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Godot.Collections;
using System;
using System.Collections.Immutable;
using System.Linq;
@@ -25,6 +24,8 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
#region Dependencies
[Dependency] protected IPlayer _player => this.DependOn(() => GetParent().GetChildren().OfType<IPlayer>().Single());
[Dependency] protected IGameRepo _gameRepo => this.DependOn<IGameRepo>();
#endregion
public IHealthComponent HealthComponent { get; private set; }
@@ -56,7 +57,11 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
[Export] public double TelluricResistance { get; set; }
public ElementalResistanceSet ElementalResistanceSet => new ElementalResistanceSet(AeolicResistance, HydricResistance, IgenousResistance, FerrumResistance, TelluricResistance);
[Export] public double HolyResistance { get; set; }
[Export] public double CurseResistance { get; set; }
public ElementalResistanceSet ElementalResistanceSet => new ElementalResistanceSet(AeolicResistance, HydricResistance, IgenousResistance, FerrumResistance, TelluricResistance, HolyResistance, CurseResistance);
[Node] private AudioStreamPlayer3D _absorbSFX { get; set; } = default!;
[Node] private AudioStreamPlayer3D _hitSFX { get; set; } = default!;
@@ -67,16 +72,6 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
protected bool _activated = false;
private Vector3 _previousPosition = Vector3.Zero;
public Enemy()
{
HealthComponent = new HealthComponent(InitialHP);
HealthComponent.HealthReachedZero += Die;
HealthComponent.DamageTaken += TakeHit;
AttackComponent = new AttackComponent(InitialAttack);
DefenseComponent = new DefenseComponent(InitialDefense);
}
#region Godot methods
public void Setup()
{
@@ -87,6 +82,13 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
EnemyModelView.HitPlayer += EnemyModelView_HitPlayer;
EnemyBinding = _enemyLogic.Bind();
HealthComponent = new HealthComponent(InitialHP);
HealthComponent.HealthReachedZero += Die;
HealthComponent.DamageTaken += TakeHit;
AttackComponent = new AttackComponent(InitialAttack);
DefenseComponent = new DefenseComponent(InitialDefense);
EnemyBinding
.Handle((in EnemyLogic.Output.Activate _) =>
{
@@ -119,6 +121,8 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
this.Provide();
_enemyLogic.Start();
_previousPosition = GlobalPosition;
}
#endregion
@@ -161,6 +165,7 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
EnemyModelView.PlayDeathAnimation();
_hitSFX.Play();
_dieSFX.Play();
_gameRepo.OnEnemyDied(this);
var tweener = CreateTween();
tweener.TweenInterval(1.0f);
tweener.TweenCallback(Callable.From(QueueFree));
@@ -207,7 +212,8 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
var spawnPointsGodotCollection = new Godot.Collections.Array<Marker3D>(spawnPoints);
var randomSpawnPoint = spawnPointsGodotCollection.PickRandom();
GlobalPosition = randomSpawnPoint.GlobalPosition;
GlobalPosition = new Vector3(randomSpawnPoint.GlobalPosition.X, 0, randomSpawnPoint.GlobalPosition.Y);
_previousPosition = GlobalPosition;
if (this is IHavePatrolBehavior patrolEnemy)
patrolEnemy.PatrolBehavior.HomePosition = GlobalPosition;
@@ -220,16 +226,11 @@ public abstract partial class Enemy : CharacterBody3D, IEnemy, IProvide<IEnemyLo
protected void LookAtTarget(Vector3 targetPosition)
{
var velocity = GlobalPosition - _previousPosition;
if (velocity.IsZeroApprox())
{
_previousPosition = GlobalPosition;
if (GlobalPosition.IsEqualApprox(targetPosition))
return;
}
var lookDirection = GlobalPosition - targetPosition;
var look = new Vector3(lookDirection.X, GlobalPosition.Y, lookDirection.Z);
if (!look.IsEqualApprox(GlobalPosition))
if (GlobalPosition.DistanceTo(look) > 0.01)
LookAt(look, Vector3.Up);
}

View File

@@ -33,7 +33,7 @@ public abstract partial class Enemy2D : Enemy
if (_enemyLogic.Value is EnemyLogic.State.FollowPlayer || _enemyLogic.Value is EnemyLogic.State.Patrolling)
{
var velocity = (GlobalPosition - _previousPosition) / (float)delta;
if (velocity.IsZeroApprox())
if (velocity.Length() < 0.3f)
_enemyLogic.Input(new EnemyLogic.Input.Idle());
else
_enemyLogic.Input(new EnemyLogic.Input.Move());
@@ -69,4 +69,10 @@ public abstract partial class Enemy2D : Enemy
if (body is IPlayer)
_enemyLogic.Input(new EnemyLogic.Input.Alert());
}
public new void OnExitTree()
{
base.OnExitTree();
LineOfSight.BodyEntered -= LineOfSight_BodyEntered;
}
}

View File

@@ -84,18 +84,12 @@ public abstract partial class EnemyModelView : Node3D, IEnemyModelView
public virtual void PlayIdleAnimation()
{
if (!AnimationTree.HasAnimation("idle_front"))
return;
_walkSFX.Stop();
_stateMachine.Travel(_idleName, false);
}
public virtual void PlayWalkAnimation()
{
if (!AnimationTree.HasAnimation("idle_front_walking"))
return;
if (!_walkSFX.Playing)
_walkSFX.Play();
_stateMachine.Travel(_walkingName, false);
@@ -135,5 +129,6 @@ public abstract partial class EnemyModelView : Node3D, IEnemyModelView
{
if (AnimationTree != null)
AnimationTree.Get(_parametersPlayback).As<AnimationNodeStateMachinePlayback>().Stop();
AnimationTree.AnimationFinished -= AnimationTree_AnimationFinished;
}
}

View File

@@ -2,7 +2,6 @@ using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using System.Linq;
using Zennysoft.Ma.Adapter;
namespace Zennysoft.Game.Ma;
[Meta(typeof(IAutoNode))]
@@ -26,8 +25,6 @@ public partial class EnemyModelView2D : EnemyModelView, IEnemyModelView
EnemyDirection _enemyDirection { get; set; } = EnemyDirection.Forward;
public AttackData AttackData { get; set; }
public new void OnReady()
{
Hitbox.AreaEntered += Hitbox_AreaEntered;
@@ -53,6 +50,7 @@ public partial class EnemyModelView2D : EnemyModelView, IEnemyModelView
public override void PlayDeathAnimation()
{
AnimationPlayer.Stop();
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 0.1f, 0.8f);

View File

@@ -13,12 +13,27 @@ public partial class EnemyModelView3D : EnemyModelView
[Node] public MeshInstance3D MeshInstance { get; set; } = default!;
public override void PlayWalkAnimation()
{
_stateMachine.Travel(_walkingName, false);
}
public override void PlayIdleAnimation()
{
_stateMachine.Travel(_idleName, false);
}
public override Vector2 GetSize()
{
var aabb = MeshInstance.GetAabb();
return new Vector2(aabb.Size.X, aabb.Position.Abs().Y);
}
public override void PlayHitAnimation()
{
}
private void ChangeMaterial()
{
var material = new StandardMaterial3D
@@ -44,4 +59,4 @@ public partial class EnemyModelView3D : EnemyModelView
{
MeshInstance.Transparency = transparencyAmount;
}
}
}

View File

@@ -1,6 +1,7 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using System.Linq;
namespace Zennysoft.Game.Ma;

View File

@@ -42,10 +42,11 @@ script = ExtResource("1_xsluo")
[node name="CollisionShape" type="CollisionShape3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 2.0617, 0)
shape = SubResource("CapsuleShape3D_cwfph")
[node name="Collision" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.0617, 0)
[node name="Collision" type="Area3D" parent="Collision"]
collision_layer = 2048
@@ -83,11 +84,13 @@ collision_mask = 34
shape = SubResource("CylinderShape3D_drfkj")
[node name="Visual" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.975554, 0)
[node name="EnemyModelView" parent="Visual" instance=ExtResource("4_o3b7p")]
unique_name_in_owner = true
[node name="Components" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.0617, 0)
[node name="PatrolBehavior" parent="Components" instance=ExtResource("4_drfkj")]
unique_name_in_owner = true
@@ -98,8 +101,8 @@ _followSpeed = 150.0
[node name="EngagePlayerBehavior" parent="Components" instance=ExtResource("5_drfkj")]
unique_name_in_owner = true
_minimumAttackTime = 3.0
_maximumAttackTime = 7.0
_minimumAttackTime = 1.0
_maximumAttackTime = 3.0
_acquireTargetTime = 2.0
[node name="NavigationAgent" type="NavigationAgent3D" parent="Components"]
@@ -108,6 +111,7 @@ avoidance_enabled = true
radius = 1.0
[node name="SFX" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.0617, 0)
[node name="AbsorbSFX" type="AudioStreamPlayer3D" parent="SFX"]
unique_name_in_owner = true

View File

@@ -666,7 +666,7 @@ EnemyLoreInfo = SubResource("Resource_ivy74")
[node name="Sprite3D" type="Sprite3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0)
transform = Transform3D(6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 1.1044, 0)
pixel_size = 0.001
billboard = 2
shaded = true
@@ -697,7 +697,7 @@ animation = &"idle_left_walk"
[node name="Hitbox" type="Area3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, -0.152949, 0, 0)
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, -0.152949, 1.1044, 0)
collision_layer = 64
collision_mask = 64
@@ -722,11 +722,12 @@ anim_player = NodePath("../AnimationPlayer")
[node name="WalkSFX" type="AudioStreamPlayer3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.1044, 0)
autoplay = true
bus = &"SFX"
[node name="Shadow" type="Sprite3D" parent="."]
transform = Transform3D(0.115, 0, 0, 0, -5.02681e-09, 0.115, 0, -0.115, -5.02681e-09, -0.00018537, -1.10125, 0.0453106)
transform = Transform3D(0.115, 0, 0, 0, -5.02681e-09, 0.115, 0, -0.115, -5.02681e-09, -0.00018537, -0.942894, 0.0453106)
transparency = 0.1
cast_shadow = 0
texture_filter = 0

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dd0ia6isdqg61"
path="res://.godot/imported/Layer 1.png-bd8d0a308ff3daec4b133fe53712d0f8.ctex"
path.s3tc="res://.godot/imported/Layer 1.png-bd8d0a308ff3daec4b133fe53712d0f8.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 1.png"
dest_files=["res://.godot/imported/Layer 1.png-bd8d0a308ff3daec4b133fe53712d0f8.ctex"]
dest_files=["res://.godot/imported/Layer 1.png-bd8d0a308ff3daec4b133fe53712d0f8.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cnd08q34wa7ww"
path="res://.godot/imported/Layer 10.png-5bf815a3d9112f8b0f5c1d296d4c79d5.ctex"
path.s3tc="res://.godot/imported/Layer 10.png-5bf815a3d9112f8b0f5c1d296d4c79d5.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 10.png"
dest_files=["res://.godot/imported/Layer 10.png-5bf815a3d9112f8b0f5c1d296d4c79d5.ctex"]
dest_files=["res://.godot/imported/Layer 10.png-5bf815a3d9112f8b0f5c1d296d4c79d5.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bs4ico5ouo5d3"
path="res://.godot/imported/Layer 2.png-ad4263d32cc8125e5db988e6008f1261.ctex"
path.s3tc="res://.godot/imported/Layer 2.png-ad4263d32cc8125e5db988e6008f1261.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 2.png"
dest_files=["res://.godot/imported/Layer 2.png-ad4263d32cc8125e5db988e6008f1261.ctex"]
dest_files=["res://.godot/imported/Layer 2.png-ad4263d32cc8125e5db988e6008f1261.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://85ki5mc4h0vs"
path="res://.godot/imported/Layer 3.png-1664f998445a2cf068e7ca8f3d037c03.ctex"
path.s3tc="res://.godot/imported/Layer 3.png-1664f998445a2cf068e7ca8f3d037c03.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 3.png"
dest_files=["res://.godot/imported/Layer 3.png-1664f998445a2cf068e7ca8f3d037c03.ctex"]
dest_files=["res://.godot/imported/Layer 3.png-1664f998445a2cf068e7ca8f3d037c03.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bwt1m2frb3r0e"
path="res://.godot/imported/Layer 4.png-4fa071fc5d0751880691269fd66e4a38.ctex"
path.s3tc="res://.godot/imported/Layer 4.png-4fa071fc5d0751880691269fd66e4a38.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 4.png"
dest_files=["res://.godot/imported/Layer 4.png-4fa071fc5d0751880691269fd66e4a38.ctex"]
dest_files=["res://.godot/imported/Layer 4.png-4fa071fc5d0751880691269fd66e4a38.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://ckssl1np6vnlu"
path="res://.godot/imported/Layer 5.png-6605d9488d5f0dd4dfc3db6d6a436cde.ctex"
path.s3tc="res://.godot/imported/Layer 5.png-6605d9488d5f0dd4dfc3db6d6a436cde.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 5.png"
dest_files=["res://.godot/imported/Layer 5.png-6605d9488d5f0dd4dfc3db6d6a436cde.ctex"]
dest_files=["res://.godot/imported/Layer 5.png-6605d9488d5f0dd4dfc3db6d6a436cde.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://c4sqc6i3xcfac"
path="res://.godot/imported/Layer 6.png-b4a8ec7de19cfe292d93ce32d6ec9ee3.ctex"
path.s3tc="res://.godot/imported/Layer 6.png-b4a8ec7de19cfe292d93ce32d6ec9ee3.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 6.png"
dest_files=["res://.godot/imported/Layer 6.png-b4a8ec7de19cfe292d93ce32d6ec9ee3.ctex"]
dest_files=["res://.godot/imported/Layer 6.png-b4a8ec7de19cfe292d93ce32d6ec9ee3.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cawexe4wkosc8"
path="res://.godot/imported/Layer 7.png-488d3fb32cd66da8971597d23bd04ba8.ctex"
path.s3tc="res://.godot/imported/Layer 7.png-488d3fb32cd66da8971597d23bd04ba8.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 7.png"
dest_files=["res://.godot/imported/Layer 7.png-488d3fb32cd66da8971597d23bd04ba8.ctex"]
dest_files=["res://.godot/imported/Layer 7.png-488d3fb32cd66da8971597d23bd04ba8.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://d0j1vrx7xdnxl"
path="res://.godot/imported/Layer 8.png-f8c8423b6ef9e0c3d6ca5229445d34a6.ctex"
path.s3tc="res://.godot/imported/Layer 8.png-f8c8423b6ef9e0c3d6ca5229445d34a6.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 8.png"
dest_files=["res://.godot/imported/Layer 8.png-f8c8423b6ef9e0c3d6ca5229445d34a6.ctex"]
dest_files=["res://.godot/imported/Layer 8.png-f8c8423b6ef9e0c3d6ca5229445d34a6.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://d0qhndaukki7c"
path="res://.godot/imported/Layer 9.png-caabc67ddb2476f5761c0554d0b4b68d.ctex"
path.s3tc="res://.godot/imported/Layer 9.png-caabc67ddb2476f5761c0554d0b4b68d.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/ATTACK/Layer 9.png"
dest_files=["res://.godot/imported/Layer 9.png-caabc67ddb2476f5761c0554d0b4b68d.ctex"]
dest_files=["res://.godot/imported/Layer 9.png-caabc67ddb2476f5761c0554d0b4b68d.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://b8ntr7hh6rr5h"
path="res://.godot/imported/Layer 1.png-1af20796814e6cbd19ad152136cda4bf.ctex"
path.s3tc="res://.godot/imported/Layer 1.png-1af20796814e6cbd19ad152136cda4bf.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 1.png"
dest_files=["res://.godot/imported/Layer 1.png-1af20796814e6cbd19ad152136cda4bf.ctex"]
dest_files=["res://.godot/imported/Layer 1.png-1af20796814e6cbd19ad152136cda4bf.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cj3m4eyagiye6"
path="res://.godot/imported/Layer 10.png-90e454e5b43acbf1f2a8a10b75127361.ctex"
path.s3tc="res://.godot/imported/Layer 10.png-90e454e5b43acbf1f2a8a10b75127361.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 10.png"
dest_files=["res://.godot/imported/Layer 10.png-90e454e5b43acbf1f2a8a10b75127361.ctex"]
dest_files=["res://.godot/imported/Layer 10.png-90e454e5b43acbf1f2a8a10b75127361.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cyigr4eip1mxt"
path="res://.godot/imported/Layer 11.png-dbe72027bf9e28d92151e3eb5302a235.ctex"
path.s3tc="res://.godot/imported/Layer 11.png-dbe72027bf9e28d92151e3eb5302a235.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 11.png"
dest_files=["res://.godot/imported/Layer 11.png-dbe72027bf9e28d92151e3eb5302a235.ctex"]
dest_files=["res://.godot/imported/Layer 11.png-dbe72027bf9e28d92151e3eb5302a235.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://kavqjxq17m0p"
path="res://.godot/imported/Layer 12.png-d451de2058e6cabf245a4e14055ca3ff.ctex"
path.s3tc="res://.godot/imported/Layer 12.png-d451de2058e6cabf245a4e14055ca3ff.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 12.png"
dest_files=["res://.godot/imported/Layer 12.png-d451de2058e6cabf245a4e14055ca3ff.ctex"]
dest_files=["res://.godot/imported/Layer 12.png-d451de2058e6cabf245a4e14055ca3ff.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bcce7b4wp6a4v"
path="res://.godot/imported/Layer 13.png-1670c6688dbe65fb29a169a6d186e0b8.ctex"
path.s3tc="res://.godot/imported/Layer 13.png-1670c6688dbe65fb29a169a6d186e0b8.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 13.png"
dest_files=["res://.godot/imported/Layer 13.png-1670c6688dbe65fb29a169a6d186e0b8.ctex"]
dest_files=["res://.godot/imported/Layer 13.png-1670c6688dbe65fb29a169a6d186e0b8.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://doiu8sug4t8ki"
path="res://.godot/imported/Layer 14.png-e35d02a2d0d59dec0fd9b289c503195f.ctex"
path.s3tc="res://.godot/imported/Layer 14.png-e35d02a2d0d59dec0fd9b289c503195f.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 14.png"
dest_files=["res://.godot/imported/Layer 14.png-e35d02a2d0d59dec0fd9b289c503195f.ctex"]
dest_files=["res://.godot/imported/Layer 14.png-e35d02a2d0d59dec0fd9b289c503195f.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dqymhvgu03xpl"
path="res://.godot/imported/Layer 15.png-4b38e38c90b8333b6dc347487db05eec.ctex"
path.s3tc="res://.godot/imported/Layer 15.png-4b38e38c90b8333b6dc347487db05eec.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 15.png"
dest_files=["res://.godot/imported/Layer 15.png-4b38e38c90b8333b6dc347487db05eec.ctex"]
dest_files=["res://.godot/imported/Layer 15.png-4b38e38c90b8333b6dc347487db05eec.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://csgthlou2tnvb"
path="res://.godot/imported/Layer 2.png-ca42949b60502fbe8427c1345eb19d2c.ctex"
path.s3tc="res://.godot/imported/Layer 2.png-ca42949b60502fbe8427c1345eb19d2c.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 2.png"
dest_files=["res://.godot/imported/Layer 2.png-ca42949b60502fbe8427c1345eb19d2c.ctex"]
dest_files=["res://.godot/imported/Layer 2.png-ca42949b60502fbe8427c1345eb19d2c.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cfyxuk85350gn"
path="res://.godot/imported/Layer 3.png-3a515f85c9b04eb7a48348228229101a.ctex"
path.s3tc="res://.godot/imported/Layer 3.png-3a515f85c9b04eb7a48348228229101a.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 3.png"
dest_files=["res://.godot/imported/Layer 3.png-3a515f85c9b04eb7a48348228229101a.ctex"]
dest_files=["res://.godot/imported/Layer 3.png-3a515f85c9b04eb7a48348228229101a.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dufdb5gc0gfkr"
path="res://.godot/imported/Layer 4.png-c7bf5b449416964c0b42e32b468194e8.ctex"
path.s3tc="res://.godot/imported/Layer 4.png-c7bf5b449416964c0b42e32b468194e8.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 4.png"
dest_files=["res://.godot/imported/Layer 4.png-c7bf5b449416964c0b42e32b468194e8.ctex"]
dest_files=["res://.godot/imported/Layer 4.png-c7bf5b449416964c0b42e32b468194e8.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://buu4btd3adrr4"
path="res://.godot/imported/Layer 5.png-4910e8406f750016c64e9645ece384cd.ctex"
path.s3tc="res://.godot/imported/Layer 5.png-4910e8406f750016c64e9645ece384cd.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 5.png"
dest_files=["res://.godot/imported/Layer 5.png-4910e8406f750016c64e9645ece384cd.ctex"]
dest_files=["res://.godot/imported/Layer 5.png-4910e8406f750016c64e9645ece384cd.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://ddgctjau0dnmh"
path="res://.godot/imported/Layer 6.png-5089fecd867d9797ab7d87b3a86569e2.ctex"
path.s3tc="res://.godot/imported/Layer 6.png-5089fecd867d9797ab7d87b3a86569e2.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 6.png"
dest_files=["res://.godot/imported/Layer 6.png-5089fecd867d9797ab7d87b3a86569e2.ctex"]
dest_files=["res://.godot/imported/Layer 6.png-5089fecd867d9797ab7d87b3a86569e2.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

View File

@@ -3,19 +3,20 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://2jwaacvarrha"
path="res://.godot/imported/Layer 7.png-f2b0baf1eb6fc935d3bf1495fadacd18.ctex"
path.s3tc="res://.godot/imported/Layer 7.png-f2b0baf1eb6fc935d3bf1495fadacd18.s3tc.ctex"
metadata={
"vram_texture": false
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://src/enemy/enemy_types/01. sproingy/animations/IDLE_WALK_BACK/Layer 7.png"
dest_files=["res://.godot/imported/Layer 7.png-f2b0baf1eb6fc935d3bf1495fadacd18.ctex"]
dest_files=["res://.godot/imported/Layer 7.png-f2b0baf1eb6fc935d3bf1495fadacd18.s3tc.ctex"]
[params]
compress/mode=0
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1

Some files were not shown because too many files have changed in this diff Show More