• 🏆 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!

Hero Selection Problem

Status
Not open for further replies.
Level 2
Joined
May 18, 2013
Messages
9
Hi, I’m new to this but my main problem I am having is hero selection. I had made hero tavern to allow the player to pick their hero manually or random. The problem is, when a player picks a hero manually and then another player pick random, there still a chance to generate the same hero. Any help would be helpful :grin:

  • Hero Array
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Set Array for Hero --------
      • Set Total_Heroes = 3
      • Set Random_Count = Total_Heroes
      • Set Hero_Array[1] = Paladin
      • Set Hero_Array[2] = Mountain King
      • Set Hero_Array[3] = Archmage
      • For each (Integer A) from 1 to 3, do (Actions)
        • Loop - Actions
          • Set Random_Data[(Integer A)] = (Integer A)
      • Trigger - Turn off (This trigger)
  • Manual Selection
    • Events
      • Unit - A unit Sells a unit
    • Conditions
      • ((Sold unit) is A Hero) Equal to True
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Player - Make (Unit-type of (Sold unit)) Unavailable for training/construction by (Picked player)
      • Game - Display to (All players) the text: (A player had chosen + (Name of (Sold unit)))
      • Unit - Move (Sold unit) instantly to (Center of Hero Spawn <gen>)
      • Set Random_Data[Random_Hero] = Random_Count
      • Set Random_Count = (Random_Count - 1)
  • Random Selection
    • Events
      • Unit - A unit Sells a unit
    • Conditions
      • (Unit-type of (Sold unit)) Equal to Random Hero
    • Actions
      • Set Random_Hero = (Random integer number between 1 and Random_Count)
      • Unit - Create 1 Hero_Array[Random_Data[Random_Hero]] for (Owner of (Sold unit)) at (Center of Hero Spawn <gen>) facing Default building facing degrees
      • Game - Display to (All players) the text: (A player had randomed + (Name of (Last created unit)))
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Player - Make (Unit-type of (Last created unit)) Unavailable for training/construction by (Picked player)
      • Set Random_Data[Random_Hero] = Random_Count
      • Set Random_Count = (Random_Count - 1)
 
Level 8
Joined
Oct 12, 2011
Messages
483
Pretty sure this will do what you want. Based on principle of elminating the unwanted data in the array, then shifting everything down.
  • Hero Array
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Set Array for Hero --------
      • Set Total_Heroes = 3
      • Set Hero_Array[1] = Paladin
      • Set Hero_Array[2] = Mountain King
      • Set Hero_Array[3] = Archmage
      • Trigger - Turn off (This trigger)
  • Manual Selection
    • Events
      • Unit - A unit Sells a unit
    • Conditions
      • ((Sold unit) is A Hero) Equal to True
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Player - Make (Unit-type of (Sold unit)) Unavailable for training/construction by (Picked player)
      • Game - Display to (All players) the text: (A player has selected + (Name of (Sold unit)))
      • Unit - Move (Sold unit) instantly to (Center of Hero Spawn <gen>)
      • For each (Integer A) from 1 to Total_Heroes, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Unit-type of (Sold unit)) Equal to Hero_Array[(Integer A)]
                  • No unit-type Equal to Hero_Array[(Integer A)]
            • Then - Actions
              • Set Hero_Array[(Integer A)] = Hero_Array[((Integer A) + 1)]
              • Set Hero_Array[((Integer A) + 1)] = No unit-type
            • Else - Actions
      • Set Total_Heroes = (Total_Heroes - 1)
  • Random Selection
    • Events
      • Unit - A unit Sells a unit
    • Conditions
      • (Unit-type of (Sold unit)) Equal to Random Hero
    • Actions
      • Set Random_Hero = (Random integer number between 1 and Random_Count)
      • Unit - Create 1 Hero_Array[(Random integer number between 1 and Total_Heroes)] for (Owner of (Sold unit)) at (Center of Hero Spawn <gen>) facing Default building facing degrees
      • Game - Display to (All players) the text: (A player has randomly selected + (Name of (Last created unit)))
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Player - Make (Unit-type of (Last created unit)) Unavailable for training/construction by (Picked player)
      • For each (Integer A) from 1 to Total_Heroes, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Unit-type of (Last Created Unit)) Equal to Hero_Array[(Integer A)]
                  • No unit-type Equal to Hero_Array[(Integer A)]
            • Then - Actions
              • Set Hero_Array[(Integer A)] = Hero_Array[((Integer A) + 1)]
              • Set Hero_Array[((Integer A) + 1)] = No unit-type
            • Else - Actions
      • Set Total_Heroes = (Total_Heroes - 1)
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
Ignoring efficiency does not have to result in a lagging game.
Edit: that doesn't mean you should ignore it all the time, though :p.
Efficiency is what we strive for (too much inefficiency will make the game noticeably heavier) endedit

But that aside: the reason why you do not have to loop, is because the list does not need to stay in order.
If that were the case, then you'd be right, but as it is: you can just replace the last index with the current index and it's done (no loop involved).

Here, this means:
  • Set Hero_Array[Random_Hero] = Hero_Array[Total_Heroes]
  • Set Total_Heroes = Total_Heroes - 1
The randomed hero will be removed from the list with this.

Edit: just checked, this is basically what deathismyfriend's tutorial also says (my version is more succinct because it's a very specific example instead of a general one).
 
Level 2
Joined
May 18, 2013
Messages
9
Thanks for the help and feedback, they were super helpful but I do have a question I would like to ask. Since Apocalypse mention you don’t need a loop on the random selection and Deathismyfriend also mention that the last hero variable need to be null before reducing the index. I try to figure out how to set to that but I got some undesirable result. Please let me know what I did wrong here.

  • Random Selection Copy 2
    • Events
      • Unit - A unit Sells a unit
    • Conditions
      • (Unit-type of (Sold unit)) Equal to Random Hero
    • Actions
      • Set Random_Hero = (Random integer number between 1 and Random_Count)
      • Unit - Create 1 Hero_Array[(Random integer number between 1 and Total_Heroes)] for (Owner of (Sold unit)) at (Center of Hero Spawn <gen>) facing Default building facing degrees
      • Game - Display to (All players) the text: (A player had randomed + (Name of (Last created unit)))
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Player - Make (Unit-type of (Last created unit)) Unavailable for training/construction by (Picked player)
      • Set Hero_Array[Random_Hero] = Hero_Array[Total_Heroes]
      • Set Hero_Array[Random_Hero] = No unit-type
      • Set Total_Heroes = (Total_Heroes - 1)
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
u leak a location.
Also y do this ?
  • Set Random_Hero = (Random integer number between 1 and Random_Count)
  • Unit - Create 1 Hero_Array[(Random integer number between 1 and Total_Heroes)] for (Owner of (Sold unit)) at (Center of Hero Spawn <gen>) facing Default building facing degrees
u set a random integer twice. They are different values but the upper one isnt used.
 
Level 2
Joined
May 18, 2013
Messages
9
Thanks for pinpointing that out. I fix that and I am very aware about leak a location, but my biggest concern I am having is -is understanding how to run my random selection trigger without the loops as Apocalypse had mention, because I am still getting hero that already been selected without loops. Other than that, I will probably stick with the example Tonex had written out, since I am not advance with GUI.
 
Level 8
Joined
Oct 12, 2011
Messages
483
Instead of
  • For each (Integer A) from 1 to Total_Heroes, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Unit-type of (Sold unit)) Equal to Hero_Array[(Integer A)]
              • No unit-type Equal to Hero_Array[(Integer A)]
        • Then - Actions
          • Set Hero_Array[(Integer A)] = Hero_Array[((Integer A) + 1)]
          • Set Hero_Array[((Integer A) + 1)] = No unit-type
        • Else - Actions
You could put
  • For each (Integer A) from 1 to Total_Heroes, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Sold unit)) Equal to Hero_Array[(Integer A)]
        • Then - Actions
          • Set Hero_Array[(Integer A)] = Hero_Array[Total_Heroes]
          • Set Hero_Array[Total_Heroes] = No unit-type
        • Else - Actions
And in the other one, replace
  • Set Random_Hero = (Random integer number between 1 and Random_Count)
  • Unit - Create 1 Hero_Array[(Random integer number between 1 and Total_Heroes)] for (Owner of (Sold unit)) at (Center of Hero Spawn <gen>)
With
  • Set Random_Hero = (Random integer number between 1 and Total_Heroes)
  • Unit - Create 1 Hero_Array[Random_Hero] for (Owner of (Sold unit)) at (Center of Hero Spawn <gen>)
And
  • For each (Integer A) from 1 to Total_Heroes, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Unit-type of (Last Created Unit)) Equal to Hero_Array[(Integer A)]
              • No unit-type Equal to Hero_Array[(Integer A)]
        • Then - Actions
          • Set Hero_Array[(Integer A)] = Hero_Array[((Integer A) + 1)]
          • Set Hero_Array[((Integer A) + 1)] = No unit-type
        • Else - Actions
With
  • Set Hero_Array[Random_Hero] = Hero_Array[Total_Heroes]
  • Set Hero_Array[Total_Heroes] = No unit-type
 
Level 8
Joined
Oct 12, 2011
Messages
483
Yes yes, I know that I'm still leaking a point. In this situation, it's fine using Integer A because there are no waits within the loop to mess up Integer A. The Boolean system is highly discouraged because there's the off chance that the game will choose the same Boolean that is set to false 100 or even 1000 times before choosing a hero. There's even a chance that every time you try to randomly select a hero it will keep looping to the same hero enough times so that the trigger quits without doing anything.
 
Level 8
Joined
Oct 12, 2011
Messages
483
I'm saying that atm I for the trigger I'm not caring about efficiency, just making sure that the poor guy knows how everything works. Can you show me an example of the Boolean system? I'm interested in how it would work.
 
Level 8
Joined
Oct 12, 2011
Messages
483
Yeah so the problem with your Boolean method is that the player may, even though it's a very very very slight chance, come up with 1000 "u dont get ur unit" messages before finally getting their unit or giving up. With my solution there is always a 100% chance that the player will get a unit.
 
Level 2
Joined
May 18, 2013
Messages
9
I am open minded to all suggestion, I even went poking around for tutorial for Boolean.

  • Set Random_Hero = (Random integer number between 1 and Total_Heroes)
  • Unit - Create 1 Hero_Array[Random_Hero] for (Owner of (Sold unit)) at (Center of Hero Spawn <gen>
Had produce some undesirable result, I am no expert like the two of you but my guess it have something to do with Random_Hero because when I remove it, it work fine.

As for the Boolean, I manage to use the tutorial from http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/hero-selection-systems-38699/, but the result I was looking for random wasn't what I wanted. I wanted it to be set, if a hero is pick it can’t be pick again. The tutorial have the triggers I was using, but if you want me to post it on here, let me know.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
if u want it to be random then u should use an indexing type of system. If u use the hashtables like i show u in the map then just index each hero into an integer array and use the hashtable to index these. basically since boolean takes up 0 in the hashtable i use then use 1 for the integer index. You will need to save index number as 1 of tempInt in the hashtable. ( tempInt being the unit type id, the custom script i used)
When someone picks random hero u will need to change the index and the boolean for the hashtable. This will allow it to work when 1 player chooses random and one doesnt. This way no1 willl be able to get the same hero.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
if he doesnt know how to de-index its easy. something like this should do.

The triggering unit will need to be changed to whatever it is. If needed.
This will need to be run whenever a hero is bought / trained

  • Actions
    • Set unitTypeId = (Unit-type of (Triggering unit))
    • For each (Integer tempInt) from 1 to maxIndex, do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • unitTypeId Equal to heroIndex[tempInt]
          • Then - Actions
            • Set heroIndex[tempInt] = heroIndex[maxIndex]
            • Set heroIndex[maxIndex] = No unit-type
            • Set maxIndex = (maxIndex - 1)
          • Else - Actions
 
Level 8
Joined
Oct 12, 2011
Messages
483
Yup yup
Tonex said:
  • For each (Integer A) from 1 to Total_Heroes, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Sold unit)) Equal to Hero_Array[(Integer A)]
        • Then - Actions
          • Set Hero_Array[(Integer A)] = Hero_Array[Total_Heroes]
          • Set Hero_Array[Total_Heroes] = No unit-type
        • Else - Actions
Though I left the
  • Set Total_Heroes = Total_Heroes - 1
outside of the loop.
 
Level 2
Joined
May 18, 2013
Messages
9
I haven’t toy around with the editor today. Yeah, I think my weakness is de-index; maybe I shouldn't had gotten ahead of myself with my silly idea. I shall play around what you two had posted and if I am having any trouble, I shall let you guys know. Also, want to thank you guys for taken the time to help me.
 
Level 2
Joined
May 18, 2013
Messages
9
Yeah, I think I should stick with simple stuff for now on until I understand what I am doing and how everything work. It would be best if I go through your entire lesson and just make baby map with triggers doing silly stuff haha. But this won't be the last of me posting, I am sure you will see more in the future haha :D
 
Status
Not open for further replies.
Top