diff --git a/assets/effects/GarlicEffect.tres b/assets/effects/GarlicEffect.tres index 0a36011..7ef6399 100644 --- a/assets/effects/GarlicEffect.tres +++ b/assets/effects/GarlicEffect.tres @@ -1,9 +1,9 @@ -[gd_resource type="Resource" load_steps=2 format=3 uid="uid://dsg1vjx76ifgu"] +[gd_resource type="Resource" script_class="RandomRedirectEffect" load_steps=2 format=3 uid="uid://dsg1vjx76ifgu"] [ext_resource type="Script" uid="uid://bb6lv1djnqjaw" path="res://scripts/systems/effects/RandomRedirectEffect.cs" id="1_rfumy"] [resource] script = ExtResource("1_rfumy") tilesWalked = 0.2 -Duration = 1.0 +Duration = 3.0 Slot = "garlic" diff --git a/scenes/projectiles/pea.tscn b/scenes/projectiles/pea.tscn index 38ac1ef..b6eb1b5 100644 --- a/scenes/projectiles/pea.tscn +++ b/scenes/projectiles/pea.tscn @@ -1,9 +1,18 @@ -[gd_scene load_steps=5 format=3 uid="uid://b2hrv0aqbui7u"] +[gd_scene load_steps=7 format=3 uid="uid://b2hrv0aqbui7u"] [ext_resource type="Script" uid="uid://dxlwvwy3hj56x" path="res://scripts/projectiles/LinearProjectile.cs" id="1_3kc4s"] [ext_resource type="Texture2D" uid="uid://dq0mul65hevtt" path="res://assets/sprites/plants/pea.tres" id="2_26q5x"] +[ext_resource type="Script" uid="uid://bb6lv1djnqjaw" path="res://scripts/systems/effects/RandomRedirectEffect.cs" id="2_fwj1o"] [ext_resource type="PackedScene" uid="uid://1d33w4ubtury" path="res://scenes/particles/pea_particles.tscn" id="2_osqrk"] +[sub_resource type="Resource" id="Resource_22ej5"] +script = ExtResource("2_fwj1o") +tilesWalked = 0.2 +travelTime = 0.2 +Duration = 0.3 +Slot = "testra" +metadata/_custom_type_script = "uid://bb6lv1djnqjaw" + [sub_resource type="CircleShape2D" id="CircleShape2D_ix1sk"] radius = 6.0 @@ -13,6 +22,7 @@ collision_mask = 8 script = ExtResource("1_3kc4s") _speed = 3.0 _damage = 10 +_impactEffect = SubResource("Resource_22ej5") particles = ExtResource("2_osqrk") [node name="Sprite" type="Sprite2D" parent="."] diff --git a/scripts/Newlon.cs b/scripts/Newlon.cs index 9a4d5ea..aa01d14 100644 --- a/scripts/Newlon.cs +++ b/scripts/Newlon.cs @@ -1,9 +1,14 @@ +using Godot; + namespace Newlon; public static class LON { - public static float Pr(string path) + public static void ForceFinishTween(Tween tween) { - return 0; + if (tween == null) return; + + tween.Pause(); + tween.CustomStep(Mathf.Inf); } } \ No newline at end of file diff --git a/scripts/entities/Entity.cs b/scripts/entities/Entity.cs index 697f69f..8720ca5 100644 --- a/scripts/entities/Entity.cs +++ b/scripts/entities/Entity.cs @@ -113,8 +113,7 @@ public partial class Entity : Node2D #region Effects [Export] private Array _effectImmunities = new(); [Export] private bool completeInvulnerability = false; - private readonly Dictionary _activeEffectSlots = new(); - private readonly Dictionary _effectSlotTimers = new(); + private readonly Dictionary effectHandlers = new(); [Signal] public delegate void EffectStartedEventHandler(Effect what); [Signal] public delegate void EffectEndedEventHandler(Effect what); @@ -123,50 +122,25 @@ public partial class Entity : Node2D public virtual void GiveEffect(Effect what) { - if (Killed) return; - if (_effectImmunities.Contains(what) || completeInvulnerability) - { + if (what == null || + Killed || + completeInvulnerability || _effectImmunities.Contains(what)) return; - } - string slot = what.Slot; - if (_activeEffectSlots.ContainsKey(slot) == false) - { + var slot = what.Slot; + if (effectHandlers.ContainsKey(slot) == false) InitSlot(slot); - } - if (what == _activeEffectSlots[slot]) + if (effectHandlers[slot].HandledEffect == what) { - EmitSignal(SignalName.EffectContinued, what); + effectHandlers[slot].Restart(); } else { - EmitSignal(SignalName.EffectStarted, what); + effectHandlers[slot].HandledEffect = what; + effectHandlers[slot].Start(); } - if (_activeEffectSlots[slot] != null) - { - _effectSlotTimers[slot].Stop(); - _activeEffectSlots[slot].Exit(this); - } - _effectSlotTimers[slot].WaitTime = what.Duration; - _effectSlotTimers[slot].Start(); - - what.Enter(this); - _activeEffectSlots[slot] = what; - - } - - private void InitSlot(string key) - { - _activeEffectSlots.Add(key, null); - - var timer = new Timer() { Autostart = false, OneShot = true }; - AddChild(timer); - timer.Timeout += () => { EndEffectAtSlot(key); }; - - _effectSlotTimers.Add(key, timer); - } public void EndEffect(Effect what) @@ -174,34 +148,48 @@ public partial class Entity : Node2D EndEffectAtSlot(what.Slot); } + public Tween CreateTweenEffect(Effect effect) + { + Tween tween = CreateTween(); + + effectHandlers[effect.Slot].EffectTween = tween; + + return tween; + } + protected void ClearEffects() { - foreach (var slot in _activeEffectSlots.Keys) + foreach (var slot in effectHandlers.Keys) { - if (_activeEffectSlots[slot] != null) - { - _activeEffectSlots[slot].Exit(this); - _effectSlotTimers[slot].Stop(); - _activeEffectSlots[slot] = null; - } + effectHandlers[slot].End(); } } + private void InitSlot(string key) + { + effectHandlers.Add(key, new EffectHandler()); + effectHandlers[key].handler = this; + effectHandlers[key].EffectTimer = new(); + + AddChild(effectHandlers[key].EffectTimer); + effectHandlers[key].EffectTimer.Name = key + "Timer"; + + effectHandlers[key].EffectTimer.Timeout += () => { EndEffectAtSlot(key); }; + } public void ProcessEffects() { - if (Killed) return; - foreach (string key in _activeEffectSlots.Keys) - _activeEffectSlots[key]?.Process(this); + foreach (var slot in effectHandlers.Keys) + { + effectHandlers[slot].Process(); + } } private void EndEffectAtSlot(string slot) { - _activeEffectSlots[slot].Exit(this); - _activeEffectSlots[slot] = null; - - EmitSignal(SignalName.EffectEnded, _activeEffectSlots[slot]); - + EmitSignal(SignalName.EffectEnded, effectHandlers[slot].HandledEffect); + effectHandlers[slot].End(); } + #endregion #region LocalTimescale private float _localTimescale = 1.0f; diff --git a/scripts/systems/effects/Effect.cs b/scripts/systems/effects/Effect.cs index 43f9ecd..738eade 100644 --- a/scripts/systems/effects/Effect.cs +++ b/scripts/systems/effects/Effect.cs @@ -1,4 +1,5 @@ using Godot; +using Newlon.Components; namespace Newlon.Systems.Effects; @@ -7,7 +8,12 @@ public abstract partial class Effect : Resource { [Export] public float Duration; [Export] public string Slot; - public abstract void Enter(Node target); - public abstract void Process(Node target); - public abstract void Exit(Node target); + public abstract void Enter(Entity target); + public abstract void Process(Entity target); + public abstract void Exit(Entity target); + + private Tween CreateTween(Entity fromEntity) + { + return fromEntity.CreateTweenEffect(this); + } } diff --git a/scripts/systems/effects/EffectHandler.cs b/scripts/systems/effects/EffectHandler.cs new file mode 100644 index 0000000..e8a6590 --- /dev/null +++ b/scripts/systems/effects/EffectHandler.cs @@ -0,0 +1,48 @@ +using Godot; +using Newlon.Components; + +namespace Newlon.Systems.Effects; + +public partial class EffectHandler : RefCounted +{ + public Entity handler; + public Effect HandledEffect; + public Timer EffectTimer; + public Tween EffectTween; + + public void Start() + { + EffectTimer.WaitTime = HandledEffect.Duration; + EffectTimer.Start(); + + HandledEffect.Enter(handler); + } + public void End() + { + HandledEffect.Exit(handler); + HandledEffect = null; + EffectTimer.Stop(); + if (EffectTween != null) + { + LON.ForceFinishTween(EffectTween); + EffectTween.Kill(); + } + } + public void Process() + { + HandledEffect.Process(handler); + } + public void Restart() + { + HandledEffect.Exit(handler); + EffectTimer.Stop(); + if (EffectTween != null) + { + LON.ForceFinishTween(EffectTween); + EffectTween.Kill(); + } + + HandledEffect.Enter(handler); + EffectTimer.Start(); + } +} diff --git a/scripts/systems/effects/EffectHandler.cs.uid b/scripts/systems/effects/EffectHandler.cs.uid new file mode 100644 index 0000000..5bbd866 --- /dev/null +++ b/scripts/systems/effects/EffectHandler.cs.uid @@ -0,0 +1 @@ +uid://csxb8rllqjb1t diff --git a/scripts/systems/effects/PermanentSpeedEffect.cs b/scripts/systems/effects/PermanentSpeedEffect.cs index e555539..88c2203 100644 --- a/scripts/systems/effects/PermanentSpeedEffect.cs +++ b/scripts/systems/effects/PermanentSpeedEffect.cs @@ -8,19 +8,16 @@ public partial class PermanentSpeedEffect : Effect { [Export] public float Multiplier; - public override void Enter(Node target) + public override void Enter(Entity target) { - if (target is Entity entity) - { - entity.LocalTimescale *= Multiplier; - } + target.LocalTimescale *= Multiplier; } - public override void Exit(Node target) + public override void Exit(Entity target) { } - public override void Process(Node target) + public override void Process(Entity target) { } diff --git a/scripts/systems/effects/RandomRedirectEffect.cs b/scripts/systems/effects/RandomRedirectEffect.cs index f57e4d2..63cd05d 100644 --- a/scripts/systems/effects/RandomRedirectEffect.cs +++ b/scripts/systems/effects/RandomRedirectEffect.cs @@ -1,4 +1,5 @@ using Godot; +using Newlon.Components; using Newlon.Components.Zombies; namespace Newlon.Systems.Effects; @@ -7,9 +8,10 @@ namespace Newlon.Systems.Effects; public partial class RandomRedirectEffect : Effect { [Export] private float tilesWalked = 0.2f; + [Export] private float travelTime = 1; RandomNumberGenerator RandomNumberGenerator; - public override void Enter(Node target) + public override void Enter(Entity target) { if (RandomNumberGenerator == null) { @@ -19,9 +21,14 @@ public partial class RandomRedirectEffect : Effect if (target is RuntimeZombieData zombieData) zombieData.AbleToEat = false; //Animation call + Animation(target); } - public override void Exit(Node target) + public override void Exit(Entity target) + { + + } + private void Animation(Entity target) { if (target is RuntimeZombieData zombieData) { @@ -46,14 +53,14 @@ public partial class RandomRedirectEffect : Effect } } zombieData.AbleToEat = false; - var tween = zombieData.CreateTween(); - tween.TweenProperty(zombieData, "position:y", zombieData.GlobalPosition.Y + FieldParams.TileHeight * mult, Duration); - tween.Parallel().TweenProperty(zombieData, "position:x", zombieData.GlobalPosition.X - FieldParams.TileHeight * tilesWalked, Duration); + var tween = zombieData.CreateTweenEffect(this); + tween.TweenInterval(Duration-travelTime); + tween.TweenProperty(zombieData, "position:y", zombieData.GlobalPosition.Y + FieldParams.TileHeight * mult, travelTime); + tween.Parallel().TweenProperty(zombieData, "position:x", zombieData.GlobalPosition.X - FieldParams.TileHeight * tilesWalked, travelTime); tween.TweenCallback(Callable.From(() => { zombieData.AbleToEat = true; })); } } - - public override void Process(Node target) + public override void Process(Entity target) { } diff --git a/scripts/systems/effects/RedirectEffect.cs b/scripts/systems/effects/RedirectEffect.cs index 988e1cf..b53ba58 100644 --- a/scripts/systems/effects/RedirectEffect.cs +++ b/scripts/systems/effects/RedirectEffect.cs @@ -1,5 +1,6 @@ using Godot; using Newlon.Components.Zombies; +using Newlon.Components; namespace Newlon.Systems.Effects; @@ -9,14 +10,14 @@ public partial class RedirectEffect : Effect [Export] private float tilesWalked = 0.2f; [Export] private bool down = false; - public override void Enter(Node target) + public override void Enter(Entity target) { if (target is RuntimeZombieData zombieData) zombieData.AbleToEat = false; //Animation call } - public override void Exit(Node target) + public override void Exit(Entity target) { if (target is RuntimeZombieData zombieData) { @@ -48,7 +49,7 @@ public partial class RedirectEffect : Effect } } - public override void Process(Node target) + public override void Process(Entity target) { } diff --git a/scripts/systems/effects/SlownessEffect.cs b/scripts/systems/effects/SlownessEffect.cs index b4d7a83..64c328e 100644 --- a/scripts/systems/effects/SlownessEffect.cs +++ b/scripts/systems/effects/SlownessEffect.cs @@ -9,25 +9,19 @@ public partial class SlownessEffect : Effect [Export] public Color ColorOverride; [Export] public float Multiplier; - public override void Enter(Node target) + public override void Enter(Entity target) { - if (target is Entity entity) - { - entity.LocalTimescale *= Multiplier; - entity.Modulate = ColorOverride; - } + target.LocalTimescale *= Multiplier; + target.Modulate = ColorOverride; } - public override void Exit(Node target) + public override void Exit(Entity target) { - if (target is Entity entity) - { - entity.LocalTimescale /= Multiplier; - entity.Modulate = Colors.White; - } + target.LocalTimescale /= Multiplier; + target.Modulate = Colors.White; } - public override void Process(Node target) + public override void Process(Entity target) { }