13 KiB
SOTS1 .gob Data-Model Inventory
Harvest of the data-driven object model from the two game archives. Both .gob
files are renamed uncompressed ZIPs (unzip -l / unzip work directly).
/srv/re-lab/sots-game/sots.gob(1.45 GB) — main asset/data archive (8,354 entries)/srv/re-lab/sots-game/sots_local_en.gob(599 MB) — English localization + voice (2,037 entries)- Extracted textual data (855 KB, 1,665 files):
/srv/re-lab/gob-extract/ - Raw
unzip -llistings:/srv/re-lab/handoff/list_sots.gob.txt,list_sots_local_en.gob.txt
TL;DR
Almost the entire content model of SOTS is data, not code. The engine ("Mars")
provides a single recursive brace-block, whitespace key/value parser; the game
("Game") loads catalogs of these blocks into definition objects at startup. Weapons
(207), ship sections (875, per-species), the full tech tree (~293 nodes, one file),
races, turrets, badges/lights, scenarios, combat missions, planet visuals, and all
tuning constants (economy, combat, AI) are external files. Code owns behavior
(how a weaponclass bullet flies and applies dam_pop), the data owns which
objects exist and their stats. @TOKEN/SOTS_* string keys resolve against
Locale/EN/Strings.csv (5,722 rows) — the model is fully localization-indirected.
1. File-type histograms
sots.gob (by extension)
| ext | count | meaning |
|---|---|---|
| x | 4302 | DirectX .X meshes (ships, turrets, planets) — binary, NOT extracted |
| tga | 1439 | textures / icons — NOT extracted |
| shipsection | 885 | ship module definitions (data) |
| dds | 482 | compressed textures — NOT extracted |
| effect | 415 | combat/visual effect defs (data, brace-block) |
| wav | 357 | sound — NOT extracted |
| weapon | 207 | weapon definitions (data) |
| txt | 59 | tuning-constant tables + list manifests (data) |
| fx / fxh | 58 / 5 | HLSL shaders / headers |
| csv | 26 | AI tables, star coords, string tables, scenarios (data) |
| script | 4 | brace-block config (GUI/planet/tech-display) |
| combat | 3 | combat-mission (encounter) defs |
| def | 2 | ShipBadges, ShipLights |
| tech | 1 | MasterTechList.tech — the entire tech tree |
| decal/jpg/bmp | 5/1/1 | misc art |
sots_local_en.gob
| ext | count | meaning |
|---|---|---|
| wav | 2002 | voice-over / speech — NOT extracted |
| txt | 8 | race descriptions, chat translations, credits |
| tga | 4 | localized art |
| csv | 2 | Strings.csv (UI strings), SpeechEvents.csv |
Extracted (textual only): 875 shipsection, 415 effect, 207 weapon, 67 txt, 58 fx, 28 csv, 5 fxh, 4 script, 3 combat, 2 def, 1 tech.
2. Top-level directory tree
sots.gob
Species/ 5522 per-race art + sections/ (the ship-section catalogs)
Effects/ 599 .effect visual defs
Models/ 506 planets, asteroids, skysphere (+ PlanetResources.script)
TechTree/ 423 one .tech file + per-tech .tga icons
GUI/ 396 UI layout, SpriteTable.csv, WeaponIcons
Sounds/ 369 SFX (+ sound_ui.csv)
Badges/ 169 emblem art + BadgeTable.txt
Weapons/ 132 .weapon defs + _weapons/_turrets manifests + art/
Avatars/ 111 leader portraits + AvatarTable.txt
Data/ 44 *** GLOBAL TUNING: Combat/, Strategy/, globals, species, encounters ***
Render/ 38 render config
Scenarios/ 26 campaign/scenario defs (.txt + .csv fleet tables)
Decals/ 14
CombatMissions/3 encounter templates (.combat)
sots_local_en.gob
Sounds/ 2018 Locale/ 10 GUI/ 6 Data/ 1
3. The core data format
One convention dominates (engine's Mars parser). Named brace blocks, nested,
with key <whitespace> value lines; value may be a bareword, number, or
"quoted string with spaces"; // line comments; @TOKEN and SOTS_*/WEAPON_*
references are localization keys resolved via Strings.csv.
weapon
{
name @WEAPON_BAL_GAUSS
cost 50
bank { turretclass standard mount { node LightGunNode01 min_azimuth -130 } }
}
Three secondary formats:
- Flat KEY value tuning tables (
Data/**/*.txt):SLAVES_DEATH_RATE 0.05— one constant per line, colors as"r g b". These are global singletons, not catalogs. - CSV (
Data/Strategy/**,Scenarios/*.csv, locale):#-commented header, comma-delimited; used for AI decision tables, star coordinates, string tables. - Numbered manifest .txt (
_weapons.txt,_shipsections.txt):<stable-int-id> <filename>— assigns the network/savegame IDs; explicit// DELETED - 36and "always use new IDs" comment => IDs are a persistent wire contract.
4. High-value catalogs (schema + excerpt)
4.1 Tech tree — TechTree/MasterTechList.tech (62 KB, ~293 nodes)
Single file, list of tech { } blocks. This is the whole research graph.
Schema per node:
| key | meaning |
|---|---|
name "IND_Waldo" |
unique tech ID (FAMILY_Short) |
family "IND" |
tech family/branch (roots mostly) |
type P |
project type flag (P seen) |
threat N |
AI/threat weighting |
allows "CHILD_ID RP:cost Human:% Zuul:% Hiver:% Tarkas:% Liir:% Morrigi:%" |
directed edge: unlocks CHILD at research-point cost, with per-species availability probability (0 = race can never get it, 100 = always). Multiple per node = the DAG. |
strategy { inc/dec TECHBEN_* } |
economic/empire modifiers granted (e.g. TECHBEN_INDOUTPUT, TECHBEN_HULLSTR, TECHBEN_SHIPCONCOST) |
ship { section DEHammerhead ... } |
ship sections unlocked by this tech (links tech -> shipsection catalog) |
Families seen: IND, NRG/EWP, SLD, DRV, TRP, WHD/WAR, BAL, BIO, CCC, DRN, XNC.
The per-species Human:0 ... Morrigi:100 weighting encodes the game's famous
race-unique-tech mechanic entirely in data (e.g. only Human gets DRV_Node, only
Tarka DRV_Hyper, only Liir DRV_StrWrp).
4.2 Weapons — Weapons/*.weapon (207) + _weapons.txt manifest
weapon {
name @WEAPON_BAL_GAUSS weaponclass bullet weaponfamily gauss
requires WEP_GsDrvr cost 50
turretsize small turretclass standard trackspeed_mod 1.0
burst_volleys 1 recharge_time 5 muzzle_speed 300
range 455 range_planet 1075
model1/2/3 barrel_*.X muzzle_effect/impact_effect effects/*.effect
fc_requires_los / fc_manual_target / fc_controllable ... (fire-control flags)
bolt { rangetable { pb_range/eff_range/max_range + _dev + _dam } <- damage falloff
dam_pop 3500 dam_infra .00005 dam_terra 0 } <- vs pop/infra/terrain
rating_frate/dam/acc/range <- UI star ratings
}
weaponclass(drives engine behavior): beam, bullet, missile, energy, torpedo, laser, col(ony), mine, rider, emitter, grapple, etc. (38 distinct).weaponfamily(AI grouping / mutual exclusion): gauss, energycannon, missile, torpedo, conventionalbeam, laser, heavybeam, conventionalmine, emitter.requires <TECH_ID>ties every weapon back to the tech tree._weapons.txtgives each weapon a stable integer ID (1..123+) for net/save.
4.3 Ship sections — Species/<Race>/sections/*.shipsection (875)
Per-race catalogs (Human 144, Hiver 137, Morrigi 141, Liir 135, Tarkas 132, Zuul 122, _NPC 64). A "ship" = 3 sections (command/mission/engine) snapped by sockets.
shipsection {
model Species/Human/art/sections/CruiserAIC.X
requires CCC_AIFrCon section_type command section_class Cruiser
health 2800 mass 2500 cost 60000 cpoints 900 crew 3
socket_fore/socket_aft <node> <- how sections join
option { option IND_PlyAlloy ... } <- tech-gated build options/upgrades
netforcelimits { force_forward/right/up torque_yaw/pitch/roll speed rotspeed }
bank { turretclass std turretsize medium
mount { node MediumGunNode01 min/max_azimuth min/max_inclination } }
}
section_type: command (164), mission (502), engine (108). => the 3-part hull.section_class: destroyer / cruiser / dreadnought (the 3 hull sizes). Name prefixes DE/CR/DN encode class.- Engine sections add
ftlspeed,nodespeed,engine_techera, thrusters. bank/mount= hardpoints (turret class+size + gimbal limits) => this is the data that constrains which.weaponcan be fitted where.
4.4 Turrets — Weapons/_turrets.txt (positional table)
size weapon-size class health track-speed azimuth% inclination% "model.x"
Cross-references weapon turretsize/turretclass and section bank slots.
4.5 Races / species
Data/species.txt— per-race scalars:SENSORMOD_<RACE>,SPECIESCOLOR_<RACE>.- Deeper per-race behavior is expressed distributed: their
sections/catalogs, theHuman:/Zuul:/...columns in the tech tree,affinity_*AI tables, and localeDesc<Race>.txt. There is no single "race stats" file — race identity is emergent from these tables. Data/Strategy/playercolors.txt,starcolors.txt,systemnames.txt— cosmetic/naming.
4.6 Planets / economy
- Economy tuning lives in flat KEY-value tables, not per-planet rows:
Data/Strategy/StrategyVars.txt(117 lines: bankruptcy, trade routesTRADE_ROUTE_REQ_*, slavesSLAVES_*, system bonuses, starmap sizing),Data/globals.txt(435 lines, mostly UI but some sim),Data/Combat/planet.txt(planetary-defense combat params). Models/Planets/PlanetResources.script— per-race x planet-quality (Ideal/…) -> texture sets; visual, not economic.Data/Strategy/RealSpace.csv—system,x,y,z,Namereal-star coordinates (~348).- Planet economic model (population growth, output, terraforming) is largely in code, tuned by the StrategyVars/globals constants — the weakest data coverage.
4.7 AI decision tables — Data/Strategy/AI/*.csv
Clean, comment-documented CSVs the AI consults:
affinity_section.csv—section,species,purpose(which sections serve which role)affinity_weapon.csv—weapon-family,purpose(e.g.gauss,reflect_cm)weapon_replacements.csv—weapon,replaces-weaponfinal substitution passaitechpri.csv—tech, <6 per-race priorities 1-255>(lower = research sooner)aitechgrp/aitechmode,stock_design_names,stock_player_names,rebelai_names,stock_diplomacy_messages,raider_sections.
4.8 Scenarios & combat missions
Scenarios/*.txt(18) —name/desc/objs/rules(all@-tokens),numplayers,numsystems,mapshape,script_object, repeatedplayer { recommended }. Backed byScenarios/*_Fleets.csv,_FleetTemplates.csv,_Techs.csv,_ShipRequests.csv— data-driven fleet/tech grants for campaigns.CombatMissions/Encounter/{DeepSpace,InSystem,NodeSpace}.combat— encounter templates:summary/combatenv/endcondition{elimination,time}/orbit{type,radius}.
4.9 Cosmetic catalogs
Species/ShipBadges.def (badge {name,w,h,depth,orientation}), ShipLights.def
(light {name,effect,period,offset,duration}), Badges/BadgeTable.txt,
Avatars/AvatarTable.txt, GUI/SpriteTable.csv, Effects/*.effect (415).
4.10 Localization — sots_local_en.gob
Locale/EN/Strings.csv (5,722 rows: Key,String,Size,Notes) resolves every
@TOKEN/SOTS_*/WEAPON_* in the data. SpeechEvents.csv, Desc<Race>.txt,
ChatTrans.txt. Confirms the whole model is name-key indirected for i18n.
5. Data-defined vs code-defined (map to Game:: classes)
| Object model area | Where | Likely class |
|---|---|---|
| Tech graph (nodes, edges, RP costs, race gating, benefits) | DATA MasterTechList.tech |
Game::TechDef / TechTree; TECHBEN_* enum in code |
| Which ship sections/weapons a tech unlocks | DATA (ship{} / requires) |
linkage tables |
| Weapon stats, damage falloff, fire-control | DATA *.weapon |
Game::WeaponDef |
Weapon flight/behavior per weaponclass |
CODE | weapon subclasses keyed by weaponclass string |
| Ship sections: stats, sockets, hardpoints, thrust | DATA *.shipsection |
Game::ShipSectionDef |
| Ship = command+mission+engine assembly rules | DATA (socket/section_type) | Game::ShipDesign |
| Turret sizes/tracking/models | DATA _turrets.txt |
Game::TurretDef |
| Stable net/save IDs | DATA _weapons.txt/_shipsections.txt |
id registry |
| Race sensor/color scalars | DATA species.txt |
Game::Species |
| Race economy/behavior specifics | CODE + tuning consts | per-race code paths |
| Economy: trade/bankruptcy/slaves/system bonus consts | DATA StrategyVars.txt |
global config singleton |
| Planet growth/output/terraform simulation | CODE (tuned by consts) | Game::Planet |
| Star map coords / names | DATA RealSpace.csv, systemnames.txt |
map generator |
| AI weapon/section/tech preferences | DATA Strategy/AI/*.csv |
AI advisor |
| Combat sim constants (ship/planet/drone/sensors…) | DATA Data/Combat/*.txt |
combat engine config |
| Scenarios / encounters | DATA .txt+.csv / .combat |
scenario loader |
| Strings / speech | DATA locale gob | string table |
Bottom line for reimplementation: stand up the Mars brace-block parser + the
flat-KV and CSV readers first; you then get the tech tree, all weapons, all ship
sections/turrets, races, scenarios, AI tables and every tuning constant essentially
for free. The remaining code work is behavior: weapon flight per weaponclass,
the planet/economy simulation (data only supplies its constants), per-race special
logic, and the combat/strategy engines that consume these catalogs.