• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • It's time for the first HD Modeling Contest of 2025. Join the theme discussion for Hive's HD Modeling Contest #7! Click here to post your idea!

[Solved] Help to Create an MMR System for Warcraft

Level 10
Joined
Oct 11, 2021
Messages
78
I'm working on a project to enhance the gameplay experience. My goal is to create an MMR (Matchmaking Rating) system that updates the MMR after each match and loads it when starting a new game. I want this system to be dynamic and efficient, similar to the one used in Direct Strike OZE.

Here are the key points I’d like to implement:

The MMR of players should be adjusted based on their performance and the result of the game after each match.
The system should load the updated MMR when starting a new game so that matchmaking reflects the current skill level of the players.

Does anyone have experience in creating MMR systems for Warcraft and can offer guidance or examples? Any advice on how to approach this project or resources I can use would be greatly appreciated.

have tried using the "Codeless Save/Load" system, but I found it difficult to understand and it's more oriented towards RPGs or campaigns, not for battle arenas like a MOBA, which is the type of map I am creating.

Thanks in advance for your help!
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,537
The Codeless Save/Load system simply saves and loads Integers. An Integer can be used to represent anything and everything. The rest of the stuff you'll find in that codeless demo map, like the Hero dialog menu or the Custom script "helpers", is optional. Unfortunately, you can't easily opt out of them without some knowledge of which triggers to disable/delete.

That's why I went ahead and attached a stripped down version of the codeless system down below. This map demonstrates autosaving/autoloading a group of heroes as well as the player's gold. Simply delete the hero stuff and you'll be left with what you want -> The ability to save/load an Integer (gold). Now using the Gold as an example, replace it with an Integer variable of your own creation -> Your MMR values.


For the actual MMR system, a basic design involves a bunch of Integer variables and some simple arithmetic. Here's what I've done in the past:

1) Players have 1500 MMR by default, or whatever you think makes sense:
  • Player Group - Pick every player in (All players) and do (Actions)
    • Loop - Actions
      • Set Variable Player_MMR[(Player number of (Picked player))] = 1500
2) You load each player's save file at the start of the game.

3) When a player loads their save file it will replace their default MMR value with the loaded value (if one is found). Otherwise, the default is used.

4) After loading in all players, calculate each team's total MMR:
  • Player Group - Pick every player in Team[1] and do (Actions)
    • Loop - Actions
      • Set Variable Team_MMR[1] = (Team_MMR[1] + Player_MMR[(Player number of (Picked player))])
  • Player Group - Pick every player in Team[2] and do (Actions)
    • Loop - Actions
      • Set Variable Team_MMR[2] = (Team_MMR[2] + Player_MMR[(Player number of (Picked player))])
^ A For Loop can be used here to further simplify the process.

5) Use these sums to calculate how much a team should earn if they're victorious and how much they should lose if they're defeated. The team with the higher MMR average should win less MMR and lose more MMR since they're favored:
  • -------- Do some math to calculate the difference between Team_MMR[1] and Team_MMR[2] to get A/B/C/D --------
  • Set Variable Team_Winnings[1] = A
  • Set Variable Team_Losings[1] = B
  • Set Variable Team_Winnings[2] = C
  • Set Variable Team_Losings[2] = D
^ ChatGPT can help you out here if you struggle with the math for this section.

6) When a team is victorious, add to their MMR variables their own Team_Winnings. Then do the opposite for the defeated team, subtracting their own Team_Losings from their MMR variables. Then save the game for everyone, in other words, save each player's MMR. Also, you probably don't want MMR to go below 0, so check for that when subtracting.

7) Optionally, you can punish early quitters with a loss by applying the calculated Team_Losings to each player right after Step 5. Then undo this effect at the end of the game for the player's that won the game. In other words: The game starts, each players loads in, each player is credited with a loss, save the game. The game ends, the winning team has their earlier loss removed and is credited with a win, the losing team keeps their earlier loss, save the game.
 

Attachments

  • SaveLoad Group Of Heroes.w3x
    155.1 KB · Views: 9
Last edited:
Level 10
Joined
Oct 11, 2021
Messages
78
The Codeless Save/Load system simply saves and loads Integers. An Integer can be used to represent anything and everything. The rest of the stuff you'll find in that codeless demo map, like the Hero dialog menu or the Custom script "helpers", is optional. Unfortunately, you can't easily opt out of them without some knowledge of which triggers to disable/delete.

That's why I went ahead and attached a stripped down version of the codeless system down below. This map demonstrates autosaving/autoloading a group of heroes as well as the player's gold. Simply delete the hero stuff and you'll be left with what you want -> The ability to save/load an Integer (gold). Now using the Gold as an example, replace it with an Integer variable of your own creation -> Your MMR values.


For the actual MMR system, a basic design involves a bunch of Integer variables and some simple arithmetic. Here's what I've done in the past:

1) Players have 1500 MMR by default, or whatever you think makes sense:
  • Player Group - Pick every player in (All players) and do (Actions)
    • Loop - Actions
      • Set Variable Player_MMR[(Player number of (Picked player))] = 1500
2) You load each player's save file at the start of the game.

3) When a player loads their save file it will replace their default MMR value with the loaded value (if one is found). Otherwise, the default is used.

4) After loading in all players, calculate each team's total MMR and average the sums:
  • Player Group - Pick every player in Team[1] and do (Actions)
    • Loop - Actions
      • Set Variable Team_MMR[1] = (Team_MMR[1] + Player_MMR[(Player number of (Picked player))])
  • Player Group - Pick every player in Team[2] and do (Actions)
    • Loop - Actions
      • Set Variable Team_MMR[2] = (Team_MMR[2] + Player_MMR[(Player number of (Picked player))])
  • Set Variable Team_MMR[1] = (Team_MMR[1] / 2)
  • Set Variable Team_MMR[2] = (Team_MMR[2] / 2)
^ A For Loop can be used here to further simplify the process.

5) Use these averages to calculate how much a team should earn if they're victorious and how much they should lose if they're defeated. The team with the higher MMR average should win less MMR and lose more MMR since they're favored:
  • -------- Do some math to calculate the difference between Team_MMR[1] and Team_MMR[2] to get A/B/C/D --------
  • Set Variable Team_Winnings[1] = A
  • Set Variable Team_Losings[1] = B
  • Set Variable Team_Winnings[2] = C
  • Set Variable Team_Losings[2] = D
^ ChatGPT can help you out here if you struggle with the math for this section.

6) When a team is victorious, add to their MMR variables their own Team_Winnings. Then do the opposite for the defeated team, subtracting their own Team_Losings from their MMR variables. Then save the game for everyone, in other words save each player's MMR. Also, you probably don't want MMR to go below 0, so check for that when subtracting.

7) Optionally, you can punish early quitters with a loss by applying the calculated MMR losses to each player right after Step 5. Then undo this effect at the end of the game for the player's that won the game. In other words: The game starts, each players loads in, each player is credited with a loss, save the game. The game ends, the winning team has their earlier loss removed and is credited with a win, the losing team keeps their earlier loss, save the game.

I managed to make it work exactly as I wanted, thank you very much, your explanation simplified what I would see as complex haha, it is true that sometimes, at least for me, I don't know what I can modify or what I can't modify in a system. So I thank you, marked as solved.
 
Level 10
Joined
Oct 11, 2021
Messages
78
The Codeless Save/Load system simply saves and loads Integers. An Integer can be used to represent anything and everything. The rest of the stuff you'll find in that codeless demo map, like the Hero dialog menu or the Custom script "helpers", is optional. Unfortunately, you can't easily opt out of them without some knowledge of which triggers to disable/delete.

That's why I went ahead and attached a stripped down version of the codeless system down below. This map demonstrates autosaving/autoloading a group of heroes as well as the player's gold. Simply delete the hero stuff and you'll be left with what you want -> The ability to save/load an Integer (gold). Now using the Gold as an example, replace it with an Integer variable of your own creation -> Your MMR values.


For the actual MMR system, a basic design involves a bunch of Integer variables and some simple arithmetic. Here's what I've done in the past:

1) Players have 1500 MMR by default, or whatever you think makes sense:
  • Player Group - Pick every player in (All players) and do (Actions)
    • Loop - Actions
      • Set Variable Player_MMR[(Player number of (Picked player))] = 1500
2) You load each player's save file at the start of the game.

3) When a player loads their save file it will replace their default MMR value with the loaded value (if one is found). Otherwise, the default is used.

4) After loading in all players, calculate each team's total MMR:
  • Player Group - Pick every player in Team[1] and do (Actions)
    • Loop - Actions
      • Set Variable Team_MMR[1] = (Team_MMR[1] + Player_MMR[(Player number of (Picked player))])
  • Player Group - Pick every player in Team[2] and do (Actions)
    • Loop - Actions
      • Set Variable Team_MMR[2] = (Team_MMR[2] + Player_MMR[(Player number of (Picked player))])
^ A For Loop can be used here to further simplify the process.

5) Use these sums to calculate how much a team should earn if they're victorious and how much they should lose if they're defeated. The team with the higher MMR average should win less MMR and lose more MMR since they're favored:
  • -------- Do some math to calculate the difference between Team_MMR[1] and Team_MMR[2] to get A/B/C/D --------
  • Set Variable Team_Winnings[1] = A
  • Set Variable Team_Losings[1] = B
  • Set Variable Team_Winnings[2] = C
  • Set Variable Team_Losings[2] = D
^ ChatGPT can help you out here if you struggle with the math for this section.

6) When a team is victorious, add to their MMR variables their own Team_Winnings. Then do the opposite for the defeated team, subtracting their own Team_Losings from their MMR variables. Then save the game for everyone, in other words, save each player's MMR. Also, you probably don't want MMR to go below 0, so check for that when subtracting.

7) Optionally, you can punish early quitters with a loss by applying the calculated Team_Losings to each player right after Step 5. Then undo this effect at the end of the game for the player's that won the game. In other words: The game starts, each players loads in, each player is credited with a loss, save the game. The game ends, the winning team has their earlier loss removed and is credited with a win, the losing team keeps their earlier loss, save the game.

Ok, at first it works, at least in the test map you provided me, but when I import the system to another map, it no longer works, it creates the folder and the slot, but it does not load the data, am I missing something? Or am I doing something wrong?
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,537
Or am I doing something wrong?
The system has a weird quirk, you need to modify the Aerial Shackles ability to have 2 Levels and change it's Tooltip. In other words, your map's Aerial Shackles ability needs to look identical to the demo map's Aerial Shackles ability. This is because the "hack" used to save data relies on the tooltip of Aerial Shackles and I believe it references the Level 2 tooltip instead of Level 1. A classic case of indexing being off by 1.

If your units were relying on that ability then you may want to create a copy of it and have them use that copy instead.

Another quirk is that you cannot Restart the map when testing the saving/loading. You have to save, exit the game and relaunch the map completely. It's a limitation related to the Preloader which reads/writes the save file. It won't cause any problems on BNET though, since you cannot restart a map in multiplayer.
 
Last edited:
Level 10
Joined
Oct 11, 2021
Messages
78
The system has a weird quirk, you need to modify the Aerial Shackles ability to have 2 Levels and change it's Tooltip. In other words, your map's Aerial Shackles ability needs to look identical to the demo map's Aerial Shackles ability. This is because the "hack" used to save data relies on the tooltip of Aerial Shackles and I believe it references the Level 2 tooltip instead of Level 1. A classic case of indexing being 1 off.

Now yes, haha, it's incredible that I didn't notice that. Normally when I import systems I usually check if there is any skill, Dummy or anything required, I didn't notice, it is already loaded appropriately. I find it to be a very curious trick.
 
Top