- Joined
- Jan 3, 2022
- Messages
- 364
There's one thing about Warcraft 3 maps that surprised me the most: the maps are entirely dynamic. Well, almost. Practically everything you think is saved permanently with WorldEdit, it is actually set up in war3map.j with code when the map loads. This means you can edit a whole lot about a map and its settings by editing war3map.j.
So I thought: can we have a backwards-compatible map file that opens in 1.26/1.27 with 12 players but with 24 players in Reforged?
I created a map in 1.26 WorldEdit and prepared spawn terrain for spawn locations of players 1-24 and touched nothing else. Saved the map and began to edit the war3map.j file:
The map now worked as before in 1.26 with 12 players and in Reforged... it still had 12 players?! WTF but I had done everything like WE would do! It turned out the game is very backwards-compatible and will initiate the game options differently for old maps 
Blizzard.j from 1.26:
Blizzard.j from 1.32:
You do see the problem, right? In 1.26 the numbers were constant-constant, I mean hardcoded constants that haven't changed since RoC. This is why obfuscators and their dog assumed that VICTIM/EXTRA player IDs were 13/14 and broke for Reforged maps. And many old maps had these values hardcoded too, so instead of bj_PLAYER_NEUTRAL_VICTIM a map maker would use 13 directly in code, optimization riii-ight? Blizzard devs could not have changed these numbers for old maps or these would have been broken.
Instead the Blizzard.j code for old and new maps in Reforged is the same, but the return values are different. When you play a Reforged map in Reforged, GetBJMaxPlayers() returns 24. If you load an old map in Reforged, GetBJMaxPlayers() returns 12 and so on.
-> It is not possible to dynamically change the player count from 12 to 24 in code.
Reforged initializes only 12 players when it detects an old map
Note: the spawns at the bottom aren't aligned perfectly, but it doesn't need to be perfect. It just needs to work
So I thought: can we have a backwards-compatible map file that opens in 1.26/1.27 with 12 players but with 24 players in Reforged?
I created a map in 1.26 WorldEdit and prepared spawn terrain for spawn locations of players 1-24 and touched nothing else. Saved the map and began to edit the war3map.j file:
- confg() function - where map preview and lobby screen is set up
- Change SetPlayers(number) and SetTeams(number)
- Add DefineStartLocation for players 13-24
- Add SetPlayerSlotAvailable for players 13-24
- InitAllyPriorities()function
- Add: (i = 0-based player ID)
call SetStartLocPrioCount( i, 1 )
call SetStartLocPrio( i, 0, i-1, MAP_LOC_PRIO_HIGH )
call SetStartLocPrio( i, 1, i+1, MAP_LOC_PRIO_HIGH )
- Add: (i = 0-based player ID)
- InitCustomTeams() function
- SetPlayerTeam(playerID) for 13-24
- InitCustomPlayerSlots() function
- Again for players 13-24:
call SetPlayerStartLocation( Player(i), i )
call ForcePlayerStartLocation( Player(i), i )
call SetPlayerColor( Player(i), ConvertPlayerColor(i) )
call SetPlayerRacePreference( Player(i), RACE_PREF_HUMAN )
call SetPlayerRaceSelectable( Player(i), true )
call SetPlayerController( Player(i), MAP_CONTROL_COMPUTER )
- Again for players 13-24:
- That's all folks! or not
Blizzard.j from 1.26:
JASS:
// Game constants
constant integer bj_MAX_PLAYERS = 12
constant integer bj_PLAYER_NEUTRAL_VICTIM = 13
constant integer bj_PLAYER_NEUTRAL_EXTRA = 14
constant integer bj_MAX_PLAYER_SLOTS = 16
JASS:
// Game constants
constant integer bj_MAX_PLAYERS = GetBJMaxPlayers()
constant integer bj_PLAYER_NEUTRAL_VICTIM = GetBJPlayerNeutralVictim()
constant integer bj_PLAYER_NEUTRAL_EXTRA = GetBJPlayerNeutralExtra()
constant integer bj_MAX_PLAYER_SLOTS = GetBJMaxPlayerSlots()
Instead the Blizzard.j code for old and new maps in Reforged is the same, but the return values are different. When you play a Reforged map in Reforged, GetBJMaxPlayers() returns 24. If you load an old map in Reforged, GetBJMaxPlayers() returns 12 and so on.
-> It is not possible to dynamically change the player count from 12 to 24 in code.

Reforged initializes only 12 players when it detects an old map
Further work: Documentation
If it's going to be required to edit the player and team settings manually in code, then these functions must be documented. You can find their usage in war3map.j when you open a map's MPQ with MPQEditor:- DefineStartLocation
- SetPlayerSlotAvailable:
- SetStartLocPrioCount:
- SetStartLocPrio:
- SetPlayerStartLocation:
- ForcePlayerStartLocation:
- SetPlayerTeam:
- SetPlayers:
- SetTeams:
- SetPlayerColor:
- SetPlayerRacePreference:
- SetPlayerRaceSelectable:
- SetPlayerController:
UPDATE: IT WORKS!
A single map file loads with:- 12 players in versions 1.24-1.28.5
- 24 players in Reforged (I set it to support 1.31+, in reality it's possible since 1.29.0.8803)
Note: the spawns at the bottom aren't aligned perfectly, but it doesn't need to be perfect. It just needs to work
Short description of what needs to be done
I feel pretty angry at Blizzard over the Warsmash take down, so I won't upload the tools nor write a proper tutorial. A legally concise spit in the face, that's something they could be proud of. Maybe I will cool down over time or a donation will soothe my stance on them, their game, and the time spent specifically on this (PM).- The map must be created and edited in old WorldEditor.
- See the spoiler above: "Code changes to war3map.j"
- This means your players 13-24 cannot be modified in WE: no priorities, tech, pre-spawned units etc. Instead this is for maps with Jass code
- war3map.w3i made for old versions:
- placed in map's MPQ root (./war3map.w3i)
- w3i_format=25
- we_version=6059
- any number of players in player array (seemingly ignored by game if >12, I didn't test impact on neutrals)
- war3map.w3i made for Reforged versions:
- placed in _Locales override folders FOR EACH locale:
- ├── _Locales
│ ├── deDE.w3mod/
│ │ └── war3map.w3i (LOADED FOR GERMAN PLAYERS)
and so on:
│ ├── enUS.w3mod/
│ ├── esES.w3mod/
│ ├── esMX.w3mod/
│ ├── frFR.w3mod/
│ ├── itIT.w3mod/
│ ├── koKR.w3mod/
│ ├── plPL.w3mod/
│ ├── ptBR.w3mod/
│ ├── ruRU.w3mod/
│ ├── zhCN.w3mod (Chinese, Mainland)
│ └── zhTW.w3mod (Chinese, Taiwan)
│ │ └──war3map.w3i (LOADED FOR zhTW PLAYERS) - Yes, it is currently replicated 12 times
- Yes, if a new locale were to be released, the map would break in Reforged for them
- ├── _Locales
- w3i_format=28 (theoretically 1.29's w3i_format is sufficient, but there's no documentation)
- The w3i must be in a correct format. I did not test yet if Reforged will take old w3i format but new we_version and work
- we_version=6060 and above (my tool set to 6072 aka 1.31.0-1.31.1)
- This is what changes game's behavior, initializes map with 24 players
- Since this is Reforged's w3i version, it must have all players 1-24
- placed in _Locales override folders FOR EACH locale:
- Your Jass code must be compatible: dynamically detect if the map is played with 12/24 players
- I didn't test GUI trigger -> code generation of old WE
Future plans
What is done:- standalone w3i parser in Lua, supports multiple format versions (as described by Hodor: TFT=25, 1.31=28, 1.32=31)
- based on above, a diff script that compares two maps' w3i data and shows differences
- [DONE] Describe w3i format for 1.29 (first version with 24-player support) - publication WIP
- Research old WE GUI Trigger code generation with regards to 12/24p support
- Does it use constants like "bj_MAX_PLAYERS"?
- Is it fixable with custom WE Trigger definitions for code gen?
- Write tutorials how to find and rewrite old hardcoded values in code
- Like loops that go from 0-11 to iterate over all players
- What constants must be used in their place
- Automate war3map.j code changes needed to initialize players
- make it user-friendly (dummy units?)
- Check if Reforged relies on w3i player information at all, for initialization (or does it only use code in war3map.j?)
- Minimap icon integration/custom map previews (war3map.mmp?) that loads correctly for 1.26/Reforged
- Find if there's a better folder than _Locales/xxxx for Reforged overrides: so it doesn't break for new locales, and eliminates the need to replicate the file N times for each locale
- Automate war3map.w3i creation
- Better CLI tool to work with MPQs than MPQEditor (it doesn't print error messages or raise exit codes)
- Automatic war3map.w3i injection into a ready map
- Integrate with a build system
Credits:
- Hodor for his excellent multi-version format description (and probably others whose prior work he used)
- @Drake53 for being right (even though I forgot about his suggestion) and the link to:
- @Firstrun70 for compiling a list of patches and version numbers
- @blufflegendaire and Ayane for providing inspiration on multi-language maps that led to groundwork (ab)used here
- Anti-credits: Blizzard for bullying a loyal community, and their management who, at the first sign of no immedaite financial success, fired the entire original Reforged team
Attachments
Last edited: