diff --git a/assets/sprites/plants/snowpea.tres b/assets/sprites/plants/snowpea.tres new file mode 100644 index 0000000..e26344f --- /dev/null +++ b/assets/sprites/plants/snowpea.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://cu7h8bot6jlug"] + +[ext_resource type="Texture2D" uid="uid://dvldjlg0nr355" path="res://assets/sprites/atlases/atlas1.png" id="1_pt3id"] + +[resource] +atlas = ExtResource("1_pt3id") +region = Rect2(253, 5, 43, 54) diff --git a/assets/sprites/plants/snowpea_projectile.tres b/assets/sprites/plants/snowpea_projectile.tres new file mode 100644 index 0000000..dd33464 --- /dev/null +++ b/assets/sprites/plants/snowpea_projectile.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://dn4l67snkx5mr"] + +[ext_resource type="Texture2D" uid="uid://dvldjlg0nr355" path="res://assets/sprites/atlases/atlas1.png" id="1_ljncc"] + +[resource] +atlas = ExtResource("1_ljncc") +region = Rect2(18, 130, 12, 12) diff --git a/resources/animations/plants/snowpea.res b/resources/animations/plants/snowpea.res new file mode 100644 index 0000000..7c24d0e Binary files /dev/null and b/resources/animations/plants/snowpea.res differ diff --git a/resources/effects/SnowSlow.tres b/resources/effects/SnowSlow.tres new file mode 100644 index 0000000..5c422ac --- /dev/null +++ b/resources/effects/SnowSlow.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" load_steps=2 format=3 uid="uid://7uj0oe656jfx"] + +[ext_resource type="Script" path="res://scripts/systems/effects/SlownessEffect.cs" id="1_8md01"] + +[resource] +script = ExtResource("1_8md01") +ColorOverride = Color(0, 1, 1, 1) +Duration = 10.0 +Multiplier = 0.75 diff --git a/resources/plants/Snowpea.tres b/resources/plants/Snowpea.tres new file mode 100644 index 0000000..cb675e7 --- /dev/null +++ b/resources/plants/Snowpea.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="PlantResource" load_steps=4 format=3 uid="uid://duflq3eexs6m"] + +[ext_resource type="Script" path="res://scripts/resources/PlantResource.cs" id="1_0cpi0"] +[ext_resource type="Texture2D" uid="uid://cu7h8bot6jlug" path="res://assets/sprites/plants/snowpea.tres" id="1_7fyy2"] +[ext_resource type="PackedScene" uid="uid://b7innrovtmf5u" path="res://scenes/entities/plants/snowpea.tscn" id="2_k47h0"] + +[resource] +script = ExtResource("1_0cpi0") +Cost = 175 +Scene = ExtResource("2_k47h0") +ReloadTime = 5.0 +StartReloadTime = 0.0 +Preview = ExtResource("1_7fyy2") +Layer = 1 diff --git a/scenes/entities/Zombies/zombie.tscn b/scenes/entities/Zombies/zombie.tscn index 394c186..657c657 100644 --- a/scenes/entities/Zombies/zombie.tscn +++ b/scenes/entities/Zombies/zombie.tscn @@ -17,10 +17,10 @@ shader_parameter/blend_color = Color(1, 1, 1, 1) shader_parameter/amount = null [sub_resource type="RectangleShape2D" id="RectangleShape2D_hxyad"] -size = Vector2(24, 84) +size = Vector2(2, 84) [sub_resource type="RectangleShape2D" id="RectangleShape2D_r4ug6"] -size = Vector2(20, 48) +size = Vector2(16, 48) [sub_resource type="Animation" id="Animation_qv5y7"] length = 0.001 @@ -202,6 +202,7 @@ parameters/conditions/end_eat = false [node name="Mover" type="Node" parent="."] script = ExtResource("4_u5syx") +_speedMultiplier = 0.25 [node name="Behaviour" type="Node" parent="."] script = ExtResource("5_2pvkr") diff --git a/scenes/entities/plants/peashooter.tscn b/scenes/entities/plants/peashooter.tscn index 8a3e0cc..e386c01 100644 --- a/scenes/entities/plants/peashooter.tscn +++ b/scenes/entities/plants/peashooter.tscn @@ -4,7 +4,7 @@ [ext_resource type="Script" path="res://scripts/components/plants/RuntimePlantData.cs" id="1_f4h5i"] [ext_resource type="AnimationLibrary" uid="uid://bv1dl1g4dmbho" path="res://resources/animations/plants/peashooter.res" id="2_vs0tj"] [ext_resource type="Script" path="res://scripts/components/plants/Shooter.cs" id="4_sbggp"] -[ext_resource type="PackedScene" uid="uid://b2hrv0aqbui7u" path="res://scenes/entities/plants/pea.tscn" id="5_66an8"] +[ext_resource type="PackedScene" uid="uid://b2hrv0aqbui7u" path="res://scenes/projectiles/pea.tscn" id="5_66an8"] [ext_resource type="Script" path="res://scripts/components/plants/PlantEyesightLimiter.cs" id="6_0812i"] [ext_resource type="Script" path="res://scripts/components/plants/behaviours/PeashooterBehaviour.cs" id="6_tdkoh"] [ext_resource type="Script" path="res://scripts/components/plants/Eyesight.cs" id="7_fdkt2"] diff --git a/scenes/entities/plants/snowpea.tscn b/scenes/entities/plants/snowpea.tscn new file mode 100644 index 0000000..2bcacac --- /dev/null +++ b/scenes/entities/plants/snowpea.tscn @@ -0,0 +1,123 @@ +[gd_scene load_steps=16 format=3 uid="uid://b7innrovtmf5u"] + +[ext_resource type="PackedScene" uid="uid://be1kgukmiu0hs" path="res://scenes/entities/plants/peashooter.tscn" id="1_lp85e"] +[ext_resource type="Texture2D" uid="uid://cu0651pvvkmvm" path="res://assets/sprites/atlases/plants/snow_pea.png" id="2_ytrm0"] +[ext_resource type="AudioStream" uid="uid://dp6k7xiptn68n" path="res://assets/audio/sfx/pop.mp3" id="3_4fpbe"] +[ext_resource type="AnimationLibrary" uid="uid://cke5wmmrvevbs" path="res://resources/animations/plants/snowpea.res" id="4_jvx5y"] +[ext_resource type="PackedScene" uid="uid://domeukw4ucmyr" path="res://scenes/projectiles/snowpea_projectile.tscn" id="5_bv86m"] + +[sub_resource type="Animation" id="Animation_pephc"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [0] +} + +[sub_resource type="Animation" id="Animation_ip1gy"] +resource_name = "shoot_2" +length = 0.666675 +step = 0.0833333 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.0833333, 0.166667, 0.25, 0.333333, 0.416667), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 1, +"values": [5, 7, 9, 11, 13, 15] +} +tracks/1/type = "method" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Shooter") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0.25), +"transitions": PackedFloat32Array(1), +"values": [{ +"args": [], +"method": &"Shoot" +}] +} +tracks/2/type = "audio" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("AudioStreamPlayer2D") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"clips": [{ +"end_offset": 0.0, +"start_offset": 0.0, +"stream": ExtResource("3_4fpbe") +}], +"times": PackedFloat32Array(0.25) +} +tracks/2/use_blend = true + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_djmlc"] +_data = { +"RESET": SubResource("Animation_pephc"), +"shoot_2": SubResource("Animation_ip1gy") +} + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_7tu1y"] +animation = &"snowpea/idle" + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_nhra5"] +animation = &"snowpea/shoot" + +[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_iyvb5"] +advance_mode = 2 + +[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_63spy"] +switch_mode = 2 +advance_mode = 2 + +[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_yr2qp"] +advance_mode = 2 +advance_condition = &"ready" + +[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_owox6"] +states/Start/position = Vector2(192, 100) +states/snowpea_idle/node = SubResource("AnimationNodeAnimation_7tu1y") +states/snowpea_idle/position = Vector2(425, 100) +states/snowpea_shoot/node = SubResource("AnimationNodeAnimation_nhra5") +states/snowpea_shoot/position = Vector2(644, 96) +transitions = ["Start", "snowpea_idle", SubResource("AnimationNodeStateMachineTransition_iyvb5"), "snowpea_shoot", "snowpea_idle", SubResource("AnimationNodeStateMachineTransition_63spy"), "snowpea_idle", "snowpea_shoot", SubResource("AnimationNodeStateMachineTransition_yr2qp")] + +[sub_resource type="SegmentShape2D" id="SegmentShape2D_k2110"] +resource_local_to_scene = true +b = Vector2(5.865, 0) + +[node name="Snowpea" instance=ExtResource("1_lp85e")] + +[node name="Sprite" parent="." index="0"] +texture = ExtResource("2_ytrm0") + +[node name="AnimationPlayer" parent="." index="1"] +libraries = { +"": SubResource("AnimationLibrary_djmlc"), +"snowpea": ExtResource("4_jvx5y") +} + +[node name="AnimationTree" parent="." index="2"] +tree_root = SubResource("AnimationNodeStateMachine_owox6") + +[node name="Shooter" parent="." index="4"] +_projectile = ExtResource("5_bv86m") + +[node name="CollisionShape2D" parent="Eyesight" index="0"] +shape = SubResource("SegmentShape2D_k2110") diff --git a/scenes/gui/choose_your_seeds.tscn b/scenes/gui/choose_your_seeds.tscn index 4eb7873..a0470f2 100644 --- a/scenes/gui/choose_your_seeds.tscn +++ b/scenes/gui/choose_your_seeds.tscn @@ -22,6 +22,18 @@ tracks/0/keys = { "points": PackedFloat32Array(64, -0.25, 0, 0.5, 7.5, 402, -0.55, -95.5, 0.25, 0), "times": PackedFloat32Array(0, 0.75) } +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:disabled") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [true] +} [sub_resource type="Animation" id="Animation_8he0w"] length = 0.001 @@ -36,6 +48,18 @@ tracks/0/keys = { "points": PackedFloat32Array(402, -0.25, 0, 0.25, 0), "times": PackedFloat32Array(0) } +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:disabled") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [false] +} [sub_resource type="Animation" id="Animation_omiwq"] resource_name = "Show" @@ -52,6 +76,18 @@ tracks/0/keys = { "points": PackedFloat32Array(402, -0.25, 0, 1, -336.5, 64, -1, 338.5, 0, 66.5, 64, -0.0571204, 1, 0.19288, 1.5), "times": PackedFloat32Array(0, 1, 1.5) } +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:disabled") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 1.5), +"transitions": PackedFloat32Array(1, 1), +"update": 1, +"values": [true, false] +} [sub_resource type="AnimationLibrary" id="AnimationLibrary_tguwa"] _data = { diff --git a/scenes/entities/plants/pea.tscn b/scenes/projectiles/pea.tscn similarity index 100% rename from scenes/entities/plants/pea.tscn rename to scenes/projectiles/pea.tscn diff --git a/scenes/projectiles/snowpea_projectile.tscn b/scenes/projectiles/snowpea_projectile.tscn new file mode 100644 index 0000000..1531a2a --- /dev/null +++ b/scenes/projectiles/snowpea_projectile.tscn @@ -0,0 +1,30 @@ +[gd_scene load_steps=5 format=3 uid="uid://domeukw4ucmyr"] + +[ext_resource type="Script" path="res://scripts/components/LinearProjectile.cs" id="1_fkydi"] +[ext_resource type="Resource" uid="uid://7uj0oe656jfx" path="res://resources/effects/SnowSlow.tres" id="2_txupr"] +[ext_resource type="Texture2D" uid="uid://dn4l67snkx5mr" path="res://assets/sprites/plants/snowpea_projectile.tres" id="2_xt8td"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_ix1sk"] +radius = 6.0 + +[node name="Snowpea" type="Area2D"] +collision_layer = 4 +collision_mask = 8 +script = ExtResource("1_fkydi") +_speed = 3.0 +_damage = 10 +_impactEffect = ExtResource("2_txupr") + +[node name="Sprite" type="Sprite2D" parent="."] +texture = ExtResource("2_xt8td") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("CircleShape2D_ix1sk") + +[node name="Timer" type="Timer" parent="."] +wait_time = 15.0 +one_shot = true +autostart = true + +[connection signal="area_entered" from="." to="." method="OnAreaEntered"] +[connection signal="timeout" from="Timer" to="." method="queue_free"] diff --git a/scripts/Utility.cs b/scripts/Utility.cs index 78bcfb8..6c168c6 100644 --- a/scripts/Utility.cs +++ b/scripts/Utility.cs @@ -7,11 +7,20 @@ namespace Newlon; // Class for general-used constants and utility tools // -public partial class Utility +public class Utility { + // + // Code-accessed enumenators + // + #region Enums + + public enum EffectSlots {FREEZE, STUN, POISON}; + + #endregion + + public const int EffectSlotCount = 3; public const int TileWidth = 50; public const int TileHeight = 60; - public const int LayersCount = 3; public static readonly Vector2I LeftFieldBoundary = new(305,76); public static readonly Vector2I RightFieldBoundary = new(755,376); diff --git a/scripts/components/LinearProjectile.cs b/scripts/components/LinearProjectile.cs index 27d73f9..d28ea6e 100644 --- a/scripts/components/LinearProjectile.cs +++ b/scripts/components/LinearProjectile.cs @@ -1,5 +1,5 @@ using Godot; -using System; +using Newlon.Systems.Effects; namespace Newlon.Components; @@ -13,6 +13,8 @@ public partial class LinearProjectile : Area2D, IProjectile private float _speed; [Export] private int _damage; + [Export] + private Effect _impactEffect; private int _line; public int Line { get => _line; set { _line = value; } } @@ -27,6 +29,8 @@ public partial class LinearProjectile : Area2D, IProjectile if (entity != null && entity.Line == _line) { entity.TakeDamage(_damage); + if (entity is IEffectHandler effectHandler && _impactEffect != null) + effectHandler.GiveEffect(_impactEffect); QueueFree(); } } diff --git a/scripts/components/zombies/RuntimeZombieData.cs b/scripts/components/zombies/RuntimeZombieData.cs index 2e869ea..5d55d5a 100644 --- a/scripts/components/zombies/RuntimeZombieData.cs +++ b/scripts/components/zombies/RuntimeZombieData.cs @@ -1,8 +1,10 @@ -using Godot; +using System.Collections.Generic; +using Godot; +using Newlon.Systems.Effects; namespace Newlon.Components.Zombies; -public partial class RuntimeZombieData : Node2D, IEntity, ILocalTimescale +public partial class RuntimeZombieData : Node2D, IEntity, ILocalTimescale, IEffectHandler { [Signal] public delegate void OnHPChangedEventHandler(int deltaHP); @@ -19,7 +21,7 @@ public partial class RuntimeZombieData : Node2D, IEntity, ILocalTimescale private float _localTimescale = 1.0f; public int Hp => _hp; - public int MaxHp => _maxHP; + public int MaxHp => _maxHP; public int Line => _line; @@ -36,6 +38,15 @@ public partial class RuntimeZombieData : Node2D, IEntity, ILocalTimescale public override void _Ready() { _hp = _maxHP; + + // Effect timers setup + for(int i = 0; i < Utility.EffectSlotCount; i++) + { + var timer = new Timer() {Autostart = false, OneShot = true}; + _effectSlotTimers[i] = timer; + AddChild(timer); + timer.Timeout += () => {EndEffectAtSlot(i);}; + } } public void Heal(int amount) @@ -59,4 +70,44 @@ public partial class RuntimeZombieData : Node2D, IEntity, ILocalTimescale QueueFree(); } } + + #region Effects system + private readonly Effect[] _activeEffectSlots = new Effect[Utility.EffectSlotCount]; + private readonly Timer[] _effectSlotTimers = new Timer[Utility.EffectSlotCount]; + + // Effect handling + + public void GiveEffect(Effect what) + { + int slot = (int)what.Slot; + 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; + } + + public void EndEffect(Effect what) + { + what.Exit(this); + _activeEffectSlots[(int)what.Slot] = null; + } + + public void ProcessEffects() + { + for(int i = 0; i < Utility.EffectSlotCount; i++) + _activeEffectSlots[i].Process(this); + } + + private void EndEffectAtSlot(int slot) + { + _activeEffectSlots[slot].Exit(this); + _activeEffectSlots[slot] = null; + } + #endregion } diff --git a/scripts/components/zombies/ZombieMover.cs b/scripts/components/zombies/ZombieMover.cs index afa26fe..7cd3beb 100644 --- a/scripts/components/zombies/ZombieMover.cs +++ b/scripts/components/zombies/ZombieMover.cs @@ -4,7 +4,10 @@ namespace Newlon.Components.Zombies; public partial class ZombieMover : Node { - private float _speed; + [Export(hintString: "suffix:tile/sec")] + private float _speedMultiplier = 1.0f; + + private float _speed = 1; private Node2D _zombie; @@ -15,7 +18,12 @@ public partial class ZombieMover : Node public override void _PhysicsProcess(double delta) { - _zombie.Position -= _zombie.Transform.X * _speed * (float)delta * Utility.TileWidth * GetParent().LocalTimescale; + _zombie.Position -= _zombie.Transform.X + * _speed + * (float)delta + * Utility.TileWidth + * GetParent().LocalTimescale + * _speedMultiplier; } public void SetSpeed(float speed) diff --git a/scripts/systems/effects/Effect.cs b/scripts/systems/effects/Effect.cs index 8a71409..43d6e0e 100644 --- a/scripts/systems/effects/Effect.cs +++ b/scripts/systems/effects/Effect.cs @@ -1,11 +1,12 @@ using Godot; -using System; namespace Newlon.Systems.Effects; public abstract partial class Effect : Resource { - public abstract void Enter(); - public abstract void Process(); - public abstract void Exit(); + [Export] public float Duration; + [Export] public Utility.EffectSlots Slot; + public abstract void Enter(Node target); + public abstract void Process(Node target); + public abstract void Exit(Node target); } diff --git a/scripts/systems/effects/IEffectHandler.cs b/scripts/systems/effects/IEffectHandler.cs index b07f020..6c9b758 100644 --- a/scripts/systems/effects/IEffectHandler.cs +++ b/scripts/systems/effects/IEffectHandler.cs @@ -2,5 +2,7 @@ namespace Newlon.Systems.Effects; public interface IEffectHandler { - + void GiveEffect(Effect what); + void EndEffect(Effect what); + void ProcessEffects(); } \ No newline at end of file diff --git a/scripts/systems/effects/SlownessEffect.cs b/scripts/systems/effects/SlownessEffect.cs new file mode 100644 index 0000000..ebef3f4 --- /dev/null +++ b/scripts/systems/effects/SlownessEffect.cs @@ -0,0 +1,35 @@ +using Godot; +using Newlon.Components; +using System; + +namespace Newlon.Systems.Effects; + +public partial class SlownessEffect : Effect +{ + [Export] public Color ColorOverride; + [Export] public float Multiplier; + + public override void Enter(Node target) + { + if(target is IEffectHandler handler) + { + if(target is ILocalTimescale timescalable) + timescalable.LocalTimescale *= Multiplier; + if(target is CanvasItem canvasItem) + canvasItem.Modulate = ColorOverride; + } + } + + public override void Exit(Node target) + { + if(target is ILocalTimescale timescalable) + timescalable.LocalTimescale /= Multiplier; + if(target is CanvasItem canvasItem) + canvasItem.Modulate = Colors.White; + } + + public override void Process(Node target) + { + + } +}