• 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.

[General] Randomized Unit Generation

Status
Not open for further replies.
Level 2
Joined
Jan 11, 2020
Messages
9
Hello, I've recently gotten into Map Development, and I think I'm doing alright for now, at least as a beginner.
I've ran into a problem that I can't solve though, I've tried in every way I can think of, but to no avail.
I want to create a system that spawns unit based on how far into the game players have made it.
I was thinking of doing this by having a Variable (UnitPoints) and make each unit "cost" UnitPoints to spawn, randomly spawn units until the UnitPoints have been spent up, but I have no idea where to start.. I'd really appreciate some help or thoughts on how to make this function, as I don't really want to make the map linear (Units always the same) and instead would love a complete random but still fair, way of doing it. I would have no problem setting the UnitPoints cost manually, of course.
Thank you for reading, and considering helping!
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
This is actually a great use for UnitPools in my opinion, but they're not accessible in GUI (can't even make a variable of one). UnitPools contain a bunch of unit types that all have an associated weight. They can be used to generate a 'random' unit from the possible options, weighted as they are defined (low weight options are less common (relative to the average weight of all possible units in the pool)).
  • Have a UnitPool for each possible UnitPoint cost, assigned to an array: PointsPool[3] contains all the units that cost 1 UnitPoint (UP), PointsPool[12] contains all 12-UP-cost units, etc.
  • Populate the PointsPool[] array members properly on map init, up to whatever your MAX_UP_COST is. You could do this 'automatically' by having a preplaced region for each UP cost with 1 of each unit that should cost that much in the region; then build PointsPool by looping over the units in each region on map init (and have some way to determine proper weight or just don't use weighting).
  • When randomized units are needed, do the following:
  • Set P = The player
  • Set PUP = The player's unit points
  • Set Where = Wherever units should be spawned
  • For each (Integer YOUR_COUNTER) from 1 to 1 do (Actions) //yes actually 1 to 1
    • Loop - Actions
      • Set Rand = (Random number from 1 to (Minimum (PUP, MAX_UP_COST)))
      • Custom script: set udg_TempUnit = PlaceRandomUnit(PointsPool[udg_Rand], udg_P, GetLocationX(udg_Where), GetLocationY(udg_Where), GetRandomReal(0,2*bj_PI))
      • Set PUP = (PUP - Rand)
      • If (All conditions are true) then do (Then actions) else do (Else actions)
        • If - Conditions
          • PUP Greater than 0
        • Then - Actions
          • Set YOUR_COUNTER = (YOUR_COUNTER - 1) //causes loop to continue, if this doesn't happen it will exit
        • Else - Actions
      • -------- do whatever else you need with TempUnit --------
This setup will produce units until there are 0 UP left. As long as there is at least one unit that costs 1 UP then this loop will always finish and won't get stuck infinitely. It's a little weighted towards the lower-cost units because overall they're more likely to be picked , so if you wanted to start high you could force Rand to be between PUP/2 and PUP for the first round or two.

Setting up the UnitPools would be a little bit more effort but the regions trick I outlined before would be pretty quick:
  • Events
    • Time - Elapsed game time is 0.50 seconds //don't use the map init event if you can avoid it
  • Conditions
  • Actions
    • Set MAX_UP_COST = (MAX_UP_COST + 1)
    • Set UPRegion[MAX_UP_COST] = UP Region 1 <gen>
    • Set MAX_UP_COST = (MAX_UP_COST + 1)
    • Set UPRegion[MAX_UP_COST] = UP Region 2 <gen>
    • Set MAX_UP_COST = (MAX_UP_COST + 1)
    • Set UPRegion[MAX_UP_COST] = UP Region 3 <gen>
    • //...
    • Set MAX_UP_COST = (MAX_UP_COST + 1)
    • Set UPRegion[MAX_UP_COST] = UP Region 35 <gen>
    • -------- --------
    • For each (Integer A) from 1 to MAX_UP_COST do (Actions)
      • Loop - Actions
        • Custom script: set PointsPool[bj_forLoopAIndex] = CreateUnitPool() //initialize array members
        • Custom script: set bj_wantDestroyGroup = true //pre-emptively cleans a group leak that would occur in the next line
        • Unit Group - Pick every unit in UPRegion[(Integer A)] and do (Actions)
          • Loop - Actions
            • Custom script: call UnitPoolAddUnitType(PointsPool[bj_forLoopAIndex], GetUnitTypeId(GetEnumUnit()), 1.0) //1.0 is the weight
            • Unit - Remove (Picked Unit)
And of course you have to make the UnitPools variable in the first place. Put this in any blank trigger, or your map's Custom Script header:
JASS:
globals
  unitpool array PointsPool
endglobals
 
Last edited:
Level 2
Joined
Jan 11, 2020
Messages
9
I've followed everything you said, created 6 Regions for Units to be picked, setup the variables and get no errors until I try to run the map, I can't get the custom scripts to work at all.

image_2023-01-24_163044085.png


That being said, thank you for the clear example!
 
Level 2
Joined
Jan 11, 2020
Messages
9
In the trigger editor menu bar go to JASSHelper > Enable JASSHelper as well as JASSHelper > Enable vJASS. Make sure they are both checked on.
Would you perhaps be available for discussing other features that I struggle a bit with?
Preferably through E-Mail or Discord as I keep having to wait for Moderator Approval.. :p
No worries if not, and I thank you for the assistance thus far. :)
 
Level 2
Joined
Jan 11, 2020
Messages
9
Hmm, I’ve had this account since 2020, must be a level thing! Well, regardless, I’ve added you on Discord, Treaty#3442.
Thanks again for the help with unit trigger, used the same kind of setup to do Shop Items! Works great.
 
Level 2
Joined
Jan 11, 2020
Messages
9
I seem to be getting an error now when I run;
JASS:
set udg_TempUnit = PlaceRandomUnit(PointsPool[udg_R], udg_P, GetLocationX(udg_Where), GetLocationY(udg_Where))
The error received is;
Code:
Line 726: Not enough arguments given to function : PlaceRandomUnit
 
Level 2
Joined
Jan 11, 2020
Messages
9
Hm, I'm now getting different errors instead.
Code:
Line 955: Undeclared variable udg_R. Maybe you meant udg_P
Line 955: Cannot convert rect to location in parameter whichLocation in call to GetLocationX
Line 955: Cannot convert rect to location in parameter whichLocation in call to GetLocationY
My exact Trigger is;
Code:
set udg_TempUnit = PlaceRandomUnit(PointsPool[udg_R], udg_P, GetLocationX(udg_Where), GetLocationY(udg_Where), GetRandomReal(0,2*bj_PI))
I understand that I'm missing a Variable named "R", but I don't even know what it's supposed to be, my best guess, it's supposed to be "Rand", but the other 2 game out of nowhere.
 
Status
Not open for further replies.
Top