Basic sigil system implementation
This commit is contained in:
26
Zennysoft.Game.Ma.Implementation/Components/ISigil.cs
Normal file
26
Zennysoft.Game.Ma.Implementation/Components/ISigil.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Godot;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
namespace Zennysoft.Ma;
|
||||
public interface ISigil : IEntityComponent
|
||||
{
|
||||
public double AttackModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public double DefenseModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public int HealthModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public int VTModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public double LuckModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public double ElementalModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public ElementType ElementType { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Zennysoft.Ma;
|
||||
|
||||
public interface ISigilComponent
|
||||
{
|
||||
ISigil Sigil { get; set; }
|
||||
|
||||
public void Reset();
|
||||
}
|
||||
@@ -28,6 +28,8 @@ public interface IPlayer : IKillable, ICharacterBody3D
|
||||
|
||||
public void PlayJumpScareAnimation();
|
||||
|
||||
public void SetSigil(ISigil sigil);
|
||||
|
||||
public void ApplyNewAugment(IAugmentItem jewel, IAugmentableItem equipableItem);
|
||||
|
||||
public IBaseInventoryItem IdentifyItem(IBaseInventoryItem unidentifiedItem);
|
||||
@@ -50,6 +52,8 @@ public interface IPlayer : IKillable, ICharacterBody3D
|
||||
|
||||
public IStatusEffectComponent StatusEffectComponent { get; }
|
||||
|
||||
public ISigilComponent SigilComponent { get; }
|
||||
|
||||
public void SetHealthTimerStatus(bool isActive);
|
||||
|
||||
public void ModifyHealthTimerSpeed(float newModifier);
|
||||
|
||||
@@ -208,45 +208,6 @@ tracks/2/keys = {
|
||||
"values": [1.0]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_dvre5"]
|
||||
resource_name = "fade_out"
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("BOTTOM:transparency")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [0.0, 1.0]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("MIDDLE:transparency")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [0.0, 1.0]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("TOP:transparency")
|
||||
tracks/2/interp = 1
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [0.0, 1.0]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_5ayrc"]
|
||||
resource_name = "fade_in"
|
||||
tracks/0/type = "value"
|
||||
@@ -286,6 +247,45 @@ tracks/2/keys = {
|
||||
"values": [1.0, 0.0]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_dvre5"]
|
||||
resource_name = "fade_out"
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("BOTTOM:transparency")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [0.0, 1.0]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("MIDDLE:transparency")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [0.0, 1.0]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("TOP:transparency")
|
||||
tracks/2/interp = 1
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [0.0, 1.0]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_5ayrc"]
|
||||
_data = {
|
||||
&"RESET": SubResource("Animation_ijggi"),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://8f3dk16nj0dn"]
|
||||
[gd_scene load_steps=6 format=3 uid="uid://8f3dk16nj0dn"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://l1v4ppubryd3" path="res://src/ui/pause_menu/PauseDebugMenu.cs" id="1_a7f7f"]
|
||||
[ext_resource type="FontFile" uid="uid://dp1k143v7cppw" path="res://src/ui/fonts/Lust_Sans_Regular.otf" id="1_dan2i"]
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1ctjd"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dan2i"]
|
||||
|
||||
[node name="Control" type="Control"]
|
||||
process_mode = 3
|
||||
top_level = true
|
||||
@@ -81,8 +83,8 @@ label_settings = ExtResource("2_a7f7f")
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
focus_neighbor_top = NodePath("../SpawnItemDropDown")
|
||||
focus_neighbor_bottom = NodePath(".")
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_1ctjd")
|
||||
focus_neighbor_bottom = NodePath("../SigilDropDown")
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_dan2i")
|
||||
item_count = 15
|
||||
popup/item_0/text = "Sproingy"
|
||||
popup/item_0/id = 0
|
||||
@@ -115,6 +117,23 @@ popup/item_13/id = 13
|
||||
popup/item_14/text = "Gold Sproingy"
|
||||
popup/item_14/id = 14
|
||||
|
||||
[node name="Label3" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VFlowContainer"]
|
||||
layout_mode = 2
|
||||
text = "Sigil:"
|
||||
label_settings = ExtResource("2_a7f7f")
|
||||
|
||||
[node name="SigilDropDown" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer/VFlowContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
focus_neighbor_top = NodePath("../SpawnEnemyDropDown")
|
||||
focus_neighbor_bottom = NodePath("../LoadNextFloorButton")
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_1ctjd")
|
||||
flat = true
|
||||
allow_reselect = true
|
||||
item_count = 1
|
||||
popup/item_0/text = "None"
|
||||
popup/item_0/id = 0
|
||||
|
||||
[node name="LoadNextFloorButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer/VFlowContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using Zennysoft.Ma;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
@@ -24,6 +25,10 @@ public partial class DummyPlayer : CharacterBody3D, IPlayer
|
||||
public IStatusEffectComponent StatusEffectComponent { get; }
|
||||
public bool BriefImmunity { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public ISigil SigilComponent => throw new NotImplementedException();
|
||||
|
||||
ISigilComponent IPlayer.SigilComponent => throw new NotImplementedException();
|
||||
|
||||
public event Action PlayerDied;
|
||||
|
||||
public void Activate() => throw new NotImplementedException();
|
||||
@@ -43,4 +48,5 @@ public partial class DummyPlayer : CharacterBody3D, IPlayer
|
||||
public void Unequip(IEquipableItem equipable) => throw new NotImplementedException();
|
||||
public IBaseInventoryItem IdentifyItem(IBaseInventoryItem unidentifiedItem) => throw new NotImplementedException();
|
||||
public void EnactBriefImmunity() => throw new NotImplementedException();
|
||||
public void SetSigil(ISigil sigil) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Godot;
|
||||
using SimpleInjector;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Zennysoft.Ma;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
using Zennysoft.Ma.Adapter.Entity;
|
||||
|
||||
@@ -39,6 +40,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
|
||||
public IStatusEffectComponent StatusEffectComponent { get; private set; }
|
||||
|
||||
public ISigilComponent SigilComponent { get; set; }
|
||||
|
||||
public Vector3 CurrentPosition => GlobalPosition;
|
||||
|
||||
public Basis CurrentBasis => Transform.Basis;
|
||||
@@ -167,6 +170,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
LuckComponent = new LuckComponent(InitialLuck);
|
||||
EquipmentComponent = new EquipmentComponent();
|
||||
StatusEffectComponent = new StatusEffectComponent(RustDuration);
|
||||
SigilComponent = new SigilComponent();
|
||||
|
||||
_itemReroller = new ItemReroller(ItemDatabase.Instance);
|
||||
_playerEffectService = new PlayerEffectService(this);
|
||||
@@ -200,6 +204,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
ExperiencePointsComponent.Reset();
|
||||
LuckComponent.Reset();
|
||||
EquipmentComponent.Reset();
|
||||
SigilComponent.Reset();
|
||||
|
||||
HealthTimer.Timeout += OnHealthTimerTimeout;
|
||||
}
|
||||
@@ -292,7 +297,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
|
||||
_camera3D.AddShake(1.0f);
|
||||
TakeDamageAnimationPlayer.Play("take_damage");
|
||||
var damageReceived = DamageCalculator.CalculateDamage(damage, TotalDefense, EquipmentComponent.ElementalResistance);
|
||||
var defense = TotalDefense * SigilComponent.Sigil.DefenseModifier;
|
||||
var damageReceived = DamageCalculator.CalculateDamage(damage, defense, EquipmentComponent.ElementalResistance);
|
||||
HealthComponent.Damage(damageReceived, damage.ElementType);
|
||||
SfxDatabase.Instance.Play(SoundEffect.TakeDamage);
|
||||
|
||||
@@ -303,6 +309,11 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSigil(ISigil sigil)
|
||||
{
|
||||
SigilComponent.Sigil = sigil;
|
||||
}
|
||||
|
||||
public void Knockback(float impulse)
|
||||
{
|
||||
_knockbackStrength = impulse;
|
||||
@@ -899,14 +910,20 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
|
||||
var isCriticalHit = BattleExtensions.IsCriticalHit(TotalLuck);
|
||||
var totalDamage = TotalAttack;
|
||||
|
||||
if (isCriticalHit)
|
||||
if (SigilComponent.Sigil.ElementType == weapon.WeaponElement)
|
||||
totalDamage = Mathf.RoundToInt(totalDamage * 1.15f);
|
||||
|
||||
totalDamage = Mathf.RoundToInt(totalDamage * SigilComponent.Sigil.AttackModifier);
|
||||
|
||||
if (isCriticalHit)
|
||||
{
|
||||
totalDamage += (int)(totalDamage * 0.5f);
|
||||
SfxDatabase.Instance.Play(SoundEffect.Crit);
|
||||
}
|
||||
|
||||
var baseAttack = new AttackData(totalDamage, weapon.WeaponElement, weapon.WeaponTag == WeaponTag.IgnoreDefense, weapon.WeaponTag == WeaponTag.IgnoreAffinity);
|
||||
var damageDealt = DamageCalculator.CalculateDamage(baseAttack, enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet);
|
||||
|
||||
var damageDealt = DamageCalculator.CalculateDamage(baseAttack, enemy.DefenseComponent.CurrentDefense.Value, enemy.ElementalResistanceSet);
|
||||
enemy.HealthComponent.Damage(damageDealt, weapon.WeaponElement);
|
||||
|
||||
if (weapon.WeaponTag == WeaponTag.Knockback && enemy is IKnockbackable knockbackable)
|
||||
|
||||
14
Zennysoft.Game.Ma/src/sigil/FireSigil.tres
Normal file
14
Zennysoft.Game.Ma/src/sigil/FireSigil.tres
Normal file
@@ -0,0 +1,14 @@
|
||||
[gd_resource type="Resource" script_class="Sigil" load_steps=2 format=3 uid="uid://bxuswp8ril05h"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cp5pnpqbde161" path="res://src/sigil/Sigil.cs" id="1_ib6yo"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_ib6yo")
|
||||
AttackModifier = 1.25
|
||||
DefenseModifier = 0.75
|
||||
HealthModifier = 0
|
||||
VTModifier = 0
|
||||
LuckModifier = 0.0
|
||||
ElementalModifier = 0.0
|
||||
ElementType = 4
|
||||
metadata/_custom_type_script = "uid://cp5pnpqbde161"
|
||||
39
Zennysoft.Game.Ma/src/sigil/Sigil.cs
Normal file
39
Zennysoft.Game.Ma/src/sigil/Sigil.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Godot;
|
||||
using Zennysoft.Ma;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class Sigil : Resource, ISigil
|
||||
{
|
||||
[Export]
|
||||
public double AttackModifier { get; set; } = 1f;
|
||||
|
||||
[Export]
|
||||
public double DefenseModifier { get; set; } = 1f;
|
||||
|
||||
[Export]
|
||||
public int HealthModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public int VTModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public double LuckModifier { get; set; }
|
||||
|
||||
[Export]
|
||||
public double ElementalModifier { get; set; } = 1;
|
||||
|
||||
[Export]
|
||||
public ElementType ElementType { get; set; } = ElementType.None;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
AttackModifier = 1;
|
||||
DefenseModifier = 1;
|
||||
HealthModifier = 0;
|
||||
VTModifier = 0;
|
||||
LuckModifier = 0;
|
||||
ElementalModifier = 1;
|
||||
ElementType = ElementType.None;
|
||||
}
|
||||
}
|
||||
1
Zennysoft.Game.Ma/src/sigil/Sigil.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/sigil/Sigil.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cp5pnpqbde161
|
||||
11
Zennysoft.Game.Ma/src/sigil/SigilComponent.cs
Normal file
11
Zennysoft.Game.Ma/src/sigil/SigilComponent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Zennysoft.Ma;
|
||||
|
||||
public class SigilComponent : ISigilComponent
|
||||
{
|
||||
public ISigil Sigil { get; set; }
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Sigil = new Sigil();
|
||||
}
|
||||
}
|
||||
1
Zennysoft.Game.Ma/src/sigil/SigilComponent.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/sigil/SigilComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dr6mlubpgujk5
|
||||
@@ -24,6 +24,8 @@ public partial class PauseDebugMenu : Control, IDebugMenu
|
||||
|
||||
[Node] public OptionButton SpawnEnemyDropDown { get; set; } = default!;
|
||||
|
||||
[Node] public OptionButton SigilDropDown { get; set; } = default!;
|
||||
|
||||
[Node] public Button LoadNextFloorButton { get; set; } = default!;
|
||||
|
||||
[Node] public Button RustButton { get; set; } = default!;
|
||||
@@ -34,6 +36,7 @@ public partial class PauseDebugMenu : Control, IDebugMenu
|
||||
|
||||
private readonly string _floorFilePath = @"res://src/map/dungeon/floors/";
|
||||
private readonly string _enemyFilePath = @"res://src/enemy/enemy_types";
|
||||
private readonly string _sigilFilePath = @"res://src/sigil";
|
||||
|
||||
private ImmutableList<IBaseInventoryItem> _spawnableItems;
|
||||
private ImmutableList<string> _spawnableEnemies;
|
||||
@@ -80,6 +83,11 @@ public partial class PauseDebugMenu : Control, IDebugMenu
|
||||
FloorSelectDropDown.AddItem(folder + "/" + file);
|
||||
}
|
||||
|
||||
var sigils = DirAccess.GetFilesAt(_sigilFilePath).Where(x => x.EndsWith(".tres"));
|
||||
foreach (var sigil in sigils)
|
||||
SigilDropDown.AddItem(sigil);
|
||||
SigilDropDown.Select(0);
|
||||
|
||||
FloorSelectDropDown.AllowReselect = true;
|
||||
SpawnItemDropDown.AllowReselect = true;
|
||||
SpawnEnemyDropDown.AllowReselect = true;
|
||||
@@ -88,9 +96,25 @@ public partial class PauseDebugMenu : Control, IDebugMenu
|
||||
SpawnItemDropDown.ItemSelected += SpawnItemDropDown_ItemSelected;
|
||||
SpawnEnemyDropDown.ItemSelected += SpawnEnemyDropDown_ItemSelected;
|
||||
|
||||
SigilDropDown.ItemSelected += SigilDropDown_ItemSelected;
|
||||
|
||||
DebugInfoCheckbox.Pressed += DebugInfoCheckbox_Pressed;
|
||||
}
|
||||
|
||||
private void SigilDropDown_ItemSelected(long index)
|
||||
{
|
||||
var sigilName = SigilDropDown.GetItemText((int)index);
|
||||
if (sigilName == "None")
|
||||
{
|
||||
_player.SigilComponent.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
var sigilComponent = ResourceLoader.Load<Sigil>(_sigilFilePath + "/" + sigilName);
|
||||
_player.SetSigil(sigilComponent);
|
||||
}
|
||||
}
|
||||
|
||||
private void DebugInfoCheckbox_Pressed() => _game.ShowDebugInfo(DebugInfoCheckbox.ButtonPressed);
|
||||
|
||||
public bool DebugOverlayVisible => DebugInfoCheckbox.ButtonPressed;
|
||||
|
||||
Reference in New Issue
Block a user