hitting is now an ability

This commit is contained in:
2026-05-02 11:19:56 +02:00
parent 24f057c15f
commit fb30a08b89
19 changed files with 588 additions and 395 deletions

View File

@@ -9,6 +9,7 @@
[ext_resource type="PackedScene" uid="uid://c4ikbhojckpnc" path="res://scenes/components/health/CHealth.tscn" id="3_q7bng"]
[ext_resource type="Resource" uid="uid://bjyd801wvverk" path="res://scenes/player_controller/resources/player_health.tres" id="4_m8gvy"]
[ext_resource type="Resource" uid="uid://cpdaw41ah5gic" path="res://inputs/base_mode/rotate_y.tres" id="4_rxwoh"]
[ext_resource type="Resource" uid="uid://dgjsi1my7nlnk" path="res://forge/resources/ability_datas/player_hit.tres" id="4_u8yay"]
[ext_resource type="Resource" uid="uid://dh437cuxgjv6b" path="res://forge/resources/effect_datas/mana_regeneration.tres" id="5_2rkt1"]
[ext_resource type="Resource" uid="uid://ccrb5xsnphc8" path="res://inputs/base_mode/rotate_floorplane.tres" id="5_4u7i3"]
[ext_resource type="PackedScene" uid="uid://hpsg4fqwrx1u" path="res://scenes/components/damage/CDamageable.tscn" id="5_jb43f"]
@@ -131,6 +132,9 @@ height = 1.0
[sub_resource type="SphereShape3D" id="SphereShape3D_abfq8"]
radius = 2.0
[sub_resource type="SphereShape3D" id="SphereShape3D_ue7xq"]
radius = 1.5
[sub_resource type="SphereShape3D" id="SphereShape3D_cmijs"]
radius = 1.0
@@ -141,9 +145,6 @@ height = 3.5
[sub_resource type="SphereShape3D" id="SphereShape3D_nob5r"]
radius = 0.4
[sub_resource type="SphereShape3D" id="SphereShape3D_ue7xq"]
radius = 1.5
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_2q0ik"]
blend_mode = 1
@@ -156,6 +157,7 @@ script = ExtResource("1_poq2x")
BaseTags = SubResource("Resource_mpigw")
EmpoweredActionUsed = SubResource("Resource_5gbhg")
InvincibleTag = SubResource("Resource_2rkt1")
HitAbility = ExtResource("4_u8yay")
EmpoweredActionAbility = ExtResource("10_2rkt1")
DefaultGrantedAbilities = [ExtResource("5_u8yay")]
DefaultPermanentEffects = [ExtResource("5_2rkt1")]
@@ -236,12 +238,6 @@ stream = ExtResource("9_jb43f")
autoplay = true
bus = &"SFX"
[node name="WallRunSnapper" type="RayCast3D" parent="." unique_id=1342764801]
unique_name_in_owner = true
transform = Transform3D(0.99999994, 0, 0, 0, 1, 0, 0, 0, 0.99999994, 0, 0, 0)
target_position = Vector3(0, 0, -5)
collision_mask = 256
[node name="InputController" type="Node3D" parent="." unique_id=846069741]
script = ExtResource("16_v31n3")
base_mode = ExtResource("3_cresl")
@@ -412,6 +408,16 @@ target_position = Vector3(0, 0, 0)
max_results = 512
collision_mask = 16
[node name="SlidingEnemyDetector" type="Area3D" parent="." unique_id=42873532]
collision_layer = 0
collision_mask = 16
monitoring = false
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="SlidingEnemyDetector" unique_id=1287455053]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("SphereShape3D_ue7xq")
[node name="CloseEnemyDetector" type="ShapeCast3D" parent="." unique_id=2109861596]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
@@ -425,6 +431,10 @@ target_position = Vector3(0, 0, -6)
collision_mask = 112
collide_with_areas = true
[node name="DirectGroundDetector" type="RayCast3D" parent="." unique_id=1037335553]
target_position = Vector3(0, -2, 0)
collision_mask = 256
[node name="GroundDetector" type="ShapeCast3D" parent="." unique_id=1681055424]
shape = SubResource("CapsuleShape3D_6lejt")
collision_mask = 256
@@ -436,20 +446,6 @@ shape = SubResource("SphereShape3D_nob5r")
target_position = Vector3(0, 0.4, 0)
collision_mask = 256
[node name="DirectGroundDetector" type="RayCast3D" parent="." unique_id=1037335553]
target_position = Vector3(0, -2, 0)
collision_mask = 256
[node name="SlidingEnemyDetector" type="Area3D" parent="." unique_id=42873532]
collision_layer = 0
collision_mask = 16
monitoring = false
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="SlidingEnemyDetector" unique_id=1287455053]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("SphereShape3D_ue7xq")
[node name="InvincibilityTime" type="Timer" parent="." unique_id=1244463585]
one_shot = true

View File

@@ -17,6 +17,8 @@ public partial class PlayerUi : Control
[Dependency]
public TagsManager TagsManager => this.DependOn<TagsManager>();
[Dependency]
public CuesManager CuesManager => this.DependOn<CuesManager>();
#region Utils
@@ -58,8 +60,8 @@ public partial class PlayerUi : Control
public void OnResolved()
{
if (_health == null || _mana == null) throw new Exception("Health and mana attributes are not set");
Healthbar.Init(_health, Tag.RequestTag(TagsManager, "cues.resources.health"));
Manabar.Init(_mana, Tag.RequestTag(TagsManager, "cues.resources.mana"));
Healthbar.Init(_health);
Manabar.Init(_mana);
}
public void SetEnemyTargetProperties(TargetProperties targetProperties)

View File

@@ -372,7 +372,7 @@ tracks/3/keys = {
}
tracks/4/type = "method"
tracks/4/imported = false
tracks/4/enabled = false
tracks/4/enabled = true
tracks/4/path = NodePath("../..")
tracks/4/interp = 1
tracks/4/loop_wrap = true

View File

@@ -116,12 +116,12 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity
#region Privates
private StateChart _weaponState = null!;
private Transition _handToFlying = null!;
private Transition _flyingToHand = null!;
private Transition _plantedToHand = null!;
private Transition _plantedToFlying = null!;
private Transition _toPlanted = null!;
private StateChart _weaponState = null!;
private Transition _handToFlying = null!;
private Transition _flyingToHand = null!;
private Transition _plantedToHand = null!;
private Transition _plantedToFlying = null!;
private Transition _toPlanted = null!;
private ShapeCast3D _dashCast3D = null!;
@@ -177,17 +177,12 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity
WeaponFlyingAbilityTag = Tag.RequestTag(tagsManager,"abilities.weapon.flying");
List<AttributeSet> attributeSetList = [];
foreach (Node node in GetChildren())
foreach (var node in GetChildren())
{
if (node is ForgeAttributeSet attributeSetNode)
{
AttributeSet? attributeSet = attributeSetNode.GetAttributeSet();
if (attributeSet is not null)
{
attributeSetList.Add(attributeSet);
}
}
if (node is not ForgeAttributeSet attributeSetNode) continue;
var attributeSet = attributeSetNode.GetAttributeSet();
if (attributeSet is not null)
attributeSetList.Add(attributeSet);
}
Attributes = new EntityAttributes([.. attributeSetList]);
@@ -458,6 +453,7 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer, IForgeEntity
public override void _Process(double delta)
{
Abilities.UpdateAbilities(delta);
EffectsManager.UpdateEffects(delta);
if (!FlyingState.Active) return;

View File

@@ -61,6 +61,7 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
#region Forge
private AbilityHandle? _empoweredActionHandle;
private AbilityHandle? _hitAbilityHandle;
public required EntityAttribute HealthAttribute { get; set; }
public required EntityAttribute ManaAttribute { get; set; }
@@ -103,12 +104,12 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
#region Publics
public EntityAttributes Attributes { get; set; } = null!;
public EntityTags Tags { get; set; } = null!;
public EffectsManager EffectsManager { get; set; } = null!;
public EntityAbilities Abilities { get; set; } = null!;
public EventManager Events { get; set; } = null!;
public Variables SharedVariables { get; }
public required EntityAttributes Attributes { get; set; }
public required EntityTags Tags { get; set; }
public required EffectsManager EffectsManager { get; set; }
public required EntityAbilities Abilities { get; set; }
public required EventManager Events { get; set; }
public required Variables SharedVariables { get; set; }
#endregion
@@ -125,7 +126,8 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
[ExportGroup("Abilities")]
[ExportSubgroup("Common and defaults")]
[Export] public ForgeAbilityData? EmpoweredActionAbility;
[Export] public required ForgeAbilityData HitAbility { get; set; }
[Export] public required ForgeAbilityData EmpoweredActionAbility { get; set; }
[Export] public ForgeAbilityData[] DefaultGrantedAbilities = [];
[ExportGroup("Effects")]
@@ -443,7 +445,7 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
}
// Damage dealing
private readonly List<IDamageable> _hitEnemies = new List<IDamageable>();
private readonly List<IForgeEntity> _hitEnemies = [];
#endregion
@@ -454,17 +456,12 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
// General use stuff
List<AttributeSet> attributeSetList = [];
foreach (Node node in GetChildren())
foreach (var node in GetChildren())
{
if (node is ForgeAttributeSet attributeSetNode)
{
AttributeSet? attributeSet = attributeSetNode.GetAttributeSet();
if (attributeSet is not null)
{
attributeSetList.Add(attributeSet);
}
}
if (node is not ForgeAttributeSet attributeSetNode) continue;
var attributeSet = attributeSetNode.GetAttributeSet();
if (attributeSet is not null)
attributeSetList.Add(attributeSet);
}
Attributes = new EntityAttributes([.. attributeSetList]);
HealthAttribute = Attributes["PlayerAttributeSet.Health"];
@@ -682,21 +679,31 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
}
#region LifecycleManagement
public override void _ExitTree()
{
base._ExitTree();
ForgeManagers.Instance.CuesManager.UnregisterCue(Tag.RequestTag(TagsManager, "cues.resources.health"), this);
}
public void OnResolved()
{
#region Forge
EffectsManager = new EffectsManager(this, CuesManager);
CuesManager.RegisterCue(Tag.RequestTag(TagsManager, "cues.resources.health"), this);
if (EmpoweredActionAbility != null)
{
_empoweredActionHandle = Abilities.GrantAbilityPermanently(
EmpoweredActionAbility.GetAbilityData(),
abilityLevel: 1,
levelOverridePolicy: LevelComparison.None,
sourceEntity: this);
}
_hitAbilityHandle = Abilities.GrantAbilityPermanently(
HitAbility.GetAbilityData(),
abilityLevel: 1,
levelOverridePolicy: LevelComparison.None,
sourceEntity: this);
_empoweredActionHandle = Abilities.GrantAbilityPermanently(
EmpoweredActionAbility.GetAbilityData(),
abilityLevel: 1,
levelOverridePolicy: LevelComparison.None,
sourceEntity: this);
foreach (var defaultGrantedAbility in DefaultGrantedAbilities)
{
@@ -713,6 +720,10 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
EffectsManager.ApplyEffect(new Effect(effect.GetEffectData(), new EffectOwnership(this, this)));
}
// Apply children node effects
// var effectApplier = new EffectApplier(this);
// effectApplier.ApplyEffects(this, this, this);
// Subscribe default empowered actions effects to the Empowered Action Used event
foreach (var effect in EmpoweredActionEffects)
{
@@ -1924,9 +1935,9 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
public void EnemyHitWhileSliding(Node enemy)
{
if(enemy is not IDamageable damageable)
if(enemy is not IForgeEntity entity)
return;
_hitEnemies.Add(damageable);
_hitEnemies.Add(entity);
TriggerDamage();
}
@@ -2145,8 +2156,8 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
for (var i = 0; i < DashDamageDetector.GetCollisionCount(); i++)
{
var collidedObject = DashDamageDetector.GetCollider(i);
if (collidedObject is not IDamageable damageable) continue;
_hitEnemies.Add(damageable);
if (collidedObject is not IForgeEntity entity) continue;
_hitEnemies.Add(entity);
}
TriggerDamage();
@@ -2296,9 +2307,9 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
public void ManageAttackedEnemyPostDash(Node? enemy)
{
if (enemy is IDamageable damageable)
if (enemy is IForgeEntity entity)
{
_hitEnemies.Add(damageable);
_hitEnemies.Add(entity);
TriggerDamage();
}
if (enemy is IStunnable stunnable)
@@ -2332,9 +2343,9 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
LookAround(delta);
}
// private float _oldMana = 100;
public override void _Process(double delta)
{
Abilities.UpdateAbilities(delta);
EffectsManager.UpdateEffects(delta);
}
@@ -2478,9 +2489,9 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
public void StopDashAction()
{
if (_targetObject is IDamageable damageable)
if (_targetObject is IForgeEntity entity)
{
_hitEnemies.Add(damageable);
_hitEnemies.Add(entity);
TriggerDamage();
}
if (_targetObject is IStunnable stunnable)
@@ -2536,9 +2547,12 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
return;
}
if (!WeaponSystem.InHandState.Active) return;
if (_hitAbilityHandle is null) return;
if (!_hitAbilityHandle.CanActivate(out _)) return;
var attackToDo = _isEnemyInDashAttackRange ? "dash_attack" : "standard_attack";
_playerState.SendEvent(attackToDo);
_playerState.SendEvent("standard_attack");
}
public void ResetAttackCooldown()
@@ -2559,16 +2573,27 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
public void RegisterHitEnnemy(Node3D body)
{
if (body is not IDamageable damageable) return;
_hitEnemies.Add(damageable);
if (body is not IForgeEntity entity) return;
_hitEnemies.Add(entity);
// return;
// if (body is not IDamageable damageable) return;
// _hitEnemies.Add(damageable);
}
public void TriggerDamage()
{
if (_hitEnemies.Count == 0) return;
foreach (var damageable in _hitEnemies)
damageable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
if (_hitAbilityHandle is null) return;
if (!_hitAbilityHandle.CanActivate(out _)) return;
foreach (var entity in _hitEnemies)
{
// TODO: WTF why doesn't health move
// GD.Print(entity.Attributes["EnemyAttributeSet.Health"].CurrentValue);
_hitAbilityHandle.Activate(out _, entity);
}
_hitEnemies.Clear();
HeadSystem.OnHitTarget();
@@ -2587,12 +2612,6 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
{
ResetTimeScale();
}
public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord)
{
// var record = CHealth!.ReduceHealth(source, damageRecord);
// HealthChanged?.Invoke(this, record);
return new HealthChangedRecord(100, 0, 100);
}
public void RegisterKnockback(KnockbackRecord knockbackRecord)
{
// CKnockback!.RegisterKnockback(knockbackRecord);
@@ -2609,7 +2628,6 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
{
Kill();
}
public void Kill()
{
HeadSystem.OnStartDeathAnimation();
@@ -2635,6 +2653,19 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl
public void OnDamageReceived(EventData data)
{
var newHealth = HealthAttribute.CurrentValue + data.EventMagnitude;
CuesManager.ExecuteCue(
Tag.RequestTag(TagsManager, "cues.resources.health"),
this,
new CueParameters(
(int) data.EventMagnitude,
data.EventMagnitude / HealthAttribute.Max,
data.Source,
new Dictionary<StringKey, object>
{
{"test", "hello"}
})
);
if (newHealth > HealthAttribute.Min) return;
var tagsManager = TagsManager;