new effect system
This commit is contained in:
parent
f3a6f7a05a
commit
22b02c4590
11 changed files with 146 additions and 89 deletions
|
|
@ -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"]
|
[ext_resource type="Script" uid="uid://bb6lv1djnqjaw" path="res://scripts/systems/effects/RandomRedirectEffect.cs" id="1_rfumy"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_rfumy")
|
script = ExtResource("1_rfumy")
|
||||||
tilesWalked = 0.2
|
tilesWalked = 0.2
|
||||||
Duration = 1.0
|
Duration = 3.0
|
||||||
Slot = "garlic"
|
Slot = "garlic"
|
||||||
|
|
|
||||||
|
|
@ -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="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="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"]
|
[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"]
|
[sub_resource type="CircleShape2D" id="CircleShape2D_ix1sk"]
|
||||||
radius = 6.0
|
radius = 6.0
|
||||||
|
|
||||||
|
|
@ -13,6 +22,7 @@ collision_mask = 8
|
||||||
script = ExtResource("1_3kc4s")
|
script = ExtResource("1_3kc4s")
|
||||||
_speed = 3.0
|
_speed = 3.0
|
||||||
_damage = 10
|
_damage = 10
|
||||||
|
_impactEffect = SubResource("Resource_22ej5")
|
||||||
particles = ExtResource("2_osqrk")
|
particles = ExtResource("2_osqrk")
|
||||||
|
|
||||||
[node name="Sprite" type="Sprite2D" parent="."]
|
[node name="Sprite" type="Sprite2D" parent="."]
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
namespace Newlon;
|
namespace Newlon;
|
||||||
|
|
||||||
public static class LON
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,8 +113,7 @@ public partial class Entity : Node2D
|
||||||
#region Effects
|
#region Effects
|
||||||
[Export] private Array<Effect> _effectImmunities = new();
|
[Export] private Array<Effect> _effectImmunities = new();
|
||||||
[Export] private bool completeInvulnerability = false;
|
[Export] private bool completeInvulnerability = false;
|
||||||
private readonly Dictionary<string, Effect> _activeEffectSlots = new();
|
private readonly Dictionary<string, EffectHandler> effectHandlers = new();
|
||||||
private readonly Dictionary<string, Timer> _effectSlotTimers = new();
|
|
||||||
|
|
||||||
[Signal] public delegate void EffectStartedEventHandler(Effect what);
|
[Signal] public delegate void EffectStartedEventHandler(Effect what);
|
||||||
[Signal] public delegate void EffectEndedEventHandler(Effect what);
|
[Signal] public delegate void EffectEndedEventHandler(Effect what);
|
||||||
|
|
@ -123,50 +122,25 @@ public partial class Entity : Node2D
|
||||||
|
|
||||||
public virtual void GiveEffect(Effect what)
|
public virtual void GiveEffect(Effect what)
|
||||||
{
|
{
|
||||||
if (Killed) return;
|
if (what == null ||
|
||||||
if (_effectImmunities.Contains(what) || completeInvulnerability)
|
Killed ||
|
||||||
{
|
completeInvulnerability || _effectImmunities.Contains(what))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
string slot = what.Slot;
|
var slot = what.Slot;
|
||||||
if (_activeEffectSlots.ContainsKey(slot) == false)
|
if (effectHandlers.ContainsKey(slot) == false)
|
||||||
{
|
|
||||||
InitSlot(slot);
|
InitSlot(slot);
|
||||||
}
|
|
||||||
|
|
||||||
if (what == _activeEffectSlots[slot])
|
if (effectHandlers[slot].HandledEffect == what)
|
||||||
{
|
{
|
||||||
EmitSignal(SignalName.EffectContinued, what);
|
effectHandlers[slot].Restart();
|
||||||
}
|
}
|
||||||
else
|
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)
|
public void EndEffect(Effect what)
|
||||||
|
|
@ -174,34 +148,48 @@ public partial class Entity : Node2D
|
||||||
EndEffectAtSlot(what.Slot);
|
EndEffectAtSlot(what.Slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tween CreateTweenEffect(Effect effect)
|
||||||
|
{
|
||||||
|
Tween tween = CreateTween();
|
||||||
|
|
||||||
|
effectHandlers[effect.Slot].EffectTween = tween;
|
||||||
|
|
||||||
|
return tween;
|
||||||
|
}
|
||||||
|
|
||||||
protected void ClearEffects()
|
protected void ClearEffects()
|
||||||
{
|
{
|
||||||
foreach (var slot in _activeEffectSlots.Keys)
|
foreach (var slot in effectHandlers.Keys)
|
||||||
{
|
{
|
||||||
if (_activeEffectSlots[slot] != null)
|
effectHandlers[slot].End();
|
||||||
{
|
|
||||||
_activeEffectSlots[slot].Exit(this);
|
|
||||||
_effectSlotTimers[slot].Stop();
|
|
||||||
_activeEffectSlots[slot] = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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()
|
public void ProcessEffects()
|
||||||
{
|
{
|
||||||
if (Killed) return;
|
foreach (var slot in effectHandlers.Keys)
|
||||||
foreach (string key in _activeEffectSlots.Keys)
|
{
|
||||||
_activeEffectSlots[key]?.Process(this);
|
effectHandlers[slot].Process();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EndEffectAtSlot(string slot)
|
private void EndEffectAtSlot(string slot)
|
||||||
{
|
{
|
||||||
_activeEffectSlots[slot].Exit(this);
|
EmitSignal(SignalName.EffectEnded, effectHandlers[slot].HandledEffect);
|
||||||
_activeEffectSlots[slot] = null;
|
effectHandlers[slot].End();
|
||||||
|
|
||||||
EmitSignal(SignalName.EffectEnded, _activeEffectSlots[slot]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
#region LocalTimescale
|
#region LocalTimescale
|
||||||
private float _localTimescale = 1.0f;
|
private float _localTimescale = 1.0f;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Newlon.Components;
|
||||||
|
|
||||||
namespace Newlon.Systems.Effects;
|
namespace Newlon.Systems.Effects;
|
||||||
|
|
||||||
|
|
@ -7,7 +8,12 @@ public abstract partial class Effect : Resource
|
||||||
{
|
{
|
||||||
[Export] public float Duration;
|
[Export] public float Duration;
|
||||||
[Export] public string Slot;
|
[Export] public string Slot;
|
||||||
public abstract void Enter(Node target);
|
public abstract void Enter(Entity target);
|
||||||
public abstract void Process(Node target);
|
public abstract void Process(Entity target);
|
||||||
public abstract void Exit(Node target);
|
public abstract void Exit(Entity target);
|
||||||
|
|
||||||
|
private Tween CreateTween(Entity fromEntity)
|
||||||
|
{
|
||||||
|
return fromEntity.CreateTweenEffect(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
48
scripts/systems/effects/EffectHandler.cs
Normal file
48
scripts/systems/effects/EffectHandler.cs
Normal file
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
1
scripts/systems/effects/EffectHandler.cs.uid
Normal file
1
scripts/systems/effects/EffectHandler.cs.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://csxb8rllqjb1t
|
||||||
|
|
@ -8,19 +8,16 @@ public partial class PermanentSpeedEffect : Effect
|
||||||
{
|
{
|
||||||
[Export] public float Multiplier;
|
[Export] public float Multiplier;
|
||||||
|
|
||||||
public override void Enter(Node target)
|
public override void Enter(Entity target)
|
||||||
{
|
{
|
||||||
if (target is Entity entity)
|
target.LocalTimescale *= Multiplier;
|
||||||
{
|
|
||||||
entity.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)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Newlon.Components;
|
||||||
using Newlon.Components.Zombies;
|
using Newlon.Components.Zombies;
|
||||||
|
|
||||||
namespace Newlon.Systems.Effects;
|
namespace Newlon.Systems.Effects;
|
||||||
|
|
@ -7,9 +8,10 @@ namespace Newlon.Systems.Effects;
|
||||||
public partial class RandomRedirectEffect : Effect
|
public partial class RandomRedirectEffect : Effect
|
||||||
{
|
{
|
||||||
[Export] private float tilesWalked = 0.2f;
|
[Export] private float tilesWalked = 0.2f;
|
||||||
|
[Export] private float travelTime = 1;
|
||||||
RandomNumberGenerator RandomNumberGenerator;
|
RandomNumberGenerator RandomNumberGenerator;
|
||||||
|
|
||||||
public override void Enter(Node target)
|
public override void Enter(Entity target)
|
||||||
{
|
{
|
||||||
if (RandomNumberGenerator == null)
|
if (RandomNumberGenerator == null)
|
||||||
{
|
{
|
||||||
|
|
@ -19,9 +21,14 @@ public partial class RandomRedirectEffect : Effect
|
||||||
if (target is RuntimeZombieData zombieData)
|
if (target is RuntimeZombieData zombieData)
|
||||||
zombieData.AbleToEat = false;
|
zombieData.AbleToEat = false;
|
||||||
//Animation call
|
//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)
|
if (target is RuntimeZombieData zombieData)
|
||||||
{
|
{
|
||||||
|
|
@ -46,14 +53,14 @@ public partial class RandomRedirectEffect : Effect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zombieData.AbleToEat = false;
|
zombieData.AbleToEat = false;
|
||||||
var tween = zombieData.CreateTween();
|
var tween = zombieData.CreateTweenEffect(this);
|
||||||
tween.TweenProperty(zombieData, "position:y", zombieData.GlobalPosition.Y + FieldParams.TileHeight * mult, Duration);
|
tween.TweenInterval(Duration-travelTime);
|
||||||
tween.Parallel().TweenProperty(zombieData, "position:x", zombieData.GlobalPosition.X - FieldParams.TileHeight * tilesWalked, Duration);
|
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; }));
|
tween.TweenCallback(Callable.From(() => { zombieData.AbleToEat = true; }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override void Process(Entity target)
|
||||||
public override void Process(Node target)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using Newlon.Components.Zombies;
|
using Newlon.Components.Zombies;
|
||||||
|
using Newlon.Components;
|
||||||
|
|
||||||
namespace Newlon.Systems.Effects;
|
namespace Newlon.Systems.Effects;
|
||||||
|
|
||||||
|
|
@ -9,14 +10,14 @@ public partial class RedirectEffect : Effect
|
||||||
[Export] private float tilesWalked = 0.2f;
|
[Export] private float tilesWalked = 0.2f;
|
||||||
[Export] private bool down = false;
|
[Export] private bool down = false;
|
||||||
|
|
||||||
public override void Enter(Node target)
|
public override void Enter(Entity target)
|
||||||
{
|
{
|
||||||
if (target is RuntimeZombieData zombieData)
|
if (target is RuntimeZombieData zombieData)
|
||||||
zombieData.AbleToEat = false;
|
zombieData.AbleToEat = false;
|
||||||
//Animation call
|
//Animation call
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Exit(Node target)
|
public override void Exit(Entity target)
|
||||||
{
|
{
|
||||||
if (target is RuntimeZombieData zombieData)
|
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)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,25 +9,19 @@ public partial class SlownessEffect : Effect
|
||||||
[Export] public Color ColorOverride;
|
[Export] public Color ColorOverride;
|
||||||
[Export] public float Multiplier;
|
[Export] public float Multiplier;
|
||||||
|
|
||||||
public override void Enter(Node target)
|
public override void Enter(Entity target)
|
||||||
{
|
{
|
||||||
if (target is Entity entity)
|
target.LocalTimescale *= Multiplier;
|
||||||
{
|
target.Modulate = ColorOverride;
|
||||||
entity.LocalTimescale *= Multiplier;
|
|
||||||
entity.Modulate = ColorOverride;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Exit(Node target)
|
public override void Exit(Entity target)
|
||||||
{
|
{
|
||||||
if (target is Entity entity)
|
target.LocalTimescale /= Multiplier;
|
||||||
{
|
target.Modulate = Colors.White;
|
||||||
entity.LocalTimescale /= Multiplier;
|
|
||||||
entity.Modulate = Colors.White;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Process(Node target)
|
public override void Process(Entity target)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue