Bullet freeze

This commit is contained in:
Marco 2025-04-26 11:24:20 +02:00
commit 34a07342ac
31 changed files with 255 additions and 8 deletions

36
Scripts/Actors/Ice.cs Normal file
View file

@ -0,0 +1,36 @@
using Cirno.Scripts.Components.FSM.Player;
using Godot;
namespace Cirno.Scripts.Actors;
public partial class Ice : Area2D
{
public double Life { get; set; } = 2f;
//public float FreezeRange { get; private set; } = 16f;
public FreezeModule FreezeModule { get; set; }
public override void _PhysicsProcess(double delta)
{
Life -= delta;
if (Life <= 0)
{
QueueFree();
}
}
private void OnAreaEntered(Area2D area)
{
if (area is not Bullet bullet) return;
if (bullet.IsFrozen) return;
if (bullet.BulletOwner is BulletOwner.Player) return;
if (!bullet.BulletInfo.Freezable) return;
bullet.Freeze();
var ice = bullet.CreateSibling<Ice>(FreezeModule.IceScene);
ice.Life = Life;
ice.FreezeModule = FreezeModule;
}
}

View file

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

View file

@ -30,6 +30,8 @@ public partial class Bullet : Area2D
public bool IsGrazed { get; set; } = false;
public bool IsFrozen { get; private set; } = false;
[Signal] public delegate void OnDestroyEventHandler();
private AudioStreamPlayer2D _grazeSound;
@ -182,8 +184,7 @@ public partial class Bullet : Area2D
{
ApplyTimeModifiers(delta);
}
if (BulletInfo.Controllabe)
{
ControlBullet(delta);
@ -273,6 +274,13 @@ public partial class Bullet : Area2D
EmitSignal(SignalName.OnDestroy);
QueueFree();
}
public void Freeze()
{
IsFrozen = true;
EmitSignal(SignalName.OnDestroy);
QueueFree();
}
}
public enum BulletOwner

View file

@ -18,4 +18,7 @@ public abstract partial class InputProvider : Node2D
public abstract bool GetWeaponNextJustPressed();
public abstract bool GetWeaponPreviousJustPressed();
public abstract bool GetPauseJustPressed();
public abstract bool GetFreezeJustPressed();
public abstract bool GetFreezePressed();
}

View file

@ -35,6 +35,7 @@ public partial class KeyboardInputProvider : InputProvider
[Export] private StringName _previousWeaponActionName = "previous_weapon";
[Export] private StringName _inventoryActionName = "inventory";
[Export] private StringName _pauseActionName = "pause";
[Export] private StringName _freezeActionName = "Freeze";
private enum AimInputMethod { RightStick, Mouse }
private AimInputMethod _lastUsedInput = AimInputMethod.RightStick;
@ -163,5 +164,15 @@ public partial class KeyboardInputProvider : InputProvider
{
return GetActionJustPressed(_pauseActionName);
}
public override bool GetFreezeJustPressed()
{
return GetActionJustPressed(_freezeActionName);
}
public override bool GetFreezePressed()
{
return GetActionPressed(_freezeActionName);
}
}

View file

@ -99,6 +99,7 @@ public class BulletInfo
public float Spread { get; set; }
public bool RotateSprite { get; set; } = false;
public bool Controllabe { get; set; } = false;
public bool Freezable { get; set; } = true;
public PackedScene BulletScene { get; set; }
public PackedScene DestructionParticlesScene { get; set; }
public IBulletModifier Modifier { get; set; }

View file

@ -0,0 +1,98 @@
using System.Collections.Generic;
using Cirno.Scripts.Actors;
using Cirno.Scripts.Components.Actors;
using Godot;
namespace Cirno.Scripts.Components.FSM.Player;
public partial class FreezeModule : ModuleBase<PlayerState, CharacterBody2D>
{
[Export] public float ResourceCost { get; private set; } = 15f;
[Export] public float FreezeRadius { get; private set; } = 64f;
[Export] public double Cooldown { get; private set; } = 0.5f;
[Export] public double IceLife { get; private set; } = 4f;
[Export] public PackedScene IceScene { get; private set; }
[ExportGroup("Providers")]
[Export]
public ActorResourceProvider Shield { get; private set; }
[Export]
public InputProvider InputProvider { get; private set; }
public bool Enabled { get; set; } = false;
private double _cooldownTimer = 0;
public override void EnterState(PlayerState state)
{
Enabled = true;
}
public override void ExitState(PlayerState state)
{
Enabled = false;
}
public override void Init(IStateMachine<PlayerState, CharacterBody2D> machine)
{
}
public override void Process(double delta)
{
if (!Enabled) return;
// TODO: Handle cooldown
}
public override void PhysicsProcess(double delta)
{
if (!Enabled) return;
if (InputProvider.GetFreezeJustPressed())
{
if (Shield.CurrentResource >= ResourceCost)
{
Shield.CurrentResource -= ResourceCost;
FreezeBullets();
}
}
}
private void FreezeBullets()
{
var bullets = GetNearbyBullets();
foreach (var bullet in bullets)
{
bullet.Freeze();
var ice = bullet.CreateSibling<Ice>(IceScene);
ice.Life = IceLife;
ice.FreezeModule = this;
}
}
private List<Bullet> GetNearbyBullets()
{
var nearbyBullets = new List<Bullet>();
foreach (var child in GameManager.Instance.BulletsContainer.GetChildren())
{
if (child is not Bullet bullet) continue;
if (bullet.BulletOwner is BulletOwner.Player)
{
continue;
}
if (bullet.IsFrozen) continue;
if (!bullet.BulletInfo.Freezable) continue;
var distance = GlobalPosition.DistanceTo(bullet.GlobalPosition);
if (distance <= FreezeRadius)
{
nearbyBullets.Add(bullet);
}
}
return nearbyBullets;
}
}

View file

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

View file

@ -25,13 +25,11 @@ public partial class PlayerFSMItemUseModule : ModuleBase<PlayerState, CharacterB
public override void EnterState(PlayerState state)
{
GD.Print("EnterState");
Enabled = true;
}
public override void ExitState(PlayerState state)
{
GD.Print("exitState");
Enabled = false;
}

View file

@ -21,6 +21,7 @@ public partial class BulletResource : Resource
[Export] public DamageType DamageType = DamageType.Neutral;
[Export] public bool RotateSprite = false;
[Export] public bool Controllable = false;
[Export] public bool Freezable { get; set; } = true;
[Export] public bool Grazeable { get; set; } = true;
[Export] public float GrazeValue { get; set; } = 0.2f;
@ -48,6 +49,7 @@ public partial class BulletResource : Resource
DestructionParticlesScene = DestructionParticlesScene,
RotateSprite = RotateSprite,
Controllabe = Controllable,
Freezable = Freezable,
TimeModifiers = TimeModifiers.Select(x => x).ToList(),
Grazeable = Grazeable,
GrazeValue = GrazeValue,