Command seam fixes: the player's switches, ping and stance flips are PilotCommand presses; triggers, switches and ping are internal
ActivatedBehavior replaces IActivatedBehavior so Activate/Deactivate can be internal under Unity's C# 9. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
25750c225b
commit
bc05417450
14 changed files with 70 additions and 66 deletions
|
|
@ -87,10 +87,15 @@ public abstract class Behavior
|
|||
}
|
||||
}
|
||||
|
||||
public interface IActivatedBehavior
|
||||
// A behaviour its pilot triggers. Only PilotApplier pulls and releases it, from the pilot's PilotCommand (Pull, Release),
|
||||
// so Activate and Deactivate are internal to the simulation: no script outside it triggers one in place.
|
||||
public abstract class ActivatedBehavior : Behavior
|
||||
{
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
protected ActivatedBehavior(BehaviorData data, EquippedItem item) : base(data, item) { }
|
||||
protected ActivatedBehavior(BehaviorData data, ConsumableItemEffect consumable) : base(data, consumable) { }
|
||||
|
||||
internal abstract void Activate();
|
||||
internal abstract void Deactivate();
|
||||
}
|
||||
|
||||
public interface IEventBehavior
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ public class ChargedWeapon : InstantWeapon
|
|||
return base.Execute(dt);
|
||||
}
|
||||
|
||||
public override void Activate()
|
||||
internal override void Activate()
|
||||
{
|
||||
// CanFire also holds a weapon whose released charge has a burst pending: its cooldown starts at its first round,
|
||||
// so a charge started before then would overlap it.
|
||||
|
|
@ -180,7 +180,7 @@ public class ChargedWeapon : InstantWeapon
|
|||
}
|
||||
}
|
||||
|
||||
public override void Deactivate()
|
||||
internal override void Deactivate()
|
||||
{
|
||||
if (_charging)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerC
|
|||
return true;
|
||||
}
|
||||
|
||||
public override void Activate()
|
||||
internal override void Activate()
|
||||
{
|
||||
// A refused beam never starts (operator ruling 2026-09-30): OnStartFiring drives the beam's visuals and
|
||||
// audio, so starting it only for Execute to stop it a tick later would flash a beam that fires nothing.
|
||||
|
|
@ -209,7 +209,7 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerC
|
|||
}
|
||||
}
|
||||
|
||||
public override void Deactivate()
|
||||
internal override void Deactivate()
|
||||
{
|
||||
if (_firing)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior, IPowerCo
|
|||
return true;
|
||||
}
|
||||
|
||||
public override void Activate()
|
||||
internal override void Activate()
|
||||
{
|
||||
if(CanFire)
|
||||
Trigger();
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ public class Sensor : Behavior, IEventBehavior, IPowerConsumer
|
|||
// Cut 5 (docs/stats-and-power-cut.md §1.3, PowerTiers.cs): Utility -- everything else.
|
||||
public int DefaultPowerTier => PowerTiers.Utility;
|
||||
|
||||
public void Ping()
|
||||
internal void Ping()
|
||||
{
|
||||
// Whole-or-nothing against the ping's own input capacitor -- fires only at full charge (operator
|
||||
// ruling: no fraction of a shot). A consumable-hosted instance (Item == null) has no PowerBus entry, so
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ public class SwitchData : BehaviorData
|
|||
}
|
||||
}
|
||||
|
||||
public class Switch : Behavior, IActivatedBehavior
|
||||
public class Switch : ActivatedBehavior
|
||||
{
|
||||
private SwitchData _data;
|
||||
|
||||
public bool Activated { get; set; }
|
||||
public bool Activated { get; private set; }
|
||||
|
||||
public Switch(SwitchData data, EquippedItem item) : base(data, item)
|
||||
{
|
||||
|
|
@ -40,12 +40,12 @@ public class Switch : Behavior, IActivatedBehavior
|
|||
return Activated;
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
internal override void Activate()
|
||||
{
|
||||
Activated = true;
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
internal override void Deactivate()
|
||||
{
|
||||
Activated = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ public class TriggerData : BehaviorData
|
|||
}
|
||||
}
|
||||
|
||||
public class Trigger : Behavior, IActivatedBehavior
|
||||
public class Trigger : ActivatedBehavior
|
||||
{
|
||||
public bool _pulled;
|
||||
private bool _pulled;
|
||||
|
||||
public Trigger(TriggerData data, EquippedItem item) : base(data, item) { }
|
||||
public Trigger(TriggerData data, ConsumableItemEffect item) : base(data, item) { }
|
||||
|
|
@ -38,12 +38,12 @@ public class Trigger : Behavior, IActivatedBehavior
|
|||
return false;
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
internal override void Activate()
|
||||
{
|
||||
_pulled = true;
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
internal override void Deactivate()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -100,7 +100,7 @@ public abstract class WeaponData : BehaviorData
|
|||
public float RatedRange => Range.Max;
|
||||
}
|
||||
|
||||
public abstract class Weapon : Behavior, IActivatedBehavior
|
||||
public abstract class Weapon : ActivatedBehavior
|
||||
{
|
||||
private WeaponData _data;
|
||||
|
||||
|
|
@ -179,12 +179,12 @@ public abstract class Weapon : Behavior, IActivatedBehavior
|
|||
return true;
|
||||
}
|
||||
|
||||
public virtual void Activate()
|
||||
internal override void Activate()
|
||||
{
|
||||
_firing = true;
|
||||
}
|
||||
|
||||
public virtual void Deactivate()
|
||||
internal override void Deactivate()
|
||||
{
|
||||
_firing = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ public abstract class Entity
|
|||
public bool HeatsinksEnabled
|
||||
{
|
||||
get => _heatsinksEnabled;
|
||||
set
|
||||
internal set
|
||||
{
|
||||
if (value == _heatsinksEnabled) return;
|
||||
_heatsinksEnabled = value;
|
||||
|
|
@ -186,7 +186,7 @@ public abstract class Entity
|
|||
|
||||
public EntitySettings Settings { get; }
|
||||
|
||||
public bool OverrideShutdown { get; set; }
|
||||
public bool OverrideShutdown { get; internal set; }
|
||||
|
||||
// The pilot's tractor command (0..1); the Pickup behaviour spins its beam toward it.
|
||||
public float TractorCommand { get; internal set; }
|
||||
|
|
@ -2170,7 +2170,7 @@ public class EquippedItem : IStatContext
|
|||
public ReactiveProperty<bool> ThermalOnline { get; } = new ReactiveProperty<bool>(false);
|
||||
public ReactiveProperty<bool> DurabilityOnline { get; } = new ReactiveProperty<bool>(false);
|
||||
public ReadOnlyReactiveProperty<bool> Online { get; }
|
||||
public ReactiveProperty<bool> Enabled { get; } = new ReactiveProperty<bool>(true);
|
||||
internal ReactiveProperty<bool> Enabled { get; } = new ReactiveProperty<bool>(true);
|
||||
public ReadOnlyReactiveProperty<bool> Active { get; }
|
||||
public ItemManager ItemManager { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -53,27 +53,35 @@ public sealed class PilotCommand
|
|||
internal readonly List<EquippedItem> Selections = new List<EquippedItem>();
|
||||
internal readonly List<string> Hails = new List<string>();
|
||||
internal readonly List<ConsumableItemData> Uses = new List<ConsumableItemData>();
|
||||
internal readonly List<(IActivatedBehavior Behavior, bool Pull)> Triggers = new List<(IActivatedBehavior, bool)>();
|
||||
internal readonly List<(Entity Other, bool? Hostile)> Iffs = new List<(Entity, bool?)>();
|
||||
internal readonly List<(ActivatedBehavior Behavior, bool Pull)> Triggers = new List<(ActivatedBehavior, bool)>();
|
||||
internal readonly List<(Entity Other, bool? Hostile, bool Toggle)> Iffs = new List<(Entity, bool?, bool)>();
|
||||
internal TargetVerb TargetVerb;
|
||||
internal int AimCycles;
|
||||
internal int ShutdownOverrideToggles, HeatsinkToggles, ShieldToggles, Pings;
|
||||
|
||||
public void Designate(TargetRef target) => Designations.Add(target);
|
||||
public void SelectItem(EquippedItem item) => Selections.Add(item);
|
||||
public void Hail(string message) => Hails.Add(message);
|
||||
public void Use(ConsumableItemData consumable) => Uses.Add(consumable);
|
||||
public void Pull(IActivatedBehavior behavior) => Triggers.Add((behavior, true));
|
||||
public void Release(IActivatedBehavior behavior) => Triggers.Add((behavior, false));
|
||||
public void Pull(ActivatedBehavior behavior) => Triggers.Add((behavior, true));
|
||||
public void Release(ActivatedBehavior behavior) => Triggers.Add((behavior, false));
|
||||
// The last verb in a step wins.
|
||||
public void Verb(TargetVerb verb) => TargetVerb = verb;
|
||||
public void CycleAim() => AimCycles++;
|
||||
public void Iff(Entity other, bool? hostile) => Iffs.Add((other, hostile));
|
||||
public void Iff(Entity other, bool? hostile) => Iffs.Add((other, hostile, false));
|
||||
// A press that flips the stance on `other` as it stands when applied, in order with Iff, so two in a step cancel.
|
||||
public void ToggleStance(Entity other) => Iffs.Add((other, null, true));
|
||||
// The entity's own switches, pressed: each press flips its switch when applied, so two in a step cancel.
|
||||
public void ToggleOverrideShutdown() => ShutdownOverrideToggles++;
|
||||
public void ToggleHeatsinks() => HeatsinkToggles++;
|
||||
public void ToggleShield() => ShieldToggles++;
|
||||
public void Ping() => Pings++;
|
||||
|
||||
// The pilot's own pending decisions, which it reads back instead of the ship (that is last step's applied state).
|
||||
public TargetRef? Designated => Designations.Count > 0 ? Designations[Designations.Count - 1] : (TargetRef?) null;
|
||||
|
||||
// Whether the last trigger this pilot commanded for `behavior` this step is a pull.
|
||||
public bool Pulls(IActivatedBehavior behavior)
|
||||
public bool Pulls(ActivatedBehavior behavior)
|
||||
{
|
||||
for (var i = Triggers.Count - 1; i >= 0; i--)
|
||||
if (ReferenceEquals(Triggers[i].Behavior, behavior)) return Triggers[i].Pull;
|
||||
|
|
@ -90,6 +98,7 @@ public sealed class PilotCommand
|
|||
Iffs.Clear();
|
||||
TargetVerb = TargetVerb.None;
|
||||
AimCycles = 0;
|
||||
ShutdownOverrideToggles = HeatsinkToggles = ShieldToggles = Pings = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +121,12 @@ public static class PilotApplier
|
|||
}
|
||||
foreach (var item in command.Selections) entity.TrySelectTargetItem(item);
|
||||
for (var i = 0; i < command.AimCycles; i++) entity.CycleAim();
|
||||
foreach (var (other, hostile) in command.Iffs) entity.SetIff(other, hostile);
|
||||
foreach (var (other, hostile, toggle) in command.Iffs) entity.SetIff(other, toggle ? !entity.IsHostileTo(other) : hostile);
|
||||
for (var i = 0; i < command.ShutdownOverrideToggles; i++) entity.OverrideShutdown = !entity.OverrideShutdown;
|
||||
for (var i = 0; i < command.HeatsinkToggles; i++) entity.HeatsinksEnabled = !entity.HeatsinksEnabled;
|
||||
if (entity.Shield != null)
|
||||
for (var i = 0; i < command.ShieldToggles; i++) entity.Shield.Item.Enabled.Value = !entity.Shield.Item.Enabled.Value;
|
||||
for (var i = 0; i < command.Pings; i++) entity.Sensor?.Ping();
|
||||
foreach (var hail in command.Hails) entity.SetMessage(hail);
|
||||
foreach (var consumable in command.Uses) entity.TryActivateConsumable(consumable);
|
||||
if (command.Aim is float3 aim) entity.Aim = aim;
|
||||
|
|
|
|||
Loading…
Reference in a new issue