• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Random Heroes in melee games

Level 13
Joined
Mar 13, 2013
Messages
299
I recently tried (and succeeded) in making a random hero system for otherwise standard melee games. This is my first attempt at any kind of trigger - indeed my first time even opening the trigger editor in the world editor - so I don't know if this is "tutorial-worthy." Also, I realize that this is a very specific function, and a bit obscure. But, since I couldn't find someone else giving the answer when I was looking for it, I figured I may as well.

First of all the rules:
1) All heroes are removed from all altars and taverns. Instead the option to "train random hero" is available.
2) Upon training, a random hero shows up instead. It could be any hero from any race.
3) You can have a max of two of the same heroes (I felt three blademasters would be a bit much, but two was manageable...)

Keep in mind these rules are specific to this tutorial. It's fairly straightforward to alter them i.e. only allowing specific heroes or not allowing repeats at all..

The overall layout of this tutorial is as follows:

Step 1) Sound. This is merely getting the sounds each hero makes upon being trained ready for the game.

Step 2) Object modification. Creating dummy random hero units and then setting up the altars and taverns to only train random heroes.

Step 3a) Trigger initialization. The Heroes and sounds from Step (1) need to be loaded into variables and the units to be built by the altars need to have limits so players can only build one per tier.

Step 3b) random hero trigger. This part is actually very short, considering it is the main function. Basically, the event is going to be "whenever a unit trains a random hero," since this can only happen due to a modified altar in step (2). Once finished, we are going to remove the trained random hero, set the number of random heros the training player can build to zero, and add a hero as prescribed from Step (3a). Of course it is 'nice' to also play the appropriate sound.

Step 4) This is the easiest of them. Once you've added the custom objects the map for some reason reverts back to some other default game values. You have to go to Scenario->Map Options... Here you must change "Game Data Set" to "Melee (Latest Patch)."

And that's it. Done!
In detail, the steps look like this:

Step 1 Sound:
Before a sound can be used with the triggers, it must be set to "use as sound." This is done in the Sound Editor. There is very little to describe here. Basically hunt for the appropriate sound, right click, and click "use as sound."

This is a lot of work, and you can use an .mpq editor to export/import these sound settings in one step, if you'd prefer. I can send the file to you if desired..

Step 2 Objects:
There are two things you must do: First, remove all of the heroes from all of the altars, and the neutral tavern (if they are used on your map - or even if you would like to set this up for generic purpose, it's a good idea).

Second, you need to create dummy units. It doesn't matter what you copy to use, but you need three total. Once you have the three units you want, you must make the following modifications:
1) Change the tooltip, name, extended tooltip, et cetera of all of these structures to reflect what they are (i.e. "A random hero")

2) at least temporarily (you can undo this once you are otherwise finished - but you need it now so that you can "see what you are doing") you need to include in the name:
-First random hero
-Second random hero
-Third random hero

At this point these should be the new names of your three newly created units.

Now, to modify the stats of each. The "first random hero" should be modified to use 5 food and 55 build time. In fact, all of these building should require 5 food and 55 build time, but this is the only one that requires "only" these modifications.

Your "Second random hero" must also require 425 gold and 100 lumber. But additionally, add a tech requirement of a "any tier 2 hall". This can be adding the tech tree requirement, click on the drop-down that says "units" and select "equivalents". Then go to the drop-down that says "any altar" and select "any tier 2 hall".

Similarly, your "Third random hero" must require 425 gold, 100 lumber, and a tech requirement of "any tier 3 hall"...

Once these are set, go back to each race's altar and add "First Random Hero" to all of them. Then add "Second random hero", as well as "Third Random hero."

And you are done with the objects!

Step 3 Triggers:
I think they are pretty straightforward, so rather than explain what to do, I'll just post my script. But before that you must first set the variables:

Heros - Unit-Type Array (24) - Full array of heroes.
Sounds - Sound Array (24) - sounds to go with heroes as ordered above.
HeroIndex - Integer Array (36) - Index of heroes as they are assigned to each player
i - integer
x - integer

Note that an integer size of 24 is only really necessary for the HeroIndex, but in case it becomes useful to store the third heroes in some future version of this, it doesn't really take up much memory to keep it at 36..

And the scripts:
  • Melee Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Melee Game - Use melee time of day (for all players)
      • Melee Game - Limit Heroes to 1 per Hero-type (for all players)
      • Melee Game - Give trained Heroes a Scroll of Town Portal (for all players)
      • Melee Game - Set starting resources (for all players)
      • Melee Game - Remove creeps and critters from used start locations (for all players)
      • Melee Game - Create starting units (for all players)
      • Melee Game - Run melee AI scripts (for computer players)
      • Melee Game - Enforce victory/defeat conditions (for all players)
      • For each (Integer x) from 1 to 12, do (Actions)
        • Loop - Actions
          • Player - Limit training of First Random Hero to 1 for (Player(x))
          • Player - Limit training of Second Random Hero to 1 for (Player(x))
          • Player - Limit training of Third Random Hero to 1 for (Player(x))
      • Set Heros[1] = Paladin
      • Set Sounds[1] = HeroPaladinReady1 <gen>
      • Set Heros[2] = Mountain King
      • Set Sounds[2] = HeroMountainKingReady1 <gen>
      • Set Heros[3] = Blademaster
      • Set Sounds[3] = HeroBladeMasterReady1 <gen>
      • Set Heros[4] = Tauren Chieftain
      • Set Sounds[4] = HeroTaurenChieftainReady1 <gen>
      • Set Heros[5] = Death Knight
      • Set Sounds[5] = DeathKnightReady1 <gen>
      • Set Heros[6] = Dreadlord
      • Set Sounds[6] = HeroDreadlordReady1 <gen>
      • Set Heros[7] = Crypt Lord
      • Set Sounds[7] = NerubianCryptLordReady1 <gen>
      • Set Heros[8] = Demon Hunter
      • Set Sounds[8] = HeroDemonHunterReady1 <gen>
      • Set Heros[9] = Warden
      • Set Sounds[9] = HeroWardenReady1 <gen>
      • Set Heros[10] = Tinker
      • Set Sounds[10] = HeroTinkerReady1 <gen>
      • Set Heros[11] = Beastmaster
      • Set Sounds[11] = OgreBeastMasterReady1 <gen>
      • Set Heros[12] = Pandaren Brewmaster
      • Set Sounds[12] = PandarenBrewmasterReady1 <gen>
      • Set Heros[13] = Pit Lord
      • Set Sounds[13] = HPitLordReady1 <gen>
      • Set Heros[14] = Alchemist
      • Set Sounds[14] = HeroAlchemistReady1 <gen>
      • Set Heros[15] = Naga Sea Witch
      • Set Sounds[15] = LadyVashjReady1 <gen>
      • Set Heros[16] = Dark Ranger
      • Set Sounds[16] = DarkRangerReady1 <gen>
      • Set Heros[17] = Firelord
      • Set Sounds[17] = HeroFirelordReady1 <gen>
      • Set Heros[18] = Keeper of the Grove
      • Set Sounds[18] = KeeperOfTheGroveReady1 <gen>
      • Set Heros[19] = Priestess of the Moon
      • Set Sounds[19] = HeroMoonPriestessReady1 <gen>
      • Set Heros[20] = Lich
      • Set Sounds[20] = HeroLichReady1 <gen>
      • Set Heros[21] = Far Seer
      • Set Sounds[21] = HeroFarseerReady1 <gen>
      • Set Heros[22] = Shadow Hunter
      • Set Sounds[22] = ShadowHunterReady1 <gen>
      • Set Heros[23] = Archmage
      • Set Sounds[23] = HeroArchMageReady1 <gen>
      • Set Heros[24] = Blood Mage
      • Set Sounds[24] = BloodElfMageReady1 <gen>
  • Train 1
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
      • (Trained unit-type) Equal to First Random Hero
    • Actions
      • Set x = (Random integer number between 1 and 24)
      • Set i = ((3 x ((Player number of (Triggering player)) - 1)) + 1)
      • Unit - Replace (Trained unit) with a Heros[x] using The new unit's max life and mana
      • Player - Limit training of First Random Hero to 0 for (Triggering player)
      • Hero - Create Scroll of Town Portal and give it to (Last replaced unit)
      • Unit - Order (Last replaced unit) to Move To (Rally-Point of (Triggering unit) as a point)
      • Set HeroIndex[i] = x
      • Sound - Play Sounds[x] at 100.00% volume, attached to (Last replaced unit)
  • Train 2
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
      • (Trained unit-type) Equal to Second Random Hero
    • Actions
      • Set x = (Random integer number between 1 and 24)
      • Set i = ((3 x ((Player number of (Triggering player)) - 1)) + 2)
      • Unit - Replace (Trained unit) with a Heros[x] using The new unit's max life and mana
      • Player - Limit training of Second Random Hero to 0 for (Triggering player)
      • Unit - Order (Last replaced unit) to Move To (Rally-Point of (Triggering unit) as a point)
      • Set HeroIndex[i] = x
      • Sound - Play Sounds[x] at 100.00% volume, attached to (Last replaced unit)
  • Train 3
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
      • (Trained unit-type) Equal to Third Random Hero
    • Actions
      • Set i = ((3 x ((Player number of (Triggering player)) - 1)) + 3)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • HeroIndex[(i - 1)] Equal to HeroIndex[(i - 2)]
        • Then - Actions
          • Set x = (HeroIndex[(i - 1)] + (Random integer number between 1 and 23))
          • Set x = (x - ((x / 25) x 24))
        • Else - Actions
          • Set x = (Random integer number between 1 and 24)
      • Unit - Replace (Trained unit) with a Heros[x] using The new unit's max life and mana
      • Player - Limit training of Third Random Hero to 0 for (Triggering player)
      • Unit - Order (Last replaced unit) to Move To (Rally-Point of (Triggering unit) as a point)
      • Set HeroIndex[i] = x
      • Sound - Play Sounds[x] at 100.00% volume, attached to (Last replaced unit)
Step 4:
Don't forget step 4!

example map
 
Last edited:
Level 13
Joined
Mar 13, 2013
Messages
299
That code looks like GUI-converted-to-JASS script. If you want it as JASS, then it will need major revisions.

You should probably just keep it as GUI. It will be more readable for everyone and you won't have to make the revisions for it to be properly coded JASS.
that's what I wanted to do, but couldn't figure out how. Is there a way to effectively copy/paste the triggers here without retyping everything and without converting them to text?

oh. right-click and copy works... who would have thought..
 
I think it is a fine tutorial. However, it is lacking a proper introduction. "Random hero system" may appear to be intuitive, but there may be people who won't understand the premise of the tutorial. Random in what sense? How will the randomness be applied? Will it be a button in the altar? It needs an introduction to clearly define (A) the purpose of the tutorial (B) how it will be carried out.

Also, for things like this, it is very helpful to have an example map attached to the main post. It isn't a requirement since you explained it quite well, but it is always a good idea to have one.
 
Level 25
Joined
Sep 26, 2009
Messages
2,373
You don't need player array, because there is already a function which converts player into number, in GUI player1 is red up to player12 who has number 12. (this goes on for neutral players, but I don't think it matters here).

  • For each (Integer Loop_var) from 1 to 12, do (Actions)
    • Loop - Actions
      • Player - Limit training of First Random Hero to 1 for (Player(Loop_var))
with Loop_var being integer.
The function is "Conversion - Convert Player index to player"



Also, get rid of all those "Do Nothing" actions, as they stress your computer for no reason (just leave all sections, where you have Do Nothing action, empty)
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,182
1. you use do nothing
2. you dont even explain anything at all about the triggers. You just "here are the triggers. copy them."
3. the trigger doesnt make sense in general. Why would I create a random hero when I finish a building?
4. I think you use a bad method for this. It can be done way easier
5. the tutorial look kinda bad. Not evea font size useage
 
Level 13
Joined
Mar 13, 2013
Messages
299
You don't need player array, because there is already a function which converts player into number, in GUI player1 is red up to player12 who has number 12. (this goes on for neutral players, but I don't think it matters here).

  • For each (Integer Loop_var) from 1 to 12, do (Actions)
    • Loop - Actions
      • Player - Limit training of First Random Hero to 1 for (Player(Loop_var))
with Loop_var being integer.
The function is "Conversion - Convert Player index to player"
yeah, i wrote this before I was aware of that function.. If I ever update it i'll do so here as well, but these scripts are currently in rotation on the PlayFFA.net bot, so even if I were to change them here it would just be an aesthetic.

And the do nothings are another thing I only learned about recently, and also something I would like to take out - but since they are only called an average of 10 times per game, it's not that big of a deal. So, I doubt Ugri will go through the hassle of changing over the scripts just because I say it'll run a teensy bit more efficiently..
 
Level 25
Joined
Sep 26, 2009
Messages
2,373
The thing is - if you want to teach people something, you should try to do it as best as possible.
If you leave unnecessary stuff, or even inefficient stuff in your tutorial because you don't want to update your map, then you will just promote those inefficient codes as "good ways to do something", which is not right.
 
Level 13
Joined
Mar 13, 2013
Messages
299
The thing is - if you want to teach people something, you should try to do it as best as possible.
If you leave unnecessary stuff, or even inefficient stuff in your tutorial because you don't want to update your map, then you will just promote those inefficient codes as "good ways to do something", which is not right.
It isn't me who doesn't want to update the maps. It's the playffa.net owner - apparently it is a very long process to do so. To update all of the random hero maps he has in rotation would basically take a whole day of tedious work. If there is some good reason (like broken code) then he'd bite the bullet and just do it, but that's not the case: the code works just fine. The minor inefficiencies are not noticeable. If I ask him to waste a day updating maps for inefficiencies I claim are there but no one else has seen any evidence of, he would politely suggest I go to hell.

Anyway, it is expected that anyone who uses this code is going to alter it to their own tastes and needs. That's true of all coding. Indeed, for a proper tutorial, it is nice to have alternatives listed in the tutorial, which I didn't do but everyone who has replied to this thread has done for me!

But, like I said, I do plan to change it. It doesn't even qualify as a hassle for me to update this thread, and there is no real reason to wait until the maps people actually use are updated. I'm only thinking of the 'audience.' I suspect the only people who may come looking for this are those who have played on the random hero maps, and they may get stuck if the tutorial here doesn't match the map exactly. But then, who would read such a tutorial without some idea of what they are doing?

Neat Avatar, btw. Does whoever made that have one of Ulquiorra?
 
Level 25
Joined
Sep 26, 2009
Messages
2,373
Oh, I see. I didn't see you also posted an example map. It was the reason why I was thinking "why don't you simply fix the text in the trigger tags".
I guess it won't be such a problem then to have it like that (though I think it is still best to post the code as optimized as possible... given people would understand it), since I don't think it will run very much to stress computer with needless data.


---
as for my avatar, it's just a pic I googled, cut off unneeded parts and resized it so I could put it as my avatar :D I think you will find similar pictures of Ulquiorra on google :)
 
Level 13
Joined
Mar 13, 2013
Messages
299
Oh, I see. I didn't see you also posted an example map. It was the reason why I was thinking "why don't you simply fix the text in the trigger tags".
I guess it won't be such a problem then to have it like that (though I think it is still best to post the code as optimized as possible... given people would understand it), since I don't think it will run very much to stress computer with needless data.


---
as for my avatar, it's just a pic I googled, cut off unneeded parts and resized it so I could put it as my avatar :D I think you will find similar pictures of Ulquiorra on google :)
unfortunately, i goes beyond the example map I posted. If you visit http://playffa.net/topic/9920304/1/#new you'll see that they currently use this script for about 14 maps in rotation..

but i do plan on updating it eventually...
 
Top