Enhanced bullet scripts

This commit is contained in:
Marco 2025-09-24 17:47:15 +02:00
commit c1f83736f0
7 changed files with 112 additions and 52 deletions

View file

@ -12,50 +12,63 @@ namespace Cirno.Scripts.AttackPatterns;
[Tool]
public partial class ShootingPattern3D : AttackPattern
{
[Export] public float Delay { get; set; }
[Export] public LoopType LoopType { get; set; }
[Export] public BulletResource BulletResource { get; set; }
[Export] public Vector3 EmitterOffset { get; set; } = Vector3.Zero;
[Export] public int bulletCount = 16;
[Export] public float rotationSpeed = 0f;
[Export] public float BurstRotationSpeed = 0f;
[Export] public bool UseParentRotationOffset { get; set; } = false;
[Export] public float _rotationOffset = 0f;
[Export] public float duration = 5f;
[Export] public float duration = -1f;
[Export] public float spread = 360f;
[Export] public float burstInterval = 0.5f;
[ExportCategory("Burst")] [Export] public int ShotsPerBurst { get; private set; } = 100;
[Export] public float BurstRate { get; private set; } = 0f;
[ExportCategory("Other")] [Export] public bool _targetPlayer = false;
[ExportCategory("Other")] [Export] public bool _predictPlayer = false;
[ExportCategory("Overrides")]
[ExportGroup("Override Damage")]
[Export(PropertyHint.GroupEnable)] public bool OverrideDamage { get; private set; } = false;
[Export(PropertyHint.GroupEnable)]
public bool OverrideDamage { get; private set; } = false;
[Export] public float DamageOverride { get; private set; } = 10f;
[ExportGroup("Override Speed")]
[Export(PropertyHint.GroupEnable)] public bool OverrideSpeed { get; private set; } = false;
[Export(PropertyHint.GroupEnable)]
public bool OverrideSpeed { get; private set; } = false;
[Export] public float SpeedOverride { get; private set; } = 10f;
[ExportGroup("Override Owner")]
[Export(PropertyHint.GroupEnable)] public bool OverrideOwner { get; private set; } = false;
[Export(PropertyHint.GroupEnable)]
public bool OverrideOwner { get; private set; } = false;
[Export] public BulletOwner Owner { get; private set; } = BulletOwner.None;
[ExportGroup("Override Damage Type")]
[Export(PropertyHint.GroupEnable)] public bool OverrideDamageType { get; private set; } = false;
[Export(PropertyHint.GroupEnable)]
public bool OverrideDamageType { get; private set; } = false;
[Export] public DamageType DamageType { get; private set; } = DamageType.Neutral;
[ExportGroup("Override Attributes")]
[Export(PropertyHint.GroupEnable)] public bool OverrideAttributes { get; private set; } = false;
[Export(PropertyHint.GroupEnable)]
public bool OverrideAttributes { get; private set; } = false;
[Export] public BulletFlags AttributesOverride { get; private set; }
[ExportGroup("Override Controllable (deprecated)")]
[Export(PropertyHint.GroupEnable)] public bool OverrideControllable { get; private set; } = false;
[Export(PropertyHint.GroupEnable)]
public bool OverrideControllable { get; private set; } = false;
[Export] public bool Controllable { get; private set; } = false;
[ExportCategory("Extra Modifiers")]
@ -64,10 +77,12 @@ public partial class ShootingPattern3D : AttackPattern
public bool OverrideCreationModifier { get; private set; } = false;
[Export] public BulletCreationModifier Modifier;
[ExportGroup("Time Modifiers")]
[Export] public Array<TimeModifier> TimeModifiers = [];
protected virtual BulletInfo MakeBullet(Vector2 position, int count = 1, float spread = 0f, float rotationOffset = 0f)
[ExportGroup("Time Modifiers")] [Export]
public Array<TimeModifier> TimeModifiers = [];
protected virtual BulletInfo MakeBullet(Vector2 position, int count = 1, float spread = 0f,
float rotationOffset = 0f)
{
var bullet = this.BulletResource.MakeBullet(position, count,
spread, rotationOffset);
@ -81,7 +96,7 @@ public partial class ShootingPattern3D : AttackPattern
{
bullet.Speed = this.SpeedOverride;
}
if (OverrideOwner)
{
bullet.Owner = this.Owner;
@ -96,7 +111,7 @@ public partial class ShootingPattern3D : AttackPattern
{
bullet.Attributes = AttributesOverride;
}
// if (OverrideControllable)
// {
// bullet.Controllabe = Controllable;
@ -111,7 +126,7 @@ public partial class ShootingPattern3D : AttackPattern
{
bullet.TimeModifiers.AddRange(TimeModifiers);
}
return bullet;
}
@ -125,29 +140,31 @@ public partial class ShootingPattern3D : AttackPattern
public Node Parent => parent;
public IScriptHost3D ScriptHost { get; private set; }
private double timer;
private double burstTimer;
//private double _burstRateTimer;
private BulletSpawner3D spawner;
private ShootStatus _state = ShootStatus.Idle;
private int _burstBullets;
private int _currentBurstOffset = 0;
public void Start()
{
ScriptHost = Parent as IScriptHost3D;
timer = 0;
_burstBullets = pattern.ShotsPerBurst;
burstTimer = pattern.burstInterval; // start immediately
spawner = parent.GetNode<BulletSpawner3D>("BulletSpawner3D");
_state = ShootStatus.Shooting;
_state = pattern.Delay == 0 ? ShootStatus.Shooting : ShootStatus.Idle;
}
private void WaitingBurstUpdate(double delta)
{
timer += delta;
@ -163,7 +180,7 @@ public partial class ShootingPattern3D : AttackPattern
{
timer += delta;
burstTimer += delta;
if (burstTimer >= pattern.BurstRate)
{
_burstBullets = pattern.ShotsPerBurst;
@ -180,6 +197,12 @@ public partial class ShootingPattern3D : AttackPattern
if (_burstBullets <= 0)
{
if (pattern.LoopType is LoopType.PlayOnce)
{
_state = ShootStatus.Done;
return;
}
_state = ShootStatus.WaitingReload;
_currentBurstOffset++;
}
@ -189,11 +212,22 @@ public partial class ShootingPattern3D : AttackPattern
}
}
private void IdleUpdate(double delta)
{
timer += delta;
if (timer >= pattern.Delay)
{
_state = ShootStatus.Shooting;
}
}
public void UpdatePattern(double delta)
{
switch (_state)
{
case ShootStatus.Idle:
IdleUpdate(delta);
break;
case ShootStatus.Done:
return;
case ShootStatus.Shooting:
@ -206,17 +240,17 @@ public partial class ShootingPattern3D : AttackPattern
WaitingReloadUpdate(delta);
break;
}
if (timer >= pattern.duration)
if (pattern.duration > -1 && timer >= pattern.duration)
{
_state = ShootStatus.Done;
}
}
private void Shoot()
{
float angleOffset = pattern._rotationOffset + (float)(pattern.rotationSpeed * timer) + (float)(pattern.BurstRotationSpeed * _currentBurstOffset);
float angleOffset = pattern._rotationOffset + (float)(pattern.rotationSpeed * timer) +
(float)(pattern.BurstRotationSpeed * _currentBurstOffset);
Vector2 direction = pattern.BulletResource.Direction;
@ -225,14 +259,15 @@ public partial class ShootingPattern3D : AttackPattern
{
direction = direction.Rotated(-spawner.GlobalRotation.Y + Mathf.DegToRad(90));
}
// TODO: Fix player aiming for 3D
if (pattern._targetPlayer && GameController.Instance.PlayerPosition.HasValue)
{
if (pattern._predictPlayer && GameController.Instance.PlayerVelocity.HasValue)
{
var predictedDirection = MathFunctions.PredictInterceptPosition(spawner.GlobalPosition.ToVector2(),
GameController.Instance.PlayerPosition.Value.ToVector2(), GameController.Instance.PlayerVelocity.Value.ToVector2(),
GameController.Instance.PlayerPosition.Value.ToVector2(),
GameController.Instance.PlayerVelocity.Value.ToVector2(),
pattern.BulletResource.BulletSpeed);
if (predictedDirection.HasValue)
{
@ -241,7 +276,8 @@ public partial class ShootingPattern3D : AttackPattern
}
else
{
direction = (GameController.Instance.PlayerPosition.Value.ToVector2() - spawner.GlobalPosition.ToVector2()).Normalized();
direction = (GameController.Instance.PlayerPosition.Value.ToVector2() -
spawner.GlobalPosition.ToVector2()).Normalized();
}
}
@ -249,7 +285,7 @@ public partial class ShootingPattern3D : AttackPattern
var bullet = pattern.MakeBullet(spawnPosition.ToVector2(), pattern.bulletCount,
pattern.spread, angleOffset);
bullet.Direction = direction;
//spawner.SpawnBullet(MakeBullet(Boss.GlobalPosition, direction, angleOffset));
@ -259,8 +295,17 @@ public partial class ShootingPattern3D : AttackPattern
public bool IsComplete()
{
//return timer >= pattern.duration;
return _state is ShootStatus.Done;
if (!pattern.WaitForCompletion) return _state is ShootStatus.Done;
if (_state is not ShootStatus.Done) return false;
// From now on the status is done
if (pattern.duration > -1)
{
// Wait for timer
return (timer >= pattern.duration);
}
// No timer, if it's done it's done
return true;
}
private enum ShootStatus

View file

@ -11,6 +11,8 @@ namespace Cirno.Scripts.Resources;
public partial class PatternGroup : AttackPattern
{
[Export] private Array<AttackPattern> patterns;
[Export(PropertyHint.None, "suffix:s")]
public float Duration { get; private set; } = -1f;
public override IPatternMachine MakeMachine(Node parent)
{
@ -53,7 +55,7 @@ public partial class PatternGroup : AttackPattern
public bool IsComplete()
{
return _currentPatternIndex >= patternGroup.patterns.Count;
return patternGroup.Duration > -1 && _currentPatternIndex >= patternGroup.patterns.Count;
}
}

View file

@ -9,9 +9,11 @@ namespace Cirno.Scripts.Resources.ScriptableBullets;
[Tool]
public partial class ParallelPatternGroup : AttackPattern
{
[Export(PropertyHint.None, "suffix:s")] public float Duration { get; private set; } = 10f;
[Export(PropertyHint.None, "suffix:s")]
public float Duration { get; private set; } = 10f;
[Export] public Array<AttackPattern> Patterns { get; private set; } = [];
public override IPatternMachine MakeMachine(Node parent)
{
return new ParallelPatternGroupMachine(this, parent);
@ -21,13 +23,13 @@ public partial class ParallelPatternGroup : AttackPattern
{
public Node Parent => parent;
//private int _currentPatternIndex = 0;
//private AttackPattern CurrentPattern => patternGroup.Patterns[_currentPatternIndex];
private double _progressTimer = 0;
private List<IPatternMachine> _patternMachines = [];
public void Start()
{
//_currentPatternIndex = 0;
@ -48,19 +50,20 @@ public partial class ParallelPatternGroup : AttackPattern
if (patternMachine.IsComplete()) continue;
patternMachine.UpdatePattern(delta);
}
}
public bool IsComplete()
{
if (patternGroup.WaitForCompletion)
{
return _patternMachines.TrueForAll(x => x.IsComplete()) && _progressTimer >= patternGroup.Duration;
return _patternMachines.TrueForAll(x => x.IsComplete()) &&
(patternGroup.Duration > -1 &&
_progressTimer >= patternGroup.Duration);
}
return _patternMachines.TrueForAll(x => x.IsComplete()) || _progressTimer >= patternGroup.Duration;
return _patternMachines.TrueForAll(x => x.IsComplete()) ||
(patternGroup.Duration > -1 &&
_progressTimer >= patternGroup.Duration);
}
}
}
}