diff --git a/assets/audio/sfx/yuck.mp3.import b/assets/audio/sfx/yuck.mp3.import index 65416f2..196eea0 100644 --- a/assets/audio/sfx/yuck.mp3.import +++ b/assets/audio/sfx/yuck.mp3.import @@ -13,7 +13,7 @@ dest_files=["res://.godot/imported/yuck.mp3-300336a3ee536c8e6db69a73706c7ea5.mp3 [params] loop=false -loop_offset=0 -bpm=0 +loop_offset=0.0 +bpm=0.0 beat_count=0 bar_beats=4 diff --git a/project.godot b/project.godot index 0ada405..6e1d07c 100644 --- a/project.godot +++ b/project.godot @@ -22,7 +22,7 @@ config/windows_native_icon="res://icon.ico" LevelController="*res://scripts/LevelController.cs" Cursor="*res://scripts/Cursor.cs" GameRegistry="*res://scripts/systems/GameRegistry.cs" -Cheats="res://scripts/debug/Cheats.cs" +Cheats="*res://scripts/debug/Cheats.cs" AudioSequencer="*res://scenes/audio_sequencer.tscn" [display] diff --git a/resources/effects/GarlicEffect.tres b/resources/effects/GarlicEffect.tres index 374c2cd..5c9f170 100644 --- a/resources/effects/GarlicEffect.tres +++ b/resources/effects/GarlicEffect.tres @@ -5,4 +5,4 @@ [resource] script = ExtResource("1_rfumy") Duration = 0.25 -Slot = 3 +Slot = "garlic" diff --git a/resources/effects/SnowSlow.tres b/resources/effects/SnowSlow.tres index 5851046..5a62fd5 100644 --- a/resources/effects/SnowSlow.tres +++ b/resources/effects/SnowSlow.tres @@ -1,10 +1,10 @@ [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"] +[ext_resource type="Script" uid="uid://dyc7fc5bfkdii" path="res://scripts/systems/effects/SlownessEffect.cs" id="1_8md01"] [resource] script = ExtResource("1_8md01") ColorOverride = Color(0, 1, 1, 1) Multiplier = 0.75 Duration = 3.25 -Slot = 0 +Slot = "freeze_slow" diff --git a/scenes/entities/Zombies/hobo.tscn b/scenes/entities/Zombies/hobo.tscn index 5cb2e5f..29ad27b 100644 --- a/scenes/entities/Zombies/hobo.tscn +++ b/scenes/entities/Zombies/hobo.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=44 format=3 uid="uid://bgqmwsb6ynm81"] +[gd_scene load_steps=46 format=3 uid="uid://bgqmwsb6ynm81"] [ext_resource type="PackedScene" uid="uid://co11v3w8hbwgf" path="res://scenes/entities/Zombies/zombie.tscn" id="1_fnu7s"] [ext_resource type="Shader" uid="uid://d0eo5uuj222c4" path="res://assets/shaders/CG_color_blender.gdshader" id="2_6qr4h"] +[ext_resource type="Script" uid="uid://bcc7skl7ts6sh" path="res://scripts/systems/effects/Effect.cs" id="2_txjqc"] [ext_resource type="Texture2D" uid="uid://cse1504ao4g8e" path="res://assets/sprites/atlases/zombies/hobo.png" id="3_6qr4h"] +[ext_resource type="Resource" uid="uid://dsg1vjx76ifgu" path="res://resources/effects/GarlicEffect.tres" id="3_b583s"] [ext_resource type="Script" uid="uid://dt5uj25u0g6y3" path="res://scripts/components/particles/FallParticle.cs" id="3_tu6af"] [ext_resource type="AnimationLibrary" uid="uid://cuh2kyb21hmkm" path="res://resources/animations/zombies/basic_zombie.res" id="4_02fim"] [ext_resource type="Script" uid="uid://c5v2og85t7s6j" path="res://scripts/components/zombies/behaviours/HoboBehaviour.cs" id="4_5selg"] @@ -227,8 +229,9 @@ percentage_value = 0.0 mult_value = 1.0 [node name="Hobo" node_paths=PackedStringArray("_armor") instance=ExtResource("1_fnu7s")] -_maxHP = 130 _armor = NodePath("CanArmor") +MaxHP = 130.0 +_effectImmunities = Array[ExtResource("2_txjqc")]([ExtResource("3_b583s")]) [node name="CanvasGroup" parent="." index="0"] material = SubResource("ShaderMaterial_w8pya") @@ -282,7 +285,6 @@ _speed = SubResource("Resource_4248q") [node name="CanArmor" type="Node" parent="." index="7"] script = ExtResource("4_w8pya") -MaxHP = 385 metadata/_custom_type_script = "uid://fd4im1fmwc5n" [node name="Behaviour" type="Node" parent="." index="8" node_paths=PackedStringArray("_eatBox", "_animationTree")] diff --git a/scenes/entities/Zombies/zombie.tscn b/scenes/entities/Zombies/zombie.tscn index 82685a4..c243a43 100644 --- a/scenes/entities/Zombies/zombie.tscn +++ b/scenes/entities/Zombies/zombie.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=24 format=3 uid="uid://co11v3w8hbwgf"] +[gd_scene load_steps=27 format=3 uid="uid://co11v3w8hbwgf"] [ext_resource type="Script" uid="uid://dildme6epx8l4" path="res://scripts/components/zombies/RuntimeZombieData.cs" id="1_qq3f1"] [ext_resource type="Texture2D" uid="uid://bwdqbrnn7ygtr" path="res://assets/sprites/atlases/zombies/Зондби.png" id="2_4pdxh"] @@ -16,6 +16,9 @@ [ext_resource type="AudioStream" uid="uid://bg76miyscfvhu" path="res://assets/audio/sfx/groan.tres" id="12_ad42i"] [ext_resource type="Script" uid="uid://cnn0ymuhypdff" path="res://scripts/audio/ChannelPlaylist.cs" id="12_he8da"] [ext_resource type="AudioStream" uid="uid://w0qfwds4o3ti" path="res://assets/audio/sfx/hit_generic.tres" id="12_vjrlo"] +[ext_resource type="Script" uid="uid://b8r6fxsfjdo3a" path="res://scripts/audio/EffectBasedPlayer.cs" id="17_ltj46"] +[ext_resource type="Resource" uid="uid://dsg1vjx76ifgu" path="res://resources/effects/GarlicEffect.tres" id="18_2q05d"] +[ext_resource type="Resource" uid="uid://7uj0oe656jfx" path="res://resources/effects/SnowSlow.tres" id="19_ccrjo"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_63ls2"] resource_local_to_scene = true @@ -66,9 +69,9 @@ mult_value = 1.0 [node name="Zombie" type="Node2D"] y_sort_enabled = true script = ExtResource("1_qq3f1") -_maxHP = 70 garlicSound = ExtResource("2_hh4qh") freezeSound = ExtResource("3_ltj46") +MaxHP = 70.0 [node name="CanvasGroup" type="CanvasGroup" parent="."] material = SubResource("ShaderMaterial_63ls2") @@ -137,6 +140,11 @@ wait_time = 5.0 one_shot = true autostart = true +[node name="EffectPlayer" type="Node" parent="."] +script = ExtResource("17_ltj46") +effectsToMap = Array[Resource]([ExtResource("18_2q05d"), ExtResource("19_ccrjo")]) +streamsToMapTo = Array[AudioStream]([ExtResource("2_hh4qh"), ExtResource("3_ltj46")]) + [connection signal="OnDamaged" from="." to="HitPlayer" method="Play"] [connection signal="OnHPChanged" from="." to="CanvasGroup" method="DamageFlash"] [connection signal="area_entered" from="Eatbox" to="Eatbox" method="OnAreaEntered"] diff --git a/scenes/entities/plants/aloe.tscn b/scenes/entities/plants/aloe.tscn index c4c75a4..00dfc9e 100644 --- a/scenes/entities/plants/aloe.tscn +++ b/scenes/entities/plants/aloe.tscn @@ -84,6 +84,8 @@ graph_offset = Vector2(-78.082, -71.7578) size = Vector2(22, 32) [node name="Aloe" instance=ExtResource("1_n25yi")] +MaxHP = 30.0 +_effectImmunities = Array[Resource]([]) [node name="Sprite2D" parent="." index="0"] position = Vector2(9, -14) diff --git a/scenes/entities/plants/garlic.tscn b/scenes/entities/plants/garlic.tscn index 67c316e..bd855b0 100644 --- a/scenes/entities/plants/garlic.tscn +++ b/scenes/entities/plants/garlic.tscn @@ -50,7 +50,8 @@ blend_mode = 1 size = Vector2(32, 29) [node name="Garlic" instance=ExtResource("1_5i0e6")] -_maxHP = 200 +MaxHP = 200.0 +_effectImmunities = Array[Resource]([]) [node name="Sprite2D" parent="." index="0"] texture = ExtResource("2_w2jbi") diff --git a/scenes/entities/plants/peashooter.tscn b/scenes/entities/plants/peashooter.tscn index 7ba01a0..d9661db 100644 --- a/scenes/entities/plants/peashooter.tscn +++ b/scenes/entities/plants/peashooter.tscn @@ -62,6 +62,7 @@ resource_local_to_scene = true size = Vector2(20, 44) [node name="Peashooter" instance=ExtResource("1_pyk3o")] +MaxHP = 30.0 [node name="Sprite2D" parent="." index="0"] texture = ExtResource("2_14qlx") diff --git a/scenes/entities/plants/potato_mine.tscn b/scenes/entities/plants/potato_mine.tscn index 03dee1e..c53e617 100644 --- a/scenes/entities/plants/potato_mine.tscn +++ b/scenes/entities/plants/potato_mine.tscn @@ -68,7 +68,8 @@ size = Vector2(15, 27) size = Vector2(34, 19) [node name="Potato mine" instance=ExtResource("1_dj7ul")] -_maxHP = 20 +MaxHP = 20.0 +_effectImmunities = Array[Resource]([]) [node name="Sprite2D" parent="." index="0"] texture = ExtResource("2_sneas") diff --git a/scenes/entities/plants/spikeweed.tscn b/scenes/entities/plants/spikeweed.tscn index 9b96cff..d44984d 100644 --- a/scenes/entities/plants/spikeweed.tscn +++ b/scenes/entities/plants/spikeweed.tscn @@ -26,6 +26,8 @@ blend_mode = 1 size = Vector2(49, 38) [node name="Spikeweed" instance=ExtResource("1_vmbvr")] +MaxHP = 30.0 +_effectImmunities = Array[Resource]([]) [node name="Sprite2D" parent="." index="0"] texture = ExtResource("2_ffrjr") diff --git a/scenes/entities/plants/sunflower.tscn b/scenes/entities/plants/sunflower.tscn index 2f23a96..045bc2f 100644 --- a/scenes/entities/plants/sunflower.tscn +++ b/scenes/entities/plants/sunflower.tscn @@ -55,13 +55,14 @@ transitions = ["Start", "sunflower_idle", SubResource("AnimationNodeStateMachine size = Vector2(26, 48) [node name="Sunflower" instance=ExtResource("1_bikjn")] -_maxHP = 30 +MaxHP = 30.0 +_effectImmunities = Array[Resource]([]) [node name="Sprite2D" parent="." index="0"] texture = ExtResource("2_fwcda") hframes = 9 vframes = 2 -frame = 1 +frame = 4 [node name="AnimationPlayer" parent="." index="1"] libraries = { diff --git a/scenes/entities/plants/wallnut.tscn b/scenes/entities/plants/wallnut.tscn index 84a0d9e..dc796e0 100644 --- a/scenes/entities/plants/wallnut.tscn +++ b/scenes/entities/plants/wallnut.tscn @@ -28,12 +28,14 @@ blend_mode = 1 size = Vector2(33, 46) [node name="Wallnut" instance=ExtResource("1_fluxn")] -_maxHP = 600 +MaxHP = 600.0 +_effectImmunities = Array[Resource]([]) [node name="Sprite2D" parent="." index="0"] texture = ExtResource("2_o5tda") hframes = 12 vframes = 3 +frame = 3 [node name="AnimationPlayer" parent="." index="1"] libraries = { diff --git a/scenes/projectiles/snowpea_projectile.tscn b/scenes/projectiles/snowpea_projectile.tscn index 001c48a..bfde097 100644 --- a/scenes/projectiles/snowpea_projectile.tscn +++ b/scenes/projectiles/snowpea_projectile.tscn @@ -18,7 +18,6 @@ script = ExtResource("1_fkydi") _speed = 3.0 _damage = 10 _impactEffect = ExtResource("2_fn62x") -_damageType = 1 particles = ExtResource("3_t6hp0") [node name="Sprite" type="Sprite2D" parent="."] diff --git a/scripts/audio/EffectBasedPlayer.cs b/scripts/audio/EffectBasedPlayer.cs new file mode 100644 index 0000000..1713e94 --- /dev/null +++ b/scripts/audio/EffectBasedPlayer.cs @@ -0,0 +1,27 @@ +using Godot; +using Godot.Collections; +using System.Collections.Generic; +using Newlon.Components; +using Newlon.Systems.Effects; + +public partial class EffectBasedPlayer : Node +{ + [Export] public Array effectsToMap; + [Export] public Array streamsToMapTo; + private System.Collections.Generic.Dictionary effectToAudioMap = new(); + public override void _Ready() + { + GetParent().EffectStarted += OnEffectStarted; + + for (int i = 0; i < effectsToMap.Count; i++) + { + effectToAudioMap.Add(effectsToMap[i], streamsToMapTo[i]); + } + } + + public void OnEffectStarted(Effect what) + { + if (effectToAudioMap.ContainsKey(what) == false) return; + AudioSequencer.Play(what.Slot, effectToAudioMap[what]); + } +} diff --git a/scripts/audio/EffectBasedPlayer.cs.uid b/scripts/audio/EffectBasedPlayer.cs.uid new file mode 100644 index 0000000..ed55549 --- /dev/null +++ b/scripts/audio/EffectBasedPlayer.cs.uid @@ -0,0 +1 @@ +uid://b8r6fxsfjdo3a diff --git a/scripts/components/Armor.cs b/scripts/components/Armor.cs index 4326ff0..7e8ba22 100644 --- a/scripts/components/Armor.cs +++ b/scripts/components/Armor.cs @@ -6,13 +6,13 @@ namespace Newlon.Components; public partial class Armor : Node { [Signal] - public delegate void ArmorDamagedEventHandler(int hp); + public delegate void ArmorDamagedEventHandler(float hp); [Signal] public delegate void ArmorLostEventHandler(); [Export] - public int MaxHP { get; private set; } - private int _hp; + public float MaxHP { get; private set; } + private float _hp; private bool _lost = false; public override void _Ready() @@ -20,11 +20,11 @@ public partial class Armor : Node _hp = MaxHP; } - public int RecieveDamage(int damage) + public float RecieveDamage(float damage) { if(_lost) return damage; - int returnAmount = 0; + float returnAmount = 0; _hp -= damage; if(_hp <= 0) { @@ -37,11 +37,11 @@ public partial class Armor : Node return returnAmount; } - public int Heal(int amount) + public float Heal(float amount) { if(_lost) return amount; - int returnAmount = 0; + float returnAmount = 0; _hp += amount; if (_hp >= MaxHP) { diff --git a/scripts/components/DegradingSprite.cs b/scripts/components/DegradingSprite.cs index baa5e8f..3c28adc 100644 --- a/scripts/components/DegradingSprite.cs +++ b/scripts/components/DegradingSprite.cs @@ -14,9 +14,9 @@ public partial class DegradingSprite : Sprite2D armor.ArmorDamaged += OnZombieHPChanged; } - private void OnZombieHPChanged(int hp) + private void OnZombieHPChanged(float hp) { - float percent = (float)hp / (float)armor.MaxHP; + float percent = hp / armor.MaxHP; for (int i = 0; i < degradationStages.Count; i++) { if (percent <= thresholdPercentage[i]) diff --git a/scripts/components/Entity.cs b/scripts/components/Entity.cs new file mode 100644 index 0000000..f4d181a --- /dev/null +++ b/scripts/components/Entity.cs @@ -0,0 +1,153 @@ +using Godot; +using Godot.Collections; +using Newlon.Systems.Effects; + +namespace Newlon.Components; + +public partial class Entity : Node2D +{ + #region Health points + [Export] public float MaxHP; + public float HP; + [Signal] public delegate void OnHPChangedEventHandler(int deltaHP, Node origin); + [Signal] public delegate void OnDamagedEventHandler(); + + public virtual void TakeDamage(float amount, Node origin) + { + HP -= amount; + EmitSignal(SignalName.OnHPChanged, -amount, origin); + EmitSignal(SignalName.OnDamaged); + if (HP <= 0) + { + KillByDamage(); + } + } + + public virtual void Heal(float amount, Node origin) + { + EmitSignal(SignalName.OnHPChanged, amount, origin); + HP += amount; + } + + public virtual void KillByDamage() + { + Kill(); + } + + public virtual void Kill() + { + QueueFree(); + } + + + #endregion + #region Brain + public virtual void DisableBrain() + { + GetNode("AnimationPlayer").ProcessMode = ProcessModeEnum.Pausable; + ProcessMode = ProcessModeEnum.Disabled; + } + + public virtual void EnableBrain() + { + GetNode("AnimationPlayer").ProcessMode = ProcessModeEnum.Inherit; + ProcessMode = ProcessModeEnum.Inherit; + } + #endregion + #region Effects + [Export] private Array _effectImmunities = new(); + private readonly Dictionary _activeEffectSlots = new(); + private readonly Dictionary _effectSlotTimers = new(); + + [Signal] public delegate void EffectStartedEventHandler(Effect what); + [Signal] public delegate void EffectEndedEventHandler(Effect what); + [Signal] public delegate void EffectContinuedEventHandler(Effect what); + + + public virtual void GiveEffect(Effect what) + { + if (_effectImmunities.Contains(what)) + { + return; + } + + string slot = what.Slot; + if (_activeEffectSlots.ContainsKey(slot) == false) + { + InitSlot(slot); + } + + if (what == _activeEffectSlots[slot]) + { + EmitSignal(SignalName.EffectContinued, what); + } + else + { + EmitSignal(SignalName.EffectStarted, what); + } + + 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) + { + EndEffectAtSlot(what.Slot); + } + + public void ProcessEffects() + { + foreach(string key in _activeEffectSlots.Keys) + _activeEffectSlots[key]?.Process(this); + } + + private void EndEffectAtSlot(string slot) + { + _activeEffectSlots[slot].Exit(this); + _activeEffectSlots[slot] = null; + + EmitSignal(SignalName.EffectEnded, _activeEffectSlots[slot]); + + } + #endregion + #region LocalTimescale + private float _localTimescale = 1.0f; + [Signal] public delegate void OnLocalTimescaleChangedEventHandler(float scale); + public float LocalTimescale + { + get => _localTimescale; + set + { + _localTimescale = value; + EmitSignal(SignalName.OnLocalTimescaleChanged, _localTimescale); + } + } + #endregion + #region Godot overrides + public override void _Ready() + { + HP = MaxHP; + } + #endregion +} diff --git a/scripts/components/Entity.cs.uid b/scripts/components/Entity.cs.uid new file mode 100644 index 0000000..c9ca417 --- /dev/null +++ b/scripts/components/Entity.cs.uid @@ -0,0 +1 @@ +uid://3tw88wj1nrj1 diff --git a/scripts/components/IEntity.cs b/scripts/components/IEntity.cs deleted file mode 100644 index 7446c70..0000000 --- a/scripts/components/IEntity.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Godot; - -namespace Newlon.Components; - -// -// Base interface for entities -// -public interface IEntity -{ - public int Hp { get; } - public int MaxHp { get; } - public void TakeDamage(int amount, Node origin, Utility.DamageTypes damageType = Utility.DamageTypes.PHYSICAL); - public void Heal(int amount, Node origin); - public void DisableBrain(); - public void EnableBrain(); -} - \ No newline at end of file diff --git a/scripts/components/IEntity.cs.uid b/scripts/components/IEntity.cs.uid deleted file mode 100644 index c16d5f4..0000000 --- a/scripts/components/IEntity.cs.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cjdeq452vk2ll diff --git a/scripts/components/ILocalTimescale.cs b/scripts/components/ILocalTimescale.cs deleted file mode 100644 index e60865a..0000000 --- a/scripts/components/ILocalTimescale.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Newlon.Components; - -public interface ILocalTimescale -{ - public float LocalTimescale { get; set; } -} \ No newline at end of file diff --git a/scripts/components/ILocalTimescale.cs.uid b/scripts/components/ILocalTimescale.cs.uid deleted file mode 100644 index 48a6d9b..0000000 --- a/scripts/components/ILocalTimescale.cs.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bxu6ljkmmlgd5 diff --git a/scripts/components/LinearProjectile.cs b/scripts/components/LinearProjectile.cs index 156c486..f9ad5c0 100644 --- a/scripts/components/LinearProjectile.cs +++ b/scripts/components/LinearProjectile.cs @@ -17,8 +17,6 @@ public partial class LinearProjectile : Area2D, IProjectile [Export] private Effect _impactEffect; [Export] - private Utility.DamageTypes _damageType = Utility.DamageTypes.PHYSICAL; - [Export] private PackedScene particles; private int _line; private bool used = false; @@ -33,13 +31,13 @@ public partial class LinearProjectile : Area2D, IProjectile public void OnAreaEntered(Area2D area) { if (used == true) return; - var entity = area.GetParent(); + var entity = area.GetParent(); if (entity != null) { - entity.TakeDamage(_damage,this,_damageType); + entity.TakeDamage(_damage,this); used = true; - if (entity is IEffectHandler effectHandler && _impactEffect != null) - effectHandler.GiveEffect(_impactEffect); + if (_impactEffect != null) + entity.GiveEffect(_impactEffect); PoolContainer.Instance.SpawnParticles(particles, GlobalPosition); diff --git a/scripts/components/gui/choose_your_seeds/Previewport.cs b/scripts/components/gui/choose_your_seeds/Previewport.cs index bb90799..71a1709 100644 --- a/scripts/components/gui/choose_your_seeds/Previewport.cs +++ b/scripts/components/gui/choose_your_seeds/Previewport.cs @@ -44,7 +44,7 @@ public partial class Previewport : SubViewport title.Text = Tr(resource.name_key); description.Text = Tr(resource.description_key); AddChild(current_display); - if (current_display is IEntity entity) + if (current_display is Entity entity) entity.DisableBrain(); } diff --git a/scripts/components/level/PoolContainer.cs b/scripts/components/level/PoolContainer.cs index 2714860..b5765fd 100644 --- a/scripts/components/level/PoolContainer.cs +++ b/scripts/components/level/PoolContainer.cs @@ -23,12 +23,12 @@ public partial class PoolContainer : Node2D public static PoolContainer Instance { get; private set; } - public Dictionary[] EntityField = { new(), new(), new() }; + public Dictionary[] EntityField = { new(), new(), new() }; public override void _Ready() { Instance = this; } - public bool TryGetEntity(Vector2 key, out IEntity result, int layer = 1) + public bool TryGetEntity(Vector2 key, out Entity result, int layer = 1) { if (EntityField[layer].ContainsKey(key)) { diff --git a/scripts/components/plants/Eyesight.cs b/scripts/components/plants/Eyesight.cs index 7922358..2480476 100644 --- a/scripts/components/plants/Eyesight.cs +++ b/scripts/components/plants/Eyesight.cs @@ -7,7 +7,7 @@ public partial class Eyesight : Area2D { private bool _enemyDetected; public bool EnemyDetected => _enemyDetected; - private readonly List _detectedEntities = new List(); + private readonly List _detectedEntities = new List(); private RuntimePlantData _plantData; public override void _Ready() @@ -19,7 +19,7 @@ public partial class Eyesight : Area2D public void OnAreaEntered(Area2D area) { - var entity = area.GetParent(); + var entity = area.GetParent(); if (entity != null) { _detectedEntities.Add(entity); @@ -30,7 +30,7 @@ public partial class Eyesight : Area2D public void OnAreaExited(Area2D area) { - var entity = area.GetParent(); + var entity = area.GetParent(); if (entity != null) { if (_detectedEntities.Contains(entity)) diff --git a/scripts/components/plants/LoseZone.cs b/scripts/components/plants/LoseZone.cs index 53e71fa..18ab886 100644 --- a/scripts/components/plants/LoseZone.cs +++ b/scripts/components/plants/LoseZone.cs @@ -4,10 +4,11 @@ namespace Newlon.Components.Plants; public partial class LoseZone : RuntimePlantData { - public override void TakeDamage(int amount, Node origin, Utility.DamageTypes damageType = Utility.DamageTypes.PHYSICAL) - { + public override void TakeDamage(float amount, Node origin) + { + + } - } public override void Kill() { diff --git a/scripts/components/plants/ReturnEffect.cs b/scripts/components/plants/ReturnEffect.cs index 149e8b5..c481de1 100644 --- a/scripts/components/plants/ReturnEffect.cs +++ b/scripts/components/plants/ReturnEffect.cs @@ -11,6 +11,7 @@ public partial class ReturnEffect : Node public void OnDamageRecieved(int delta,Node origin) { + if (delta >= 0) return; if (origin is RuntimeZombieData zombie) { zombie.GiveEffect(_effectToReturn); diff --git a/scripts/components/plants/RuntimePlantData.cs b/scripts/components/plants/RuntimePlantData.cs index ce189c5..6968e5d 100644 --- a/scripts/components/plants/RuntimePlantData.cs +++ b/scripts/components/plants/RuntimePlantData.cs @@ -7,64 +7,19 @@ namespace Newlon.Components.Plants; // Data that plant stores during runtime // -public partial class RuntimePlantData : Node2D, IEntity +public partial class RuntimePlantData : Entity { - [Export] - private int _maxHP; - private int _hp; - public int Hp => _hp; - public int MaxHp => _maxHP; public int Line { get; set; } public PlantResource Resource; - - private AudioStream eatenSound; - - [Signal] - public delegate void OnHPChangedEventHandler(int amount, Node origin); - - public override void _Ready() + private AudioStream eatenSound = ResourceLoader.Load("res://assets/audio/sfx/gulp.mp3"); + public override void KillByDamage() { - _hp = _maxHP; - eatenSound = ResourceLoader.Load("res://assets/audio/sfx/gulp.mp3"); + AudioSequencer.Play("plant_eaten", eatenSound); + base.KillByDamage(); } - - public virtual void Heal(int amount, Node origin) - { - _hp += amount; - - EmitSignal(SignalName.OnHPChanged, amount, origin); - - if (MaxHp > 0) - { - _hp = MaxHp; - } - } - - public virtual void TakeDamage(int amount, Node origin, Utility.DamageTypes damageType = Utility.DamageTypes.PHYSICAL) - { - _hp -= amount; - - EmitSignal(SignalName.OnHPChanged, -amount, origin); - - if (_hp <= 0) - { - Kill(); - AudioSequencer.Play("plant_eaten", eatenSound); - } - } - public virtual void Kill() + public override void Kill() { PoolContainer.Instance.EntityField[Resource.Layer].Remove(GlobalPosition); QueueFree(); } - - public virtual void DisableBrain() - { - GetNode("Behaviour").ProcessMode = ProcessModeEnum.Disabled; - } - - public virtual void EnableBrain() - { - GetNode("Behaviour").ProcessMode = ProcessModeEnum.Inherit; - } } diff --git a/scripts/components/plants/behaviours/AloeBehaviour.cs b/scripts/components/plants/behaviours/AloeBehaviour.cs index 323f8ab..f9dde56 100644 --- a/scripts/components/plants/behaviours/AloeBehaviour.cs +++ b/scripts/components/plants/behaviours/AloeBehaviour.cs @@ -22,7 +22,7 @@ public partial class AloeBehaviour : BaseBehaviour var checkPos = GetParent().GlobalPosition + Vector2.Right * Utility.TileWidth; if(_charge && PoolContainer.Instance.TryGetEntity(checkPos, out RuntimePlantData plantData)) { - if((float)plantData.Hp / (float)plantData.MaxHp < _hpTreshold) + if((float)plantData.HP / (float)plantData.MaxHP < _hpTreshold) { _charge = false; _tree.Set("parameters/conditions/heal",true); @@ -36,7 +36,7 @@ public partial class AloeBehaviour : BaseBehaviour var checkPos = GetParent().GlobalPosition + Vector2.Right * Utility.TileWidth; if (PoolContainer.Instance.TryGetEntity(checkPos, out RuntimePlantData plantData)) { - plantData.Heal(3000 + 25 * plantData.MaxHp, GetParent()); + plantData.Heal(3000 + 25 * plantData.MaxHP, GetParent()); } } diff --git a/scripts/components/plants/behaviours/HpBasedBehaviour.cs b/scripts/components/plants/behaviours/HpBasedBehaviour.cs index d49af31..a234287 100644 --- a/scripts/components/plants/behaviours/HpBasedBehaviour.cs +++ b/scripts/components/plants/behaviours/HpBasedBehaviour.cs @@ -13,6 +13,6 @@ public partial class HpBasedBehaviour : BaseBehaviour public void OnHPChanged(int amount,Node origin) { - _tree.Set("parameters/blend_position",(float)_data.Hp/_data.MaxHp); + _tree.Set("parameters/blend_position",(float)_data.HP/_data.MaxHP); } } diff --git a/scripts/components/zombies/RuntimeZombieData.cs b/scripts/components/zombies/RuntimeZombieData.cs index e0fcef0..bf4a64a 100644 --- a/scripts/components/zombies/RuntimeZombieData.cs +++ b/scripts/components/zombies/RuntimeZombieData.cs @@ -1,162 +1,48 @@ -using System.Collections.Generic; using Godot; -using Newlon.Systems.Effects; namespace Newlon.Components.Zombies; -public partial class RuntimeZombieData : Node2D, IEntity, ILocalTimescale, IEffectHandler +public partial class RuntimeZombieData : Entity { - [Signal] - public delegate void OnHPChangedEventHandler(int deltaHP, Node origin); - [Signal] - public delegate void OnDamagedEventHandler(); - - [Signal] - public delegate void OnLocalTimescaleChangedEventHandler(int currentTimescale); - - [Export] - private int _hp; - [Export] - private int _maxHP; [Export] private Armor _armor; - [Export] private AudioStream garlicSound; [Export] private AudioStream freezeSound; - - - private float _localTimescale = 1.0f; - public int Hp => _hp; - - public int MaxHp => _maxHP; - public bool AbleToEat = true; - public float LocalTimescale - { - get => _localTimescale; - set - { - _localTimescale = value; - EmitSignal(SignalName.OnLocalTimescaleChanged,_localTimescale); - } - } - - 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); - int current_index = i; - timer.Timeout += () => {EndEffectAtSlot(current_index);}; - } - } - - public void Heal(int amount,Node origin) - { - if(_armor != null) - { - _hp += _armor.Heal(amount); - } - else - _hp += amount; - EmitSignal(SignalName.OnHPChanged,amount,origin); - - if (MaxHp > 0) - { - _hp = MaxHp; - } - } - - public void TakeDamage(int amount, Node origin, Utility.DamageTypes damageType = Utility.DamageTypes.PHYSICAL) + public override void Heal(float amount, Node origin) { if (_armor != null) { - _hp -= _armor.RecieveDamage(amount); + HP += _armor.Heal(amount); } else - _hp -= amount; - EmitSignal(SignalName.OnHPChanged,-amount, origin); + HP += amount; + EmitSignal(SignalName.OnHPChanged, amount, origin); + + if (HP > MaxHP) + { + HP = MaxHP; + } + } + + public override void TakeDamage(float amount, Node origin) + { + if (_armor != null) + { + HP -= _armor.RecieveDamage(amount); + } + else + HP -= amount; + EmitSignal(SignalName.OnHPChanged, -amount, origin); EmitSignal(SignalName.OnDamaged); - if (_hp <= 0) + if (HP <= 0) { - QueueFree(); + KillByDamage(); } } - #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) - { - switch (what.Slot) - { - case Utility.EffectSlots.FREEZE: - AudioSequencer.Play("zombie_freeze", freezeSound); - var settings = new ChannelSettings(); - settings.restartTreshold = -1; - AudioSequencer.ChangeSettings("zombie_freeze",settings); - break; - case Utility.EffectSlots.GARLIC: - AudioSequencer.Play("zombie_garlic", garlicSound); - - break; - } - } - 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; - } - - public void DisableBrain() - { - GetNode("AnimationPlayer").ProcessMode = ProcessModeEnum.Pausable; - ProcessMode = ProcessModeEnum.Disabled; - } - - public void EnableBrain() - { - GetNode("AnimationPlayer").ProcessMode = ProcessModeEnum.Inherit; - ProcessMode = ProcessModeEnum.Inherit; - } - #endregion } diff --git a/scripts/systems/effects/Effect.cs b/scripts/systems/effects/Effect.cs index 43d6e0e..aa80f70 100644 --- a/scripts/systems/effects/Effect.cs +++ b/scripts/systems/effects/Effect.cs @@ -5,7 +5,7 @@ namespace Newlon.Systems.Effects; public abstract partial class Effect : Resource { [Export] public float Duration; - [Export] public Utility.EffectSlots Slot; + [Export] public string 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 deleted file mode 100644 index 6c9b758..0000000 --- a/scripts/systems/effects/IEffectHandler.cs +++ /dev/null @@ -1,8 +0,0 @@ -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/IEffectHandler.cs.uid b/scripts/systems/effects/IEffectHandler.cs.uid deleted file mode 100644 index 8c581ef..0000000 --- a/scripts/systems/effects/IEffectHandler.cs.uid +++ /dev/null @@ -1 +0,0 @@ -uid://eeqk3fvjwg31 diff --git a/scripts/systems/effects/SlownessEffect.cs b/scripts/systems/effects/SlownessEffect.cs index 1491a2c..19d7a4e 100644 --- a/scripts/systems/effects/SlownessEffect.cs +++ b/scripts/systems/effects/SlownessEffect.cs @@ -11,21 +11,20 @@ public partial class SlownessEffect : Effect public override void Enter(Node target) { - if (target is IEffectHandler handler) + if (target is Entity entity) { - if (target is ILocalTimescale timescalable) - timescalable.LocalTimescale *= Multiplier; - if (target is CanvasItem canvasItem) - canvasItem.Modulate = ColorOverride; + entity.LocalTimescale *= Multiplier; + entity.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; + if (target is Entity entity) + { + entity.LocalTimescale /= Multiplier; + entity.Modulate = Colors.White; + } } public override void Process(Node target) diff --git a/translations/zombies.csv b/translations/zombies.csv index fda31d7..0e3d7eb 100644 --- a/translations/zombies.csv +++ b/translations/zombies.csv @@ -34,13 +34,15 @@ Attack damage: [color=darkred]1 bite[/color]. ","Бронированная ве Скорость атаки: [color=darkred]1 Гц[/color]. Урон от атаки: [color=darkred]1 укус[/color]." hobo,Trash can zombie,Зомби в мусорке -hobo_desc,"Some time in the past he met a great conqueror. Hates to live without his can. Equivalent of ~8 zombies. +hobo_desc,"Some time in the past he met a great conqueror. Hates to live without his can. Equivalent of ~8 zombies. +[color=darkgreen]He is immune to garlic-like effects. [/color] Health points: [color=darkred]13 peas[/color]. Armour points: [color=darkred]39 peas[/color]. Walk speed: [color=darkred]0.2 tiles/second[/color]. Run speed: [color=darkred]0.6 tiles/second[/color]. Attack speed: [color=darkred]1 Hz[/color]. Attack damage: [color=darkred]1 bite[/color]. ","Однажды повстречал великого полководца. Ненавидит жить без своего ведра. Равен примерно 8 зомби. +[color=darkgreen]Имеет иммунитет к эффектам как у чеснока. [/color] Очки здоровья: [color=darkred]13 горошин[/color]. Armour points: [color=darkred]39 горошин[/color]. Скорость ходьбы: [color=darkred]0.2 клеток/сек[/color]. diff --git a/translations/zombies.en.translation b/translations/zombies.en.translation index 45f31c8..184a456 100644 Binary files a/translations/zombies.en.translation and b/translations/zombies.en.translation differ diff --git a/translations/zombies.ru.translation b/translations/zombies.ru.translation index aa9df63..6189382 100644 Binary files a/translations/zombies.ru.translation and b/translations/zombies.ru.translation differ