b4 static findings: 22 formula corrections, 3 verified signatures, contract -> 324 entries
This commit is contained in:
parent
535d1c3b58
commit
4d535028ed
8 changed files with 1269 additions and 18 deletions
|
|
@ -63,5 +63,5 @@ Status flow: `backlog → in-progress → mapped → verified` (or `blocked`).
|
|||
| budget tail coverage (expenses/aid/debt) | verify | backlog | — | 0% | 2026-09-08 | 8 ComputeBudget slots were always 0 in ref-turn2 (no sliders, no aid, no debt, no handicap). Need a save with expense sliders, a debtor and a research-aid treaty to exercise ExpenseTotal + the aid/bonus tail |
|
||||
| hook GetDifficultyMods | meta | backlog | — | 0% | 2026-09-08 | B1 derived the two difficulty rows from trace values (AI maintenance divisor 3, research x1.5) instead of snapshotting them; hook it properly so they stop being constants |
|
||||
| section-loader compare crash | verify | backlog | — | 0% | 2026-09-08 | SectionDictionary compare crashes the engine while the identical weapon path succeeds -> fault is in re-running LoadSection, not the manifest reader. Next boundary: hook LoadSection itself. docs/M2.md has 3 ranked leads |
|
||||
| P2-B4 colony + movement (behavioral) | phase2 | in-progress | — | 0% | 2026-09-08 | offline lane + Ghidra: verify ServerSystem::ProcessTurn / MoveFleet signatures (unverified), then hook vs game/sim colony+movement; RNG-snapshot design (colony consumes RNG for plague/rebellion) |
|
||||
| P2-B4 colony + movement (behavioral) | phase2 | code-complete | high | 80% | 2026-09-08 | offline+Ghidra done: all 3 prototypes VERIFIED from the instruction stream (ProcessTurn takes NO args - the decompile's 2nd param is a Ghidra fiction) and written back to the project; 22 formula corrections (growth curve has no pop/cap term; range grace is +0.05 not -0.05; jump SCATTERS not stops; ntdev not rbtn; ties-to-even rounding; stutter overlap is not a midpoint); ONLY ProcessRebellion draws RNG in a colony turn, so the generator region has teeth. 3 hooks + 2 host-tested adapters staged in /srv/re-lab/shim/dist-b4 (b4-646e4e8-dirty-20260908T0447Z), ctest 30/30. REMAINING: VM140 window - scout/trace/compare per docs/B4.md. No replace mode (input boundary) |
|
||||
| harness gap: undeclared side-effect lists | verify | backlog | — | 0% | 2026-09-08 | B3's replace-oracle failed on one unposted event while compare passed, because the player's EVENT list was never a declared region. Every hook that can post events or append to a list must declare that list, else compare gives false confidence. Audit B1/B2/M2 descriptors for the same blind spot |
|
||||
|
|
|
|||
|
|
@ -195,3 +195,138 @@ From the `ProcessResearch` trace/compare/replace runs (engine repo `docs/B3.md`;
|
|||
`EvNxID`. A replace-mode run that sets only the flag differs from the oracle by exactly this one
|
||||
event and nothing else in 40,300 save items.
|
||||
* Tech-tree size in this game: **293 nodes** per player tree.
|
||||
|
||||
---
|
||||
|
||||
## B4 (2026-09-08) — colony turn + fleet movement re-read instruction by instruction
|
||||
|
||||
Prompted by the old-vs-new milestone for `ServerSystem::ProcessTurn` and
|
||||
`MoveFleet`/`ProcessFleetMovement` (engine repo `docs/B4.md`). Evidence: own `objdump -d` pass
|
||||
over `Sword of the Stars.exe`. Every entry below is now in `ghidra/addresses.json` (status
|
||||
`verified`, 113 new entries) and the three target prototypes plus six helpers were written back
|
||||
into the Ghidra project.
|
||||
|
||||
### Prototypes (all three were `unverified`; all three are now pinned)
|
||||
|
||||
* **`ServerSystem::ProcessTurn` 0x007598e0 takes NO arguments.** Plain `ret`, nothing reads
|
||||
`[ebp+8]`. `turn-decompiles/*/007598e0.c` shows a second parameter `void* stream`; that is a
|
||||
Ghidra guess and it is wrong. Hooking it as a one-argument function corrupts the stack.
|
||||
* **`MoveFleet` 0x007d9ee0 is `bool __thiscall (StrategyServer*, StarFleet*, float dt)`,
|
||||
`ret 8`.** `dt` is a 4-byte float (`fld DWORD`), pushed at every call site with
|
||||
`push ecx; fstp DWORD PTR [esp]`. Returns AL, and the caller tests it.
|
||||
* **`ProcessFleetMovement` 0x007da9a0 is `void __thiscall (StrategyServer*)`**, plain `ret`.
|
||||
|
||||
### Movement — where §4 was wrong
|
||||
|
||||
* **Q7 revisited.** `BuildStutterSegments` does **not** merge overlaps at the midpoint. When
|
||||
`seg[i].end > seg[i+1].start` it sets *both* boundaries to
|
||||
`float32(end_i + 0.5 x (end_i − start_{i+1}))` — the mirror of the midpoint about `end_i`,
|
||||
pushed forward past both chords. Nothing is dropped and nothing is clipped back, so a chord
|
||||
swallowed by its predecessor comes out inverted (`start > end`). The chord parameters are also
|
||||
clamped to `[0, length]` before the drop test (the note omitted this; without it the
|
||||
ray/sphere routine's `±FLT_MAX` sentinels poison the list), the drop threshold is
|
||||
`fabs(start−end) <= 0.01f` (float32, inclusive), and the sort is a real `std::sort` on `start`
|
||||
alone. There is genuinely no clamp on `dist/RADIUS`, as the note said — but after the merge
|
||||
`dist <= RADIUS` is no longer guaranteed, so the ramp can exceed MAX.
|
||||
* **`STUTTER_MIN_SPEED == STUTTER_MAX_SPEED == 0.33` in the shipped data** (radius 2), so the
|
||||
ramp collapses to a constant 0.33x inside any sphere and 1.0x outside. The image bytes for all
|
||||
three constants are zero (they live past `.data`'s file image), so a run that skips the config
|
||||
load divides by zero.
|
||||
* **`range = MinRange(fleet) + 0.05f`, not `− 0.05`.** 0x00a1d2c0 is `0x3d4ccccd` (sign bit
|
||||
clear) and `MinRange` *adds* its argument. The out-of-range case zeroes the **range**, not the
|
||||
step — `step` remains the divisor of the pass fraction. `move = min(min(range, step), distance)`
|
||||
with **no floor at 0**. `MinRange` seeds with `FLT_MAX` (an empty fleet is unconstrained) and
|
||||
skips no ship, so a range-exempt tanker still clamps the fleet.
|
||||
* **The probabilistic jump (type 5) scatters, it does not stop part-way.** `v = float32(roll x
|
||||
CstE)`; it arrives iff `!(v > CstT)` (equality arrives); on a miss the fleet is placed at
|
||||
`dest + randomUnitVector x v`, which costs a **second** raw draw. 1 word on success, 2 on a
|
||||
miss. `CstE` is `player+0x154`, `CstT` `player+0x158`. No fuel and no clamp on this path, and
|
||||
the pass fraction is 1.0 either way.
|
||||
* **`IsNodeWaypoint` (0x0056e720) is true for type 3 only**; the node-*line* case of the switch
|
||||
is type 2. `IsGateTransitWaypoint` (0x0056e6e0) is true for 4 and 5. Only a type-3 waypoint
|
||||
reports a partial pass fraction (`clamp01(distance/step)`); a blocked move reports
|
||||
`clamp01(move/step)`; everything else reports 1.0.
|
||||
* **The recursion threshold at 0x00a261f0 is an 8-byte double whose value is exactly
|
||||
`(double)0.9999f`** = 0.9998999834060669, and the test is strict, so `fraction == threshold`
|
||||
does not recurse. `dt' = float32((1 − fraction) x dt)`.
|
||||
* **§4.2's bucketing is wrong.** The schedule is a **pursuit model**: classify every fleet whose
|
||||
current waypoint targets another *fleet* by the owner-to-owner relation (0 = pursuer, else
|
||||
follower); prey move 0.5, pursuers move 0.5 and a pursuer that arrives retires itself and its
|
||||
prey, surviving prey take a second 0.5, everything unscheduled takes 1.0 (an uncaught pursuer
|
||||
takes another 0.5), followers take 1.0. One of the six local containers is never inserted into
|
||||
and its two guards are vacuous — it can be deleted from any reimplementation.
|
||||
* **`FPogn2` at `fleet+0xec` is really `FPdpos`** (FlightPlan+0x28); `FPogn2` is at `+0xe0`.
|
||||
The pass writes the current waypoint target's position there, with no waypoint-type and no
|
||||
entity-kind check, and clears flag `0x2` on every fleet in the same loop. Flag `0x100` is
|
||||
cleared for every fleet in a final loop.
|
||||
* **Gate traffic** sums a **signed int16** at `fleet+0xc0` over fleets whose *front* waypoint is
|
||||
a gate transit, into a fixed 32-int accumulator indexed by `player+0x28`, then **assigns** it
|
||||
to `player+0x14c` indexed by the player's *position* in the server's vector — the two agree
|
||||
only while `players[j]->index == j`. `ProcessFleetMovement` makes no RNG draw of its own.
|
||||
|
||||
### Colony — where §3 was wrong
|
||||
|
||||
* **The population growth curve has no `pop/cap` term.** §3.2's
|
||||
`g = clamp01((1 − clamp01(pop/cap))^EXP)` is wrong: the capacity never enters the chain
|
||||
(0x00748100 → 0x00537140 → 0x00536fb0). The base is a suitability term,
|
||||
`1 − clamp01(min(|ideal − clamp(suit, 0, 20)|, SuitTol) / SuitTol)`, the exponent is clamped
|
||||
into `[0.01f, 1000]` before a real `__CIpow`, and every modifier after it is gated on a strict
|
||||
`> 0` and stored back to float32. `delta = trunc(pop x g)`, forced to 1 only when that
|
||||
truncates to 0 with `g > 0`. A zero `SuitTol` makes the quotient 0/0 and the NaN wipes the
|
||||
colony — a real hazard.
|
||||
* **The 50,000,000 cap and the 100 floor live in the apply (0x0074b230), not in the growth.**
|
||||
The over-cap shrink runs only when the colony was *already* over the cap and is computed from
|
||||
the **old** population; a colony that merely grows past the cap lands exactly on it.
|
||||
* **`AccrueSystemBonus`'s second gate is `ntdev` (+0x2c4), not `rbtn`** — §3.2 said `rbtn`; Q4
|
||||
said `ntdev` and Q4 was right. Both bonus-apply helpers (0x00746780, 0x0074b510) **reset
|
||||
`ntdev` to 0** on a colony that is not the owner's home system (`player+0x2c`), which is a real
|
||||
feedback loop: a colony still absorbing a bonus never reaches the gate. `ApplyInfraBonus` snaps
|
||||
`Infra` to **exactly 1.0f** when the pool covers the remainder; `ApplyPopBonus` drops the whole
|
||||
pool on an unowned system; `pbon` (+0x194) is an **int32**.
|
||||
* **The unowned infra decay constant at 0x009e9170 is `(double)0.02f`** = 0.019999999552965164,
|
||||
not the decimal, and the floor is `Infra <= 0 → 0` (inclusive; NaN also collapses to 0).
|
||||
* **§3.1's `0x007514f0` row is wrong.** The globals are not `DAT_00aeca78`/`7c`; the only global
|
||||
read is **0x00aeca80, a hard-coded `float 0.05f`** with no GlobalConst key. The helper takes
|
||||
four arguments — `(0, 1, indi->indsp, 0.05f)` then `(1, 0, indi->indsp, 0.05f)`.
|
||||
* **§3.1's addiction row is misleading.** Player flag bit 5 (temperance) does not skip the block:
|
||||
it takes the other branch and still raises morale event `0x1b` (−1). Bit 5 *clear* runs the
|
||||
phase path: `0x1c` (+1) at onset, **nothing at all** in phase 2, `0x1d` (−2) at terminal. Both
|
||||
phase comparisons are strict `>`. `0x00752a10` is the MoraleEvent **constructor**; the apply is
|
||||
**0x00839d60**, and the delta travels in `ev->deltas[species]` (int[7] at ev+0x18), not as an
|
||||
argument.
|
||||
* **§3.1's call table omits `TRes = 0` (+0x74) and the `haltv[0..2] = false` clear (+0x78).**
|
||||
* **RNG, and this is the load-bearing one for any oracle:** `ProcessTurn` itself, `ProcessPlague`,
|
||||
`GrowCivilianPops` and `ProcessSlaves` are **all draw-free** (swept to call depth one).
|
||||
**`ProcessRebellion` is the sole consumer in a colony turn**, and its count is data-dependent:
|
||||
one `RandChance` per iteration of a 64-bit rebel counter (0x0074fbe0), a short-circuiting
|
||||
per-species roll loop (0x00753c60), and one outcome roll (0x00756350), plus one 0.2f
|
||||
continuation roll. `RNG::Chance` (0x008e6dd0) makes **no** draw for `p <= 0` or `p >= 1`.
|
||||
The generator is reached as `*(RNG**)((char*)sys->owner + 0x168)` — Ghidra's
|
||||
"StrategyServer+0x16c" is relative to the −4-adjusted base.
|
||||
* **`ServerSystem::MaxPop` 0x0074ab20 is `(ServerPlayer* p, int flag)`, not `(species, group)`.**
|
||||
Species comes from `p->Species` and the group type is hard-coded 0, which makes the
|
||||
cross-species and INDSYS branches dead in that specialisation. The result is clamped to
|
||||
`[0, INT32_MAX]`. **Every capacity is rounded down to a multiple of 10** by the shared helper
|
||||
0x00535eb0, and `Size x 1e8` is an exact 64-bit *integer* product (the 1e8 is the immediate
|
||||
0x05f5e100). The arcology bonus is 0 for slaves.
|
||||
* **`ComputeOutputFromRates` corrections.** `NormaliseOutputRates` (0x00747390) is `__cdecl` with
|
||||
a third *pinned channel* argument that every call site leaves null, selecting trade: only trade
|
||||
is clamped to `[0,1]`, the other three are summed in float32 (trade excluded) and rescaled to
|
||||
`1 − trade`, and the all-zero fallback is an equal split over **three** channels. The engine's
|
||||
"round" (0x008e5660) is `fistp`/`fild` — **ties to even** — while `out[0]`, `out[3]` and the
|
||||
construction points use the truncating `_ftol2`. `out[1]` is `min(out[2], stripMineDemand)`,
|
||||
not a shortfall; `out[9]` is the amount **spent** on repairs. **Unspent terraforming points
|
||||
cascade into the money channel** (an edge the notes missed entirely). The terraforming modifier
|
||||
is inside the *point count* (0x00746890), the sign is `-1` only for `suit > ideal` strictly, and
|
||||
the infra chain is `spend/500 x 0.01 x 1.65` in three 80-bit steps — not one `x3.3e-5`.
|
||||
**The function repairs damaged ships in orbit** (0x00751590 with its estimate flag clear), so it
|
||||
is not side-effect free and cannot be compared on a scratch system.
|
||||
* **`BuildQueue::ProcessTurn` 0x00890d50** takes `points` by value and **returns the leftover**.
|
||||
A money refusal **skips** that order and continues rather than stopping the pass; removal is a
|
||||
separate sweep afterwards that unlinks every order with `conleft <= 0`.
|
||||
* **Slaves.** The term order is `((|Δsuit| x BYHAZARD + DEATH_RATE) + SRs x BYOUTPUT) x mod`, every
|
||||
step narrowed to float32; an unowned system returns **1.0**, not 0; the worst plague at the
|
||||
system contributes an **additive** rate term; and `SLAVES_MIN/MAX_DEATHS` are each disabled by
|
||||
**any** negative value, with the result clamped into `[0, adjustedSlaveCount]`.
|
||||
* **`HazardMod`'s 0.1 (0x00a1a438) is a true double**, not `(double)0.1f`, and a zero band at the
|
||||
ideal returns NaN (which the capacity's `max(v,0)` then turns into 0).
|
||||
|
|
|
|||
|
|
@ -283,6 +283,20 @@ tree roll from 0x005822d0). MEDIUM: cost-multiplier trio identity, accident odds
|
|||
|
||||
## 3. Colonies (`Game::ServerSystem::ProcessTurn` 0x007598e0)
|
||||
|
||||
> **B4 CORRECTIONS (2026-09-08).** This section was re-read instruction by instruction for the
|
||||
> old-vs-new milestone; the full list is in `formula-gaps.md` ("B4"). The load-bearing ones:
|
||||
> `ProcessTurn` takes **no arguments** (the decompile's `void* stream` is a Ghidra guess); the
|
||||
> growth curve in §3.2 has **no `pop/cap` term** (the base is a suitability ratio); the second
|
||||
> `SYSTEMBONUS_MINTURNS` gate is **`ntdev`, not `rbtn`**, and both bonus-apply helpers reset
|
||||
> `ntdev` on a non-home colony; the `0x007514f0` row's globals are wrong (it reads a hard-coded
|
||||
> `float 0.05f` at 0x00aeca80 and takes four arguments); the addiction row is misleading
|
||||
> (temperance still raises event 0x1b, and phase 2 raises nothing); the unowned decay constant is
|
||||
> `(double)0.02f`; every capacity is quantised down to a multiple of 10; and **the only RNG
|
||||
> consumer in a colony turn is `ProcessRebellion`** — `ProcessTurn`, `ProcessPlague`,
|
||||
> `GrowCivilianPops` and `ProcessSlaves` are all draw-free. §3.1's call table also omits
|
||||
> `TRes = 0` (+0x74) and the `haltv[0..2] = false` clear (+0x78).
|
||||
|
||||
|
||||
### 3.1 Function map (in call order)
|
||||
| addr | name / *proposed* | what |
|
||||
|---|---|---|
|
||||
|
|
@ -397,6 +411,20 @@ per the enum in §0 (resolved).
|
|||
|
||||
## 4. Movement
|
||||
|
||||
> **B4 CORRECTIONS (movement) (2026-09-08).** Re-read instruction by instruction; full list in
|
||||
> `formula-gaps.md` ("B4"). §4.2's bucketing is wrong — the schedule is a **pursuit model**
|
||||
> (prey 0.5, pursuers 0.5 with an arrival retiring the pair, surviving prey 0.5, everything else
|
||||
> 1.0 with an uncaught pursuer taking another 0.5, followers 1.0). `range = MinRange + 0.05f`
|
||||
> (**added**, not subtracted), and the out-of-range case zeroes the **range**, not the step.
|
||||
> `move` has **no floor at 0**. The type-5 jump **scatters the fleet around the destination** by
|
||||
> `float32(roll x CstE)` on a miss, at the cost of a second draw — it does not stop part-way
|
||||
> along the vector — and it arrives on equality. `IsNodeWaypoint` is true for type **3 only**.
|
||||
> The recursion threshold is `(double)0.9999f` and the test is strict. `fleet+0xec` is `FPdpos`,
|
||||
> not `FPogn2`. Gate traffic is a **signed int16** per fleet. The stutter overlap rule is
|
||||
> **not** a midpoint (see Q7 in `formula-gaps.md`), and `STUTTER_MIN_SPEED == STUTTER_MAX_SPEED`
|
||||
> in the shipped data, so the ramp is a constant 0.33x.
|
||||
|
||||
|
||||
### 4.1 Function map
|
||||
| addr | name | role |
|
||||
|---|---|---|
|
||||
|
|
|
|||
|
|
@ -1154,22 +1154,6 @@
|
|||
"status": "verified",
|
||||
"source": "handoff/formula-gaps.md#q4"
|
||||
},
|
||||
{
|
||||
"name": "NodeLine_Step",
|
||||
"addr": "0x00705510",
|
||||
"convention": "cdecl",
|
||||
"prototype": "void (Vector3* posOut, bool* arrivedOut, float nodespeed, float dt, void* lines, Vector3* from, Vector3* to)",
|
||||
"status": "unverified",
|
||||
"source": "handoff/formula-gaps.md#q7"
|
||||
},
|
||||
{
|
||||
"name": "NodeLine_BuildStutterSegments",
|
||||
"addr": "0x00705280",
|
||||
"convention": "cdecl",
|
||||
"prototype": "void (vector* segsOut, vector* systems, Vector3* from, Vector3* to)",
|
||||
"status": "unverified",
|
||||
"source": "handoff/formula-gaps.md#q7"
|
||||
},
|
||||
{
|
||||
"name": "g_TechIdNames",
|
||||
"addr": "0x009ff9e4",
|
||||
|
|
@ -1689,6 +1673,926 @@
|
|||
"prototype": "int -- number of rows in g_AITechValueTable (6)",
|
||||
"status": "verified",
|
||||
"source": "B2 own disassembly pass 2026-09-08 (ReVa read-memory + objdump -b binary -m i386): ServerPlayer::OnTechResearched 0x00891790, RebuildSpeciesTechFlags 0x0082bf10, ApplyAITechBonus 0x0080e330, SetAIBenefit 0x008186b0, UpdateNodeBoreParams 0x008182c0, SelectNodeBoreParams 0x006e18e0, GetPlagueCureMask 0x00537240"
|
||||
},
|
||||
{
|
||||
"name": "ServerPlayer_off_ServerLink",
|
||||
"offset": "0x8",
|
||||
"convention": "offset",
|
||||
"prototype": "void* -- the StrategyServer subobject pointer; StrategyServer = *(void**)(player+8) - 4. Its +0x16c is the Mars::RNG* the strategic sim draws from, and its +8 the event manager",
|
||||
"status": "verified",
|
||||
"source": "B2 own disassembly pass 2026-09-08 (ReVa read-memory + objdump -b binary -m i386): ServerPlayer::RollResearchEvent 0x0088df20, ResearchEventOdds 0x00820380, ServerPlayer::OnTechResearched 0x00891790"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_off_RNG",
|
||||
"offset": "0x16c",
|
||||
"convention": "offset",
|
||||
"prototype": "Mars::RNG* -- the strategic generator (same object TechTree::ProcessResearch is handed)",
|
||||
"status": "verified",
|
||||
"source": "B2 own disassembly pass 2026-09-08 (ReVa read-memory + objdump -b binary -m i386): ServerPlayer::RollResearchEvent 0x0088df20, ResearchEventOdds 0x00820380, ServerPlayer::OnTechResearched 0x00891790"
|
||||
},
|
||||
{
|
||||
"name": "ServerPlayer_RollResearchEvent",
|
||||
"addr": "0x0088df20",
|
||||
"convention": "fastcall",
|
||||
"prototype": "void (ServerPlayer* this) -- odds = ResearchEventOdds(this, this->ResT); draws EXACTLY ONE NextFloat from StrategyServer's generator, unconditionally, then fires 0x00889d60 when odds > roll. Called from OnTechResearched when the completing def is the current research target and the pending-roll byte at +0x3b4 is set. This is the extra RNG draw B3 observed on a completion",
|
||||
"status": "verified",
|
||||
"source": "B2 own disassembly pass 2026-09-08 (ReVa read-memory + objdump -b binary -m i386): ServerPlayer::RollResearchEvent 0x0088df20, ResearchEventOdds 0x00820380, ServerPlayer::OnTechResearched 0x00891790"
|
||||
},
|
||||
{
|
||||
"name": "ServerPlayer_ResearchEventOdds",
|
||||
"addr": "0x00820380",
|
||||
"convention": "thiscall",
|
||||
"prototype": "float (ServerPlayer* this, TechDef* def) -- 0 when def is null; a plague-family path via 0x00535480, else the AI-rebellion path via AITechRow (odds column) gated on !NPC. Read-only, makes no draw",
|
||||
"status": "verified",
|
||||
"source": "B2 own disassembly pass 2026-09-08 (ReVa read-memory + objdump -b binary -m i386): ServerPlayer::RollResearchEvent 0x0088df20, ResearchEventOdds 0x00820380, ServerPlayer::OnTechResearched 0x00891790"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ProcessTurn",
|
||||
"addr": "0x007598e0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this) /* NO stack arguments -- plain RET, nothing reads [ebp+8]; Ghidra's decompile shows a spurious second parameter. Body order: unowned Infra decay -> ApplyInfraBonus -> ApplyPopBonus -> independent pop drift -> IsStable/ntdev -> AccrueSystemBonus -> ProcessPlague -> ProcessBuildQueue -> imperial growth -> civilian growth -> AdjustResources(-out[2]) -> TRes=0 -> RefuelInOrbit(1) -> Bats2 tick -> rcex tick -> haltv[0..2]=false -> ProcessSlaves -> ProcessRebellion -> addiction sweep. Consumes no RNG itself; ProcessPlague / civilian growth / ProcessSlaves are draw-free to depth 1, and ProcessRebellion is the only consumer */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_MoveFleet",
|
||||
"addr": "0x007d9ee0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "bool (StrategyServer* this, StarFleet* fleet, float dt) /* RET 8; dt is a 4-byte float pushed with fstp DWORD [esp]; returns AL, true only when the fleet ends exactly on a waypoint destination at the deepest recursion level. range = MinRange(fleet, +0.05f) -- ADDED, not subtracted; out of range with MinRange(0)==0 zeroes the RANGE, not the step; move = min(min(range, step), distance) with no floor at 0; recursion iff fraction < (double)0.9999f with dt' = float32((1-fraction)*dt) */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_ProcessFleetMovement",
|
||||
"addr": "0x007da9a0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (StrategyServer* this) /* no stack args, plain RET. Pursuit schedule, not a departing/in-transit split: classify every fleet whose current waypoint targets a fleet by owner relation (0 = pursuer, else follower); pass1 prey dt 0.5, pass2 pursuers dt 0.5 (an arrival retires the pair), pass3 remaining prey dt 0.5, pass4 everything unscheduled dt 1.0 (an uncaught pursuer gets 0.5), pass5 followers dt 1.0. Then FPdpos, gate traffic, OnFleetArrived, and clears flag 0x100 on every fleet. Makes no RNG draw of its own */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_MinRange",
|
||||
"addr": "0x006ff6a0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "float (StarFleet* this, float bias) /* RET 4; min over ships of ship->Range seeded with FLT_MAX (an empty fleet is unconstrained), then + bias, narrowed to float32. No ship is skipped -- range-exempt tankers still clamp the fleet */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_HasAllFlags",
|
||||
"addr": "0x006fe1d0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "bool (StarFleet* this, uint32 mask) /* (flags & mask) == mask, flags at fleet+0x10c */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_SetFlag",
|
||||
"addr": "0x006fe1a0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (StarFleet* this, uint32 mask, bool on) /* the only two writers of fleet+0x10c in the image */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_ResolveWaypoint",
|
||||
"addr": "0x00701390",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void* (StarFleet* this) /* no args; NULL when the waypoint vector is empty or the front waypoint's target id does not resolve in the entity hash at fleet->galaxy(+0x10)+0x80 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "IsGateTransitWaypoint",
|
||||
"addr": "0x0056e6e0",
|
||||
"convention": "cdecl",
|
||||
"prototype": "bool (int waypointType) /* 7-entry jump table: true only for 4 and 5; false default */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "IsNodeWaypoint",
|
||||
"addr": "0x0056e720",
|
||||
"convention": "cdecl",
|
||||
"prototype": "bool (int waypointType) /* 7-entry jump table: true only for 3. NOTE the node-LINE case of the movement switch is type 2, which this does NOT accept */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ProbabilisticJump",
|
||||
"addr": "0x007b6700",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (StrategyServer* this, StarFleet* fleet, void* dest) /* waypoint type 5. v = float32(NextFloat() * player->CstE); arrives iff !(v > player->CstT) (equality arrives); on a miss the fleet is placed at dest + randomUnitVector * v -- scattered AROUND the destination by v, not advanced a fraction along the vector -- which costs a second raw draw. 1 draw on success, 2 on a miss */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "NodeLine_Step",
|
||||
"addr": "0x00705510",
|
||||
"convention": "cdecl",
|
||||
"prototype": "void (Vector3* posOut, bool* arrivedOut, float nodespeed, float dt, vector<StarSystem*>* systems, const Vector3* from, const Vector3* to) /* builds the stutter segments, reverses them and pops from the back (so ascending by start); plain nodespeed between spheres, a constant per-segment speed inside one; arrived = (time < dt) || |along - length| < FLT_EPSILON, and on arrival the destination is copied verbatim */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "NodeLine_BuildStutterSegments",
|
||||
"addr": "0x00705280",
|
||||
"convention": "cdecl",
|
||||
"prototype": "void (vector<StutterSegment>* out, vector<StarSystem*>* systems, const Vector3* from, const Vector3* to) /* chord parameters scaled to world distance and clamped to [0, length]; a chord with |start-end| <= 0.01f is dropped; std::sort ascending by start; then ONE forward pass over adjacent pairs sets BOTH boundaries of an overlap to end_i + 0.5*(end_i - start_{i+1}) -- the mirror of the midpoint, pushed forward past both chords. Nothing is dropped or clipped back, so a swallowed chord comes out inverted */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "SegmentSphereIntersect",
|
||||
"addr": "0x008a64f0",
|
||||
"convention": "cdecl",
|
||||
"prototype": "bool (float* tNear, float* tFar, const Sphere4* s, const Vector3* from, const Vector3* to) /* wraps the quadratic solver 0x008a62c0; rejects a sphere the segment does not reach and reports an open end as -FLT_MAX / +FLT_MAX */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "DistPointToSegment",
|
||||
"addr": "0x008e8eb0",
|
||||
"convention": "cdecl",
|
||||
"prototype": "float (const Vector3* p, const Vector3* a, const Vector3* b) /* projection parameter clamped to [0,1]. NOTE 0x008c8eb0 is a varargs formatter, not this */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_MaxPop",
|
||||
"addr": "0x0074ab20",
|
||||
"convention": "thiscall",
|
||||
"prototype": "int (ServerSystem* this, ServerPlayer* p, int flag) /* RET 8 -- (player, flag), NOT (species, groupType). Species is derived from p->Species and the group type is hard-coded to 0, which makes the cross-species and INDSYS branches dead in this specialisation. Returns the int64 result clamped to [0, INT32_MAX], low dword only */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_MaxPopGeneric",
|
||||
"addr": "0x0074a4a0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "int64 (ServerSystem* this, int groupType, int species, ServerPlayer* p, float* suitOverride) /* RET 0x10 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_IsStable",
|
||||
"addr": "0x0074ad90",
|
||||
"convention": "thiscall",
|
||||
"prototype": "bool (ServerSystem* this) /* false without an owner, with Infra < 1.0, or with Suit != IdealSuit */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ApplyInfraBonus",
|
||||
"addr": "0x00746780",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this) /* returns early unless ibon > 0 and Infra < 1; resets ntdev to 0 when the system is not the owner's home system; applied = min(ibon, float32(1 - Infra)); Infra becomes EXACTLY 1.0f when applied == the remainder, else float32(Infra + applied); ibon -= applied */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ApplyPopBonus",
|
||||
"addr": "0x0074b510",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this) /* nothing unless pbon > 0; an unowned system drops the whole pool; returns when Pop >= MaxPop; resets ntdev for a non-home system; Pop += min(cap - Pop, pbon); pbon -= same. Pop and pbon are int32 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ApplyInfraDelta",
|
||||
"addr": "0x00748270",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this, float delta) /* no-op once Infra >= 1; clamps to 1 and re-normalises the system's own output rates when it lands there */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ApplySuitDelta",
|
||||
"addr": "0x007481c0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this, float delta) /* clamps at the ideal from whichever side it approached, so suitability never overshoots; re-normalises the rates when it lands exactly on the ideal */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ComputeOutputFromRates",
|
||||
"addr": "0x00751bb0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this, int out[12], float rates[7]) /* RET 8. `out` is 12 dwords of MIXED type: 0 total (truncated), 1 strip-mined resources, 2 resources consumed, 3 money, 7 gross construction, 8 points to the queue, 9 points SPENT on repairs, 10 float32 infra delta, 11 float32 suitability delta. `rates` is copied to the stack first, so the caller's struct is untouched. NOT side-effect free: it repairs damaged ships in orbit via 0x00751590(points, estimateOnly=0) */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_NormaliseOutputRates",
|
||||
"addr": "0x00747390",
|
||||
"convention": "cdecl",
|
||||
"prototype": "void (float rates[7], ServerSystem* sys, float* pinned) /* `pinned` defaults to &rates[0] (trade) and every call site passes NULL or that. Suppress terraform at the ideal (exact ==) and infra when float32(ibon+Infra) >= 1; zero any channel <= (double)1e-4f; clamp ONLY the pinned channel to [0,1]; sum the other three in float32; an exactly-zero sum seeds them with 1e-4f (honouring the suppressions); each becomes (r/sum)*(1-pinned) */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ProcessBuildQueue",
|
||||
"addr": "0x00752500",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this, int* resourcesConsumedOut) /* computes the turn's output vector, writes out[2] (resources consumed) through the pointer, applies out[11] via ApplySuitDelta and out[10] via ApplyInfraDelta, and feeds out[8] to BuildQueue::ProcessTurn. Increments TnsOH while SRoh > 0 && out[1] > 0 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "BuildQueue_ProcessTurn",
|
||||
"addr": "0x00890d50",
|
||||
"convention": "thiscall",
|
||||
"prototype": "int (BuildQueue* this, ServerSystem* sys, int points) /* RET 8; `points` is BY VALUE and the leftover is the RETURN value. An order needing more than what is left absorbs everything and stops the pass; a design that costs money asks this->vft[9](sys, (int64)cost) and a refusal SKIPS that order and continues rather than stopping. Removal is a separate sweep afterwards that unlinks every order with conleft <= 0 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_AdjustResources",
|
||||
"addr": "0x00745f30",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this, int delta, int mode) /* RET 8; ProcessTurn passes -out[2] with mode 0 when the owner has AMine, else mode 3. Mode 3 takes it all from Res; mode 0 splits it proportionally over Res / ARes2 / MRes */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_PopGrowthDelta",
|
||||
"addr": "0x00748100",
|
||||
"convention": "thiscall",
|
||||
"prototype": "int64 (ServerSystem* this, int groupType, int species) /* RET 8; 0 without an owner or when haltv[groupType] is set */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "PopGrowthFraction",
|
||||
"addr": "0x00536fb0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "float (ServerPlayer* p, int groupType, int species, float suit, float factor) /* the growth curve. base = 1 - clamp01(min(|ideal - clamp(suit,0,20)|, SuitTol) / SuitTol) -- there is NO pop/capacity term anywhere; g = clamp01(pow(base, clamp(POPULATION_GROWTH_EXP, 0.01f, 1000))) then x MOD x PopMod x factor x groupdef[+4], each gated on a strict > 0 and each stored back to a float32 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_SlaveDeathRate",
|
||||
"addr": "0x0074b110",
|
||||
"convention": "thiscall",
|
||||
"prototype": "float (ServerSystem* this, int species) /* RET 4; 1.0 when unowned. mod = (bit0 ? 0.8f : 1) - 0.2*bit1 - 0.2*bit2, no clamp; rate = ((|Ideal-Suit| x BYHAZARD + DEATH_RATE) + SRs x BYOUTPUT) x mod, every step narrowed to float32 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ProcessSlaves",
|
||||
"addr": "0x007537b0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this) /* the worst plague's rate is ADDED to the death rate; SLAVES_MIN/MAX_DEATHS are each disabled by ANY negative value; deaths are clamped into [0, adjusted slave count]. Consumes no RNG */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ProcessPlague",
|
||||
"addr": "0x00756a90",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this) /* consumes no RNG, at depth 1 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_ProcessRebellion",
|
||||
"addr": "0x007583b0",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this) /* the ONLY RNG consumer in a colony turn, and its draw count is data-dependent: one RandChance per iteration of a 64-bit rebel counter (0x0074fbe0), a short-circuiting per-species roll loop (0x00753c60), one outcome roll (0x00756350) and one 0.2f continuation roll */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_GrowCivilianPops",
|
||||
"addr": "0x00754220",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerSystem* this) /* consumes no RNG, at depth 1 */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "RNG_Chance",
|
||||
"addr": "0x008e6dd0",
|
||||
"convention": "stdcall",
|
||||
"prototype": "bool (RNG* this /*ecx, the object*/, float p) /* p <= 0 -> false and p >= 1 -> true, both WITHOUT a draw; otherwise exactly one NextFloat and `r < p` */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerPlayer_AddMoraleEvent",
|
||||
"addr": "0x00839d60",
|
||||
"convention": "thiscall",
|
||||
"prototype": "void (ServerPlayer* this, MoraleEvent* ev, ServerSystem* sys) /* the actual apply. 0x00752a10 is only the MoraleEvent constructor; the per-species delta is carried in ev->deltas[species] (int[7] at ev+0x18), not as an argument */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "MoraleEvent_ctor",
|
||||
"addr": "0x00752a10",
|
||||
"convention": "thiscall",
|
||||
"prototype": "MoraleEvent* (MoraleEvent* this) /* 0x50 bytes: {vptr, ints (+0x10 = event id), vptr2 @+0x14, int deltas[7] @+0x18, std::string name @+0x34} */",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Owner",
|
||||
"offset": "0x00000010",
|
||||
"convention": "offset",
|
||||
"prototype": "StrategyServer* owner (the RAW base; the RNG accessor uses owner-4)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Idx",
|
||||
"offset": "0x0000005c",
|
||||
"convention": "offset",
|
||||
"prototype": "int Idx",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Size",
|
||||
"offset": "0x00000060",
|
||||
"convention": "offset",
|
||||
"prototype": "int Size (1..10); the capacity base is Size * 100000000 as an exact int64 product",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Suit",
|
||||
"offset": "0x00000064",
|
||||
"convention": "offset",
|
||||
"prototype": "float Suit",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Res",
|
||||
"offset": "0x00000068",
|
||||
"convention": "offset",
|
||||
"prototype": "int Res",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_ARes2",
|
||||
"offset": "0x0000006c",
|
||||
"convention": "offset",
|
||||
"prototype": "int ARes2",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_MRes",
|
||||
"offset": "0x00000070",
|
||||
"convention": "offset",
|
||||
"prototype": "int MRes",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_TRes",
|
||||
"offset": "0x00000074",
|
||||
"convention": "offset",
|
||||
"prototype": "int TRes -- zeroed every turn by ProcessTurn",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_haltv",
|
||||
"offset": "0x00000078",
|
||||
"convention": "offset",
|
||||
"prototype": "bool haltv[3] -- growth halt per group; cleared every turn by ProcessTurn",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_OutMod",
|
||||
"offset": "0x0000007c",
|
||||
"convention": "offset",
|
||||
"prototype": "float OutMod",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_TAcq",
|
||||
"offset": "0x00000080",
|
||||
"convention": "offset",
|
||||
"prototype": "int TAcq (turn acquired)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Rates",
|
||||
"offset": "0x00000088",
|
||||
"convention": "offset",
|
||||
"prototype": "StarSystem::OutputRates (0x1c): float SRt, SRsc, SRtf, SRi, SRoh, SRs; int SRnr",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_SRoh",
|
||||
"offset": "0x00000098",
|
||||
"convention": "offset",
|
||||
"prototype": "float SRoh -- the over-harvest slider (Rates + 0x10)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_BuildQueue",
|
||||
"offset": "0x000000a4",
|
||||
"convention": "offset",
|
||||
"prototype": "BuildQueue*",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Name",
|
||||
"offset": "0x000000a8",
|
||||
"convention": "offset",
|
||||
"prototype": "std::string Name (0x1c, MSVC SSO; capacity word at +0xbc)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Abdn",
|
||||
"offset": "0x000000c4",
|
||||
"convention": "offset",
|
||||
"prototype": "bool Abdn",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Bats2",
|
||||
"offset": "0x000000f0",
|
||||
"convention": "offset",
|
||||
"prototype": "int64 Bats2 -- player i's 4-bit battle-recent counter at bits [4i, 4i+4), i < 15",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Rcex",
|
||||
"offset": "0x000000f8",
|
||||
"convention": "offset",
|
||||
"prototype": "int64 rcex -- the same shape for the explored/recon-recent counter",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_PID",
|
||||
"offset": "0x00000100",
|
||||
"convention": "offset",
|
||||
"prototype": "ServerPlayer* PID (null = unowned)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Morale",
|
||||
"offset": "0x0000011c",
|
||||
"convention": "offset",
|
||||
"prototype": "Morale cm (0x20: vptr + int[7])",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Fleets",
|
||||
"offset": "0x0000016c",
|
||||
"convention": "offset",
|
||||
"prototype": "std::vector<StarFleet*>",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Pop",
|
||||
"offset": "0x0000018c",
|
||||
"convention": "offset",
|
||||
"prototype": "int Pop (imperial)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Infra",
|
||||
"offset": "0x00000190",
|
||||
"convention": "offset",
|
||||
"prototype": "float Infra",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_pbon",
|
||||
"offset": "0x00000194",
|
||||
"convention": "offset",
|
||||
"prototype": "int pbon -- the pending population bonus (int32, not a float)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_ibon",
|
||||
"offset": "0x00000198",
|
||||
"convention": "offset",
|
||||
"prototype": "float ibon -- the pending infrastructure bonus",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Pop2",
|
||||
"offset": "0x000001a0",
|
||||
"convention": "offset",
|
||||
"prototype": "Population Pop2 (civilians): {vptr, vector<PopulationGroup> @+4}, 24-byte entries {?, int type @+4, int species @+8, int64 count @+0x10}",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_pbon2",
|
||||
"offset": "0x000001b4",
|
||||
"convention": "offset",
|
||||
"prototype": "Population pbon2 -- the civilian analogue of pbon",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_Indi",
|
||||
"offset": "0x000001c8",
|
||||
"convention": "offset",
|
||||
"prototype": "IndependenceInfo* indi (int indsp at +4)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_rbfl",
|
||||
"offset": "0x000001dc",
|
||||
"convention": "offset",
|
||||
"prototype": "int rbfl -- rebelling-species bitmask",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_adt",
|
||||
"offset": "0x000001e4",
|
||||
"convention": "offset",
|
||||
"prototype": "int adt[7] -- per-species addiction start turn; 0 means never addicted",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_BatsMask",
|
||||
"offset": "0x000002a0",
|
||||
"convention": "offset",
|
||||
"prototype": "uint32 -- bit i is cleared when player i's Bats2 counter reaches 0",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_RcexMask",
|
||||
"offset": "0x000002a4",
|
||||
"convention": "offset",
|
||||
"prototype": "uint32 -- the same for rcex",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_TnsOH",
|
||||
"offset": "0x000002b8",
|
||||
"convention": "offset",
|
||||
"prototype": "int TnsOH (turns over-harvesting)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_ntdev",
|
||||
"offset": "0x000002c4",
|
||||
"convention": "offset",
|
||||
"prototype": "int ntdev -- turns developing; ++ when IsStable, reset to 0 otherwise AND by either bonus-apply helper on a non-home system. This is the second SYSTEMBONUS_MINTURNS gate, not rbtn",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerSystem_off_rbtn",
|
||||
"offset": "0x000002cc",
|
||||
"convention": "offset",
|
||||
"prototype": "int rbtn",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_off_ModCount",
|
||||
"offset": "0x00000008",
|
||||
"convention": "offset",
|
||||
"prototype": "int ModCount (the turn counter), relative to the RAW server base a ServerSystem's +0x10 points at",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_off_Players",
|
||||
"offset": "0x00000050",
|
||||
"convention": "offset",
|
||||
"prototype": "std::vector<ServerPlayer*> (begin @+0x50, end @+0x54); numPlayers = (end-begin)>>2",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_off_Fleets",
|
||||
"offset": "0x00000064",
|
||||
"convention": "offset",
|
||||
"prototype": "std::vector<StarFleet*> (begin @+0x64, end @+0x68) -- one flat global list, not per player",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_off_EntityHash",
|
||||
"offset": "0x00000084",
|
||||
"convention": "offset",
|
||||
"prototype": "16-bucket hash of entity id -> object, hashed by (key & 0xF); 0x008b9240 is the lookup",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_off_RNGPtr",
|
||||
"offset": "0x00000168",
|
||||
"convention": "offset",
|
||||
"prototype": "Mars::RNG* relative to the RAW base (== the -4-adjusted base's +0x16c)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_off_ArrivedSet",
|
||||
"offset": "0x00000204",
|
||||
"convention": "offset",
|
||||
"prototype": "std::set<pair<FleetId,LocationId>> cleared at the head of ProcessFleetMovement",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StrategyServer_off_InMotionSet",
|
||||
"offset": "0x00000214",
|
||||
"convention": "offset",
|
||||
"prototype": "std::set<pair<FleetId,LocationId>> that MoveFleet fills for fleets still in motion; OnFleetArrived takes the set difference",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_Id",
|
||||
"offset": "0x00000004",
|
||||
"convention": "offset",
|
||||
"prototype": "int id (also the entity-hash key)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_Galaxy",
|
||||
"offset": "0x00000010",
|
||||
"convention": "offset",
|
||||
"prototype": "the object whose +0x80 holds the entity hash the waypoint target is resolved in",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_Pos",
|
||||
"offset": "0x00000018",
|
||||
"convention": "offset",
|
||||
"prototype": "Vector3 Pos",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_PrvPos",
|
||||
"offset": "0x0000004c",
|
||||
"convention": "offset",
|
||||
"prototype": "Vector3 PrvPos -- set to the ENTRY position when the fleet moved",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_PID",
|
||||
"offset": "0x00000058",
|
||||
"convention": "offset",
|
||||
"prototype": "ServerPlayer* owner",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_Location",
|
||||
"offset": "0x000000a0",
|
||||
"convention": "offset",
|
||||
"prototype": "Location*; kind at Location+0x14 (0 system, 1 fleet, 2 point)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_Ships",
|
||||
"offset": "0x000000a4",
|
||||
"convention": "offset",
|
||||
"prototype": "std::vector<StarShip*> (begin @+0xa4, end @+0xa8)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_GateTraffic",
|
||||
"offset": "0x000000c0",
|
||||
"convention": "offset",
|
||||
"prototype": "int16 -- SIGNED, summed into the owner's gate traffic",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_Waypoints",
|
||||
"offset": "0x000000c8",
|
||||
"convention": "offset",
|
||||
"prototype": "std::vector<Waypoint> _Myfirst (proxy @+0xc4, last @+0xcc, end @+0xd0)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_Speed",
|
||||
"offset": "0x000000d8",
|
||||
"convention": "offset",
|
||||
"prototype": "float FPsp2 -- the fleet's strategic speed",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_DestPos",
|
||||
"offset": "0x000000ec",
|
||||
"convention": "offset",
|
||||
"prototype": "Vector3 -- set after every pass to the current waypoint target's position. The notes called this FPogn2; by the FlightPlan layout it is FPdpos",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarFleet_off_Flags",
|
||||
"offset": "0x0000010c",
|
||||
"convention": "offset",
|
||||
"prototype": "uint32; bit 0x100 = held this turn (cleared for every fleet at the end of ProcessFleetMovement), bit 0x2 cleared in the destination pass, bit 0x1 set by MoveFleet when the fleet moved",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "Waypoint_stride",
|
||||
"offset": "0x0000001c",
|
||||
"convention": "offset",
|
||||
"prototype": "sizeof(Waypoint) -- pinned by the divide-by-28 reciprocal multiply in the iterator arithmetic",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "Waypoint_off_Target",
|
||||
"offset": "0x00000004",
|
||||
"convention": "offset",
|
||||
"prototype": "int -- the destination entity id",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "Waypoint_off_Type",
|
||||
"offset": "0x00000008",
|
||||
"convention": "offset",
|
||||
"prototype": "int -- 2 node line, 3 node route, 4 gate teleport, 5 probabilistic jump, otherwise a straight run",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarShip_off_Flags",
|
||||
"offset": "0x00000018",
|
||||
"convention": "offset",
|
||||
"prototype": "uint64 flag pair; bit 0x1000 exempts the ship from movement fuel and marks it a tanker",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarShip_off_Range",
|
||||
"offset": "0x00000020",
|
||||
"convention": "offset",
|
||||
"prototype": "float Range -- remaining strategic range",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "StarShip_off_MaxRange",
|
||||
"offset": "0x00000078",
|
||||
"convention": "offset",
|
||||
"prototype": "float -- the cap the refuel helper clamps Range to",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerPlayer_off_HomeSystem",
|
||||
"offset": "0x0000002c",
|
||||
"convention": "offset",
|
||||
"prototype": "ServerSystem* -- the bonus-apply helpers skip the ntdev reset for this system",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerPlayer_off_GateTraffic",
|
||||
"offset": "0x0000014c",
|
||||
"convention": "offset",
|
||||
"prototype": "int GTraf -- assigned (not accumulated) once per turn",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerPlayer_off_CstE",
|
||||
"offset": "0x00000154",
|
||||
"convention": "offset",
|
||||
"prototype": "float CstE -- the probabilistic jump's efficiency",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "ServerPlayer_off_CstT",
|
||||
"offset": "0x00000158",
|
||||
"convention": "offset",
|
||||
"prototype": "float CstT -- the probabilistic jump's threshold",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_SYSTEMBONUS_MINTURNS",
|
||||
"addr": "0x00aeca10",
|
||||
"convention": "data",
|
||||
"prototype": "int** -- the GlobalConst pointer slot; the storage word is *slot",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_SYSTEMBONUS_POPBONUS",
|
||||
"addr": "0x00aeca18",
|
||||
"convention": "data",
|
||||
"prototype": "float** -- pointer slot",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_SYSTEMBONUS_INFRABONUS",
|
||||
"addr": "0x00aeca20",
|
||||
"convention": "data",
|
||||
"prototype": "float** -- pointer slot",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_SYSTEMBONUS_POPBONUS_INC",
|
||||
"addr": "0x00aeca38",
|
||||
"convention": "data",
|
||||
"prototype": "float** -- pointer slot",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_SYSTEMBONUS_INFRABONUS_INC",
|
||||
"addr": "0x00aeca40",
|
||||
"convention": "data",
|
||||
"prototype": "float** -- pointer slot",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_ADDICTION_PHASE2_START",
|
||||
"addr": "0x00aeca58",
|
||||
"convention": "data",
|
||||
"prototype": "int** -- pointer slot (image default 10)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_ADDICTION_PHASE3_START",
|
||||
"addr": "0x00aeca60",
|
||||
"convention": "data",
|
||||
"prototype": "int** -- pointer slot (image default 15)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_IndependentPopDriftRate",
|
||||
"addr": "0x00aeca80",
|
||||
"convention": "data",
|
||||
"prototype": "float -- 0.05f, a hard-coded literal in .data, NOT a GlobalConst; both ServerSystem::ProcessTurn calls to the independent pop-drift helper pass it",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_STUTTER_SYSTEM_INFLUENCE_RADIUS",
|
||||
"addr": "0x00aebc44",
|
||||
"convention": "data",
|
||||
"prototype": "float** -- pointer slot; storage 0x00b212cc (shipped value 2)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_STUTTER_MIN_SPEED",
|
||||
"addr": "0x00aebc48",
|
||||
"convention": "data",
|
||||
"prototype": "float** -- pointer slot; storage 0x00b212d0 (shipped value 0.33)",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
},
|
||||
{
|
||||
"name": "g_ptr_STUTTER_MAX_SPEED",
|
||||
"addr": "0x00aebc4c",
|
||||
"convention": "data",
|
||||
"prototype": "float** -- pointer slot; storage 0x00b212d4 (shipped value 0.33). NOTE min == max in the shipped data, so the stutter ramp collapses to a constant 0.33x inside any influence sphere",
|
||||
"status": "verified",
|
||||
"source": "handoff/b4-colony-movement.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
74
verify/results/compare/b2-techfx-compare.json
Normal file
74
verify/results/compare/b2-techfx-compare.json
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"format": 1,
|
||||
"hooks": {
|
||||
"Game::ServerPlayer::OnTechResearched": {
|
||||
"calls": 3,
|
||||
"compared": 3,
|
||||
"diffs": [],
|
||||
"diverged": 0,
|
||||
"diverged_call_ids": [],
|
||||
"errors": 0,
|
||||
"modes": {
|
||||
"compare": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
"inputs": [
|
||||
"verify/traces/b2-techfx-compare.jsonl"
|
||||
],
|
||||
"invalid": [],
|
||||
"kind": "report",
|
||||
"meta": [
|
||||
{
|
||||
"build": "b2-646e4e8-dirty-20260908T0434Z",
|
||||
"exe_sha256": "970b7de729956a53094c7eb98aba4270aee98e2fed5daf0d39e290013c90c841",
|
||||
"format": 1,
|
||||
"hooks": {
|
||||
"Game::SectionDictionary::SectionDictionary": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Game::ServerPlayer::ComputeBudget": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Game::ServerPlayer::OnTechResearched": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Game::TechTree::ProcessResearch": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Game::WeaponDictionary::Init": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Mars::GlobalConsts::LoadFile": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Shim::SelfTest::Fill": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
}
|
||||
},
|
||||
"inline_max": 256,
|
||||
"started": "2026-09-08T04:48:48Z"
|
||||
}
|
||||
],
|
||||
"totals": {
|
||||
"calls": 3,
|
||||
"compared": 3,
|
||||
"diverged": 0,
|
||||
"invalid_records": 0
|
||||
},
|
||||
"warnings": []
|
||||
}
|
||||
85
verify/results/compare/b2-techfx-golden.json
Normal file
85
verify/results/compare/b2-techfx-golden.json
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
"format": 1,
|
||||
"hooks": {
|
||||
"Game::ServerPlayer::OnTechResearched": {
|
||||
"calls": 2,
|
||||
"compared": 0,
|
||||
"diffs": [],
|
||||
"diverged": 0,
|
||||
"diverged_call_ids": [],
|
||||
"errors": 0,
|
||||
"modes": {
|
||||
"trace": 2
|
||||
}
|
||||
},
|
||||
"Game::TechTree::ProcessResearch": {
|
||||
"calls": 18,
|
||||
"compared": 0,
|
||||
"diffs": [],
|
||||
"diverged": 0,
|
||||
"diverged_call_ids": [],
|
||||
"errors": 0,
|
||||
"modes": {
|
||||
"trace": 18
|
||||
}
|
||||
}
|
||||
},
|
||||
"inputs": [
|
||||
"verify/traces/b2-techfx-golden.jsonl"
|
||||
],
|
||||
"invalid": [],
|
||||
"kind": "report",
|
||||
"meta": [
|
||||
{
|
||||
"build": "b2-646e4e8-dirty-20260908T0434Z",
|
||||
"exe_sha256": "970b7de729956a53094c7eb98aba4270aee98e2fed5daf0d39e290013c90c841",
|
||||
"format": 1,
|
||||
"hooks": {
|
||||
"Game::SectionDictionary::SectionDictionary": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Game::ServerPlayer::ComputeBudget": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Game::ServerPlayer::OnTechResearched": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Game::TechTree::ProcessResearch": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Game::WeaponDictionary::Init": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Mars::GlobalConsts::LoadFile": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
},
|
||||
"Shim::SelfTest::Fill": {
|
||||
"ftol": 0,
|
||||
"ftol_kind": "abs",
|
||||
"ptr": "ignore"
|
||||
}
|
||||
},
|
||||
"inline_max": 256,
|
||||
"started": "2026-09-08T04:36:07Z"
|
||||
}
|
||||
],
|
||||
"totals": {
|
||||
"calls": 20,
|
||||
"compared": 0,
|
||||
"diverged": 0,
|
||||
"invalid_records": 0
|
||||
},
|
||||
"warnings": []
|
||||
}
|
||||
4
verify/traces/b2-techfx-compare.jsonl
Normal file
4
verify/traces/b2-techfx-compare.jsonl
Normal file
File diff suppressed because one or more lines are too long
21
verify/traces/b2-techfx-golden.jsonl
Normal file
21
verify/traces/b2-techfx-golden.jsonl
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue