Plants flash and shovel alt

This commit is contained in:
Rendo 2025-07-23 16:07:55 +05:00
commit e4c25a1ca5
23 changed files with 451 additions and 195 deletions

View file

@ -6,7 +6,9 @@ namespace Newlon.Components;
public partial class Armor : Node
{
[Signal]
public delegate void ArmorDamagedEventHandler(float hp);
public delegate void DamagedEventHandler();
[Signal]
public delegate void HpChangedEventHandler(float hp);
[Signal]
public delegate void ArmorLostEventHandler();
@ -32,14 +34,16 @@ public partial class Armor : Node
{
var delta = _hp;
_hp = 0;
EmitSignal(SignalName.ArmorDamaged, delta);
EmitSignal(SignalName.HpChanged, -delta);
EmitSignal(SignalName.Damaged);
EmitSignal(SignalName.ArmorLost);
_lost = true;
}
else
{
_hp -= damage;
EmitSignal(SignalName.ArmorDamaged, damage);
EmitSignal(SignalName.HpChanged, -damage);
EmitSignal(SignalName.Damaged);
}
return returnAmount;
}
@ -55,7 +59,7 @@ public partial class Armor : Node
returnAmount = _hp-MaxHP;
_hp = MaxHP;
}
EmitSignal(SignalName.ArmorDamaged,_hp);
EmitSignal(SignalName.HpChanged,_hp);
return returnAmount;
}
}

View file

@ -11,21 +11,21 @@ public partial class ArmorHPObserver : Node
public override void _Ready()
{
_observedArmor.ArmorDamaged += OnHPChanged;
_observedArmor.Damaged += OnDamaged;
}
private void OnHPChanged(float delta)
private void OnDamaged()
{
if (_setGreater == false && _observedArmor._hp / _observedArmor.MaxHP < _threshold)
{
EmitSignal(SignalName.ThresholdReached);
_observedArmor.ArmorDamaged -= OnHPChanged;
_observedArmor.Damaged -= OnDamaged;
QueueFree();
}
else if (_setGreater && _observedArmor._hp / _observedArmor.MaxHP > _threshold)
{
EmitSignal(SignalName.ThresholdReached);
_observedArmor.ArmorDamaged -= OnHPChanged;
_observedArmor.Damaged -= OnDamaged;
QueueFree();
}
}

View file

@ -11,10 +11,10 @@ public partial class DegradingSprite : Sprite2D
public override void _Ready()
{
armor.ArmorDamaged += OnArmorHPChanged;
armor.Damaged += OnDamaged;
}
private void OnArmorHPChanged(float hp)
private void OnDamaged()
{
float percent = armor._hp / armor.MaxHP;
for (int i = 0; i < degradationStages.Count; i++)

View file

@ -10,13 +10,15 @@ public partial class Entity : Node2D
{
#region Health points
[Export] public float MaxHP;
public float HP;
[Export]public float HP;
[Signal] public delegate void OnHPChangedEventHandler(EntitySignalContext context);
[Signal] public delegate void OnDamagedEventHandler();
public virtual void TakeDamage(float amount, Node origin)
{
EmitSignal(SignalName.OnDamaged);
if(amount > 0)
EmitSignal(SignalName.OnDamaged);
var context = new EntitySignalContext()
{
target = this,

View file

@ -1,36 +0,0 @@
using Godot;
using System;
namespace Newlon.Components;
public partial class FlashComponent : CanvasGroup
{
[Export] private float _flashDuration = 0.1f;
private Tween _tween;
private ShaderMaterial _shaderMaterial;
public override void _Ready()
{
_shaderMaterial = Material as ShaderMaterial;
}
public void DamageFlash(EntitySignalContext context)
{
Flash();
}
public void Flash()
{
_tween?.Kill();
_tween = CreateTween();
Action<float> action = SetAmount;
_tween.TweenMethod(Callable.From(action),0.8f,0.0f,_flashDuration);
}
private void SetAmount(float amount)
{
_shaderMaterial.SetShaderParameter("amount",amount);
}
}

View file

@ -1 +0,0 @@
uid://c5vfccegyy01t

View file

@ -0,0 +1,51 @@
using Godot;
using Newlon.Components;
public partial class FlashShaderController : Node
{
[Export] public float flashTime = 0.5f;
[Export]
private ShaderMaterial shaderMaterial;
private uint toggleStack = 0;
private Tween flashTween;
public void DamageFlash()
{
Flash();
}
public void Flash(float customFlashTime = 0)
{
if (flashTween != null)
flashTween.Kill();
var time = flashTime;
if (customFlashTime > 0)
time = customFlashTime;
flashTween = CreateTween();
flashTween.TweenMethod(Callable.From<float>(SetBlend), 1.0, 0.0, time);
}
public void Select()
{
toggleStack++;
UpdateSelected();
}
public void Deselect()
{
toggleStack--;
UpdateSelected();
}
private void SetBlend(float blend)
{
shaderMaterial.SetShaderParameter("blend", blend);
}
private void UpdateSelected()
{
if (toggleStack > 0)
{
shaderMaterial.SetShaderParameter("selected", true);
}
else
{
shaderMaterial.SetShaderParameter("selected", false);
}
}
}

View file

@ -0,0 +1 @@
uid://30pbgasu64aw

View file

@ -49,15 +49,18 @@ public partial class RuntimeZombieData : Entity
damage = _armor.RecieveDamage(amount);
}
EmitSignal(SignalName.OnDamaged);
var context = new EntitySignalContext()
{
source = origin,
target = this,
actionAmount = amount
};
if(damage > 0)
EmitSignal(SignalName.OnDamaged);
if (HP - damage <= 0)
{
var delta = -HP;
HP = 0;
EmitSignal(SignalName.OnHPChanged, context);
@ -80,7 +83,7 @@ public partial class RuntimeZombieData : Entity
EmitSignal(SignalName.HPChangedMixed, new EntitySignalContext()
{
deltaHP = -delta,
deltaHP = delta,
source = null,
target = this,
actionAmount = delta

View file

@ -1,16 +1,26 @@
using Godot;
using Newlon.Components.Plants;
using Newlon.Components.Level;
using Newlon.Components.Zombies;
namespace Newlon.Components.GUI;
public partial class ShovelButton : TextureButton
{
[Export] private PackedScene particles;
private Entity hoveredEntity;
private bool Selected => hoveredEntity != null;
[Export]
private RayCast2D raycast;
private void OnFocusExited()
{
ButtonPressed = false;
}
public override void _Ready()
{
raycast.Reparent(PoolContainer.Instance);
}
public override void _Toggled(bool toggledOn)
{
Cursor.Instance.shovel = toggledOn;
@ -22,24 +32,118 @@ public partial class ShovelButton : TextureButton
if (@event.IsActionPressed("primary_action") && ButtonPressed)
{
var checkedPosition = (PoolContainer.Instance.Plants.GetGlobalMousePosition() / FieldParams.Tile).Ceil() * FieldParams.Tile - new Vector2(20, 14);
for (int i = FieldParams.LayersCount - 1; i >= 0; i--)
if (hoveredEntity != null)
{
if (PoolContainer.Instance.EntityField[i].TryGetValue(checkedPosition, out var entity) && entity is RuntimePlantData plantData)
if (hoveredEntity is RuntimePlantData hoveredPlant)
{
plantData.Kill();
PoolContainer.Instance.SpawnParticles(particles, plantData.GlobalPosition + Vector2.Down * FieldParams.TileHeight / 2.0f);
break;
hoveredPlant.Kill();
PoolContainer.Instance.SpawnParticles(particles, hoveredPlant.GlobalPosition + Vector2.Down * FieldParams.TileHeight / 2.0f);
}
else
{
hoveredEntity.TakeDamage(205, null);
}
}
hoveredEntity?.GetNode<FlashShaderController>("FlashController").Deselect();
hoveredEntity = null;
ButtonPressed = false;
}
if (@event.IsActionPressed("cancel_plant") && ButtonPressed)
{
hoveredEntity?.GetNode<FlashShaderController>("FlashController").Deselect();
hoveredEntity = null;
ButtonPressed = false;
}
}
public override void _Process(double delta)
{
if (ButtonPressed)
{
var gridEntity = GetTile(PoolContainer.Instance.Plants.GetGlobalMousePosition());
if (TrySetGridEntity(gridEntity)) return;
if (TrySetDynEntity()) return;
else
{
if (Selected)
{
hoveredEntity.GetNode<FlashShaderController>("FlashController").Deselect();
hoveredEntity = null;
return;
}
}
}
else
{
if (Selected)
{
hoveredEntity.GetNode<FlashShaderController>("FlashController").Deselect();
hoveredEntity = null;
}
}
}
private Entity GetTile(Vector2 position)
{
var checkedPosition = (position / FieldParams.Tile).Ceil() * FieldParams.Tile - new Vector2(20, 14);
for (int i = FieldParams.LayersCount - 1; i >= 0; i--)
{
if (PoolContainer.Instance.EntityField[i].TryGetValue(checkedPosition, out var entity) && entity is RuntimePlantData plantData)
{
return plantData;
}
}
return null;
}
private bool TrySetGridEntity(Entity chosenEntity)
{
if (chosenEntity != null && Selected == false)
{
hoveredEntity = chosenEntity;
hoveredEntity.GetNode<FlashShaderController>("FlashController").Select();
return true;
}
if (chosenEntity == null && Selected && hoveredEntity is RuntimePlantData)
{
hoveredEntity.GetNode<FlashShaderController>("FlashController").Deselect();
hoveredEntity = null;
return true;
}
if (hoveredEntity == null || chosenEntity == null) return false;
if (chosenEntity != hoveredEntity && Selected)
{
hoveredEntity.GetNode<FlashShaderController>("FlashController").Deselect();
hoveredEntity = chosenEntity;
hoveredEntity.GetNode<FlashShaderController>("FlashController").Select();
return true;
}
return hoveredEntity != null && hoveredEntity is RuntimeZombieData == false;
}
private bool TrySetDynEntity()
{
raycast.GlobalPosition = PoolContainer.Instance.GetGlobalMousePosition();
if (raycast.IsColliding())
{
var entity = ((Area2D)raycast.GetCollider()).GetParent() as Entity;
if (entity == null) return false;
if (Selected == false)
{
hoveredEntity = entity;
hoveredEntity.GetNode<FlashShaderController>("FlashController").Select();
return true;
}
if (hoveredEntity == null) return false;
if (Selected && hoveredEntity != entity)
{
hoveredEntity.GetNode<FlashShaderController>("FlashController").Deselect();
entity.GetNode<FlashShaderController>("FlashController").Select();
hoveredEntity = entity;
return true;
}
}
return hoveredEntity != null && hoveredEntity is RuntimeZombieData;
}
}