From afa335e7bf3dfbe1fba3f226eb1f53e22d7d9e67 Mon Sep 17 00:00:00 2001 From: Minimata Date: Fri, 15 May 2026 15:29:24 +0200 Subject: [PATCH] stunnable targets on hit --- .../keyboard_shift_icon_outline.svg.import | 14 +-- .../abilities/ForgeManualCancelHitBehavior.cs | 17 ++-- forge/calculators/ForgeKnockbackExecution.cs | 15 ++-- forge/forge_data.tres | 2 +- forge/resources/ability_datas/player_hit.tres | 87 ++++++++++++++++++- .../player_hit_knoback_calculation.tres | 2 + .../effect_components/stunnable.tres | 20 +++++ .../tag_containers/enemy_base_tags.tres | 2 +- .../tag_containers/knockback_immune.tres | 8 ++ interfaces/IMoveable.cs | 7 +- maps/levels/2 - tuto_sword.tscn | 17 ++-- scenes/components/movement/CFlyingMovement.cs | 6 +- .../components/movement/CGroundedMovement.cs | 13 +-- scenes/enemies/Enemy.cs | 29 +++++-- scenes/enemies/flying_enemy/flying_enemy.tscn | 4 +- .../projectile_enemy/projectile_enemy.tscn | 5 +- .../player_controller/PlayerController.tscn | 2 +- .../scripts/PlayerController.cs | 4 +- tests/components/MovementSystemUnitTest.cs | 6 +- 19 files changed, 200 insertions(+), 60 deletions(-) create mode 100644 forge/resources/effect_components/stunnable.tres create mode 100644 forge/resources/tag_containers/knockback_immune.tres diff --git a/assets/ui/input-prompts/Keyboard & Mouse/Vector/keyboard_shift_icon_outline.svg.import b/assets/ui/input-prompts/Keyboard & Mouse/Vector/keyboard_shift_icon_outline.svg.import index e04a7e7b..b09d4ec5 100644 --- a/assets/ui/input-prompts/Keyboard & Mouse/Vector/keyboard_shift_icon_outline.svg.import +++ b/assets/ui/input-prompts/Keyboard & Mouse/Vector/keyboard_shift_icon_outline.svg.import @@ -3,19 +3,21 @@ importer="texture" type="CompressedTexture2D" uid="uid://bun38n3ff5wvv" -path="res://.godot/imported/keyboard_shift_icon_outline.svg-21854f9aeab065c26ab9185b7d09e5f2.ctex" +path.s3tc="res://.godot/imported/keyboard_shift_icon_outline.svg-21854f9aeab065c26ab9185b7d09e5f2.s3tc.ctex" +path.etc2="res://.godot/imported/keyboard_shift_icon_outline.svg-21854f9aeab065c26ab9185b7d09e5f2.etc2.ctex" metadata={ -"vram_texture": false +"imported_formats": ["s3tc_bptc", "etc2_astc"], +"vram_texture": true } [deps] source_file="res://assets/ui/input-prompts/Keyboard & Mouse/Vector/keyboard_shift_icon_outline.svg" -dest_files=["res://.godot/imported/keyboard_shift_icon_outline.svg-21854f9aeab065c26ab9185b7d09e5f2.ctex"] +dest_files=["res://.godot/imported/keyboard_shift_icon_outline.svg-21854f9aeab065c26ab9185b7d09e5f2.s3tc.ctex", "res://.godot/imported/keyboard_shift_icon_outline.svg-21854f9aeab065c26ab9185b7d09e5f2.etc2.ctex"] [params] -compress/mode=0 +compress/mode=2 compress/high_quality=false compress/lossy_quality=0.7 compress/uastc_level=0 @@ -23,7 +25,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=false +mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" @@ -37,7 +39,7 @@ process/normal_map_invert_y=false process/hdr_as_srgb=false process/hdr_clamp_exposure=false process/size_limit=0 -detect_3d/compress_to=1 +detect_3d/compress_to=0 svg/scale=1.0 editor/scale_with_editor_scale=false editor/convert_colors_with_editor_theme=false diff --git a/forge/abilities/ForgeManualCancelHitBehavior.cs b/forge/abilities/ForgeManualCancelHitBehavior.cs index 6a41fc59..c9b68cf1 100644 --- a/forge/abilities/ForgeManualCancelHitBehavior.cs +++ b/forge/abilities/ForgeManualCancelHitBehavior.cs @@ -6,18 +6,21 @@ using Godot; namespace Movementtests.forge.abilities; -public class ManualCancelHitBehavior(ForgeEffectData? damage) : IAbilityBehavior +public class ManualCancelHitBehavior(ForgeEffectData[] effects) : IAbilityBehavior { public void OnStarted(AbilityBehaviorContext context) { - if (context.Target == null || damage == null) return; + if (context.Target == null) return; var sourceLocation = (context.Source as Node3D)?.GlobalPosition ?? Vector3.Zero; var targetLocation = (context.Target as Node3D)?.GlobalPosition ?? Vector3.Zero; - var magnitude = context.Magnitude == 0 ? 1 : context.Magnitude; - var effect = new Effect(damage.GetEffectData(), new EffectOwnership(context.Owner, context.Owner)); - context.Target.EffectsManager.ApplyEffect(effect, new SimpleHitEffectData(sourceLocation, targetLocation, magnitude)); + + foreach (var effectData in effects) + { + var effect = new Effect(effectData.GetEffectData(), new EffectOwnership(context.Owner, context.Owner)); + context.Target.EffectsManager.ApplyEffect(effect, new SimpleHitEffectData(sourceLocation, targetLocation, magnitude)); + } } public void OnEnded(AbilityBehaviorContext context) @@ -30,6 +33,6 @@ public class ManualCancelHitBehavior(ForgeEffectData? damage) : IAbilityBehavior [GlobalClass] public partial class ForgeManualCancelHitBehavior : ForgeAbilityBehavior { - [Export] public ForgeEffectData? DamageEffect { get; set; } - public override IAbilityBehavior GetBehavior() => new ManualCancelHitBehavior(DamageEffect); + [Export] public ForgeEffectData[] OnHitEffects { get; set; } = []; + public override IAbilityBehavior GetBehavior() => new ManualCancelHitBehavior(OnHitEffects); } \ No newline at end of file diff --git a/forge/calculators/ForgeKnockbackExecution.cs b/forge/calculators/ForgeKnockbackExecution.cs index 9f1573bd..5bbc5c7e 100644 --- a/forge/calculators/ForgeKnockbackExecution.cs +++ b/forge/calculators/ForgeKnockbackExecution.cs @@ -18,16 +18,18 @@ public record KnockbackDone(float KnockbackValue, Vector3 knockbackDirection); public class KnockbackExecution : CustomExecution { private readonly RKnockback _knockback; - private readonly ForgeTag _knockbackTag; + private readonly ForgeTag _knockbackableTag; + private readonly ForgeTag _knockbackImmuneTag; private readonly ForgeTagContainer? _knockbackReceiverEventTags; private readonly ForgeTagContainer? _knockbackDealerEventTags; public AttributeCaptureDefinition TargetIncomingDamage { get; } - public KnockbackExecution(ForgeTag knockbackTag, RKnockback knockback, ForgeTagContainer? knockbackDealerEventTags, ForgeTagContainer? knockbackReceiverEventTags) + public KnockbackExecution(ForgeTag knockbackableTag, ForgeTag knockbackImmuneTag, RKnockback knockback, ForgeTagContainer? knockbackDealerEventTags, ForgeTagContainer? knockbackReceiverEventTags) { _knockback = knockback; - _knockbackTag = knockbackTag; + _knockbackableTag = knockbackableTag; + _knockbackImmuneTag = knockbackImmuneTag; _knockbackDealerEventTags = knockbackDealerEventTags; _knockbackReceiverEventTags = knockbackReceiverEventTags; @@ -40,7 +42,7 @@ public class KnockbackExecution : CustomExecution public override ModifierEvaluatedData[] EvaluateExecution(Effect effect, IForgeEntity target, EffectEvaluatedData? effectEvaluatedData) { var results = new List(); - if (!target.Tags.CombinedTags.HasTag(_knockbackTag.GetTag())) + if (!target.Tags.CombinedTags.HasTag(_knockbackableTag.GetTag()) || target.Tags.CombinedTags.HasTag(_knockbackImmuneTag.GetTag())) return [.. results]; float targetIncomingDamage = CaptureAttributeMagnitude( @@ -91,12 +93,13 @@ public class KnockbackExecution : CustomExecution public partial class ForgeKnockbackExecution : ForgeCustomExecution { [Export] public ForgeTag? KnockbackableTag { get; set; } + [Export] public ForgeTag? KnockbackImmuneTag { get; set; } [Export] public RKnockback? Knockback { get; set; } [Export] public ForgeTagContainer? KnockbackDealerEventTags { get; set; } [Export] public ForgeTagContainer? KnockbackReceiverEventTags { get; set; } public override CustomExecution GetExecutionClass() { - if (Knockback == null || KnockbackableTag == null) throw new System.ArgumentException("Knockback or KnockbackableTag is null"); - return new KnockbackExecution(KnockbackableTag, Knockback, KnockbackDealerEventTags, KnockbackReceiverEventTags); + if (Knockback == null || KnockbackableTag == null || KnockbackImmuneTag == null) throw new System.ArgumentException("Knockback or KnockbackableTag is null"); + return new KnockbackExecution(KnockbackableTag, KnockbackImmuneTag, Knockback, KnockbackDealerEventTags, KnockbackReceiverEventTags); } } \ No newline at end of file diff --git a/forge/forge_data.tres b/forge/forge_data.tres index 6f3fda66..4b3c2d94 100644 --- a/forge/forge_data.tres +++ b/forge/forge_data.tres @@ -4,4 +4,4 @@ [resource] script = ExtResource("1_l686n") -RegisteredTags = Array[String](["character.player", "character.enemy", "status.stunned", "status.burning", "status.frozen", "abilities.weapon.land", "abilities.weapon.flying", "abilities.weapon.left", "events.combat.damage", "events.combat.hit", "events.weapon.flyingTick", "events.weapon.startedFlying", "events.weapon.stoppedFlying", "events.weapon.handToFlying", "events.weapon.flyingToHand", "events.weapon.plantedToHand", "events.weapon.plantedToFlying", "events.weapon.planted", "cooldown.empoweredAction", "cooldown.empoweredSwordThrow", "cues.resources.mana", "events.player.empowered_action_used", "cues.resources.mana.inhibited", "cues.resources.health", "cooldown.enemy.hit", "events.combat.death", "cooldown.hit", "events.player.hit", "cues.enemy.health", "immunity.damage", "status", "traits.damageable", "traits.knockbackable", "events.combat.knockback_dealt", "events.combat.knockback_received", "events.weapon.plantedtick", "events.weapon.unplanted", "abilities.weapon.planted", "events.enemy.try_hit", "events.enemy.launch_projectile", "objects.projectile", "objects.weapon", "events.enemy.request_projectile", "events.player.parry"]) +RegisteredTags = Array[String](["character.player", "character.enemy", "status.stunned", "status.burning", "status.frozen", "abilities.weapon.land", "abilities.weapon.flying", "abilities.weapon.left", "events.combat.damage", "events.combat.hit", "events.weapon.flyingTick", "events.weapon.startedFlying", "events.weapon.stoppedFlying", "events.weapon.handToFlying", "events.weapon.flyingToHand", "events.weapon.plantedToHand", "events.weapon.plantedToFlying", "events.weapon.planted", "cooldown.empoweredAction", "cooldown.empoweredSwordThrow", "cues.resources.mana", "events.player.empowered_action_used", "cues.resources.mana.inhibited", "cues.resources.health", "cooldown.enemy.hit", "events.combat.death", "cooldown.hit", "events.player.hit", "cues.enemy.health", "immunity.damage", "status", "traits.damageable", "traits.knockbackable", "events.combat.knockback_dealt", "events.combat.knockback_received", "events.weapon.plantedtick", "events.weapon.unplanted", "abilities.weapon.planted", "events.enemy.try_hit", "events.enemy.launch_projectile", "objects.projectile", "objects.weapon", "events.enemy.request_projectile", "events.player.parry", "traits.stunnable", "immunity.knockback", "immunity.stun", "events.combat.stun_applied", "events.combat.stun_received"]) diff --git a/forge/resources/ability_datas/player_hit.tres b/forge/resources/ability_datas/player_hit.tres index c147a878..4a3ed7d5 100644 --- a/forge/resources/ability_datas/player_hit.tres +++ b/forge/resources/ability_datas/player_hit.tres @@ -6,13 +6,98 @@ [ext_resource type="Script" uid="uid://b83hf13nj37k3" path="res://addons/forge/resources/ForgeEffectData.cs" id="2_5vjbv"] [ext_resource type="Script" uid="uid://d1bb1fvh1mnpd" path="res://forge/abilities/ForgeManualCancelHitBehavior.cs" id="2_c4wry"] [ext_resource type="Script" uid="uid://dngf30hxy5go4" path="res://addons/forge/resources/components/ModifierTags.cs" id="2_jwyed"] +[ext_resource type="Resource" uid="uid://vs6kfo2ubhvr" path="res://forge/resources/effect_components/stunnable.tres" id="2_r7waw"] [ext_resource type="Script" uid="uid://dhxfbxh54pyxp" path="res://addons/forge/resources/abilities/ForgeAbilityData.cs" id="3_w1wo0"] [ext_resource type="Script" uid="uid://cn3b4ya15fg7e" path="res://addons/forge/resources/magnitudes/ForgeScalableFloat.cs" id="4_c4wry"] [ext_resource type="Script" uid="uid://2gm1hdhi8u08" path="res://addons/forge/resources/magnitudes/ForgeModifierMagnitude.cs" id="5_0cyim"] +[ext_resource type="Script" uid="uid://br7ut4lbau66w" path="res://forge/calculators/ForgeRaiseEventTagExecution.cs" id="7_l5emy"] + +[sub_resource type="Resource" id="Resource_h8gc3"] +script = ExtResource("1_w1wo0") +ContainerTags = Array[String](["status.stunned"]) +metadata/_custom_type_script = "uid://cw525n4mjqgw0" + +[sub_resource type="Resource" id="Resource_vioyh"] +script = ExtResource("2_jwyed") +TagsToAdd = SubResource("Resource_h8gc3") +metadata/_custom_type_script = "uid://dngf30hxy5go4" + +[sub_resource type="Resource" id="Resource_m6xnn"] +script = ExtResource("4_c4wry") +BaseValue = 1.0 + +[sub_resource type="Resource" id="Resource_uinv8"] +script = ExtResource("4_c4wry") + +[sub_resource type="Resource" id="Resource_04hqa"] +script = ExtResource("4_c4wry") + +[sub_resource type="Resource" id="Resource_8fbeq"] +script = ExtResource("4_c4wry") +BaseValue = 1.0 + +[sub_resource type="Resource" id="Resource_ees2v"] +script = ExtResource("4_c4wry") + +[sub_resource type="Resource" id="Resource_6x2ov"] +script = ExtResource("4_c4wry") + +[sub_resource type="Resource" id="Resource_ml8x2"] +script = ExtResource("4_c4wry") +BaseValue = 1.0 +metadata/_custom_type_script = "uid://cn3b4ya15fg7e" + +[sub_resource type="Resource" id="Resource_1uqo4"] +script = ExtResource("5_0cyim") +ScalableFloat = SubResource("Resource_ml8x2") +Coefficient = SubResource("Resource_8fbeq") +PreMultiplyAdditiveValue = SubResource("Resource_6x2ov") +PostMultiplyAdditiveValue = SubResource("Resource_ees2v") +CalculatorCoefficient = SubResource("Resource_m6xnn") +CalculatorPreMultiplyAdditiveValue = SubResource("Resource_04hqa") +CalculatorPostMultiplyAdditiveValue = SubResource("Resource_uinv8") +metadata/_custom_type_script = "uid://2gm1hdhi8u08" + +[sub_resource type="Resource" id="Resource_fyrcc"] +script = ExtResource("1_w1wo0") +ContainerTags = Array[String](["events.combat.stun_applied"]) +metadata/_custom_type_script = "uid://cw525n4mjqgw0" + +[sub_resource type="Resource" id="Resource_sgtcb"] +script = ExtResource("1_w1wo0") +ContainerTags = Array[String](["events.combat.stun_received"]) +metadata/_custom_type_script = "uid://cw525n4mjqgw0" + +[sub_resource type="Resource" id="Resource_3p0ly"] +script = ExtResource("7_l5emy") +EventTags = SubResource("Resource_fyrcc") +TargetEventTags = SubResource("Resource_sgtcb") +metadata/_custom_type_script = "uid://br7ut4lbau66w" + +[sub_resource type="Resource" id="Resource_ewmvj"] +script = ExtResource("1_l0l1a") +BaseValue = 1 + +[sub_resource type="Resource" id="Resource_8wvcn"] +script = ExtResource("1_l0l1a") +BaseValue = 1 + +[sub_resource type="Resource" id="Resource_no8t2"] +script = ExtResource("2_5vjbv") +Name = "Basic stun" +Modifiers = Array[Object]([]) +Components = Array[Object]([ExtResource("2_r7waw"), SubResource("Resource_vioyh")]) +Executions = [SubResource("Resource_3p0ly")] +DurationType = 2 +Duration = SubResource("Resource_1uqo4") +StackLimit = SubResource("Resource_8wvcn") +InitialStack = SubResource("Resource_ewmvj") +Cues = [] +metadata/_custom_type_script = "uid://b83hf13nj37k3" [sub_resource type="Resource" id="Resource_0cyim"] script = ExtResource("2_c4wry") -DamageEffect = ExtResource("1_c4wry") +OnHitEffects = [ExtResource("1_c4wry"), SubResource("Resource_no8t2")] Name = "Player hit" metadata/_custom_type_script = "uid://d1bb1fvh1mnpd" diff --git a/forge/resources/custom_executions/player_hit_knoback_calculation.tres b/forge/resources/custom_executions/player_hit_knoback_calculation.tres index c97f3d76..f90a5afd 100644 --- a/forge/resources/custom_executions/player_hit_knoback_calculation.tres +++ b/forge/resources/custom_executions/player_hit_knoback_calculation.tres @@ -3,6 +3,7 @@ [ext_resource type="Script" uid="uid://b44cse62qru7j" path="res://scenes/components/knockback/RKnockback.cs" id="1_kcl5u"] [ext_resource type="Resource" uid="uid://bhn27s8ne0uyg" path="res://forge/resources/tag_containers/on_knockback_dealt.tres" id="2_oqtq1"] [ext_resource type="Resource" uid="uid://bkr6uu57wm3o3" path="res://forge/resources/tag_containers/on_knockback_received.tres" id="3_1va1b"] +[ext_resource type="Resource" uid="uid://5obdxlcpw8qt" path="res://forge/resources/tag_containers/knockback_immune.tres" id="3_oqtq1"] [ext_resource type="Resource" uid="uid://45l7vnfs72b" path="res://forge/resources/tag_containers/knockbackable_tag.tres" id="4_0i0oh"] [ext_resource type="Script" uid="uid://diondfg5xp78h" path="res://forge/calculators/ForgeKnockbackExecution.cs" id="5_babc1"] @@ -14,6 +15,7 @@ metadata/_custom_type_script = "uid://b44cse62qru7j" [resource] script = ExtResource("5_babc1") KnockbackableTag = ExtResource("4_0i0oh") +KnockbackImmuneTag = ExtResource("3_oqtq1") Knockback = SubResource("Resource_6x2ov") KnockbackDealerEventTags = ExtResource("2_oqtq1") KnockbackReceiverEventTags = ExtResource("3_1va1b") diff --git a/forge/resources/effect_components/stunnable.tres b/forge/resources/effect_components/stunnable.tres new file mode 100644 index 00000000..6966c236 --- /dev/null +++ b/forge/resources/effect_components/stunnable.tres @@ -0,0 +1,20 @@ +[gd_resource type="Resource" script_class="TargetTagRequirements" format=3 uid="uid://vs6kfo2ubhvr"] + +[ext_resource type="Script" uid="uid://cw525n4mjqgw0" path="res://addons/forge/resources/ForgeTagContainer.cs" id="1_52mex"] +[ext_resource type="Script" uid="uid://b0eq12mjqfage" path="res://addons/forge/resources/components/TargetTagRequirements.cs" id="2_d06a4"] + +[sub_resource type="Resource" id="Resource_r7waw"] +script = ExtResource("1_52mex") +ContainerTags = Array[String](["immunity.stun"]) +metadata/_custom_type_script = "uid://cw525n4mjqgw0" + +[sub_resource type="Resource" id="Resource_vioyh"] +script = ExtResource("1_52mex") +ContainerTags = Array[String](["traits.stunnable"]) +metadata/_custom_type_script = "uid://cw525n4mjqgw0" + +[resource] +script = ExtResource("2_d06a4") +ApplicationRequiredTags = SubResource("Resource_vioyh") +ApplicationIgnoredTags = SubResource("Resource_r7waw") +metadata/_custom_type_script = "uid://b0eq12mjqfage" diff --git a/forge/resources/tag_containers/enemy_base_tags.tres b/forge/resources/tag_containers/enemy_base_tags.tres index 7e182b3c..a0de01a7 100644 --- a/forge/resources/tag_containers/enemy_base_tags.tres +++ b/forge/resources/tag_containers/enemy_base_tags.tres @@ -4,5 +4,5 @@ [resource] script = ExtResource("1_kdy2b") -ContainerTags = Array[String](["character.enemy", "traits.damageable", "traits.knockbackable"]) +ContainerTags = Array[String](["character.enemy", "traits.damageable", "traits.knockbackable", "traits.stunnable"]) metadata/_custom_type_script = "uid://cw525n4mjqgw0" diff --git a/forge/resources/tag_containers/knockback_immune.tres b/forge/resources/tag_containers/knockback_immune.tres new file mode 100644 index 00000000..0a446430 --- /dev/null +++ b/forge/resources/tag_containers/knockback_immune.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="ForgeTag" format=3 uid="uid://5obdxlcpw8qt"] + +[ext_resource type="Script" uid="uid://dpakv7agvir6y" path="res://addons/forge/resources/ForgeTag.cs" id="1_pjklh"] + +[resource] +script = ExtResource("1_pjklh") +Tag = "immunity.knockback" +metadata/_custom_type_script = "uid://dpakv7agvir6y" diff --git a/interfaces/IMoveable.cs b/interfaces/IMoveable.cs index fd505a28..a5298335 100644 --- a/interfaces/IMoveable.cs +++ b/interfaces/IMoveable.cs @@ -5,9 +5,10 @@ namespace Movementtests.interfaces; public record MovementInputs( Vector3 Velocity = default, Vector3 TargetLocation = default, - bool isOnFloor = false, - Vector3 gravity = default, - double delta = 0); + bool IsOnFloor = false, + bool IsStunned = false, + Vector3 Gravity = default, + double Delta = 0); public interface IMoveable { diff --git a/maps/levels/2 - tuto_sword.tscn b/maps/levels/2 - tuto_sword.tscn index 3352c03b..60d69ef1 100644 --- a/maps/levels/2 - tuto_sword.tscn +++ b/maps/levels/2 - tuto_sword.tscn @@ -16,8 +16,6 @@ [ext_resource type="Texture2D" uid="uid://bhlrmh5v3fa2n" path="res://assets/ui/input-prompts/Keyboard & Mouse/Vector/mouse_left_outline.svg" id="16_ca01l"] [ext_resource type="Texture2D" uid="uid://b580m114ivbse" path="res://assets/ui/input-prompts/Xbox Series/Vector/xbox_button_menu_outline.svg" id="17_5461m"] [ext_resource type="Texture2D" uid="uid://goerc3svgoqd" path="res://assets/ui/input-prompts/Keyboard & Mouse/Vector/keyboard_escape_outline.svg" id="18_22eiu"] -[ext_resource type="Texture2D" uid="uid://db6uqhcmcfs5t" path="res://assets/ui/input-prompts/Xbox Series/Vector/xbox_lb_outline.svg" id="19_ci5dp"] -[ext_resource type="Texture2D" uid="uid://ybwqghk70io" path="res://assets/ui/input-prompts/Keyboard & Mouse/Vector/keyboard_f_outline.svg" id="20_4ouww"] [sub_resource type="Resource" id="Resource_nwk5u"] script = ExtResource("6_465vr") @@ -345,8 +343,8 @@ shape = SubResource("BoxShape3D_dkfm7") [node name="TutoTrigger4" parent="Tutorial/Triggers" index="3" unique_id=321542244 instance=ExtResource("10_vqwwk")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -11.5, 17.75, -27.5) -first_input_icon = ExtResource("15_1s3jl") -first_input_icon_keyboard = ExtResource("16_ca01l") +first_input_icon = ExtResource("13_ocbap") +first_input_icon_keyboard = ExtResource("14_4hfom") input_related_text = "at target" tuto_text = "dash through" @@ -356,8 +354,8 @@ shape = SubResource("BoxShape3D_nwk5u") [node name="TutoTrigger6" parent="Tutorial/Triggers" index="4" unique_id=26112457 instance=ExtResource("10_vqwwk")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.75, 22.75, 11.25) -first_input_icon = ExtResource("15_1s3jl") -first_input_icon_keyboard = ExtResource("16_ca01l") +first_input_icon = ExtResource("13_ocbap") +first_input_icon_keyboard = ExtResource("14_4hfom") input_related_text = "at enemy" tuto_text = "dash through" @@ -389,10 +387,9 @@ shape = SubResource("BoxShape3D_trte5") [node name="TutoTrigger8" parent="Tutorial/Triggers" index="7" unique_id=36196488 instance=ExtResource("10_vqwwk")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 21.75, 28.25) -first_input_icon = ExtResource("19_ci5dp") -first_input_icon_keyboard = ExtResource("20_4ouww") -input_related_text = "at enemy" -tuto_text = "knockback" +first_input_icon = ExtResource("15_1s3jl") +first_input_icon_keyboard = ExtResource("16_ca01l") +tuto_text = "hit" [node name="CollisionShape3D" type="CollisionShape3D" parent="Tutorial/Triggers/TutoTrigger8" index="1" unique_id=929676345] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.125, 1.875, 0.375) diff --git a/scenes/components/movement/CFlyingMovement.cs b/scenes/components/movement/CFlyingMovement.cs index 69aea8d8..0f711034 100644 --- a/scenes/components/movement/CFlyingMovement.cs +++ b/scenes/components/movement/CFlyingMovement.cs @@ -21,6 +21,8 @@ public partial class CFlyingMovement : Node3D, IMoveable public Vector3 ComputeVelocity(MovementInputs inputs) { + if (inputs.IsStunned) return inputs.Velocity.Lerp(Vector3.Zero, (float) inputs.Delta * RMovement.Acceleration); + var velocity = inputs.Velocity; var spaceState = GetWorld3D().DirectSpaceState; var target = inputs.TargetLocation; @@ -28,7 +30,7 @@ public partial class CFlyingMovement : Node3D, IMoveable // Check if we have a direct line of sight to the player if (!_movingToDesiredHeight) { - velocity = velocity.Lerp(direction * RMovement.Speed, (float) inputs.delta * RMovement.Acceleration); + velocity = velocity.Lerp(direction * RMovement.Speed, (float) inputs.Delta * RMovement.Acceleration); var query = PhysicsRayQueryParameters3D.Create(GlobalPosition, target, TerrainCollision); var result = spaceState.IntersectRay(query); @@ -40,7 +42,7 @@ public partial class CFlyingMovement : Node3D, IMoveable } else { - velocity = velocity.Lerp(_randomDirection * RMovement.Speed, (float) inputs.delta * RMovement.Acceleration); + velocity = velocity.Lerp(_randomDirection * RMovement.Speed, (float) inputs.Delta * RMovement.Acceleration); var groundQuery = PhysicsRayQueryParameters3D.Create(GlobalPosition, GlobalPosition+Vector3.Down*RMovement.TargetHeight, TerrainCollision); var groundResult = spaceState.IntersectRay(groundQuery); diff --git a/scenes/components/movement/CGroundedMovement.cs b/scenes/components/movement/CGroundedMovement.cs index bd804fca..cc62f16d 100644 --- a/scenes/components/movement/CGroundedMovement.cs +++ b/scenes/components/movement/CGroundedMovement.cs @@ -19,15 +19,18 @@ public partial class CGroundedMovement : Node3D, IMoveable var targetPlane = new Vector3(target.X, GlobalPosition.Y, target.Z); LookAt(targetPlane); - float xAcc = (float) Mathf.Lerp(velocity.X, direction.X * RMovement.Speed, inputs.delta * RMovement.Acceleration); - float zAcc = (float) Mathf.Lerp(velocity.Z, direction.Z * RMovement.Speed, inputs.delta * RMovement.Acceleration); + + var targetXSpeed = inputs.IsStunned ? 0 : direction.X * RMovement.Speed; + var targetZSpeed = inputs.IsStunned ? 0 : direction.Z * RMovement.Speed; + float xAcc = (float) Mathf.Lerp(velocity.X, targetXSpeed, inputs.Delta * RMovement.Acceleration); + float zAcc = (float) Mathf.Lerp(velocity.Z, targetZSpeed, inputs.Delta * RMovement.Acceleration); velocity.X = xAcc; velocity.Z = zAcc; - if (WallInFrontRayCast.IsColliding()) + if (WallInFrontRayCast.IsColliding() && !inputs.IsStunned) velocity.Y = RMovement.Speed; - else if (!inputs.isOnFloor) - velocity += inputs.gravity * (float)inputs.delta * RMovement.GravityModifier; + else if (!inputs.IsOnFloor) + velocity += inputs.Gravity * (float)inputs.Delta * RMovement.GravityModifier; return velocity; } diff --git a/scenes/enemies/Enemy.cs b/scenes/enemies/Enemy.cs index 7cf0354d..bf753420 100644 --- a/scenes/enemies/Enemy.cs +++ b/scenes/enemies/Enemy.cs @@ -130,11 +130,16 @@ public partial class Enemy : CharacterBody3D, Events.Subscribe(Tag.RequestTag(TagsManager, "events.combat.knockback_received"), OnKnockbackReceived); Events.Subscribe(Tag.RequestTag(TagsManager, "events.combat.death"), OnDeath); Events.Subscribe(Tag.RequestTag(TagsManager, "events.enemy.request_projectile"), ProjectileTokenRequested); - + } + + private bool IsStunned() + { + return Tags.CombinedTags.HasTag(Tag.RequestTag(TagsManager, "status.stunned")); } private void ProjectileTokenRequested(EventData obj) { + if (IsStunned()) return; // TODO: replace with token manager Events.Raise(new EventData { @@ -154,24 +159,34 @@ public partial class Enemy : CharacterBody3D, { // Only trigger gameplay-related effects on specific frames if(Engine.GetPhysicsFrames() % 10 == 0) ProcessGameplay(delta); - - var targetPlanar = new Vector3(Target.GlobalPosition.X, GlobalPosition.Y, Target.GlobalPosition.Z); - LookAt(targetPlanar); + + if (!IsStunned()) + { + var targetPlanar = new Vector3(Target.GlobalPosition.X, GlobalPosition.Y, Target.GlobalPosition.Z); + LookAt(targetPlanar); + } var inputs = new MovementInputs( Velocity: Velocity, TargetLocation: Target.GlobalPosition, - isOnFloor: IsOnFloor(), - gravity: GetGravity(), - delta: delta + IsOnFloor: IsOnFloor(), + IsStunned: IsStunned(), + Gravity: GetGravity(), + Delta: delta ); Velocity = ComputeVelocity(inputs); + Velocity += ComputeKnockback(); MoveAndSlide(); } public void ProcessGameplay(double delta) { + if (IsStunned()) + { + GD.Print("Cannot attack, stunned!"); + return; + } // if (_hitAbilityHandle == null) return; var bodies = DamageBox.GetOverlappingBodies(); diff --git a/scenes/enemies/flying_enemy/flying_enemy.tscn b/scenes/enemies/flying_enemy/flying_enemy.tscn index 254cae9c..0540832d 100644 --- a/scenes/enemies/flying_enemy/flying_enemy.tscn +++ b/scenes/enemies/flying_enemy/flying_enemy.tscn @@ -64,7 +64,7 @@ InitialStack = SubResource("Resource_8x1id") Cues = [] metadata/_custom_type_script = "uid://b83hf13nj37k3" -[sub_resource type="ViewportTexture" id="ViewportTexture_4oy82"] +[sub_resource type="ViewportTexture" id="ViewportTexture_46wn3"] viewport_path = NodePath("SubViewport") [sub_resource type="Resource" id="Resource_on7rt"] @@ -141,7 +141,7 @@ metadata/_custom_type_script = "uid://dps0oef50noil" [node name="CHealthBar" parent="." unique_id=1635725931 instance=ExtResource("7_ykkxn")] transform = Transform3D(0.3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.70000005, 0) -texture = SubResource("ViewportTexture_4oy82") +texture = SubResource("ViewportTexture_46wn3") [node name="CMovement" parent="." unique_id=1699571730 instance=ExtResource("7_vaeds")] RMovement = SubResource("Resource_on7rt") diff --git a/scenes/enemies/projectile_enemy/projectile_enemy.tscn b/scenes/enemies/projectile_enemy/projectile_enemy.tscn index 4bc5fcae..4ebd7480 100644 --- a/scenes/enemies/projectile_enemy/projectile_enemy.tscn +++ b/scenes/enemies/projectile_enemy/projectile_enemy.tscn @@ -141,7 +141,7 @@ InitialStack = SubResource("Resource_hgi6f") Cues = [] metadata/_custom_type_script = "uid://b83hf13nj37k3" -[sub_resource type="ViewportTexture" id="ViewportTexture_xabdf"] +[sub_resource type="ViewportTexture" id="ViewportTexture_rlvdp"] viewport_path = NodePath("SubViewport") [sub_resource type="Resource" id="Resource_6d4gl"] @@ -177,7 +177,6 @@ collision_layer = 16 collision_mask = 273 script = ExtResource("1_ha67n") EnemyHeight = 2.0 -LaunchProjectileAbility = ExtResource("2_rlvdp") RKnockback = ExtResource("3_ymgar") RMovement = ExtResource("4_0f52b") @@ -222,7 +221,7 @@ metadata/_custom_type_script = "uid://dps0oef50noil" [node name="CHealthBar" parent="." unique_id=1278247727 instance=ExtResource("9_6ew2r")] transform = Transform3D(0.4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.2, 0) -texture = SubResource("ViewportTexture_xabdf") +texture = SubResource("ViewportTexture_rlvdp") [node name="CMovement" parent="." unique_id=1080640834 node_paths=PackedStringArray("WallInFrontRayCast") instance=ExtResource("10_d3cra")] RMovement = SubResource("Resource_6d4gl") diff --git a/scenes/player_controller/PlayerController.tscn b/scenes/player_controller/PlayerController.tscn index 5a75da5d..dfc962bf 100644 --- a/scenes/player_controller/PlayerController.tscn +++ b/scenes/player_controller/PlayerController.tscn @@ -89,7 +89,7 @@ metadata/_custom_type_script = "uid://dpakv7agvir6y" [sub_resource type="Resource" id="Resource_cmmfb"] script = ExtResource("10_b0xmb") Name = "Parry projectile" -CooldownEffects = null +CooldownEffects = [] AbilityBehavior = SubResource("Resource_xs7wf") TriggerSource = 1 TriggerTag = SubResource("Resource_cm4e8") diff --git a/scenes/player_controller/scripts/PlayerController.cs b/scenes/player_controller/scripts/PlayerController.cs index 8768d415..e25655e3 100644 --- a/scenes/player_controller/scripts/PlayerController.cs +++ b/scenes/player_controller/scripts/PlayerController.cs @@ -2467,7 +2467,7 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl // else HeadSystem.OnHit(); // var streamName = isParry ? "parry" : "attacks"; _audioStream.SwitchToClipByName("dash"); - IsInvincible = true; + OnHitInvincibility(); var plannedDashLocation = _targetLocation + Vector3.Down*_playerHeight/2; // var enemySurfaceQuery = PhysicsRayQueryParameters3D.Create(HeadSystem.GlobalPosition, plannedDashLocation, DashSystem.DashCast3D.CollisionMask); @@ -2511,7 +2511,7 @@ public partial class PlayerController : CharacterBody3D, IForgeEntity, ICueHandl { disableable.Disable(); } - IsInvincible = false; + // IsInvincible = false; _playerState.SendEvent("attack_finished"); } diff --git a/tests/components/MovementSystemUnitTest.cs b/tests/components/MovementSystemUnitTest.cs index 4e075eef..32909ebc 100644 --- a/tests/components/MovementSystemUnitTest.cs +++ b/tests/components/MovementSystemUnitTest.cs @@ -20,9 +20,9 @@ public class MovementSystemUnitTest var inputs = new MovementInputs( Velocity: Vector3.Zero, TargetLocation: new Vector3(10, 0, 0), - isOnFloor: false, - gravity: Vector3.Down * 9.8f, - delta: 1.0 + IsOnFloor: false, + Gravity: Vector3.Down * 9.8f, + Delta: 1.0 ); var v = move.ComputeVelocity(inputs);