Layers: one owner puts orbitals above the ship plane and floaters below; per-hull GridOffset is deleted
GameplaySettings carries ShipLayerHeight 3, OrbitalLayerHeight 15, FloaterLayerHeight 0 (authored in Settings.asset). Entity.LayerHeight (Ship, OrbitalEntity) is the one offset RideHeight adds; DrawAhead.FloaterHeight is the floater height ItemPickup and MineInstance draw at. HullData.GridOffset (Key 26) and the pickup/mine/prefab GridOffset fields are gone with every reader. Fixtures (DrawnPose, FireControl*, ImpactFeedback) take heights from the layer owner; LayerTests pin each kind's layer. FloatingItemsDrawnSmoke follows. ItemPickup/MineInstance.Bind take the settings from ZoneRenderer. Builds as one commit with its tests; not compile-verified until the cut's head run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
624d5420e9
commit
be7f2b0787
23 changed files with 205 additions and 51 deletions
|
|
@ -90,6 +90,8 @@ public static class FloatingItemsDrawnSmoke
|
|||
{
|
||||
var settings = AssetDatabase.LoadAssetAtPath<GameSettings>("Assets/Resources/Settings.asset")?.GameplaySettings
|
||||
?? throw new InvalidOperationException("No Settings.asset.");
|
||||
// A floater rides its own layer: a nonzero one (never saved back to the asset), so a presenter that drops it fails.
|
||||
settings.FloaterLayerHeight = -1.5f;
|
||||
|
||||
// The wiring: the scene's ZoneRenderer names an ItemPickup prefab in each of the four fields, and none of those
|
||||
// prefabs keeps a script that no longer exists.
|
||||
|
|
@ -159,7 +161,7 @@ public static class FloatingItemsDrawnSmoke
|
|||
{
|
||||
var lead = ActionGameManager.Clock.Lead;
|
||||
var at = DrawAhead.Position(floating.Body, lead);
|
||||
var want = new Vector3(at.x, DrawAhead.Height(zone, at, lead), at.y);
|
||||
var want = new Vector3(at.x, DrawAhead.FloaterHeight(zone, settings, at, lead), at.y);
|
||||
Require(Vector3.Distance(pickup.transform.position, want) < 1e-3f,
|
||||
$"{what}: the pickup is at {pickup.transform.position}, the body at {want}.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ using Random = UnityEngine.Random;
|
|||
public class ItemPickup : MonoBehaviour
|
||||
{
|
||||
public float RotationSpeed = 1f;
|
||||
public float GridOffset;
|
||||
public float LabelFadeDuration = .5f;
|
||||
public float LabelPersistDuration = 3;
|
||||
public float LabelDisplayAngle = 15;
|
||||
|
|
@ -27,11 +26,13 @@ public class ItemPickup : MonoBehaviour
|
|||
private float _displayTime;
|
||||
private float _timeOffset;
|
||||
private Zone _zone;
|
||||
private GameplaySettings _settings;
|
||||
private FloatingItem _floating;
|
||||
|
||||
public void Bind(Zone zone, FloatingItem floating)
|
||||
public void Bind(Zone zone, FloatingItem floating, GameplaySettings settings)
|
||||
{
|
||||
_zone = zone;
|
||||
_settings = settings;
|
||||
_floating = floating;
|
||||
Item = floating.Item;
|
||||
_timeOffset = Random.value * 100;
|
||||
|
|
@ -42,7 +43,7 @@ public class ItemPickup : MonoBehaviour
|
|||
{
|
||||
var lead = ActionGameManager.Clock.Lead;
|
||||
var p = DrawAhead.Position(_floating.Body, lead);
|
||||
transform.position = new Vector3(p.x, DrawAhead.Height(_zone, p, lead) + GridOffset, p.y);
|
||||
transform.position = new Vector3(p.x, DrawAhead.FloaterHeight(_zone, _settings, p, lead), p.y);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
|
|
|
|||
|
|
@ -17,21 +17,22 @@ public class MineInstance : MonoBehaviour
|
|||
public float ActiveEmission = 100f;
|
||||
public float ArmedEmission = 1000f;
|
||||
public float RotationSpeed = 1f;
|
||||
public float GridOffset;
|
||||
// The blast's particles; the effect prefab destroys itself when its particle system stops.
|
||||
public GameObject HitEffect;
|
||||
public float HitEffectScale = 10f;
|
||||
|
||||
private Zone _zone;
|
||||
private GameplaySettings _settings;
|
||||
private Mine _mine;
|
||||
private Material _material;
|
||||
private float _timeOffset;
|
||||
private float _pulse;
|
||||
private float _emission;
|
||||
|
||||
public void Bind(Zone zone, Mine mine)
|
||||
public void Bind(Zone zone, Mine mine, GameplaySettings settings)
|
||||
{
|
||||
_zone = zone;
|
||||
_settings = settings;
|
||||
_mine = mine;
|
||||
_material = MeshRenderer.materials[EmissionSubmesh];
|
||||
_timeOffset = Random.value * 100;
|
||||
|
|
@ -57,7 +58,7 @@ public class MineInstance : MonoBehaviour
|
|||
{
|
||||
var lead = ActionGameManager.Clock.Lead;
|
||||
var p = DrawAhead.Position(_mine.Body, lead);
|
||||
transform.position = new Vector3(p.x, DrawAhead.Height(_zone, p, lead) + GridOffset, p.y);
|
||||
transform.position = new Vector3(p.x, DrawAhead.FloaterHeight(_zone, _settings, p, lead), p.y);
|
||||
}
|
||||
|
||||
// The mine left Zone.Mines, which only its blast does: show it where it was drawn last.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ public static class DrawAhead
|
|||
// The field's height at a point at the drawn time, its wells where their rails put them at T.
|
||||
public static float Height(Zone zone, float2 planar, float lead) => zone.GetHeight(planar, Time(zone, lead));
|
||||
|
||||
// The drawn height of a floater (loot, mines): the field at the drawn time plus the floater layer.
|
||||
public static float FloaterHeight(Zone zone, GameplaySettings settings, float2 planar, float lead) => Height(zone, planar, lead) + settings.FloaterLayerHeight;
|
||||
|
||||
// A ship in a wormhole animation has its pose scripted by the step, not integrated from Velocity and TurnRate,
|
||||
// so it is drawn where the step put it: extrapolating a scripted pose draws a streak that resets every step.
|
||||
// A child is drawn where its parent is drawn, as the step copies the parent's pose onto it.
|
||||
|
|
|
|||
|
|
@ -1974,9 +1974,13 @@ public abstract class Entity
|
|||
Manoeuvre.Observe(Acceleration, delta, ItemManager.GameplaySettings.SolutionWindow);
|
||||
}
|
||||
|
||||
// Where an unparented entity sits on the field at a planar point: the zone's height there plus the hull's grid offset.
|
||||
// The step rides at its own time and xz, the presenter at the drawn time and its drawn xz (DrawAhead).
|
||||
public float RideHeight(float2 planar, double time) => Zone.GetHeight(planar, time) + (ItemManager.GetData(Hull) as HullData).GridOffset;
|
||||
// The height above the field of the layer this kind of entity rides on (GameplaySettings): ships the ship plane,
|
||||
// orbital entities the orbital layer above it.
|
||||
public abstract float LayerHeight { get; }
|
||||
|
||||
// Where an unparented entity sits on the field at a planar point: the zone's height there plus the layer this kind of
|
||||
// entity rides on. The step rides at its own time and xz, the presenter at the drawn time and its drawn xz (DrawAhead).
|
||||
public float RideHeight(float2 planar, double time) => Zone.GetHeight(planar, time) + LayerHeight;
|
||||
|
||||
public float RideHeight(float2 planar) => RideHeight(planar, Zone.ExactTime);
|
||||
|
||||
|
|
|
|||
|
|
@ -519,8 +519,7 @@ public class HullData : EquippableItemData
|
|||
[Inspectable, JsonProperty("hullType"), Key(25)]
|
||||
public HullType HullType;
|
||||
|
||||
[Inspectable, JsonProperty("gridOffset"), Key(26)]
|
||||
public float GridOffset;
|
||||
// Key(26) retired 2026-10-16 (per-hull GridOffset; the layer is the kind's, GameplaySettings). Do not reuse.
|
||||
|
||||
[Inspectable, JsonProperty("armor"), Key(27)]
|
||||
public float Armor;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ public class OrbitalEntity : Entity
|
|||
OrbitData = orbit;
|
||||
}
|
||||
|
||||
public override float LayerHeight => ItemManager.GameplaySettings.OrbitalLayerHeight;
|
||||
|
||||
public override void Update(float delta)
|
||||
{
|
||||
if (OrbitData.IsSet())
|
||||
|
|
|
|||
|
|
@ -278,6 +278,13 @@ public class GameplaySettings
|
|||
// normal is this times the speed at which it closed. 0 is perfectly inelastic, 1 perfectly elastic.
|
||||
public float ContactRestitution = .5f;
|
||||
|
||||
// Heights above the field of the ship plane, the orbital layer (stations, turrets: every OrbitalEntity) and the floater
|
||||
// layer (loot, mines): orbitals above ships and floaters below them, so no ship ever touches either (ruling
|
||||
// aetheria-gravity:orbitals-above-floaters-below).
|
||||
public float ShipLayerHeight = 3f;
|
||||
public float OrbitalLayerHeight = 15f;
|
||||
public float FloaterLayerHeight = 0f;
|
||||
|
||||
// The floor an AI's own predicted hit probability (FireControl.HitProbability) must clear before it counts
|
||||
// a firing solution worth taking (Combat.cs, TurretController.cs). Player fire is gated on arc alone
|
||||
// (Weapon.ArcAllowsFire, Q2) -- this threshold is an AI fire-discipline heuristic, not part of the roll.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ using quaternion = CultMath.quaternion;
|
|||
[MessagePackObject]
|
||||
public class Ship : Entity
|
||||
{
|
||||
public override float LayerHeight => ItemManager.GameplaySettings.ShipLayerHeight;
|
||||
|
||||
|
||||
// [Key("bindings")] public Dictionary<KeyCode,Guid> Bindings = new Dictionary<KeyCode,Guid>();
|
||||
//[IgnoreMember] public int HullHardpointCount;
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ public class ZoneRenderer : MonoBehaviour
|
|||
private void LoadMine(Zone zone, Mine mine)
|
||||
{
|
||||
var instance = Instantiate(MinePrefab);
|
||||
instance.Bind(zone, mine);
|
||||
instance.Bind(zone, mine, ItemManager.GameplaySettings);
|
||||
_mines.Add(mine, instance);
|
||||
}
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ public class ZoneRenderer : MonoBehaviour
|
|||
_ => throw new NotImplementedException()
|
||||
};
|
||||
var pickup = Instantiate(prefab, ZoneRoot);
|
||||
pickup.Bind(zone, floating);
|
||||
pickup.Bind(zone, floating, ItemManager.GameplaySettings);
|
||||
pickup.ScanLabel.text = ItemManager.Title(floating.Item);
|
||||
if (floating.Item is CraftedItemInstance craftedItemInstance)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue