Implement most jewels

This commit is contained in:
2026-02-12 02:36:25 -08:00
parent 230b47061d
commit b475df6f68
27 changed files with 681 additions and 162 deletions

View File

@@ -4,6 +4,7 @@ using Chickensoft.Introspection;
using Godot;
using SimpleInjector;
using System;
using System.Linq;
using Zennysoft.Ma.Adapter;
using Zennysoft.Ma.Adapter.Entity;
@@ -100,7 +101,17 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
#endregion
public bool CanEquipState { get; set; } = true;
[Export]
public int HealthTimerHPRate { get; set; } = 2;
[Export]
public bool AutoIdentifyItems { get; set; } = false;
[Export]
public float HealthTimerSpeedModifier { get; set; } = 1f;
[Export]
public bool AutoRevive { get; set; } = false;
private bool flipAttack = false;
@@ -126,6 +137,7 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
PlayerLogic.Set(Settings);
Inventory = new Inventory();
Inventory.InventoryChanged += Inventory_InventoryChanged;
HealthComponent = new HealthComponent(InitialHP);
VTComponent = new VTComponent(InitialVT);
AttackComponent = new AttackComponent(InitialAttack);
@@ -208,6 +220,19 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
HealthTimer.Stop();
}
public void ModifyHealthTimerSpeed(float newSpeed)
{
HealthTimerSpeedModifier = newSpeed;
HealthTimer.Stop();
HealthTimer.WaitTime = _healthTimerWaitTime * newSpeed;
HealthTimer.Start();
}
public void ModifyHealthRecoveryAmount(int newAmount)
{
}
public void TeleportPlayer((Vector3 Rotation, Vector3 Position) newTransform)
{
Rotation = newTransform.Rotation;
@@ -231,6 +256,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
public void PlayJumpScareAnimation() => PlayerFXAnimations.Play("jump_scare");
public void IdentifyItem(InventoryItem unidentifiedItem) => _itemReroller.RerollItem(unidentifiedItem, Inventory);
public int TotalAttack => AttackComponent.CurrentAttack.Value + EquipmentComponent.BonusAttack;
public int TotalDefense => DefenseComponent.CurrentDefense.Value + EquipmentComponent.BonusDefense;
@@ -245,6 +272,10 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
public void Die()
{
PlayerFXAnimations.Play("death");
if (AutoRevive)
return;
HealthTimer.WaitTime = _healthTimerWaitTime;
HealthTimer.Timeout -= OnHealthTimerTimeout;
SetProcessInput(false);
@@ -279,8 +310,9 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
HealthComponent.RaiseMaximumHP(equipable.BonusHP, false);
VTComponent.RaiseMaximumVT(equipable.BonusVT, false);
//if (equipable.Augment != null)
// Augment(equipable.Augment, equipable);
if (equipable.Augment != null)
equipable.Augment.AugmentType.Apply();
EquipmentComponent.Equip(equipable);
SfxDatabase.Instance.Play(SoundEffect.Equip);
@@ -293,8 +325,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
HealthComponent.SetMaximumHealth(HealthComponent.MaximumHP.Value - equipable.BonusHP);
VTComponent.SetMaximumVT(VTComponent.MaximumVT.Value - equipable.BonusVT);
//if (equipable.Augment != null)
// Deaugment(equipable.Augment);
if (equipable.Augment != null)
equipable.Augment.AugmentType.Remove();
EquipmentComponent.Unequip(equipable);
SfxDatabase.Instance.Play(SoundEffect.Unequip);
@@ -303,35 +335,175 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
PersuaderCrosshair.Hide();
}
//public void ApplyNewAugment(Jewel jewel, EquipableItem equipableItem)
//{
// _player.Inventory.Remove(jewel);
// jewel.ApplyAugment((dynamic)equipableItem);
// if (!_player.EquipmentComponent.IsItemEquipped(equipableItem))
// return;
// if (jewel.Stats.JewelTag == JewelTags.IncreaseEXPGain)
// _player.ExperiencePointsComponent.ModifyExpGainRate(_player.ExperiencePointsComponent.ExpGainRate.Value + 0.25f);
//}
private void Augment(IAugmentItem augment, EquipableItem equipable)
public void ApplyNewAugment(IAugmentItem augmentItem, EquipableItem equipableItem)
{
var jewel = augment as Jewel;
switch (augment.Augment)
var jewel = augmentItem as Jewel;
Inventory.Remove(jewel);
ApplyNewAugment((dynamic)equipableItem, jewel.Augment);
if (EquipmentComponent.IsItemEquipped(equipableItem))
equipableItem.Augment.AugmentType.Apply();
}
private void ApplyNewAugment(Weapon weapon, JewelTags tag)
{
switch (tag)
{
case JewelTags.IncreaseEXPGain:
ExperiencePointsComponent.ModifyExpGainRate(ExperiencePointsComponent.ExpGainRate.Value + 0.25f);
case JewelTags.AeolicElement:
weapon.Stats.WeaponElement = ElementType.Aeolic;
weapon.Augment = new Augment(JewelTags.AeolicElement, new BasicAugment());
break;
case JewelTags.HydricElement:
weapon.Stats.WeaponElement = ElementType.Hydric;
weapon.Augment = new Augment(JewelTags.HydricElement, new BasicAugment());
break;
case JewelTags.SlowVTReduction:
weapon.Augment = new Augment(JewelTags.SlowVTReduction, new SlowVTReductionAugment(this));
break;
case JewelTags.HastenVT:
weapon.Augment = new Augment(JewelTags.HastenVT, new HastenVTAugment(this));
break;
case JewelTags.ReviveUserOnce:
weapon.Augment = new Augment(JewelTags.ReviveUserOnce, new RevivePlayerAugment(this));
break;
case JewelTags.IncreaseHPRecovery:
weapon.Augment = new Augment(JewelTags.IncreaseHPRecovery, new HPRecoverySpeedAugment(this));
break;
case JewelTags.LowerEXPGain:
weapon.Augment = new Augment(JewelTags.LowerEXPGain, new LowerEXPRateAugment(this));
break;
case JewelTags.ItemRescue:
Inventory.Remove(weapon);
break;
case JewelTags.Glue:
weapon.Glued = true;
weapon.Augment = new Augment(JewelTags.Glue, new BasicAugment());
break;
case JewelTags.TelluricElement:
weapon.Stats.WeaponElement = ElementType.Telluric;
weapon.Augment = new Augment(JewelTags.TelluricElement, new BasicAugment());
break;
case JewelTags.AutoIdentifyAllItems:
weapon.Augment = new Augment(JewelTags.AutoIdentifyAllItems, new IdentifyAllItemsAugment(this));
break;
case JewelTags.IncreaseAtkDefLuck:
weapon.Stats.BonusAttack += 2;
weapon.Stats.BonusDefense += 2;
weapon.Stats.BonusLuck += 10;
weapon.Augment = new Augment(JewelTags.IncreaseAtkDefLuck, new BasicAugment());
break;
case JewelTags.IncreaseLuck:
weapon.Stats.BonusLuck += 25;
weapon.Augment = new Augment(JewelTags.IncreaseLuck, new BasicAugment());
break;
}
}
private void Deaugment(Augment augment)
private void ApplyNewAugment(Armor armor, JewelTags tag)
{
switch (augment.AugmentTag)
switch (tag)
{
case JewelTags.IncreaseEXPGain:
ExperiencePointsComponent.ModifyExpGainRate(ExperiencePointsComponent.ExpGainRate.Value - 0.25f);
case JewelTags.AeolicElement:
armor.Stats.AeolicResistance += 25;
armor.Augment = new Augment(JewelTags.AeolicElement, new BasicAugment());
break;
case JewelTags.HydricElement:
armor.Stats.HydricResistance += 25;
armor.Augment = new Augment(JewelTags.HydricElement, new BasicAugment());
break;
case JewelTags.SlowVTReduction:
armor.Augment = new Augment(JewelTags.SlowVTReduction, new SlowVTReductionAugment(this));
break;
case JewelTags.HastenVT:
armor.Augment = new Augment(JewelTags.HastenVT, new HastenVTAugment(this));
break;
case JewelTags.ReviveUserOnce:
armor.Augment = new Augment(JewelTags.ReviveUserOnce, new RevivePlayerAugment(this));
break;
case JewelTags.IncreaseHPRecovery:
armor.Augment = new Augment(JewelTags.IncreaseHPRecovery, new HPRecoverySpeedAugment(this));
break;
case JewelTags.LowerEXPGain:
armor.Augment = new Augment(JewelTags.LowerEXPGain, new LowerEXPRateAugment(this));
break;
case JewelTags.ItemRescue:
Inventory.Remove(armor);
break;
case JewelTags.Glue:
armor.Glued = true;
armor.Augment = new Augment(JewelTags.Glue, new BasicAugment());
break;
case JewelTags.TelluricElement:
armor.Stats.TelluricResistance += 25;
armor.Augment = new Augment(JewelTags.TelluricElement, new BasicAugment());
break;
case JewelTags.AutoIdentifyAllItems:
armor.Augment = new Augment(JewelTags.AutoIdentifyAllItems, new IdentifyAllItemsAugment(this));
break;
case JewelTags.IncreaseAtkDefLuck:
armor.Stats.BonusAttack += 2;
armor.Stats.BonusDefense += 2;
armor.Stats.BonusLuck += 10;
armor.Augment = new Augment(JewelTags.IncreaseAtkDefLuck, new BasicAugment());
break;
case JewelTags.IncreaseLuck:
armor.Stats.BonusLuck += 25;
armor.Augment = new Augment(JewelTags.IncreaseLuck, new BasicAugment());
break;
}
}
private void ApplyNewAugment(Accessory accessory, JewelTags tag)
{
switch (tag)
{
case JewelTags.AeolicElement:
accessory.Stats.AeolicResistance += 25;
accessory.Augment = new Augment(JewelTags.AeolicElement, new BasicAugment());
break;
case JewelTags.HydricElement:
accessory.Stats.HydricResistance += 25;
accessory.Augment = new Augment(JewelTags.HydricElement, new BasicAugment());
break;
case JewelTags.SlowVTReduction:
accessory.Augment = new Augment(JewelTags.SlowVTReduction, new SlowVTReductionAugment(this));
break;
case JewelTags.HastenVT:
accessory.Augment = new Augment(JewelTags.HastenVT, new HastenVTAugment(this));
break;
case JewelTags.ReviveUserOnce:
accessory.Augment = new Augment(JewelTags.ReviveUserOnce, new RevivePlayerAugment(this));
break;
case JewelTags.IncreaseHPRecovery:
accessory.Augment = new Augment(JewelTags.IncreaseHPRecovery, new HPRecoverySpeedAugment(this));
break;
case JewelTags.LowerEXPGain:
accessory.Augment = new Augment(JewelTags.LowerEXPGain, new LowerEXPRateAugment(this));
break;
case JewelTags.ItemRescue:
Inventory.Remove(accessory);
break;
case JewelTags.Glue:
accessory.Glued = true;
accessory.Augment = new Augment(JewelTags.Glue, new BasicAugment());
break;
case JewelTags.TelluricElement:
accessory.Stats.TelluricResistance += 25;
accessory.Augment = new Augment(JewelTags.TelluricElement, new BasicAugment());
break;
case JewelTags.AutoIdentifyAllItems:
accessory.Augment = new Augment(JewelTags.AutoIdentifyAllItems, new IdentifyAllItemsAugment(this));
break;
case JewelTags.IncreaseAtkDefLuck:
accessory.Stats.BonusAttack += 2;
accessory.Stats.BonusDefense += 2;
accessory.Stats.BonusLuck += 10;
accessory.Augment = new Augment(JewelTags.IncreaseAtkDefLuck, new BasicAugment());
break;
case JewelTags.IncreaseLuck:
accessory.Stats.BonusLuck += 25;
accessory.Augment = new Augment(JewelTags.IncreaseLuck, new BasicAugment());
break;
}
}
@@ -456,7 +628,42 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
private void PlayerFXAnimations_AnimationFinished(StringName animName)
{
if (animName == "death")
PlayerDied?.Invoke();
{
if (AutoRevive)
PlayerFXAnimations.PlayBackwards("revive");
else
PlayerDied?.Invoke();
}
if (animName == "revive")
{
Revive();
}
}
private void Revive()
{
HealthComponent.SetCurrentHealth(HealthComponent.MaximumHP.Value);
VTComponent.SetVT(VTComponent.MaximumVT.Value);
if (EquipmentComponent.EquippedAccessory.Value.Augment?.AugmentTag == JewelTags.ReviveUserOnce)
{
var itemToBreak = EquipmentComponent.EquippedAccessory.Value;
Unequip(EquipmentComponent.EquippedAccessory.Value);
Inventory.Remove(itemToBreak);
}
else if (EquipmentComponent.EquippedArmor.Value.Augment?.AugmentTag == JewelTags.ReviveUserOnce)
{
var itemToBreak = EquipmentComponent.EquippedArmor.Value;
Unequip(EquipmentComponent.EquippedArmor.Value);
Inventory.Remove(itemToBreak);
}
else if (EquipmentComponent.EquippedWeapon.Value.Augment?.AugmentTag == JewelTags.ReviveUserOnce)
{
var itemToBreak = EquipmentComponent.EquippedWeapon.Value;
Unequip(EquipmentComponent.EquippedWeapon.Value);
Inventory.Remove(itemToBreak);
}
else
PlayJumpScareAnimation();
}
private void InverseHPToAttackPowerSync(int obj)
@@ -595,4 +802,16 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide<IPlayer>
GD.Print("Hit wall");
WeaponAnimations.Stop();
}
private void Inventory_InventoryChanged()
{
if (AutoIdentifyItems)
{
foreach (var item in Inventory.Items.ToList())
{
if (item.ItemTag == ItemTag.MysteryItem)
IdentifyItem(item);
}
}
}
}

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=1585 format=3 uid="uid://cfecvvav8kkp6"]
[gd_scene load_steps=1586 format=3 uid="uid://cfecvvav8kkp6"]
[ext_resource type="Script" uid="uid://yxmiqy7i0t7r" path="res://src/player/Player.cs" id="1_xcol5"]
[ext_resource type="PackedScene" uid="uid://didc6vnf5ftlg" path="res://src/camera/ShakeCamera.tscn" id="2_jtmj1"]
@@ -780,70 +780,6 @@ tracks/12/keys = {
"values": [127]
}
[sub_resource type="Animation" id="Animation_es4xk"]
resource_name = "death"
length = 2.5
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("../Camera/Camera3D:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 2),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(0.003, 2.1, -0.01), Vector3(0.003, 0, -1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(3.35872e-05),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("4_v5qoq")]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/colorCount")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(-0.266666, 0, 0.0333338),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector3(640.06, 1, 640), Vector3(640, 640, 640), Vector3(640.06, 1, 640)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/includeAlpha")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/colorShift")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 2.5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(1, 1, 1), Vector3(1, 1, 0)]
}
[sub_resource type="Animation" id="Animation_ebyyx"]
resource_name = "hit_wall"
length = 0.453127
@@ -930,6 +866,134 @@ tracks/1/keys = {
"values": [0, 30]
}
[sub_resource type="Animation" id="Animation_es4xk"]
resource_name = "death"
length = 2.5
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("../Camera/Camera3D:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 2),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(0.003, 2.1, -0.01), Vector3(0.003, 0, -1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(3.35872e-05),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("4_v5qoq")]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/colorCount")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(-0.266666, 0, 0.0333338),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector3(640.06, 1, 640), Vector3(640, 640, 640), Vector3(640.06, 1, 640)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/includeAlpha")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/colorShift")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 2.5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(1, 1, 1), Vector3(1, 1, 0)]
}
[sub_resource type="Animation" id="Animation_sq73w"]
resource_name = "revive"
length = 2.5
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("../Camera/Camera3D:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 2),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(0.003, 2.1, -0.01), Vector3(0.003, 0, -1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(3.35872e-05),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("4_v5qoq")]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/colorCount")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(-0.266666, 0, 0.0333338),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector3(640.06, 1, 640), Vector3(640, 640, 640), Vector3(640.06, 1, 640)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/includeAlpha")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("../Camera/Camera3D/MeshInstance3D:mesh:material:shader_parameter/colorShift")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0, 2.5),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Vector3(1, 1, 1), Vector3(1, 1, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ebyyx"]
_data = {
&"Divinity_Recall": SubResource("Animation_j5wmh"),
@@ -939,7 +1003,8 @@ _data = {
&"death": SubResource("Animation_es4xk"),
&"hit_wall": SubResource("Animation_ebyyx"),
&"jump_scare": SubResource("Animation_wvcio"),
&"normal_attack": SubResource("Animation_v5qoq")
&"normal_attack": SubResource("Animation_v5qoq"),
&"revive": SubResource("Animation_sq73w")
}
[sub_resource type="Animation" id="Animation_74hqa"]
@@ -10273,6 +10338,7 @@ collision_layer = 802
collision_mask = 775
script = ExtResource("1_xcol5")
HealthTimerIsActive = true
AutoRevive = true
[node name="MainCollision" type="CollisionShape3D" parent="."]
unique_name_in_owner = true