Aetheria/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs
Meta Vens 23aa848315 Mines in the sim: a mine layer lays a free-floating mine body in Zone
MineLayerData (union 40) lays through InstantWeapon -> FireControl.Fire -> Lay;
Zone.Mines steps each mine as a KinematicBody after the entity loop, arms it,
triggers it on a hostile hull its blast disc touches (FireControl.Touches, the
coverage Detonate uses) and detonates it through FireControl.Detonate at the
fuse delay or lifetime. Hostile trigger, faction-blind blast, no owner leash.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:47:21 +02:00

203 lines
No EOL
6.6 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 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);
// Nominal-request ruling (docs/stats-and-power-cut.md, operator ruling 2026-09-19): the read a PowerRequest
// implementation uses for a stat named in StatValidation.PowerRequestFields, in place of Evaluate above. A
// consumable-hosted instance (Item == null) never reaches PowerBus.Step at all (see e.g. EnergyDraw.Execute's
// own comment), and ConsumableItemEffect.PowerSupplyFactor is already the identity (1) unconditionally, so
// Consumable.Evaluate is already nominal with respect to power and needs no separate context.
public float EvaluateNominalPower(PerformanceStat stat) => Item?.EvaluateNominalPower(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 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.
//
// Cut 5 (docs/stats-and-power-cut.md §1.3): every kind of consumer also names the priority tier (PowerTiers.cs)
// it defaults to. EquippedItem reads this exactly once, to seed EquippableItem.PowerTier the first time an item
// without a player-chosen tier gets equipped -- after that the stored field is what PowerBus reads, never this.
public interface IPowerConsumer
{
float PowerRequest(float dt);
int DefaultPowerTier { get; }
}
[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): retired, do not reuse -- was the "hit it with a tool" behavior deleted in Cut 2 (docs/mining-cut.md, Q1=A).
// 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)),
// Cut 2 (docs/fire-control-cut.md): 39 is the next free index against this list, not the 39 the
// superseded draft quoted -- checked directly here rather than trusted from that document.
Union(39, typeof(TargetingSystemData)),
Union(40, typeof(MineLayerData)),
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();
}
}