Deletes Entity.CanConsumeEnergy/TryConsumeEnergy and Reactor's own capacitor draining/filling (the demand-mechanism halves of Reactor.cs:90-141); adds PowerBus (one per Entity, stepped once per tick before equipment executes), IPowerConsumer on the five continuous draw sites (EnergyDraw, Thruster, AetherDrive, Radiator, ConstantWeapon), and EquippedItem.PowerSupply as the bus's grant ratio. Reactor keeps only its heat/throttle arithmetic, now driven by PowerBus.NetDraw instead of an accumulator any behaviour could add into. The four instant draws (InstantWeapon's burst/shot, Sensor's ping, Shield's hit taken) are out of scope for the bus this cut per the map; they spend capacitor charge directly and atomically via the new Entity.TrySpendCapacitorCharge/ CanSpendCapacitorCharge, replacing TryConsumeEnergy's old partial-drain-then- refuse bug for that path too. Named, temporary exception closed by Cut 4. docs/stats-and-power-cut.md Cut 3. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
200 lines
No EOL
5.7 KiB
C#
200 lines
No EOL
5.7 KiB
C#
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using MessagePack;
|
|
using Newtonsoft.Json;
|
|
using CultMath;
|
|
using static CultMath.math;
|
|
|
|
public abstract class Behavior
|
|
{
|
|
public BehaviorData Data { get; }
|
|
public EquippedItem Item { get; }
|
|
private ConsumableItemEffect Consumable { get; }
|
|
protected ItemManager ItemManager { get; }
|
|
|
|
protected Entity Entity => Item?.Entity ?? Consumable.Entity;
|
|
public float Temperature => Item?.Temperature ?? Consumable.Entity.MaxTemp;
|
|
|
|
public float3 Direction
|
|
{
|
|
get
|
|
{
|
|
if(Item != null)
|
|
{
|
|
var hardpoint = Entity.Hardpoints[Item.Position.x, Item.Position.y];
|
|
if (hardpoint != null && Entity.HardpointTransforms.ContainsKey(hardpoint))
|
|
{
|
|
return normalize(Entity.HardpointTransforms[hardpoint].direction);
|
|
}
|
|
else
|
|
{
|
|
var itemDirection = Entity.Direction.Rotate(Item.EquippableItem.Rotation);
|
|
return float3(itemDirection.x, 0, itemDirection.y);
|
|
}
|
|
}
|
|
|
|
return float3(Entity.Direction.x, 0, Entity.Direction.y);
|
|
}
|
|
}
|
|
|
|
protected Behavior(BehaviorData data, EquippedItem item)
|
|
{
|
|
Data = data;
|
|
Item = item;
|
|
ItemManager = Item.ItemManager;
|
|
}
|
|
|
|
protected Behavior(BehaviorData data, ConsumableItemEffect consumable)
|
|
{
|
|
Data = data;
|
|
Consumable = consumable;
|
|
ItemManager = consumable.Entity.ItemManager;
|
|
}
|
|
|
|
public float Evaluate(PerformanceStat stat) => Item?.Evaluate(stat) ?? Consumable.Evaluate(stat);
|
|
protected void AddHeat(float heat) => Item?.AddHeat(heat); // TODO: Heat for Consumables
|
|
|
|
protected void CauseDamage(float damage)
|
|
{
|
|
if (Item != null)
|
|
{
|
|
Item.EquippableItem.Durability -= damage;
|
|
Entity.ItemDamage.OnNext((Item, damage));
|
|
}
|
|
else
|
|
{
|
|
Consumable.Entity.Hull.Durability -= damage;
|
|
Consumable.Entity.HullDamage.OnNext(damage);
|
|
}
|
|
}
|
|
|
|
protected void CauseWearDamage(float multiplier)
|
|
{
|
|
if (Item != null)
|
|
{
|
|
CauseDamage(Item.Wear * multiplier);
|
|
}
|
|
}
|
|
|
|
public virtual bool Execute(float dt)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public interface IActivatedBehavior
|
|
{
|
|
void Activate();
|
|
void Deactivate();
|
|
}
|
|
|
|
public interface IAnalogBehavior
|
|
{
|
|
float Axis { get; set; }
|
|
}
|
|
|
|
public interface IEventBehavior
|
|
{
|
|
void ResetEvents();
|
|
}
|
|
|
|
public interface IInitializableBehavior
|
|
{
|
|
void Initialize();
|
|
}
|
|
|
|
public interface IInteractiveBehavior
|
|
{
|
|
bool Exposed { get; }
|
|
}
|
|
|
|
public interface IAlwaysUpdatedBehavior
|
|
{
|
|
void Update(float delta);
|
|
}
|
|
|
|
public interface IProgressBehavior
|
|
{
|
|
float Progress { get; }
|
|
}
|
|
|
|
public interface IOrderedBehavior
|
|
{
|
|
int Order { get; }
|
|
}
|
|
|
|
public interface IPopulationAssignment
|
|
{
|
|
int AssignedPopulation { get; set; }
|
|
}
|
|
|
|
// Cut 3 (docs/stats-and-power-cut.md §1.2): a behaviour that wants to draw from its entity's PowerBus declares a
|
|
// request instead of spending energy itself. PowerBus.Step calls this on every consumer once per tick, before
|
|
// any behaviour's Execute runs, so PowerRequest must be computable from state that is already current at that
|
|
// point -- a resolved stat and, where the map calls for one, a behaviour-supplied scalar such as Thruster's
|
|
// throttle axis (set externally before the tick) -- never from work Execute itself would otherwise do. The
|
|
// behaviour reads back how much of its own request was granted from Item.PowerSupply during its own Execute.
|
|
public interface IPowerConsumer
|
|
{
|
|
float PowerRequest(float dt);
|
|
}
|
|
|
|
[Inspectable,
|
|
Union(0, typeof(GuidedWeaponData)),
|
|
Union(1, typeof(LauncherData)),
|
|
Union(2, typeof(ReactorData)),
|
|
Union(3, typeof(RadiatorData)),
|
|
Union(4, typeof(StatModifierData)),
|
|
Union(5, typeof(SensorData)),
|
|
Union(6, typeof(ReflectorData)),
|
|
Union(7, typeof(ShieldData)),
|
|
Union(8, typeof(ThrusterData)),
|
|
Union(9, typeof(WearData)),
|
|
Union(10, typeof(VelocityConversionData)),
|
|
Union(11, typeof(VelocityLimitData)),
|
|
Union(12, typeof(AetherDriveData)),
|
|
// Union(14, typeof(TowingControllerData)),
|
|
Union(15, typeof(CooldownData)),
|
|
Union(16, typeof(HeatData)),
|
|
// Union(17, typeof(HitscanData)),
|
|
Union(18, typeof(ItemUsageData)),
|
|
//Union(19, typeof(RadianceData)),
|
|
Union(20, typeof(SwitchData)),
|
|
Union(21, typeof(TriggerData)),
|
|
Union(22, typeof(VisibilityData)),
|
|
Union(23, typeof(ThermotoggleData)),
|
|
Union(24, typeof(EnergyDrawData)),
|
|
// Union(25, typeof(MiningControllerData)),
|
|
Union(26, typeof(MiningToolData)),
|
|
// Union(27, typeof(SurveyControllerData)),
|
|
Union(28, typeof(ResourceScannerData)),
|
|
// Union(29, typeof(WanderControllerData)),
|
|
// Union(30, typeof(HaulingControllerData)),
|
|
Union(31, typeof(CapacitorData)),
|
|
Union(32, typeof(CockpitData)),
|
|
Union(33, typeof(HeatStorageData)),
|
|
Union(34, typeof(TurretControllerData)),
|
|
Union(35, typeof(InstantWeaponData)),
|
|
Union(36, typeof(ConstantWeaponData)),
|
|
Union(37, typeof(ChargedWeaponData)),
|
|
Union(38, typeof(AutoWeaponData)),
|
|
JsonObject(MemberSerialization.OptIn)]
|
|
public abstract class BehaviorData
|
|
{
|
|
[Inspectable, JsonProperty("group"), Key(0)]
|
|
public int Group;
|
|
|
|
public abstract Behavior CreateInstance(EquippedItem item);
|
|
public abstract Behavior CreateInstance(ConsumableItemEffect consumable);
|
|
|
|
public override string ToString()
|
|
{
|
|
return base.ToString().FormatTypeName();
|
|
}
|
|
} |