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

[General] GUI - Disabled random

Status
Not open for further replies.
Level 30
Joined
Jan 31, 2010
Messages
3,551
I have encountered some annoying issues recently.
Whenever I set my mode to normal or All pick, and players get the heroes they want, if I try to get random hero, it succeeds. However, occasionally, after I -random my hero, I can end up getting a hero that is already in game, selected by other player.

How to make heroes that are already selected not available for -random command?
  • Random All Heroes
    • Events
      • Player - Player 2 (Blue) types a chat message containing -random as An exact match
      • Player - Player 3 (Teal) types a chat message containing -random as An exact match
      • Player - Player 4 (Purple) types a chat message containing -random as An exact match
      • Player - Player 6 (Orange) types a chat message containing -random as An exact match
      • Player - Player 7 (Green) types a chat message containing -random as An exact match
      • Player - Player 8 (Pink) types a chat message containing -random as An exact match
    • Conditions
      • GameMode Equal to MODE_AllRandom_AllPick
      • Player_Already_Picked[(Player number of (Triggering player))] Equal to 0
    • Actions
      • Set Random_Hero = (Random integer number between 1 and RandomTotal_All)
      • Unit - Create 1 Heroes_All[RandomData_All[Random_Hero]] for (Triggering player) at ((Triggering player) start location) facing Default building facing degrees
      • Set Player_Already_Picked[(Player number of (Triggering player))] = (Player_Already_Picked[(Player number of (Triggering player))] + 1)
      • Player Group - Pick every player in Players and do (Actions)
        • Loop - Actions
          • Player - Make (Unit-type of (Last created unit)) Unavailable for training/construction by (Picked player)
      • Set RandomData_All[Random_Hero] = RandomData_All[RandomTotal_All]
      • Set RandomTotal_All = (RandomTotal_All - 1)
      • Player - Limit training of Heroes to 0 for (Triggering player)
      • Quest - Display to (All players matching (((Matching player) is an enemy of (Owner of (Last created unit))) Equal to True)) the Hint message: ((PlayerColors[(Player number of (Owner of (Entering unit)))] + ((Name of (Owner of (Entering unit))) + |r)) + ( has randomed + (Name of (Entering unit))))
  • Move Heroes
    • Events
      • Unit - A unit enters Taverns <gen>
    • Conditions
      • ((Entering unit) is A Hero) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Entering unit) belongs to an ally of Player 1 (Red)) Equal to True
          • (Owner of (Entering unit)) Not equal to Neutral Passive
        • Then - Actions
          • Unit - Move (Entering unit) instantly to (Center of NE Base <gen>)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Entering unit) belongs to an ally of Player 5 (Yellow)) Equal to True
          • (Owner of (Entering unit)) Not equal to Neutral Passive
        • Then - Actions
          • Unit - Move (Entering unit) instantly to (Center of NA Base <gen>)
        • Else - Actions
      • Camera - Pan camera for (Owner of (Entering unit)) to (Position of (Entering unit)) over 0.00 seconds
      • Selection - Select (Entering unit) for (Owner of (Entering unit))
      • Player - Limit training of Heroes to 0 for (Owner of (Entering unit))
      • Quest - Display to (All players matching (((Matching player) is an enemy of (Owner of (Last created unit))) Equal to True)) the Hint message: ((PlayerColors[(Player number of (Owner of (Entering unit)))] + ((Name of (Owner of (Entering unit))) + |r)) + ( has selected + (Name of (Entering unit))))
Thanks in forward.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Ofcourse it alows you to random existing heroes as nothing stops random from choosing heroes that were activly picked. When a player chooses a hero and when a player randoms a hero you need to remove the hero from the collection of available heroes to random. Currently you are just removing when you choose a random hero, meaning that heroes choosen normally will still be in the collection of random heroes.

Easiest solution would be a linear search through the collection to find the hero type the player just choose and then to remove it in the same way you do in the random function. The O(n) complexity of a linear search for this task does not mater.
 
Level 8
Joined
Apr 26, 2011
Messages
403
1, create a trigger call: getRandomHero
2, change the code in your first trigger
"Set Random_Hero = (Random integer number between 1 and RandomTotal_All)"
to
"call trigger getRandomHero(ignore condiction)"

inside Trigger getRandom :

Set Random_Hero = (Random integer number between 1 and RandomTotal_All)
if (Random_Hero is in group_of_already_pick_hero) then // or write your own rules to check if they are already picked
call trigger getRandomHero (ignore condiction) //this will random hero again untill it havnt pick
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
This is a very easy solution:


  • Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set point = (Center of (Playable map area))
      • -------- --------------------------------------- --------
      • Unit - Create 1 Paladin for Neutral Passive at point facing Default building facing degrees
      • Unit - Hide (Last created unit)
      • Unit Group - Add (Last created unit) to HeroGroup
      • -------- --------------------------------------- --------
      • Unit - Create 1 Archmage for Neutral Passive at point facing Default building facing degrees
      • Unit - Hide (Last created unit)
      • Unit Group - Add (Last created unit) to HeroGroup
      • -------- --------------------------------------- --------
      • Unit - Create 1 Mountain King for Neutral Passive at point facing Default building facing degrees
      • Unit - Hide (Last created unit)
      • Unit Group - Add (Last created unit) to HeroGroup
      • -------- --------------------------------------- --------
      • Unit - Create 1 Blood Mage for Neutral Passive at point facing Default building facing degrees
      • Unit - Hide (Last created unit)
      • Unit Group - Add (Last created unit) to HeroGroup
      • -------- --------------------------------------- --------
      • Custom script: call RemoveLocation(udg_point)
  • Random
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Set unit = (Random unit from HeroGroup)
      • Unit - Change ownership of unit to (Triggering player) and Change color
      • Unit - Unhide unit
      • Unit Group - Remove unit from HeroGroup


You should prevent a player from being able to select a hero again. And if not all heroes are picked, remove the units after all players have selected their heroes.
 
Level 13
Joined
Mar 24, 2010
Messages
950
honestly just saw Makers solution and i like that better lol but this also works 100%
Its more messy looking tho :p but it is like 6am and im quite tired..

Its assumed here u have 4 heros in your array (for example)

the first loop is double your total heros. (8)
This just loops a bit to make sure it gets a random number thats not picked, it works.. but makers i like better :p

  • Random Hero
    • Events
      • Player - Player 1 (Red) types a chat message containing -Random as An exact match
    • Conditions
    • Actions
      • Set Temp_Integer = (Random integer number between 1 and 4)
      • For each (Integer A) from 1 to 8, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Heros_Picked[Temp_Integer] Equal to True
            • Then - Actions
              • Set Temp_Integer = (Random integer number between 1 and 4)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Heros_Picked[Temp_Integer] Equal to True
        • Then - Actions
          • For each (Integer A) from 1 to 4, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Heros_Picked[(Integer A)] Equal to False
                • Then - Actions
                  • Set Temp_Integer = (Integer A)
                • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Heros_Picked[Temp_Integer] Equal to False
            • Then - Actions
              • Set Heros_Picked[Temp_Integer] = True
              • Unit - Create 1 Heros[Temp_Integer] for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
            • Else - Actions
        • Else - Actions
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
If you ever get around to using JNGP (or JassHelper) and knowing a bit of Jass, you can solve this problem really nicely with unitpools.

Anyway, Maker's method works, but I think it's a bit too much for something that shouldn't happen frequently and becomes a hassle when you have more heroes.

I'd go with something like this instead (similar to DSG's suggestion):
  • Custom script: loop
  • Set Random_Hero = (Random integer number between 1 and RandomTotal_All)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • AlreadyPicked[Random_Hero] Equal to False
    • Then - Actions
      • Custom script: exitwhen true
    • Else - Actions
  • Custom script: endloop
  • Set AlreadyPicked[Random_Hero] = True
  • -------- Create the hero like you normally would. Don't forget to remove leaks! --------
AlreadyPicked is a boolean array that returns true if a hero has been picked with that index.
When heroes are picked normally, AlreadyPicked needs to be updated by finding the index of the hero type. (You can do this by looping through the array RandomData_All to find an index match between the choosen hero's type)
 
Level 30
Joined
Jan 31, 2010
Messages
3,551
watermelon_1234's suggestion sounds easiest for me, so I guess I will use that one. Just one question, the custom script is only "loop"? This thread is solved, by the way.

Reputation is coming when I get off the limit.

Oh, and I use JNPG, but I am not familiar too much with (v)Jass.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Yes, the custom script is loop and endloop. My method is basically repeating the process of getting a random int until it finds an integer for a hero that wasn't picked. It's not that efficient but it shouldn't really matter since randoming a hero shouldn't happen that much.

Unitpools are still the easiest way to go though (Look back at my previous post for a good tutorial).
If you're not afraid of Jass, I suggest you do this instead:
JASS:
// In a trigger named HeroPool

globals
    unitpool HeroPool = CreateUnitPool()
endglobals

// Runs on map init to add hero type ids to the pool.
function InitTrig_HeroPool takes nothing returns nothing   
    call UnitPoolAddUnitType(HeroPool, 'Hpal', 1.)    
    call UnitPoolAddUnitType(HeroPool, 'Hamg', 1.)
    call UnitPoolAddUnitType(HeroPool, 'Hmkg', 1.)
    // etc...
endfunction
To create a random hero along with removing it from the pool (In your first trigger):
  • Custom script: local integer id = GetPlayerId(GetTriggerPlayer())
  • -------- Place a random hero from the pool at the triggering player's start location. --------
  • Custom script: set bj_lastCreatedUnit = PlaceRandomUnit(HeroPool, GetTriggerPlayer(), GetStartLocationX(id), GetStartLocationY(id), 270)
  • -------- Remove the hero type id from the pool --------
  • Custom script: call UnitPoolRemoveUnitType(HeroPool, GetUnitTypeId(bj_lastCreatedUnit))
This is how you would remove the normally picked hero type ids from the pool (Just add it somewhere in your 2nd trigger).
  • Custom script: call UnitPoolRemoveUnitType(HeroPool, GetUnitTypeId(GetTriggerUnit()))
 
You have turned off the "use fixed seed" option in the editor right? As long as all heroes are in the group, the result should be atleast slightly random.
Yes that was problem, so actually system worked then :D

EDIT:

Here "Maker explained it" GUI coded test map.
Don't forget to remove leaks, or should I say destroy group and remove location once when all players pick their hero.
 

Attachments

  • test map.w3x
    16.8 KB · Views: 69
Status
Not open for further replies.
Top