sots-engine/include/generated/sots_addresses.h

363 lines
29 KiB
C++

// GENERATED — do not edit. Facts about Sword of the Stars.exe (GOG 1.8.1).
// Source: sots-re ghidra/addresses.json @ 73f5f1e, generated 2026-09-07 by tools/gen_addresses.py
// Runtime address = (uintptr_t)GetModuleHandle(NULL) + RVA (the exe is ASLR-relocated).
#pragma once
#include <cstdint>
namespace sots::addr {
constexpr uint32_t IMAGE_BASE = 0x00400000;
// thiscall bool (Application* this, AppStartup* startup) /* ONE stack arg, RET 4, returns AL; EDX unused. startup = {HINSTANCE hInst; std::vector<std::string> args; ...; int nShow; const char* wndClass; int iconId} built in WinMain */ [verified]
constexpr uint32_t Mars_Application_Initialize = 0x004a0e50;
// thiscall void (Application* this) /* no stack args, plain RET, EDX not an input, EAX = last PumpMessages result (ignore) */ [verified]
constexpr uint32_t Mars_Application_Run = 0x0049f5b0;
// cdecl void (int coreIndex) [unverified]
constexpr uint32_t Process_PinAffinity = 0x0049ee70;
// thiscall GlobalConst* (GlobalConst* this, void* storage, const char* key, ParseFn parser, const char* file) // RET 0x10 [verified]
constexpr uint32_t CfgVar_RegisterKey = 0x004b76a0;
// thiscall bool (DemoApp* this) /* no stack args; returns 0 when quitting (this+0x1b2), else 1 */ [verified]
constexpr uint32_t DemoApp_OnTick = 0x0049a640;
// thiscall void (StrategyClient* this) [unverified]
constexpr uint32_t StrategyClient_EndTurn = 0x00383be0;
// thiscall void (StrategyServer* this) [unverified]
constexpr uint32_t StrategyServer_BeginProcessTurn = 0x003d98e0;
// thiscall void (StrategyServer* this) [unverified]
constexpr uint32_t StrategyServer_ProcessTurn = 0x003dc6c0;
// thiscall void (ServerPlayer* this, Budget* out, bool projected) /* Budget = { int slot[22]; std::vector<{Tech* node, int points}> researchAlloc (3 words @+0x58); int overBudget @+0x64 }. The array is 22 ints, not 25: the three words after slot 21 are the allocation vector and grow by one 8-byte element exactly when the player has a research target. Slots: 0 Sav, 1 systemIncome+, 2 trade, 3 shipCarriedPop, 4 secondaryManager, 5 savingsInterest, 6 bonusIncome, 7 systemIncome-, 8 maintenance, 9 researchMoneyKept (written only when ResT is set), 10 debtInterest, 11 construction, 12 expenses, 13 researchMoneyGiven, 14 savingsGiven, 15 available, 16 researchMoney, 17 researchPoints, 18 TRA, 19 researchPointsGiven, 20 TRP, 21 totalResearchPoints */ [verified-by-trace]
constexpr uint32_t ServerPlayer_ComputeBudget = 0x00463030;
// thiscall void (TechTree* this, Mars::RNG* rng, std::vector<{TechDef* target, int points}>* alloc, int* overbudget) /* args confirmed at the single call site: rng = StrategyServer+0x16c object, passed as the RNG *object* and re-based to &mt with lea ecx,[rng+4] before each NextFloat. Loop: node = this->nodes[*(int*)entry.target]; lo/hi from Cost x 50/150 /100 (32-bit imul, signed /100); spend = min(points, hi-progress) with NO clamp at 0; *overbudget += points-spend; odds and roll are both narrowed to float32 before the compare; decay loop hits every state-2 node with progress != 0; the trailing unlock-event loop makes no RNG draw and writes no node */ [verified]
constexpr uint32_t TechTree_ProcessResearch = 0x001876c0;
// thiscall void (ServerSystem* this /*+8 IStreamable*/, Stream* s) [verified-by-save]
constexpr uint32_t ServerSystem_Read = 0x0035d4b0;
// thiscall void (ServerSystem* this /*+8*/, Stream* s) [verified-by-save]
constexpr uint32_t ServerSystem_Write = 0x00349630;
// thiscall void (ServerPlayer* this /*+0x3a0*/, Stream* s) [verified-by-save]
constexpr uint32_t ServerPlayer_Read = 0x004804d0;
// thiscall void (ServerPlayer* this /*+0x3a0*/, Stream* s) [verified-by-save]
constexpr uint32_t ServerPlayer_Write = 0x004563e0;
// thiscall void (StarFleet* this /*+8*/, Stream* s) [verified-by-save]
constexpr uint32_t StarFleet_Read = 0x00302470;
// thiscall void (StarFleet* this /*+8*/, Stream* s) [verified-by-save]
constexpr uint32_t StarFleet_Write = 0x00301070;
// thiscall void (StarShip* this /*+8*/, Stream* s) [verified-by-save]
constexpr uint32_t StarShip_Read = 0x00453fa0;
// thiscall void (StarShip* this /*+8*/, Stream* s) [verified-by-save]
constexpr uint32_t StarShip_Write = 0x004291f0;
// thiscall void (StrategyServer* this, Stream* s) [verified-by-save]
constexpr uint32_t StrategyServer_Read = 0x003d27a0;
// thiscall void (StrategyServer* this, Stream* s) [verified-by-save]
constexpr uint32_t StrategyServer_Write = 0x0039fa70;
// thiscall void (Stream* this, const char* tag, NetworkObject* obj) [unverified]
constexpr uint32_t Stream_WriteNetworkObjectId = 0x00416490;
// thiscall void (uint32_t* mtBlock) // ECX = &mt = RNG object + 4 (NOT the object). N=624 M=397 MATRIX_A 0x9908b0df, 227/396 split; ends with left(&mt+0x9c4) = 624 and next(&mt+0x9c0) = &mt[0]. RET 0 [verified]
constexpr uint32_t RNG_Twist = 0x00026e00;
// thiscall RNG* (RNG* this, uint32_t seed) // RET 4; writes vftable 0x009e9aec, seeds from &mt = this+4: mt[0]=seed, mt[i]=0x6c078965*(mt[i-1]^(mt[i-1]>>30))+i for i=1..623, then Twist(&mt). OBJECT layout: {vftable @+0; uint32 mt[624] @+4 .. +0x9c3; uint32* next @+0x9c4; int left @+0x9c8} = 0x9cc bytes. Beware: NextFloat/NextInt/Twist take &mt, so *their* this+0x9c0/+0x9c4 are next/left [verified]
constexpr uint32_t RNG_Seed = 0x0009fdf0;
// thiscall float (uint32_t* mtBlock) // ECX = &mt = RNG object + 4. Lazy twist (if left==0 Twist()), y = *next++, left--, standard MT tempering, then value = (double)(uint32)y * 1/(2^32-1) -- the multiplier at 0x009e61b0 is 0x3df0000000001000 = 1/4294967295.0, NOT 2^-32; the unsigned fix-up at 0x009e61b8 is +2^32 after a signed fild. Left in st(0) at the current x87 precision and narrowed by the caller; range [0,1] INCLUSIVE [verified]
constexpr uint32_t RNG_NextFloat = 0x0007d830;
// thiscall uint32_t (uint32_t* mtBlock, const uint32_t* n) // ECX = &mt; the bound is passed BY POINTER, RET 4. mask = smallest 2^k-1 >= *n via the or/shift cascade; draws (lazy twist + tempering) until (y & mask) <= *n -- note the loop condition is `ja`, so the result is uniform on [0, *n] INCLUSIVE, not [0, n) [verified]
constexpr uint32_t RNG_NextInt = 0x000271c0;
// offset sizeof(Mars::RNG) -- {vftable @+0; uint32 mt[624] @+4; uint32* next @+0x9c4; int left @+0x9c8} [verified]
constexpr uint32_t RNG_size = 0x000009cc;
// offset uint32 mt[624]; also the pointer Twist/NextFloat/NextInt receive in ECX [verified]
constexpr uint32_t RNG_off_State = 0x00000004;
// offset uint32* next; always &mt[624 - left], and recomputed from left on load, so `left` alone pins the stream position [verified]
constexpr uint32_t RNG_off_Next = 0x000009c4;
// offset int left; words still unread in the current block [verified]
constexpr uint32_t RNG_off_Left = 0x000009c8;
// offset int tech id -- the index into TechTree_off_Nodes [verified]
constexpr uint32_t TechDef_off_TechId = 0x00000000;
// offset sizeof({TechDef* target, int points}) -- the element of the vector ProcessResearch walks [verified]
constexpr uint32_t ResearchAlloc_stride = 0x00000008;
// cdecl void (void) /* sots.ini [Modules] Mount<N> -> gobio::Init */ [verified]
constexpr uint32_t Mars_Application_MountModules = 0x004a0a20;
// cdecl void (int* count, const char*** table) /* count 3 @0x00b2d514, table @0x00a35e98 */ [verified]
constexpr uint32_t Game_GetDefaultMounts = 0x004991c0;
// thiscall GlobalConst* (GlobalConst* this, void* storage, const char* key, GlobalConstParseFn parser, const char* file) /* RET 0x10; static-init stub call. GlobalConst 0x10 bytes: {+0 void* storage (int/float/float[4]), +4 const char* key, +8 parser, +c const char* file} */ [verified]
constexpr uint32_t GlobalConst_ctor = 0x004b76a0;
// cdecl void (GlobalConst* g) [verified]
constexpr uint32_t GlobalConst_Register = 0x004b7610;
// cdecl void (int* storage, const char* text) [verified]
constexpr uint32_t GlobalConst_ParseInt = 0x004b7000;
// cdecl void (float* storage, const char* text) [verified]
constexpr uint32_t GlobalConst_ParseFloat = 0x004b7020;
// cdecl void (float* storage, const char* text) /* sscanf(%f) into *storage, then *storage = (float)((double)*storage * *(double*)0x00af5210) */ [verified]
constexpr uint32_t GlobalConst_ParseFloatScaled = 0x004b70e0;
// cdecl void (float rgba[4], const char* text) /* '%d %d %d %d', defaults 255, /255, clamp 0..1 */ [verified]
constexpr uint32_t GlobalConst_ParseColour = 0x004b7110;
// cdecl void (int rect[4], const char* text) /* '%d %d %d %d' (x y w h); 2 keys (COMBATSETUP_CARD_*_RECT); layout inferred from the M1 trace, int vs float unconfirmed */ [verified-by-trace]
constexpr uint32_t GlobalConst_ParseRect = 0x004b7040;
// cdecl void (float xyz[3], const char* text) /* '%f %f %f'; 5 keys (HIVER_SPAWN_*_GATE_HEIGHT / _SHIP_OFFSET ...); inferred from the M1 trace */ [verified-by-trace]
constexpr uint32_t GlobalConst_ParseVec3 = 0x004b7080;
// cdecl void (std::string* storage, const char* text) /* *storage = text; MSVC2010 std::string 0x18 bytes {+0 char buf[16] | char* ptr when capacity > 15, +0x10 size, +0x14 capacity}; 146 keys (*_NAME, *_SOUND, *_TEXTURENAME, DERELICT_SECTION_nn ...); seen in the M1 trace */ [verified-by-trace]
constexpr uint32_t GlobalConst_ParseString = 0x004b7670;
// cdecl void (void) /* called once from Application::Initialize; sets g_GlobalConstsLoaded */ [verified]
constexpr uint32_t GlobalConsts_LoadAll = 0x004b76d0;
// cdecl void (const char* file, GlobalConstMap* consts) /* consts = std::map<const char*,GlobalConst*,stricmp> of the keys registered for this file; MSVC2010 layout: map {+4 head node, +8 size}; node {+0 left, +4 parent, +8 right, +0xc const char* key, +0x10 GlobalConst*, +0x14 color, +0x15 isnil}; head: isnil=1, parent=root. Consumed keys are erased from the map. Hook this for the file-level read */ [verified]
constexpr uint32_t GlobalConsts_LoadFile = 0x004b73c0;
// data bool [verified]
constexpr uint32_t g_GlobalConstsLoaded = 0x0072d740;
// data std::map<const char*,GlobalConst*,stricmp_less> /* +4 (0x00b2d748) = header node pointer */ [verified]
constexpr uint32_t g_GlobalConstRegistry = 0x0072d744;
// data double /* pi/180 as a DOUBLE (0x3f91df46a2529d39); GlobalConst_ParseFloatScaled does float word *= this in x87 and stores float */ [verified]
constexpr uint32_t g_GlobalConstFloatScale = 0x006f5210;
// thiscall Script* (Script* this) /* sizeof(Script) = 0x28 */ [verified]
constexpr uint32_t Script_ctor = 0x004cd700;
// thiscall void (Script* this) [verified]
constexpr uint32_t Script_dtor = 0x004cd720;
// thiscall bool (Script* this, const char* path) /* gobio::ReadFile into this->buf */ [verified]
constexpr uint32_t Script_Open = 0x004cd7d0;
// thiscall void (Script* this) [verified]
constexpr uint32_t Script_Close = 0x004cd6c0;
// thiscall int (Script* this, char* out, uint outMax) /* 0 token, 1 no buffer/past end, 2 reached end */ [verified]
constexpr uint32_t Script_ReadToken = 0x004cd2f0;
// thiscall int (Script* this, ScriptToken* tok) /* tok: {int type; char key[1024]; char value[1024]}; type 1 kv, 2 block open, 3 '}' */ [verified]
constexpr uint32_t Script_Next = 0x004cd3e0;
// thiscall int (Script* this, int depth) /* 0 ok, nonzero EOF */ [verified]
constexpr uint32_t Script_SkipBlock = 0x004cd4b0;
// custom /* EAX=cursor, ECX=&quotedFlag, EDX=out; stack: end, outEnd, &len — internal, do not hook */ [verified]
constexpr uint32_t Script_ScanToken = 0x004cd1f0;
// cdecl void (IConfigCallback* cb, const char* path, const char* blockName, bool* found) /* cb->vft[1](Script*) per matching block */ [verified]
constexpr uint32_t ConfigParser_ParseFile = 0x004cd820;
// fastcall int (IBuffer* obj) /* ECX=obj; --refcount, vft[0](1) at 0 */ [verified]
constexpr uint32_t RefCounted_Release = 0x004a7230;
// thiscall void (WeaponDictionary* this) /* reads Weapons/_weapons.txt manifest */ [verified]
constexpr uint32_t WeaponDictionary_Init = 0x0019a4c0;
// thiscall void (WeaponDictionary* this, const char* path, int id, WeaponDef** out) [verified]
constexpr uint32_t WeaponDictionary_LoadWeapon = 0x0019a230;
// thiscall WeaponDef* (WeaponDictionary* this, const char* name) /* _stricmp over def->name @+0x40 */ [verified]
constexpr uint32_t WeaponDictionary_FindByName = 0x00190a10;
// thiscall WeaponDef* (WeaponDictionary* this, const char* name) /* 'Weapon not found: "%s" - Was it added to the index file?' */ [verified]
constexpr uint32_t WeaponDictionary_FindByNameSorted = 0x00191e30;
// thiscall WeaponDef* (WeaponDef* this, int index, int id, const char* path) /* sizeof 0x278 */ [verified]
constexpr uint32_t WeaponDef_ctor = 0x00198a20;
// thiscall bool (WeaponDef* this, Script* script, int* rc, TechTree* tree) [verified]
constexpr uint32_t WeaponDef_ParseScript = 0x00199070;
// thiscall SectionDictionary* (SectionDictionary* this, TechTree* tree) /* reads Species/<Race>/_shipsections.txt for species 0..6 */ [verified]
constexpr uint32_t SectionDictionary_ctor = 0x00176f40;
// thiscall SectionDef* (SectionDictionary* this, const char* path, int species, int id) [verified]
constexpr uint32_t SectionDictionary_LoadSection = 0x00176cd0;
// thiscall SectionDef* (SectionDef* this, int index, int species, int id) /* sizeof 0x3d8 */ [verified]
constexpr uint32_t SectionDef_ctor = 0x00174020;
// thiscall bool (SectionDef* this, Script* script, int* rc, TechTree* tree) [verified]
constexpr uint32_t SectionDef_ParseScript = 0x001744e0;
// cdecl const char* (uint species) [verified]
constexpr uint32_t Species_GetDirName = 0x00145ec0;
// thiscall MasterTechTree* (MasterTechTree* this) /* TechTree/MasterTechList.tech */ [verified]
constexpr uint32_t MasterTechTree_ctor = 0x0018b870;
// thiscall void (MasterTechTree* this, const char* path, int flag) [verified]
constexpr uint32_t MasterTechTree_LoadTechFile = 0x0018b770;
// thiscall void (MasterTechTree* this, Script* script, int flag) /* one tech{} block */ [verified]
constexpr uint32_t MasterTechTree_ParseTech = 0x0018b050;
// thiscall void (DemoApp* this) /* MasterTechTree -> +0x110, WeaponDictionary -> +0x118, SectionDictionary -> +0x114 */ [verified]
constexpr uint32_t DemoApp_LoadGameData = 0x00499280;
// thiscall void (DemoApp* this) /* once, from OnTick when this+0x10c is set */ [verified]
constexpr uint32_t DemoApp_EnsureGameData = 0x00499870;
// cdecl void (std::vector<std::string>* mountPaths) [verified]
constexpr uint32_t gobio_Init = 0x004d7010;
// thiscall FileSystemSet* (FileSystemSet* this, std::vector<std::string>* mounts) [verified]
constexpr uint32_t gobio_FileSystemSet_ctor = 0x004d6d60;
// thiscall bool (FileSystemSet* this, const char* path) [verified]
constexpr uint32_t gobio_FileSystemSet_Open = 0x004d5060;
// thiscall void (FileSystemSet* this, const char* pattern, std::vector<std::string>* out) [verified]
constexpr uint32_t gobio_FileSystemSet_ListFiles = 0x004d7090;
// cdecl bool (const char* path, IBuffer** out) /* whole file by relative path; THE hook point for M4 */ [verified]
constexpr uint32_t gobio_ReadFile = 0x004d5140;
// cdecl bool (const char* path) [verified]
constexpr uint32_t gobio_Open = 0x004d50d0;
// cdecl void (void) [verified]
constexpr uint32_t gobio_Close = 0x004d4d20;
// cdecl uint (void) [verified]
constexpr uint32_t gobio_Size = 0x004d4d50;
// cdecl uint (void* dst, uint n) [verified]
constexpr uint32_t gobio_Read = 0x004d4d80;
// cdecl bool (const char* path) [verified]
constexpr uint32_t gobio_Exists = 0x004d50f0;
// cdecl void (const char* pattern, std::vector<std::string>* out) [verified]
constexpr uint32_t gobio_ListFiles = 0x004d71d0;
// custom /* size in EBX, IBuffer** out on stack — internal, do not hook */ [verified]
constexpr uint32_t gobio_Buffer_Create = 0x004d4c90;
// thiscall void* (IBuffer* this) /* vft[1] and vft[2]; = this+8 */ [verified]
constexpr uint32_t gobio_Buffer_Data = 0x00282d50;
// thiscall uint (IBuffer* this) /* vft[3]; = this+0xc */ [verified]
constexpr uint32_t gobio_Buffer_Size = 0x004d4c80;
// thiscall NativeFileSystem* (NativeFileSystem* this, const char* root) /* sizeof 0x28; vtable 0x00a398ac */ [verified]
constexpr uint32_t gobio_NativeFileSystem_ctor = 0x004d57a0;
// thiscall bool (NativeFileSystem* this, const char* path) /* vft[1] fopen(root+path,'rb') */ [verified]
constexpr uint32_t gobio_NativeFileSystem_Open = 0x004d4ef0;
// thiscall uint (NativeFileSystem* this, void* dst, uint n) /* vft[4] */ [verified]
constexpr uint32_t gobio_NativeFileSystem_Read = 0x004d4c30;
// thiscall ZipFileSystem* (ZipFileSystem* this, const char* zipPath) /* sizeof 0x34; vtable 0x00a39934 */ [verified]
constexpr uint32_t gobio_ZipFileSystem_ctor = 0x004d6c40;
// thiscall bool (ZipFileSystem* this, const char* path) /* vft[1]; case- and slash-insensitive */ [verified]
constexpr uint32_t gobio_ZipFileSystem_Open = 0x004d56a0;
// thiscall uint (ZipFileSystem* this, void* dst, uint n) /* vft[4] */ [verified]
constexpr uint32_t gobio_ZipFileSystem_Read = 0x004d4b40;
// data FileSystemSet* /* -> 0x00b2e274 after gobio::Init */ [verified]
constexpr uint32_t g_gobio = 0x0072e270;
// data const char*[3] /* used when sots.ini has no [Modules] Mount<N>; contains sots_local_en.gob, sots.gob */ [verified]
constexpr uint32_t g_DefaultMountTable = 0x00635e98;
// cdecl Stream* (const char* path) /* sniffs 'TXT' magic, returns a TextFileStream (0x420 bytes) opened for read */ [verified]
constexpr uint32_t Stream_OpenFile = 0x004cfcb0;
// thiscall TextFileStream* (TextFileStream* this) /* vtable 0x00a428c0 */ [verified]
constexpr uint32_t TextFileStream_ctor = 0x0051e460;
// thiscall bool (TextFileStream* this, const char* path, int mode /*1*/) [verified]
constexpr uint32_t TextFileStream_Open = 0x004cfb90;
// thiscall uint (Stream* this, char* out, int max) [verified]
constexpr uint32_t FileStream_ReadLine = 0x004cfa30;
// thiscall const char* (TextFileStream* this, const char* line, const char* label) /* NULL on END/mismatch */ [verified]
constexpr uint32_t TextFileStream_MatchLabel = 0x0051e760;
// thiscall bool (TextFileStream* this, const char* label, char* out, int outMax) /* vft[1] */ [verified]
constexpr uint32_t TextFileStream_ReadString = 0x0051ec90;
// thiscall bool (TextFileStream* this, const char* label, bool* out) /* vft[2] */ [verified]
constexpr uint32_t TextFileStream_ReadBool = 0x0051eba0;
// thiscall bool (TextFileStream* this, const char* label, float* out) /* vft[3] */ [verified]
constexpr uint32_t TextFileStream_ReadFloat = 0x0051eb30;
// thiscall bool (TextFileStream* this, const char* label, int* out, int dflt) /* vft[4] */ [verified]
constexpr uint32_t TextFileStream_ReadInt = 0x0051eab0;
// thiscall void (TextFileStream* this, const char* label, IStreamable* obj /*NULL=skip*/) /* vft[5]; BEGIN..END */ [verified]
constexpr uint32_t TextFileStream_ReadNested = 0x0051e8e0;
// thiscall void (ParticleSystem* this, Stream* s) /* .effect body */ [verified]
constexpr uint32_t ParticleSystem_Read = 0x004db650;
// thiscall void (ParticleSystem* this, Stream* s) [verified]
constexpr uint32_t ParticleSystem_Write = 0x004dad60;
// thiscall void* (EffectDictionary* this, const char* name) /* 'effects/' + name; Stream::OpenFile; 0x1c0-byte effect */ [unverified]
constexpr uint32_t EffectDictionary_Load = 0x004b42b0;
// cdecl void (Stream* s, const char* label, std::string* out, int flag) /* wrapper over vft[1] */ [verified]
constexpr uint32_t Stream_ReadString = 0x004b9d90;
// cdecl void (Stream* s, const char* label, int* out, int dflt) /* wrapper over vft[4] */ [verified]
constexpr uint32_t Stream_ReadInt = 0x004b9d20;
// cdecl void (Stream* s, const char* label, bool* out) /* wrapper over vft[2] */ [verified]
constexpr uint32_t Stream_ReadBool = 0x004b9c00;
// cdecl void (Stream* s, const char* label, float* out, int flag) /* wrapper over vft[3] */ [verified]
constexpr uint32_t Stream_ReadFloat = 0x004b9bc0;
// thiscall void (ServerPlayer* this, TechDef* def, bool silent) /* vft slot 4 of 0x00a327a4; hard-coded tech effects */ [verified]
constexpr uint32_t ServerPlayer_OnTechResearched = 0x00491790;
// thiscall bool (MasterTechTree* this, TechDef* def, int techId) /* techId = 10000+index into g_TechIdNames; 0xc5 = none */ [verified]
constexpr uint32_t MasterTechTree_IsTech = 0x0017d5d0;
// thiscall TechDef* (MasterTechTree* this, int techId) [verified]
constexpr uint32_t MasterTechTree_GetTechDef = 0x0017d610;
// thiscall bool (TechTree* this, int techId) [verified]
constexpr uint32_t TechTree_HasResearched = 0x0017d810;
// thiscall int (TechTree* this, TechNode* node) // RET 4. node==0 -> INT_MAX; node->costRP(+0x18)==INT_MAX -> INT_MAX; costRP<=0 or this->owner(+0xc)==0 or mult<=0 -> 0; else max(1, _ftol2((float)TechCostMult(owner, node->def) * costRP)). Reads only (no RNG, no writes), so a reimplementation may call it on a scratch tree whose +0xc is the real owner [verified]
constexpr uint32_t TechTree_Cost = 0x0017da00;
// thiscall float (ServerPlayer* this, TechDef* def) // 1.0 - 0.25 per applicable species research-bonus tech owned; read-only [verified]
constexpr uint32_t ServerPlayer_TechCostMult = 0x0040db50;
// thiscall void (TechTree* this, TechDef* def, int flags) // state 4 + turn/order stamps + owner callback + child unlock cascade. Makes no direct RNG draw; the owner callback is not audited, so a compare that runs it is out of scope [verified]
constexpr uint32_t TechTree_SetResearched = 0x00181e10;
// offset ServerPlayer* owner (0 for a tree with no player) [verified]
constexpr uint32_t TechTree_off_Owner = 0x0000000c;
// offset std::vector<TechNode*> indexed by tech id (MSVC2010: 3 words {first@+0x10, last@+0x14, end@+0x18}); entries may be NULL [verified]
constexpr uint32_t TechTree_off_Nodes = 0x00000010;
// offset sizeof(TechNode) -- the ctor's operator new argument [verified]
constexpr uint32_t TechNode_size = 0x00000034;
// offset TechDef* def; *(int*)def is the tech id used to index TechTree_off_Nodes [verified]
constexpr uint32_t TechNode_off_Def = 0x00000000;
// offset int state (0 hidden, 1 parent researched, 2 available, 4 researched); ctor writes 0 [verified]
constexpr uint32_t TechNode_off_State = 0x00000014;
// offset int costRP, INT_MAX = no researched parent yet; ctor writes 0x7fffffff [verified]
constexpr uint32_t TechNode_off_CostRP = 0x00000018;
// offset int progress in RP; the only node word ProcessResearch itself writes besides the flag [verified]
constexpr uint32_t TechNode_off_Progress = 0x0000001c;
// offset int flag (1 default from the ctor, 0 completed below 80% of cost, 2 over-budget event raised) [verified]
constexpr uint32_t TechNode_off_Flag = 0x0000002c;
// thiscall void (MasterTechTree* this) /* fills TechDef*[196] at this+0 from g_TechIdNames */ [verified]
constexpr uint32_t MasterTechTree_ResolveTechIds = 0x00181c10;
// cdecl int (std::string* name) /* membership in g_CombatTechNames (116) */ [verified]
constexpr uint32_t IsCombatTechName = 0x002965c0;
// fastcall void (ServerPlayer* this) /* flags[7] at +0x348 from SpeciesDef xnc tech ids */ [verified]
constexpr uint32_t ServerPlayer_RebuildSpeciesTechFlags = 0x0042bf10;
// thiscall void (ServerPlayer* this, TechDef* def) [verified]
constexpr uint32_t ServerPlayer_ApplyAITechBonus = 0x0040e330;
// thiscall void (ServerPlayer* this, bool on) [verified]
constexpr uint32_t ServerPlayer_SetAIBenefit = 0x004186b0;
// cdecl bool (TechDef* def, uint* maskOut) [verified]
constexpr uint32_t TechDef_GetPlagueCureMask = 0x00137240;
// cdecl uint* (uint out[2], TechTree* tree) /* EBX-passed tree in caller; tables 0x00adf378 / 0x00adf478 */ [unverified]
constexpr uint32_t ComputeTechBitmasks = 0x000d7960;
// cdecl SpeciesDef* (uint species) /* 0x00b10a00 + i*0x184 */ [verified]
constexpr uint32_t SpeciesDef_Get = 0x00145cc0;
// cdecl void (void) [verified]
constexpr uint32_t SpeciesDef_InitTable = 0x001453a0;
// fastcall void (ServerPlayer* this) [verified]
constexpr uint32_t ServerPlayer_UpdateBankruptcyLimits = 0x00418600;
// thiscall void (ServerPlayer* this, int level) [verified]
constexpr uint32_t ServerPlayer_SetBankruptcyState = 0x0040e260;
// fastcall int (ServerPlayer* this) [verified]
constexpr uint32_t ServerPlayer_BankruptcyLevel = 0x0040db10;
// cdecl double (double suit, double ideal, double tol) /* clamp01(1-|suit-ideal|/(tol+0.1)) */ [verified]
constexpr uint32_t ServerSystem_HazardMod = 0x00347ae0;
// thiscall double (ServerSystem* this, double tradePoints) /* RET 8 */ [verified]
constexpr uint32_t ServerSystem_TradePointsToMoney = 0x003505b0;
// thiscall double (ServerSystem* this, int species) [verified]
constexpr uint32_t ServerSystem_CalcSuitMod = 0x003484d0;
// fastcall void (ServerSystem* this) [verified]
constexpr uint32_t ServerSystem_AccrueSystemBonus = 0x0034d4f0;
// thiscall int (ServerSystem* this, float frac) [verified]
constexpr uint32_t ServerSystem_SystemBonusPopTarget = 0x0034b5a0;
// cdecl void (Vector3* posOut, bool* arrivedOut, float nodespeed, float dt, void* lines, Vector3* from, Vector3* to) [unverified]
constexpr uint32_t NodeLine_Step = 0x00305510;
// cdecl void (vector* segsOut, vector* systems, Vector3* from, Vector3* to) [unverified]
constexpr uint32_t NodeLine_BuildStutterSegments = 0x00305280;
// data struct { const char* name; int x; }[196] /* TechId = 10000+i */ [verified]
constexpr uint32_t g_TechIdNames = 0x005ff9e4;
// data const char*[116] [verified]
constexpr uint32_t g_CombatTechNames = 0x00619718;
// data SpeciesDef[7] (0x184 B each, .bss, filled by SpeciesDef_InitTable) [verified]
constexpr uint32_t g_SpeciesDefTable = 0x00710a00;
// data struct { int techId; uint bit; }[32] [verified]
constexpr uint32_t g_TechBitmaskTableA = 0x006df378;
// data struct { int techId; uint bit; }[29] [verified]
constexpr uint32_t g_TechBitmaskTableB = 0x006df478;
// data struct { int techId; int a; float value; }[6] /* values not dumped */ [unverified]
constexpr uint32_t g_AITechValueTable = 0x00617888;
// data int (config storage; PTR slot 0x00aedfe0) [verified]
constexpr uint32_t g_PERGATETRAFFIC_DRV_TpGate = 0x00723e2c;
// data int (config storage; PTR slot 0x00aedfe4) [verified]
constexpr uint32_t g_PERGATETRAFFIC_DRV_GatAmp = 0x00723e30;
// offset int PlyrIdx [verified-by-save]
constexpr uint32_t ServerPlayer_off_PlyrIdx = 0x00000028;
// offset std::vector<ServerSystem*> owned systems (MSVC2010 release layout: 3 words {first@+0, last@+4, end@+8}, handle ids, 4 B stride); save tag NumOwn/OwnId [verified-by-save]
constexpr uint32_t ServerPlayer_off_OwnedSystems = 0x00000030;
// offset int Species (0 Human .. 6 Morrigi) [verified-by-save]
constexpr uint32_t ServerPlayer_off_Species = 0x0000005c;
// offset float ResRate (research share of available money, 0..1) [verified-by-save]
constexpr uint32_t ServerPlayer_off_ResRate = 0x000000bc;
// offset float ResMod [verified-by-save]
constexpr uint32_t ServerPlayer_off_ResMod = 0x000000c0;
// offset float ResScl [verified-by-save]
constexpr uint32_t ServerPlayer_off_ResScl = 0x000000c4;
// offset float TRM (timed research multiplier bonuses) [verified-by-save]
constexpr uint32_t ServerPlayer_off_TRM = 0x000000d0;
// offset int TRA (per-turn research-point contribution) [verified-by-save]
constexpr uint32_t ServerPlayer_off_TRA = 0x000000d4;
// offset int TRP (per-turn research-point contribution) [verified-by-save]
constexpr uint32_t ServerPlayer_off_TRP = 0x000000d8;
// offset bool Elim [verified-by-save]
constexpr uint32_t ServerPlayer_off_Elim = 0x000000f8;
// offset bool isAI /* gate ComputeBudget reads for the construction slot and for picking the AI difficulty-mod row */ [verified]
constexpr uint32_t ServerPlayer_off_IsAI = 0x000000f9;
// offset bool NPC [verified-by-save]
constexpr uint32_t ServerPlayer_off_NPC = 0x000000fb;
// offset bool RebAI [verified-by-save]
constexpr uint32_t ServerPlayer_off_RebAI = 0x000000fc;
// offset int Maint (raw fleet upkeep, before the difficulty divisor) [verified-by-save]
constexpr uint32_t ServerPlayer_off_Maint = 0x0000015c;
// offset float shrm (shared research modifier) [verified-by-save]
constexpr uint32_t ServerPlayer_off_shrm = 0x00000160;
// offset std::vector<ExpenseEntry> expense sliders (3 words; entry 16 B {int xid, int xmin, int xmax, float xper}); save tag Nexp [verified-by-save]
constexpr uint32_t ServerPlayer_off_Nexp = 0x00000204;
// offset float income multiplier from the game-setup handicap block; ComputeBudget bonus slot = ftol((this - 1.0) x net) [verified]
constexpr uint32_t ServerPlayer_off_SetupIncomeMult = 0x00000228;
// offset float research multiplier from the game-setup handicap block; a factor of the research-points slot [verified]
constexpr uint32_t ServerPlayer_off_SetupResearchMult = 0x0000022c;
// offset int Sav (treasury) [verified-by-save]
constexpr uint32_t ServerPlayer_off_Sav = 0x00000284;
// offset Tech* current research target (ResT); NULL = none [verified-by-save]
constexpr uint32_t ServerPlayer_off_ResearchTarget = 0x00000294;
// offset float IncMod [verified-by-save]
constexpr uint32_t ServerPlayer_off_IncMod = 0x0000030c;
// offset std::vector<PlayerAid> (3 words; entry 0x18 B, {+0x8 int researchPercent, +0xc int researchActive, +0x10 int savings, +0x14 int savingsActive}) [verified]
constexpr uint32_t ServerPlayer_off_Aid = 0x00000310;
} // namespace sots::addr