599b9b4255
Data-driven ItemDatabase catalog + per-player replicated InventorySlot ([GhostField] OwnerSendType.All, a StatModifier twin). Harvest reroutes to the firing player's personal inventory (optional ComponentLookup<GhostOwner> in ResourceHarvestSystem; remainder/un-owned -> ledger); the G-key InventoryDepositRequest RPC moves the bag into the shared ledger the build economy spends. Catalog asset (Aether/Ore/Biomass + Stone Pickaxe) wired into the Gameplay subscene; read-only HUD inventory panel. ushort ItemId subsumes ResourceId; byte Category/Tier baked for gear-tier progression. Session-only (no SaveData bump). Play-validated host+client: catalog baked into both worlds, the re-baked player ghost carries InventorySlot with a clean handshake, a server write replicates to the client owner, the deposit RPC round-trips, and the HUD renders catalog names. See DR-026. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
3.9 KiB
C#
69 lines
3.9 KiB
C#
namespace ProjectM.Simulation
|
|
{
|
|
/// <summary>
|
|
/// Central home for gameplay-balance constants that were previously buried as <c>private const</c>s
|
|
/// inside individual systems, so designers have one searchable place to tune them. Burst-safe (compile-time
|
|
/// <c>const</c>s only — they inline into the consuming systems with no runtime cost or managed reference).
|
|
/// <para>
|
|
/// Systems reference these via <c>Tuning.*</c> (wired in the 2026-06-04 polish pass, Stage C). When adding a
|
|
/// new tunable value, prefer adding it here over a local private const UNLESS it already has an obvious,
|
|
/// well-named public home (see the cross-references below) — duplicating a literal creates two sources of truth.
|
|
/// </para>
|
|
/// <para>
|
|
/// <b>Values that already live in a clear, public, semantically-named home (NOT duplicated here):</b>
|
|
/// <list type="bullet">
|
|
/// <item><see cref="CyclePhase.ExpeditionTicks"/> / <see cref="CyclePhase.BuildTicks"/> — cycle phase durations.</item>
|
|
/// <item><see cref="RegionMath.ExpeditionOffsetX"/> — base→expedition world-space offset.</item>
|
|
/// <item>Per-ability/character stats — authored in ScriptableObjects, baked to the AbilityDatabase blob (M3).</item>
|
|
/// </list>
|
|
/// </para>
|
|
/// </summary>
|
|
public static class Tuning
|
|
{
|
|
// ---- Ability damage upgrade (AbilityUpgradeSystem) ----
|
|
|
|
/// <summary>Distinct sentinel SourceId so the upgrade <c>StatModifier</c> is found + grown in place
|
|
/// (replace-by-SourceId keeps the bounded modifier buffer from growing a row per upgrade).</summary>
|
|
public const uint AbilityUpgradeSourceId = 0x00A0E711u;
|
|
|
|
/// <summary>Damage bonus added per upgrade tier (PercentAdd op): +25% per tier.</summary>
|
|
public const float AbilityUpgradeTierStep = 0.25f;
|
|
|
|
/// <summary>Aether cost charged to the shared ledger per upgrade tier.</summary>
|
|
public const int AbilityUpgradeCostAmount = 20;
|
|
|
|
// ---- Resource harvest (ResourceHarvestSystem) ----
|
|
|
|
/// <summary>Effective projectile radius used by the swept-segment node-hit test (added to the node's
|
|
/// <c>HitRadius</c>). Tunnel-safe because the segment is reconstructed from <c>Projectile.LastStep</c>.</summary>
|
|
public const float HarvestProjectileRadius = 0.2f;
|
|
|
|
// ---- Enemy knockback (ProjectileDamageSystem stamps on hit; EnemyAISystem applies + suppresses seek/strike) ----
|
|
|
|
/// <summary>Knockback speed (world units/sec) a Husk recoils at when shot; 0 disables knockback globally.</summary>
|
|
public const float KnockbackSpeed = 8f;
|
|
|
|
/// <summary>Server ticks the knockback lasts (~60 ticks/sec).</summary>
|
|
public const int KnockbackDurationTicks = 8;
|
|
|
|
// ---- Husk attack telegraph (EnemyAISystem 2-phase strike; client cue in CombatFeedbackSystem) ----
|
|
|
|
/// <summary>Wind-up ticks before a Husk strike lands (~0.3s @ 60 ticks/sec). 0/1 = near-instant (legacy behaviour).</summary>
|
|
public const int AttackWindupTicks = 18;
|
|
|
|
// ---- Production / automation (M7: Harvester/Conveyor/Fabricator) ----
|
|
|
|
/// <summary>Max production cycles a single machine awards in one process (bounds within-session
|
|
/// catch-up after any skipped ticks; restore re-seats the baseline so this never reflects wall-clock).</summary>
|
|
public const int MaxProductionCatchup = 600;
|
|
|
|
// ---- Inventory (per-player bag; InventoryMath / ResourceHarvestSystem / InventoryDepositSystem) ----
|
|
|
|
/// <summary>Max stacks a player can carry; InventoryMath rejects deposits past this and the harvest remainder spills to the global ledger.</summary>
|
|
public const int InventoryMaxSlots = 24;
|
|
|
|
/// <summary>Default per-slot stack cap when an item has no ItemDatabase entry (the catalog is optional at runtime).</summary>
|
|
public const int DefaultStackMax = 999;
|
|
}
|
|
}
|