Extend event effects through add-building strip

This commit is contained in:
Jan Petykiewicz 2026-04-19 01:46:59 -07:00
commit b2da02befa
7 changed files with 3319 additions and 1161 deletions

View file

@ -1,6 +1,6 @@
{
"descriptor_count": 520,
"raw_table_binary_sha256": "01b0d2496cddefd80e7e8678930e00b13eb8607dd4960096f527564f02af36d4",
"descriptor_count": 614,
"raw_table_binary_sha256": "9e96b0695cb722a700f99c8dce498d34da7235e562b1e275bcc1764f8c9b7eb1",
"semantic_catalog_version": 1,
"descriptors": [
{
@ -2175,7 +2175,7 @@
{
"descriptor_id": 241,
"label": "2-D-2 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2184,7 +2184,7 @@
{
"descriptor_id": 242,
"label": "E-88 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2193,7 +2193,7 @@
{
"descriptor_id": 243,
"label": "Adler 2-2-2 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2202,7 +2202,7 @@
{
"descriptor_id": 244,
"label": "USA 103 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2211,7 +2211,7 @@
{
"descriptor_id": 245,
"label": "American 4-4-0 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2220,7 +2220,7 @@
{
"descriptor_id": 246,
"label": "Atlantic 4-4-2 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2229,7 +2229,7 @@
{
"descriptor_id": 247,
"label": "Baldwin 0-6-0 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2238,7 +2238,7 @@
{
"descriptor_id": 248,
"label": "Be 5/7 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2247,7 +2247,7 @@
{
"descriptor_id": 249,
"label": "Beuth 2-2-2 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -2256,7 +2256,7 @@
{
"descriptor_id": 250,
"label": "Big Boy 4-8-8-4 Availability",
"target_mask_bits": 11,
"target_mask_bits": 15,
"parameter_family": "locomotive_availability_scalar",
"runtime_key": null,
"runtime_status": "executable",
@ -4682,6 +4682,852 @@
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 520,
"label": "Add Building Slot 18",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 521,
"label": "Add Building Slot 19",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 522,
"label": "Add Building Slot 20",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 523,
"label": "Add Building Slot 21",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 524,
"label": "Add Building Slot 22",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 525,
"label": "Add Building Slot 23",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 526,
"label": "Add Building Slot 24",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 527,
"label": "Add Building Slot 25",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 528,
"label": "Add Building Slot 26",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 529,
"label": "Add Building Slot 27",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 530,
"label": "Add Building Slot 28",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 531,
"label": "Add Building Slot 29",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 532,
"label": "Add Building Slot 30",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 533,
"label": "Add Building Slot 31",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 534,
"label": "Add Building Slot 32",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 535,
"label": "Add Building Slot 33",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 536,
"label": "Add Building Slot 34",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 537,
"label": "Add Building Slot 35",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 538,
"label": "Add Building Slot 36",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 539,
"label": "Add Building Slot 37",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 540,
"label": "Add Building Slot 38",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 541,
"label": "Add Building Slot 39",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 542,
"label": "Add Building Slot 40",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 543,
"label": "Add Building Slot 41",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 544,
"label": "Add Building Slot 42",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 545,
"label": "Add Building Slot 43",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 546,
"label": "Add Building Slot 44",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 547,
"label": "Add Building Slot 45",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 548,
"label": "Add Building Slot 46",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 549,
"label": "Add Building Slot 47",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 550,
"label": "Add Building Slot 48",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 551,
"label": "Add Building Slot 49",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 552,
"label": "Add Building Slot 50",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 553,
"label": "Add Building Slot 51",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 554,
"label": "Add Building Slot 52",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 555,
"label": "Add Building Slot 53",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 556,
"label": "Add Building Slot 54",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 557,
"label": "Add Building Slot 55",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 558,
"label": "Add Building Slot 56",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 559,
"label": "Add Building Slot 57",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 560,
"label": "Add Building Slot 58",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 561,
"label": "Add Building Slot 59",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 562,
"label": "Add Building Slot 60",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 563,
"label": "Add Building Slot 61",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 564,
"label": "Add Building Slot 62",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 565,
"label": "Add Building Slot 63",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 566,
"label": "Add Building Slot 64",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 567,
"label": "Add Building Slot 65",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 568,
"label": "Add Building Slot 66",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 569,
"label": "Add Building Slot 67",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 570,
"label": "Add Building Slot 68",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 571,
"label": "Add Building Slot 69",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 572,
"label": "Add Building Slot 70",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 573,
"label": "Add Building Slot 71",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 574,
"label": "Add Building Slot 72",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 575,
"label": "Add Building Slot 73",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 576,
"label": "Add Building Slot 74",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 577,
"label": "Add Building Slot 75",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 578,
"label": "Add Building Slot 76",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 579,
"label": "Add Building Slot 77",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 580,
"label": "Add Building Slot 78",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 581,
"label": "Add Building Slot 79",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 582,
"label": "Add Building Slot 80",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 583,
"label": "Add Building Slot 81",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 584,
"label": "Add Building Slot 82",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 585,
"label": "Add Building Slot 83",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 586,
"label": "Add Building Slot 84",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 587,
"label": "Add Building Slot 85",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 588,
"label": "Add Building Slot 86",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 589,
"label": "Add Building Slot 87",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 590,
"label": "Add Building Slot 88",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 591,
"label": "Add Building Slot 89",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 592,
"label": "Add Building Slot 90",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 593,
"label": "Add Building Slot 91",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 594,
"label": "Add Building Slot 92",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 595,
"label": "Add Building Slot 93",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 596,
"label": "Add Building Slot 94",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 597,
"label": "Add Building Slot 95",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 598,
"label": "Add Building Slot 96",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 599,
"label": "Add Building Slot 97",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 600,
"label": "Add Building Slot 98",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 601,
"label": "Add Building Slot 99",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 602,
"label": "Add Building Slot 100",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 603,
"label": "Add Building Slot 101",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 604,
"label": "Add Building Slot 102",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 605,
"label": "Add Building Slot 103",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 606,
"label": "Add Building Slot 104",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 607,
"label": "Add Building Slot 105",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 608,
"label": "Add Building Slot 106",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 609,
"label": "Add Building Slot 107",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 610,
"label": "Add Building Slot 108",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 611,
"label": "Add Building Slot 109",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 612,
"label": "Add Building Slot 110",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
},
{
"descriptor_id": 613,
"label": "Add Building Slot 111",
"target_mask_bits": 8,
"parameter_family": "world_building_spawn",
"runtime_key": null,
"runtime_status": "shell_owned",
"executable_in_runtime": false
}
]
}

File diff suppressed because it is too large Load diff

View file

@ -125,6 +125,9 @@ enum Command {
RuntimeInspectSmp {
smp_path: PathBuf,
},
RuntimeInspectCompactEventDispatchCluster {
root_path: PathBuf,
},
RuntimeSummarizeSaveLoad {
smp_path: PathBuf,
},
@ -293,6 +296,51 @@ struct RuntimeSmpInspectionOutput {
inspection: SmpInspectionReport,
}
#[derive(Debug, Serialize)]
struct RuntimeCompactEventDispatchClusterOutput {
root_path: String,
report: RuntimeCompactEventDispatchClusterReport,
}
#[derive(Debug, Serialize)]
struct RuntimeCompactEventDispatchClusterReport {
maps_scanned: usize,
maps_with_event_runtime_collection: usize,
maps_with_dispatch_strip_records: usize,
dispatch_strip_record_count: usize,
unknown_descriptor_ids: Vec<u32>,
unknown_descriptor_special_condition_label_matches: Vec<String>,
unknown_descriptor_occurrences:
BTreeMap<u32, Vec<RuntimeCompactEventDispatchClusterOccurrence>>,
}
#[derive(Debug, Clone, Serialize)]
struct RuntimeCompactEventDispatchClusterOccurrence {
path: String,
record_index: usize,
live_entry_id: u32,
payload_family: String,
signature_family: Option<String>,
condition_tuples: Vec<RuntimeCompactEventDispatchClusterConditionTuple>,
rows: Vec<RuntimeCompactEventDispatchClusterRow>,
}
#[derive(Debug, Clone, Serialize)]
struct RuntimeCompactEventDispatchClusterConditionTuple {
raw_condition_id: i32,
subtype: u8,
metric: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
struct RuntimeCompactEventDispatchClusterRow {
group_index: usize,
descriptor_id: u32,
descriptor_label: Option<String>,
opcode: u8,
raw_scalar_value: i32,
}
#[derive(Debug, Serialize)]
struct RuntimeSaveLoadSummaryOutput {
path: String,
@ -898,6 +946,9 @@ fn real_main() -> Result<(), Box<dyn std::error::Error>> {
Command::RuntimeInspectSmp { smp_path } => {
run_runtime_inspect_smp(&smp_path)?;
}
Command::RuntimeInspectCompactEventDispatchCluster { root_path } => {
run_runtime_inspect_compact_event_dispatch_cluster(&root_path)?;
}
Command::RuntimeSummarizeSaveLoad { smp_path } => {
run_runtime_summarize_save_load(&smp_path)?;
}
@ -1116,6 +1167,14 @@ fn parse_command() -> Result<Command, Box<dyn std::error::Error>> {
smp_path: PathBuf::from(path),
})
}
[command, subcommand, root_path]
if command == "runtime"
&& subcommand == "inspect-compact-event-dispatch-cluster" =>
{
Ok(Command::RuntimeInspectCompactEventDispatchCluster {
root_path: PathBuf::from(root_path),
})
}
[command, subcommand, path]
if command == "runtime" && subcommand == "summarize-save-load" =>
{
@ -1400,7 +1459,7 @@ fn parse_command() -> Result<Command, Box<dyn std::error::Error>> {
})
}
_ => Err(
"usage: rrt-cli [validate [repo-root] | finance eval <snapshot.json> | finance diff <left.json> <right.json> | runtime validate-fixture <fixture.json> | runtime summarize-fixture <fixture.json> | runtime export-fixture-state <fixture.json> <snapshot.json> | runtime diff-state <left.json> <right.json> | runtime summarize-state <snapshot.json> | runtime import-state <input.json> <snapshot.json> | runtime inspect-smp <file.smp> | runtime summarize-save-load <file.smp> | runtime load-save-slice <file.smp> | runtime inspect-save-company-chairman <file.smp> | runtime inspect-save-placed-structure-triplets <file.smp> | runtime compare-region-fixed-row-runs <left.gms> <right.gms> | runtime inspect-periodic-company-service-trace <file.smp> | runtime inspect-region-service-trace <file.smp> | runtime inspect-infrastructure-asset-trace <file.smp> | runtime inspect-save-region-queued-notice-records <file.smp> | runtime inspect-placed-structure-dynamic-side-buffer <file.smp> | runtime inspect-unclassified-save-collections <file.smp> | runtime import-save-state <file.smp> <snapshot.json> | runtime export-save-slice <file.smp> <save-slice.json> | runtime export-overlay-import <snapshot.json> <save-slice.json> <overlay-import.json> | runtime inspect-pk4 <file.pk4> | runtime inspect-cargo-types <CargoTypes-dir> | runtime inspect-cargo-skins <Cargo106.PK4> | runtime inspect-cargo-economy-sources <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-cargo-production-selector <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-cargo-price-selector <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-win <file.win> | runtime extract-pk4-entry <file.pk4> <entry-name> <output-path> | runtime inspect-campaign-exe <RT3.exe> | runtime compare-classic-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-105-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-candidate-table <file1> <file2> [fileN...] | runtime compare-recipe-book-lines <file1> <file2> [fileN...] | runtime compare-setup-payload-core <file1> <file2> [fileN...] | runtime compare-setup-launch-payload <file1> <file2> [fileN...] | runtime compare-post-special-conditions-scalars <file1> <file2> [fileN...] | runtime scan-candidate-table-headers <root-dir> | runtime scan-special-conditions <root-dir> | runtime scan-aligned-runtime-rule-band <root-dir> | runtime scan-post-special-conditions-scalars <root-dir> | runtime scan-post-special-conditions-tail <root-dir> | runtime scan-recipe-book-lines <root-dir> | runtime export-profile-block <save.gms> <profile.json>]"
"usage: rrt-cli [validate [repo-root] | finance eval <snapshot.json> | finance diff <left.json> <right.json> | runtime validate-fixture <fixture.json> | runtime summarize-fixture <fixture.json> | runtime export-fixture-state <fixture.json> <snapshot.json> | runtime diff-state <left.json> <right.json> | runtime summarize-state <snapshot.json> | runtime import-state <input.json> <snapshot.json> | runtime inspect-smp <file.smp> | runtime inspect-compact-event-dispatch-cluster <maps-dir> | runtime summarize-save-load <file.smp> | runtime load-save-slice <file.smp> | runtime inspect-save-company-chairman <file.smp> | runtime inspect-save-placed-structure-triplets <file.smp> | runtime compare-region-fixed-row-runs <left.gms> <right.gms> | runtime inspect-periodic-company-service-trace <file.smp> | runtime inspect-region-service-trace <file.smp> | runtime inspect-infrastructure-asset-trace <file.smp> | runtime inspect-save-region-queued-notice-records <file.smp> | runtime inspect-placed-structure-dynamic-side-buffer <file.smp> | runtime inspect-unclassified-save-collections <file.smp> | runtime import-save-state <file.smp> <snapshot.json> | runtime export-save-slice <file.smp> <save-slice.json> | runtime export-overlay-import <snapshot.json> <save-slice.json> <overlay-import.json> | runtime inspect-pk4 <file.pk4> | runtime inspect-cargo-types <CargoTypes-dir> | runtime inspect-cargo-skins <Cargo106.PK4> | runtime inspect-cargo-economy-sources <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-cargo-production-selector <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-cargo-price-selector <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-win <file.win> | runtime extract-pk4-entry <file.pk4> <entry-name> <output-path> | runtime inspect-campaign-exe <RT3.exe> | runtime compare-classic-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-105-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-candidate-table <file1> <file2> [fileN...] | runtime compare-recipe-book-lines <file1> <file2> [fileN...] | runtime compare-setup-payload-core <file1> <file2> [fileN...] | runtime compare-setup-launch-payload <file1> <file2> [fileN...] | runtime compare-post-special-conditions-scalars <file1> <file2> [fileN...] | runtime scan-candidate-table-headers <root-dir> | runtime scan-special-conditions <root-dir> | runtime scan-aligned-runtime-rule-band <root-dir> | runtime scan-post-special-conditions-scalars <root-dir> | runtime scan-post-special-conditions-tail <root-dir> | runtime scan-recipe-book-lines <root-dir> | runtime export-profile-block <save.gms> <profile.json>]"
.into(),
),
}
@ -1605,6 +1664,116 @@ fn run_runtime_inspect_smp(smp_path: &Path) -> Result<(), Box<dyn std::error::Er
Ok(())
}
fn run_runtime_inspect_compact_event_dispatch_cluster(
root_path: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
let mut input_paths = Vec::new();
collect_compact_event_dispatch_cluster_input_paths(root_path, &mut input_paths)?;
input_paths.sort();
let mut maps_with_event_runtime_collection = 0usize;
let mut maps_with_dispatch_strip_records = 0usize;
let mut dispatch_strip_record_count = 0usize;
let mut unknown_descriptor_occurrences =
BTreeMap::<u32, Vec<RuntimeCompactEventDispatchClusterOccurrence>>::new();
for path in &input_paths {
let inspection = inspect_smp_file(path)?;
let Some(summary) = inspection.event_runtime_collection_summary else {
continue;
};
maps_with_event_runtime_collection += 1;
let mut map_dispatch_strip_record_count = 0usize;
for record in &summary.records {
let matching_rows = record
.grouped_effect_rows
.iter()
.filter(|row| {
compact_event_dispatch_strip_opcode(row.opcode)
&& row.descriptor_label.is_none()
})
.fold(
BTreeMap::<u32, Vec<RuntimeCompactEventDispatchClusterRow>>::new(),
|mut grouped, row| {
grouped.entry(row.descriptor_id).or_default().push(
RuntimeCompactEventDispatchClusterRow {
group_index: row.group_index,
descriptor_id: row.descriptor_id,
descriptor_label: row.descriptor_label.clone(),
opcode: row.opcode,
raw_scalar_value: row.raw_scalar_value,
},
);
grouped
},
);
if matching_rows.is_empty() {
continue;
}
map_dispatch_strip_record_count += 1;
let condition_tuples = record
.standalone_condition_rows
.iter()
.map(|row| RuntimeCompactEventDispatchClusterConditionTuple {
raw_condition_id: row.raw_condition_id,
subtype: row.subtype,
metric: row.metric.clone(),
})
.collect::<Vec<_>>();
let signature_family = compact_event_signature_family_from_notes(&record.notes);
for (descriptor_id, rows) in matching_rows {
unknown_descriptor_occurrences
.entry(descriptor_id)
.or_default()
.push(RuntimeCompactEventDispatchClusterOccurrence {
path: path.display().to_string(),
record_index: record.record_index,
live_entry_id: record.live_entry_id,
payload_family: record.payload_family.clone(),
signature_family: signature_family.clone(),
condition_tuples: condition_tuples.clone(),
rows,
});
}
}
if map_dispatch_strip_record_count > 0 {
maps_with_dispatch_strip_records += 1;
dispatch_strip_record_count += map_dispatch_strip_record_count;
}
}
let unknown_descriptor_ids = unknown_descriptor_occurrences
.keys()
.copied()
.collect::<Vec<_>>();
let unknown_descriptor_special_condition_label_matches = unknown_descriptor_ids
.iter()
.filter_map(|descriptor_id| {
special_condition_label_for_compact_dispatch_descriptor(*descriptor_id)
.map(|label| format!("{descriptor_id} -> {label}"))
})
.collect::<Vec<_>>();
let report = RuntimeCompactEventDispatchClusterOutput {
root_path: root_path.display().to_string(),
report: RuntimeCompactEventDispatchClusterReport {
maps_scanned: input_paths.len(),
maps_with_event_runtime_collection,
maps_with_dispatch_strip_records,
dispatch_strip_record_count,
unknown_descriptor_ids,
unknown_descriptor_special_condition_label_matches,
unknown_descriptor_occurrences,
},
};
println!("{}", serde_json::to_string_pretty(&report)?);
Ok(())
}
fn run_runtime_summarize_save_load(smp_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
let inspection = inspect_smp_file(smp_path)?;
let summary = inspection.save_load_summary.ok_or_else(|| {
@ -3731,6 +3900,73 @@ fn parse_special_condition_slot_index(label: &str) -> Option<u8> {
slot_index.parse().ok()
}
fn compact_event_dispatch_strip_opcode(opcode: u8) -> bool {
matches!(opcode, 0x04..=0x08 | 0x0d | 0x10..=0x13 | 0x16)
}
fn compact_event_signature_family_from_notes(notes: &[String]) -> Option<String> {
notes.iter().find_map(|note| {
note.strip_prefix("compact signature family = ")
.map(ToString::to_string)
})
}
fn special_condition_label_for_compact_dispatch_descriptor(
descriptor_id: u32,
) -> Option<&'static str> {
let band_index = descriptor_id.checked_sub(535)? as usize;
SPECIAL_CONDITION_LABELS.get(band_index).copied()
}
fn collect_compact_event_dispatch_cluster_input_paths(
root_path: &Path,
out: &mut Vec<PathBuf>,
) -> Result<(), Box<dyn std::error::Error>> {
let metadata = match fs::symlink_metadata(root_path) {
Ok(metadata) => metadata,
Err(err) if err.kind() == std::io::ErrorKind::PermissionDenied => return Ok(()),
Err(err) => return Err(err.into()),
};
if metadata.file_type().is_symlink() {
return Ok(());
}
if root_path.is_file() {
if root_path
.extension()
.and_then(|ext| ext.to_str())
.is_some_and(|ext| ext.eq_ignore_ascii_case("gmp"))
{
out.push(root_path.to_path_buf());
}
return Ok(());
}
let entries = match fs::read_dir(root_path) {
Ok(entries) => entries,
Err(err) if err.kind() == std::io::ErrorKind::PermissionDenied => return Ok(()),
Err(err) => return Err(err.into()),
};
for entry in entries {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
collect_compact_event_dispatch_cluster_input_paths(&path, out)?;
continue;
}
if path
.extension()
.and_then(|ext| ext.to_str())
.is_some_and(|ext| ext.eq_ignore_ascii_case("gmp"))
{
out.push(path);
}
}
Ok(())
}
fn parse_hex_offset(text: &str) -> Option<usize> {
text.strip_prefix("0x")
.and_then(|digits| usize::from_str_radix(digits, 16).ok())

View file

@ -9485,6 +9485,16 @@ fn parse_event_runtime_collection_summary_with_tag_width(
.collect::<Vec<_>>();
mutation_candidate_unknown_descriptor_ids.sort_unstable();
mutation_candidate_unknown_descriptor_ids.dedup();
let mut mutation_candidate_special_condition_label_matches =
mutation_candidate_unknown_descriptor_ids
.iter()
.filter_map(|descriptor_id| {
known_special_condition_label_for_compact_descriptor_id(*descriptor_id)
.map(|label| format!("{descriptor_id} -> {label}"))
})
.collect::<Vec<_>>();
mutation_candidate_special_condition_label_matches.sort();
mutation_candidate_special_condition_label_matches.dedup();
let mut dispatch_strip_unknown_condition_ids = records
.iter()
.filter(|record| {
@ -9533,6 +9543,12 @@ fn parse_event_runtime_collection_summary_with_tag_width(
mutation_candidate_unknown_descriptor_ids
));
}
if !mutation_candidate_special_condition_label_matches.is_empty() {
control_lane_notes.push(format!(
"unlabeled 0x00431b20 dispatch-strip descriptor ids matching known special-condition label_id-2000 values = {:?}",
mutation_candidate_special_condition_label_matches
));
}
if !dispatch_strip_unknown_condition_ids.is_empty() {
control_lane_notes.push(format!(
"standalone condition ids still missing checked-in labels in the 0x00431b20 dispatch strip = {:?}",
@ -9587,6 +9603,16 @@ fn opcode_reaches_world_apply_compact_runtime_effect_dispatch_strip(opcode: u8)
matches!(opcode, 0x04..=0x08 | 0x0d | 0x10..=0x13 | 0x16)
}
fn known_special_condition_label_for_compact_descriptor_id(
descriptor_id: u32,
) -> Option<&'static str> {
let label_id = descriptor_id.checked_add(2000)?;
KNOWN_SPECIAL_CONDITION_DEFINITIONS
.iter()
.find(|definition| definition.label_id == label_id)
.map(|definition| definition.label)
}
fn try_parse_nondirect_event_runtime_record_summaries(
records_payload: &[u8],
records_payload_offset: usize,
@ -23874,8 +23900,8 @@ mod tests {
#[test]
fn checked_in_event_effect_table_covers_the_full_exported_descriptor_set() {
let rows = checked_in_event_effect_descriptor_rows();
assert_eq!(rows.len(), 520);
for descriptor_id in 0..520_u32 {
assert_eq!(rows.len(), 614);
for descriptor_id in 0..614_u32 {
assert!(
real_grouped_effect_descriptor_metadata(descriptor_id).is_some(),
"descriptor {descriptor_id} should be recoverable from the checked-in effect table"

View file

@ -281,13 +281,26 @@ Working rule:
`East Coast, USA.gmp`, `Japan Trembles.gmp`, and `State of Germany.gmp`; it does not appear on
the `opcode 8` deactivation branch, so grouped descriptor id `548` is not just the obvious
compact stand-in for ordinary descriptor `13`
- the frontier is now best treated as a small compact-only opcode-`8` cluster rather than a
one-id anomaly:
the installed-map sweep now shows unlabeled grouped descriptor ids `[521, 526, 528, 548, 563]`
in the `0x00431b20` dispatch strip, all currently on opcode `8`, with current sightings in
`Alternate USA.gmp`, `Rhodes Unfinished.gmp`, `Louisiana.gmp`, and `Texas Tea.gmp`; the next
static-analysis pass should treat that as one branch family above `0x00426d60`, not five
unrelated missing labels
- that compact opcode-`8` cluster is now grounded as an artifact-boundary problem rather than a
mysterious compact-only id family:
direct binary inspection of the `0x00610398` EventEffects table shows the contiguous table does
not stop at row `519`; it continues cleanly through row `613`, with the extractor-side
sequential descriptor invariant still holding. The checked-in extractor and semantic catalog now
cover the full `614`-row export instead of the old truncated `520`-row slice
- that closes the earlier unlabeled cluster:
grouped descriptor ids `521`, `526`, `528`, `548`, and `563` are now recovered as
`Add Building Slot 19`, `Add Building Slot 24`, `Add Building Slot 26`, `Add Building Slot 46`,
and `Add Building Slot 61` respectively, all in the widened shell-owned add-building strip
`503..613`
- the earlier `label_id - 2000` bridge for `548` and `563` is now known to be a false lead:
those numeric collisions hit the special-condition label table
(`Disable Building Stations`, `Completely Disable Money-Related Things`), but the extended
EventEffects table proves the actual grouped descriptors are add-building slots, not
special-condition verbs
- the compact opcode-`8` frontier therefore shifts:
the next static-analysis pass should target which add-building slot numbers correspond to which
concrete building classes and whether opcode `8` on that shell-owned strip means a distinct
add-building shell flow, not more missing-label recovery
- the concrete owner strip above that bundle is grounded now too:
`0x00433060` is the direct non-direct serializer loop that writes `0x4e99/0x4e9a/0x4e9b`,
calls `0x00430d70` per live collection row, and sits beside the sibling `0x00433130` size/load

View file

@ -147,6 +147,10 @@ def classify(
parameter_family = "company_governance_scalar"
runtime_status = "executable"
executable_in_runtime = True
elif 39 <= descriptor_id <= 54:
parameter_family = "runtime_variable_scalar"
runtime_status = "executable"
executable_in_runtime = True
elif 59 <= descriptor_id <= 104:
parameter_family = "world_scalar_override"
runtime_key = normalize_world_scalar_key(label)
@ -217,14 +221,10 @@ def classify(
runtime_key = "world.all_electric_locos_available"
runtime_status = "executable"
executable_in_runtime = True
elif 503 <= descriptor_id <= 519:
elif 503 <= descriptor_id <= 613:
parameter_family = "world_building_spawn"
label = f"Add Building Slot {descriptor_id - 502}"
runtime_status = "shell_owned"
elif signature_byte_0x63 == 0 and signature_byte_0x64 == 0x8F:
parameter_family = "runtime_variable_scalar"
runtime_status = "executable"
executable_in_runtime = True
elif "Earthquake" in label or "Storm" in label:
parameter_family = "world_disaster_scalar"

View file

@ -11,7 +11,7 @@ from pathlib import Path
TABLE_BASE_VA = 0x00610398
ROW_STRIDE = 0x6E
ROW_COUNT = 520
MAX_ROW_COUNT = 2048
IMAGE_BASE = 0x00400000
@ -27,17 +27,20 @@ def load_lng_labels(path: Path) -> dict[int, str]:
def extract_rows(exe_bytes: bytes, labels: dict[int, str]) -> list[dict[str, object]]:
table_offset = TABLE_BASE_VA - IMAGE_BASE
rows: list[dict[str, object]] = []
for row_index in range(ROW_COUNT):
for row_index in range(MAX_ROW_COUNT):
row = exe_bytes[
table_offset + row_index * ROW_STRIDE : table_offset + (row_index + 1) * ROW_STRIDE
]
if len(row) < ROW_STRIDE:
break
descriptor_id = struct.unpack_from("<I", row, 0x04)[0]
if descriptor_id != row_index:
break
label_id = struct.unpack_from("<H", row, 0x6A)[0]
rows.append(
{
"row_index": row_index,
"descriptor_id": struct.unpack_from("<I", row, 0x04)[0],
"descriptor_id": descriptor_id,
"selector_order": struct.unpack_from("<f", row, 0x00)[0],
"target_mask_bits": row[0x65],
"label_id": label_id,
@ -62,12 +65,12 @@ def main() -> None:
artifact = {
"table_base_va": f"0x{TABLE_BASE_VA:08x}",
"row_stride_hex": f"0x{ROW_STRIDE:02x}",
"descriptor_count": ROW_COUNT,
"binary_path_hint": str(args.exe),
"language_path_hint": str(args.lng),
"binary_sha256": hashlib.sha256(exe_bytes).hexdigest(),
"descriptors": extract_rows(exe_bytes, labels),
}
artifact["descriptors"] = extract_rows(exe_bytes, labels)
artifact["descriptor_count"] = len(artifact["descriptors"])
args.out.write_text(json.dumps(artifact, indent=2) + "\n", encoding="utf-8")