Skip to content

research.json: Allow inline resmessage definition, derive major research from msgName/intel* properties#4810

Open
aubergineagain wants to merge 5 commits intoWarzone2100:masterfrom
aubergineagain:remove-research-json-techCode
Open

research.json: Allow inline resmessage definition, derive major research from msgName/intel* properties#4810
aubergineagain wants to merge 5 commits intoWarzone2100:masterfrom
aubergineagain:remove-research-json-techCode

Conversation

@aubergineagain
Copy link
Contributor

@aubergineagain aubergineagain commented Feb 5, 2026

Summary:

  • Allow research message audio and text to be defined inline within the research definition in research.json:
    • Specify both intelAudio and intelText (array of 4 strings) in the research definition to create a custom research message for that item, which will use the same icon as the research item.
  • Backwards compatible: If research item specifies msgName, it will work as expected. Note that intel* properties take precedence over msgName.
  • techCode property removed (or ignored); presence of intel* or msgName properties will make it major research, otherwise minor research.
  • Moddable: Filename is stored with the custom messages so game can load/unload when switching game mode or changing mods, etc. Compatible with diff mods.

Ultimate goal is complete removal of messages/resmessages*.json files at some point in the future.

TODO: Add some missing research messages that were identified during work on this PR (see original PR description below).

Fixes #4839

Click for original PR description...

All major research should specify msgName (the RES_MSG to display in intel screen), and all minor research should not. As such, techCode property in research.json files seems superfluous as it is mutually exclusive with msgName in those files.

This update uses the presence, or lack thereof, of msgName in the research.json file to set the research.techCode property, and removes all techCode properties from the research.json files in base/stats/ and mp/stats/ folders as they are no longer required.

EDIT: Refactored research.techCode (enum) -> research.isMajor (bool) to make code more legible. ini2json_research.py still references techCode but left that unchanged. Any occurrences of techCode in research.json files (eg. in Reclamation addon campaign) will be ignored.

Some research topics were missing both techCode (thus defaulting to 0 = major research) and msgName (effectively = minor research) properties, as follows:

base/stats/research.json:

ID Name Notes
"R-Defense-Pillbox-RotMG" Assault Gun Bunker Major research; msgName missing
"R-Wpn-RocketSlow-ROFRR01" Ripple Rocket Rapid Loader Minor research; techCode: 1 was missing
"R-Wpn-Missile2A-T" Scourge Missile Major research; msgName missing

mp/stats/research.json:

ID Name Notes
"R-Defense-MRLHvy" Heavy Rocket Battery Major research; msgName missing
"R-Sys-SpyTower" Nexus Link Tower Major research; msgName missing
"R-Wpn-Missile2A-T" Scourge Missile Major research; msgName missing
"R-Wpn-Rocket02-MRLHvy" Heavy Rocket Array Major research; msgName missing

Questions:

  • Should I do additional commit to copy the missing RES_MSG stuff between base/messages/ and mp/messages/, including the messages/strings/resstrings.txt, as applicable?
  • In the case of Scourge Missile, should I add a new RES_MSG - and if so, what ID should it use, and which resmessages*.json file(s) should it go in?
  • Is there any point to having multiple mp/messages/resmessages*.json files, given there are no campaign chapters in mp/skirmish/challenge games? Could it be pruned to just resmessagesall.json (in another PR)?

All major research should specify `msgName` (the `RES_MSG` to display in intel screen), and all minor research should not. As such, `techCode` property in `research.json` files seems superfluous as it is mutually exclusive with `msgName` in those files.

This update uses the presence, or lack thereof, of `msgName` in the `research.json` file to set the `research.techCode` property in research data, and then removes all `techCode` properties from the `research.json` files in `base/stats/` and `mp/stats/` folders.

Some research topics had neither `techCode: 1` nor `msgName`, which will be discussed in the PR and may require further commits to add missing research messages for those items.
Refactor emum `research.techCode` to a bool `research.isMajor` to make code more legible.
@KJeff01
Copy link
Member

KJeff01 commented Feb 17, 2026

Alfred added a few more mortar upgrades for campaign so you may have to look at those and rebase off master.

IDK what messages are missing between campaign/mp, or how much some of those .txt are still playing a role. Ultimately I could envision that we can probably rip out similar stuff away from the MP files to isolate the unique messages, and MP can have its own (small) unique files for mp-specific stuff only (and then resmessages from data/base gets loaded along side a resmessagemp).

For Scourge, I happened to find "msgName": "RES_W_ASM_AT" was good enough. Had to invent new messages for the AG bunker and RR rapid loader. For the MP side of that table, HRA and Nexus Link probably need new messages. I noticed MP TAC bunker was using a message for Assault Gun. So there is a possibility that there are duplicate or incorrect Intel Messages on some research.

And no, we don't need multiple message files for skirmish (or really campaign either). It's a relic from when there were split research files for the 3 campaigns (and probably a similar system for tech levels) when Pumpkin probably did init stuff in a more piecemeal fashion. As of now all those resmessageX.json files are loaded all at once together.

@aubergineagain
Copy link
Contributor Author

I've been making JSON Schemas for all the JSON files so should be able to detect any other missing stuff; will take a look at the weekend. I'll also take a look at what's going on in the code to see what's involved in trimming down to a single file for cam and a single file for mp. While it would be trivial to filter out any unused resmessage ids for mp, I don't know if they're used by mods so probably best to keep them.

@aubergineagain
Copy link
Contributor Author

tl;dr: Merging the resmessage*.json files would likely break mods so going to skip that. Will focus on investigating missing/duplicate/incorrect messages this weekend.

What I've found so far with the `resmessage*.json` loading - pure horror...

stats.wrf determines which files get loaded and what folder they are in (relative to either base/ or mp/ as applicable):

directory	"messages"
file		RESEARCHMSG	"messages.json"
file		RESEARCHMSG	"resmessages1.json"
file		RESEARCHMSG	"resmessages12.json"
file		RESEARCHMSG	"resmessages2.json"
file		RESEARCHMSG	"resmessages23.json"
file		RESEARCHMSG	"resmessages3.json"
file		RESEARCHMSG	"resmessagesall.json"

But any .wrf file could define RESEARCHMSG files, not just stats.wrf.

There doesn't seem to be any duplication (I'll need to write a script to fully confirm) across the files.

As an initial step to getting a handle on what's in each file, I asked an AI to categorize the messages - this is for campaign and I assume mp is similar:

- `resmessages1.json`: Early cyborg research (RES_CYMET1, RES_CYW_*)
- `resmessages2.json`: Mid-game cyborg and weapon research (RES_CYMET4, RES_W_*)
- `resmessages3.json`: Late-game research (RES_CYMET10, advanced weapons)
- `resmessages12.json`: Defensive structures and early weapons
- `resmessages23.json`: Engineering upgrades and mid-game weapons
- `resmessagesall.json`: General/base research items

So yeah, looks like cam 1, 2, 3, then stuff relating to cam 1+2, and 2+3, and general stuff that's not specific to a particular campaign. Knowing this at least gives some indication of where to add any missing messages.

To "confirm" that the entries in stats.wrf determine what gets loaded, went digging in code. All of the RESEARCHMSG files in the stats.wrf get loaded in sequence defined:

  • resource_parser.cpp seems to read the stats.wrf; I have literally no clue what kind of alien technology created this file.
// around line 1446 in whatever this is 👀🤷‍♀️:

bool success;
/* load a data file */
debug(LOG_NEVER, "file: %s %s", (yyvsp[(2) - (3)].sval), (yyvsp[(3) - (3)].sval));
success = resLoadFile((yyvsp[(2) - (3)].sval), (yyvsp[(3) - (3)].sval)); // <-- here
free((yyvsp[(2) - (3)].sval));
free((yyvsp[(3) - (3)].sval));

There's an ancient map somewhere drawn in charcoal with a drawing of a UFO with tentacles captioned "here be low level tokenizer".

  • so each file is passed to resLoadFile("RESEARCHMSG", "filename.json") (I assume path is appended to filename but not sure) in frameresource.cpp
  • which looks up "RESEARCHMSG" in psResTypes to determine what function to call?!
  • which results in a call to dataResearchMsgLoad() in data.cpp
  • which in turn calls loadResearchViewData() in data.cpp
  • all resmsg from all researchmessage*.json files ends up in a single apsViewData map, keyed by the id of the resmsg
  • if there's a duplicate resmsg id it looks like it will just silently overwrite the existing one, I think?

Anyways, there's no technical reason to have multiple files, but I suspect if they were combined in to single files, or even renamed, it would break any mods that alter research, so... looks like we're stuck with multi-file chaos.

That being said, if there's a will to break some mods I'd totally be up for merging them or at the very least renaming them so it's obvious what's in them. Or put them in a resmsg folder and just load all *.json in that folder rather than parsing .wrf files. But I think a more beneficial task would be rewriting resource_parser.cpp in javascript at some point, or converting .wrf to .json. But that's for later date, if ever.

@aubergineagain
Copy link
Contributor Author

aubergineagain commented Feb 19, 2026

Initial scans of the json files with basic validation script... loads of unused research messages in both cam and mp.

How much stuff would break if we renamed all the research messages to be the same as the id of the research they are linked to, because that would make so much more sense?

Checking research/resmessages json in BASE

./base/*.json

Loading files...

  • research.json
  • resmessages1.json
  • resmessages2.json
  • resmessages3.json
  • resmessages12.json
  • resmessages23.json
  • resmessagesall.json

7 Files Loaded

research.json 1/2

Check syntax/duplicates

  • [R-Cyborg-Legs02]: Missing both msgName and techCode
  • [R-Vehicle-Metals10]: Missing both msgName and techCode
  • [R-Vehicle-Metals11]: Missing both msgName and techCode
  • [R-Struc-Factory-Upgrade01]: Duplicate 'msgName': RES_ST_FU1 (already used by [R-Struc-Factory-Upgrade-AI])
  • [R-Wpn-Flamer-Range01-ScavReduce]: Missing both msgName and techCode
  • [R-Wpn-Flamer-Range01-ScavReduce-Undo]: Missing both msgName and techCode
  • [R-Defense-Pillbox-RotMG]: Missing both msgName and techCode
  • [R-Wpn-RocketSlow-ROFRR01]: Missing both msgName and techCode
  • [R-Wpn-Missile2A-T]: Missing both msgName and techCode

407 Topics Scanned

resmessages1.json

Check syntax/duplicates/usage

  • [RES_ST_FCY01]: Message not used in research.json

63 Messages Scanned

resmessages2.json

Check syntax/duplicates/usage

  • [RES_CYW_BB1]: Message not used in research.json
  • [RES_EMP_AA4]: Message not used in research.json
  • [RES_EMP_IncHOW]: Message not used in research.json
  • [RES_ST_FCY4]: Message not used in research.json
  • [RES_ST_VFU1]: Message not used in research.json
  • [RES_SY_VCBSU1]: Message not used in research.json
  • [RES_SY_VS1]: Message not used in research.json
  • [RES_WT11_HFL]: Message not used in research.json
  • [RES_W_AA1]: Message not used in research.json
  • [RES_W_IHOW]: Message not used in research.json
  • [RES_W_PBMB1]: Message not used in research.json
  • [RES_W_PBMB2]: Message not used in research.json

76 Messages Scanned

resmessages3.json

Check syntax/duplicates/usage

  • [RES_CYJ_ATM]: Message not used in research.json
  • [RES_CYJ_LS1]: Message not used in research.json
  • [RES_CYJ_MG4]: Message not used in research.json
  • [RES_CYJ_RKT]: Message not used in research.json
  • [RES_CYJ_RL1]: Message not used in research.json
  • [RES_CYMET10]: Message not used in research.json
  • [RES_CYW_MIS]: Message not used in research.json
  • [RES_CY_JP1]: Message not used in research.json
  • [RES_CY_LG3]: Message not used in research.json
  • [RES_HALFT3]: Message not used in research.json
  • [RES_ST_MAT10]: Message not used in research.json
  • [RES_ST_RFU7]: Message not used in research.json
  • [RES_ST_VFU4]: Message not used in research.json
  • [RES_SY_ACYB]: Message not used in research.json
  • [RES_SY_ADEF]: Message not used in research.json
  • [RES_SY_ASTRUC]: Message not used in research.json
  • [RES_SY_AVEH]: Message not used in research.json
  • [RES_SY_CBSU3]: Message not used in research.json
  • [RES_SY_VCBSU3]: Message not used in research.json
  • [RES_SY_VS3]: Message not used in research.json
  • [RES_TRACK3]: Message not used in research.json
  • [RES_V_EN10]: Message not used in research.json
  • [RES_V_MET10]: Message not used in research.json
  • [RES_V_P_H3]: Message not used in research.json
  • [RES_V_P_V3]: Message not used in research.json
  • [RES_V_P_W3]: Message not used in research.json
  • [RES_W_ASM_AT]: Message not used in research.json
  • [RES_W_ASM_BB]: Message not used in research.json
  • [RES_W_MG_D10]: Message not used in research.json
  • [RES_W_SMS_ROF1]: Message not used in research.json

101 Messages Scanned

resmessages12.json

Check syntax/duplicates/usage

  • [RES_SY_CBSU1]: Message not used in research.json

21 Messages Scanned

resmessages23.json

Check syntax/duplicates/usage

  • [RES_CY_LG2]: Message not used in research.json
  • [RES_SY_CBSU2]: Message not used in research.json
  • [RES_SY_VCBSU2]: Message not used in research.json
  • [RES_SY_VS2]: Message not used in research.json

18 Messages Scanned

resmessagesall.json

Check syntax/duplicates/usage

  • No errors found

14 Messages Scanned

research.json 2/2

Check msgName have corresponding resmessages*.json entry

  • No errors found

407 Topics Scanned


Checking research/resmessages json in MP

./mp/*.json

Loading files...

  • research.json
  • resmessages1.json
  • resmessages2.json
  • resmessages3.json
  • resmessages12.json
  • resmessages23.json
  • resmessagesall.json

7 Files Loaded

research.json 1/2

Check syntax/duplicates

  • [R-Defense-MRLHvy]: Missing both msgName and techCode
  • [R-Defense-RotMG]: Duplicate 'msgName': RES_DEF_RotMG (already used by [R-Defense-Cannon6])
  • [R-Sys-SpyTower]: Missing both msgName and techCode
  • [R-Wpn-Missile2A-T]: Missing both msgName and techCode
  • [R-Wpn-MortarEMP]: Duplicate 'msgName': RES_W_M2 (already used by [R-Wpn-Mortar02Hvy])
  • [R-Wpn-Rocket-Damage07]: Duplicate 'msgName': RES_W_RK_D4 (already used by [R-Wpn-Rocket-Damage04])
  • [R-Wpn-Rocket02-MRLHvy]: Missing both msgName and techCode

390 Topics Scanned

resmessages1.json

Check syntax/duplicates/usage

  • [RES_CYW_CN1]: Message not used in research.json
  • [RES_CYW_FL1]: Message not used in research.json
  • [RES_CYW_MG1]: Message not used in research.json
  • [RES_CYW_RK1]: Message not used in research.json
  • [RES_C_SL1]: Message not used in research.json
  • [RES_ST_FCY01]: Message not used in research.json
  • [RES_W_SRK_D1]: Message not used in research.json

59 Messages Scanned

resmessages2.json

Check syntax/duplicates/usage

  • [RES_CYW_BB1]: Message not used in research.json
  • [RES_CYW_MG4]: Message not used in research.json
  • [RES_EMP_IncHOW]: Message not used in research.json
  • [RES_EMP_RotCan]: Message not used in research.json
  • [RES_HALFT2]: Message not used in research.json
  • [RES_ST_FCY4]: Message not used in research.json
  • [RES_ST_VFU1]: Message not used in research.json
  • [RES_SY_VCBSU1]: Message not used in research.json
  • [RES_SY_VS1]: Message not used in research.json
  • [RES_TRACK2]: Message not used in research.json
  • [RES_V_P_H2]: Message not used in research.json
  • [RES_V_P_W2]: Message not used in research.json
  • [RES_WT11_HFL]: Message not used in research.json
  • [RES_W_AAAC1]: Message not used in research.json
  • [RES_W_AAD1]: Message not used in research.json
  • [RES_W_AAROF1]: Message not used in research.json
  • [RES_W_IHOW]: Message not used in research.json
  • [RES_W_MG_D5]: Message not used in research.json
  • [RES_W_PBMB1]: Message not used in research.json
  • [RES_W_PBMB2]: Message not used in research.json
  • [RES_W_SRK_D4]: Message not used in research.json

73 Messages Scanned

resmessages3.json

Check syntax/duplicates/usage

  • [RES_CYJ_ATM]: Message not used in research.json
  • [RES_CYJ_LS1]: Message not used in research.json
  • [RES_CYJ_MG4]: Message not used in research.json
  • [RES_CYJ_RKT]: Message not used in research.json
  • [RES_CYJ_RL1]: Message not used in research.json
  • [RES_CYMET10]: Message not used in research.json
  • [RES_CYW_ATM]: Message not used in research.json
  • [RES_CYW_LS1]: Message not used in research.json
  • [RES_CYW_MIS]: Message not used in research.json
  • [RES_CYW_RL1]: Message not used in research.json
  • [RES_CY_JP1]: Message not used in research.json
  • [RES_CY_LG3]: Message not used in research.json
  • [RES_DF_WU10]: Message not used in research.json
  • [RES_HALFT3]: Message not used in research.json
  • [RES_ST_MAT10]: Message not used in research.json
  • [RES_ST_RFU7]: Message not used in research.json
  • [RES_ST_VFU4]: Message not used in research.json
  • [RES_SY_ACYB]: Message not used in research.json
  • [RES_SY_ADEF]: Message not used in research.json
  • [RES_SY_ASTRUC]: Message not used in research.json
  • [RES_SY_AVEH]: Message not used in research.json
  • [RES_SY_CBSU3]: Message not used in research.json
  • [RES_SY_RESU1]: Message not used in research.json
  • [RES_SY_RESU2]: Message not used in research.json
  • [RES_SY_ST1]: Message not used in research.json
  • [RES_SY_VCBSU3]: Message not used in research.json
  • [RES_SY_VS3]: Message not used in research.json
  • [RES_TRACK3]: Message not used in research.json
  • [RES_V_EN10]: Message not used in research.json
  • [RES_V_MET10]: Message not used in research.json
  • [RES_V_P_H3]: Message not used in research.json
  • [RES_V_P_V2]: Message not used in research.json
  • [RES_V_P_V3]: Message not used in research.json
  • [RES_V_P_W3]: Message not used in research.json
  • [RES_W_AAAC3]: Message not used in research.json
  • [RES_W_AAD4]: Message not used in research.json
  • [RES_W_AAROF4]: Message not used in research.json
  • [RES_W_ASM_AT]: Message not used in research.json
  • [RES_W_ASM_BB]: Message not used in research.json
  • [RES_W_MG_D10]: Message not used in research.json
  • [RES_W_MG_D8]: Message not used in research.json
  • [RES_W_SMS_ROF1]: Message not used in research.json

98 Messages Scanned

resmessages12.json

Check syntax/duplicates/usage

  • [RES_SY_CBSU1]: Message not used in research.json
  • [RES_W_SRK_ROF1]: Message not used in research.json

21 Messages Scanned

resmessages23.json

Check syntax/duplicates/usage

  • [RES_CY_LG2]: Message not used in research.json
  • [RES_SY_CBSU2]: Message not used in research.json
  • [RES_SY_VCBSU2]: Message not used in research.json
  • [RES_SY_VS2]: Message not used in research.json
  • [RES_W_AAAC2]: Message not used in research.json

17 Messages Scanned

resmessagesall.json

Check syntax/duplicates/usage

  • [RES_CYS_CEN]: Message not used in research.json
  • [RES_CYS_MCH]: Message not used in research.json
  • [RES_CYW_GRN]: Message not used in research.json
  • [RES_CYW_TFL]: Message not used in research.json
  • [RES_C_CT3]: Message not used in research.json
  • [RES_C_CT4]: Message not used in research.json
  • [RES_ST_FCY7]: Message not used in research.json
  • [RES_SY_SPYT]: Message not used in research.json
  • [RES_SY_SUE1]: Message not used in research.json
  • [RES_W_SRK_AC3]: Message not used in research.json

83 Messages Scanned

research.json 2/2

Check msgName have corresponding resmessages*.json entry

  • No errors found

390 Topics Scanned


Script and files attached. Uses yoctocolors npm module to make errors red in console but can easily be removed.

resmsg.zip

@aubergineagain
Copy link
Contributor Author

aubergineagain commented Feb 20, 2026

I did some experimentation with putting resmessages in to single file, but also moving the resmsg audio / text in to research.json - super clean approach which would completely obsolete resmessages*.json and also the concept of major/minor research. Also means that for large mods (NRS, etc) or addon campaigns, we can batch convert their existing files to new format. See #4839 for examples.

I feel like this PR is probably obsolete if we go with enhanced research.json approach, but will wait to see what others think.

This is backwards compatible so shouldn't break any mods or addon campaigns.

If both `intelAudio` (string) and `intelText` (array of 4 strings) are defined in a `research.json` entry, create a `VIEWDATA` (id = research id) based on the research data, store it in `apsViewData`, and update `msgName` property in research data to be value of the research id. Additionally, the icon used for the intel screen is derived from the research item :)

If a research entry contains both `msgName` and `intel*` properties, the `intel*` properties take presendence over `msgName`.

The WzConfig filename is stored in the VIEWDATA, allowing modded `research.json` to be used, and also handles switching between campaign and multiplayer modes, etc., loading/unloading VIEWDATA as expected.

While this will add a little RAM bloat, due to duplication of the existing messages, that can be offset if we cull unused messages from the current `resmessages*.json` files (there are loads of messages defined that don't get used anywhere as far as I can tell).

This will enable mods / addon cams / etc, to port over to new format as and when desired, with the ultimate goal of completely removing the `messages/resmessages*.json` files as that data can be put in `research.json` instead.
@aubergineagain
Copy link
Contributor Author

New commit allows research message to be defined inline within the research data in research.json (and updates those json files accordingly). This is backwards compatible so shouldn't break any mods or addon campaigns:

If both intelAudio (string) and intelText (array of 4 strings) are defined in a research.json entry, create a VIEWDATA (id = research id) based on the research data, store it in apsViewData, and update msgName property in research data to be value of the research id. Additionally, the icon used for the intel screen is derived from the research item :)

If a research entry contains both msgName and intel* properties, the intel* properties take precedence over msgName.

The WzConfig.filename is stored in the VIEWDATA, allowing modded research.json to be used, and also handles switching between campaign and multiplayer modes, etc., loading/unloading VIEWDATA as expected.

While this will add a little RAM bloat, due to duplication of the existing messages, that can be offset if we cull unused messages from the current resmessages*.json files (there are loads of messages defined that don't get used anywhere as far as I can tell).

This will enable mods / addon cams / etc, to port over to new format as and when desired, with the ultimate goal of completely removing the messages/resmessages*.json files as that data can be put in research.json instead.

@aubergineagain aubergineagain changed the title Derive techCode from msgName presence in stats/research.json research.json: Allow inline resmessage definition, derive major research from msgName/intel* properties Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rethinking resmessages (research messages on intel screen)

2 participants