HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

The Impossible Trigger

01-18-2007, 04:48 AM#1
|)@rk-Revenant
I have a dillema.

On my map-in-development, I have a nice and unorganized nest of triggers that I have yet to optimize. My system of spawning units is nearly completed, save for a small (but extremely huge) problem.

Domination, my map, is a capture-the-points type map, where you must select your races and heroes, then use your army and hold dominance over the four points against 3 other teams. When the game starts, you get a small amount of army points that you must spend on eight categories of units: Light Melee, Light Ranged, Medium/Mounted, Artillery, Flying, Spellcaster, Tanker, and Elite. As the game progresses and your team accumulates kills, you will get more army points to spend at your lesiure.

Right now, the race and hero selection, initilization and start features, events, statistics, victory/scoring conditions, and all other normal game elements are all fine and working acceptably. Except for one element, though. That element would be the system that actually randomly selects the units that must be made.

It sounds like a simple system, right? WRONG. It must factor in several factors:
1. The units must be of levels that are affordable from all the points you allocated. Otherwise, you might not spawn anything!
2. The allocated points for each category must be divided absolutely evenly between all of the unit-levels of that category. This is very important for unit categories that span five levels; you may not have a level 6, 7, 8, 9, and 10 elite unit, so the system would have to divide those points among the levels that you have, not the ones you don't have.
3. It has to know if you allocated enough points for everything. For example, you allocated 7 points towards light melee units. A level 1 light melee unit costs 2 points, a level 2 light melee unit costs 4 points, and a level 3 light melee unit costs 7 points. The level 3 possibility would have to be omitted because 7*3 and 7*2 are 21 and 14, which is above your price range, UNLESS you ONLY have a level 3 light melee unit, then 7*1 would be simply 7, which you CAN afford. Repeat that process for the other levels.

I am at a loss of how to implement this system. I tried brute-forcing it the time consuming way, but the editor just spit errors at me for having too many IF THEN ELSE functions nested inside eachother.

If anyone can help me with this, I would be eternally grateful.
01-19-2007, 03:35 AM#2
Here-b-Trollz
hmm... I'll give it a shot...

Assuming that you have a global integer for SpawnInterval, an array of integers stored in the globals PlayerLightMeleePoints[1-12], PlayerLightRangedPoints[1-12], etc., an integer array for PlayerLightMeleeLevel[1-12], etc., and an integer array for PointCostForLevel[1-Number of Levels], a global integer for NumberOfUnitsSpawned[1-12] (We'll do this in case you want to handicap a player), and a global srting array MeleeUnitTypes_StringValue[1-NumberofTypes], RangedUnitTypes, etc., then perhaps:

Collapse JASS:
function TimerSpawnUnits takes nothing returns nothing
    local timer time=CreateTimer()
    call TimerStart(time, udg_SpawnInterval, true,function SpawnUnits)
endfunction    
    
function SpawnUnits takes nothing returns nothing
    
    local integer a=1
    local integer b
    local integer c
    
    loop
        exitwhen a==13 //this will loop 12 times, once per player. We do this to avoid the playergroup leak that the ForPlayerGroup creates
            set b=udg_NumberOfUnitsSpawned[a]
            loop
                exitwhen b==0
                    if ( not (udg_PlayerLightMeleePoints[a] < b*(PointCostPerLevel[PlayerLightMeleeLevel[a]]) ) ) then
                        set c=udg_NumberOfUnitsSpawned[a]
                        loop
                            exitwhen c==0
                                call CreateNUnitsAtLoc(1, S2I(LightMeleeUnitTypes[GetRandomInt(1,6)])
                                set c=c-1 //we do this to avoid the CreateNUnitsAtLoc leak, which creates a unit group that cannot be destroyed
                        endloop
                    else
                        set b=b-1
            endloop
            set b=udg_NumberOfUnitsSpawned[a]
            loop
                exitwhen b==0
                    if ( not (udg_PlayerLightRangedPoints[a] < b*(PointCostPerLevel[PlayerLightRangedLevel[a]) ) ) then
                        set c=udg_NumberOfUnitsSpawned[a]
                        loop
                            exitwhen c==0
                                call CreateNUnitsAtLoc(1, S2I(LightRangedUnitTypes[GetRandomInt(1,6)])
                                set c=c-1 //we do this to avoid the CreateNUnitsAtLoc leak, which creates a unit group that cannot be destroyed
                        endloop
                    else                    
                        set b=b-1
            endloop
            
            //...
            //replace the globals for all the different catagories and I beleive this will work. If not, then I have no idea how to do this.
        set a=a+1
endloop
endfunction

//===========================================================================
function InitTrig_SpawnTheUnits takes nothing returns nothing
    set gg_trg_SpawnTheUnits = CreateTrigger(  )
    call TriggerAddAction( gg_trg_SpawnTheUnits, function TimerSpawnUnits )
endfunction

Although I'm almost positive that this wouldn't work if you just copied and pasted it into your trigger, I hope this gives you an idea of how to figure this out.
01-19-2007, 04:53 AM#3
|)@rk-Revenant
I seem to have made a huge discovery that would make it somewhat easier: I don't have a variable for the point costs per unit. That would make it a hell of a lot easier for me, but I never thought of it until you mentioned it. My variables are slightly different, one being a huge array of 960. I'l try it again tomorrow, and see if it works.
01-21-2007, 04:22 AM#4
|)@rk-Revenant
Uh, crap. My trigger sort of works, but it sometimes spawns the wrong type of unit, or doesn't spawn enough units. With small numbers of some types of units, this problem does not exist, but once the number of units goes into the threes and higher for each category, I get these anomalies, even in single player.
01-21-2007, 04:31 AM#5
Av3n
Check the unit type for GUI and Rawcodes for JASS. Also check how much it creates as well.

-Av3n
01-21-2007, 07:10 AM#6
Chocobo
Don't put SpawnUnits after TimerSpawnUnits.


Collapse JASS:
                    if ( not (udg_PlayerLightMeleePoints[a] < b*(PointCostPerLevel[PlayerLightMeleeLevel[a]]) ) ) then

Should be Boolean comparaison.



Collapse JASS:
                                call CreateNUnitsAtLoc(1, S2I(LightMeleeUnitTypes[GetRandomInt(1,6)])
//...
                                call CreateNUnitsAtLoc(1, S2I(LightRangedUnitTypes[GetRandomInt(1,6)])

Missing 2 parameters.


You are playing weirdly with loops, aren't you?
01-21-2007, 06:45 PM#7
|)@rk-Revenant
The trigger that he made is not the trigger I used. Each unit has a custom value that corresponds with its category. 1 for light melee, 3 for medium/mounted, 7 for spellcaster, etc... The trigger, theoretically, shouldn't be giving the user random units of the wrong category that has no allocated points in it. There are several triggers for this:

This one is the setup to catalog each unit:
Trigger:
For each (Integer A) from 1 to 12, do (Actions)
Collapse Loop - Actions
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Collapse For each (Integer C) from 1 to 10, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
(Number of units in (Units in PlayerAreaALT[(Integer A)] matching (((Level of (Matching unit)) Equal to C) and ((Custom value of (Matching unit)) Equal to (Integer B))))) Greater than 0
Collapse Then - Actions
Set HasLevelSpecific[(((Integer A) x (Integer B)) x C)] = True
Set SupremeLevels[((Integer A) x (Integer B))] = (SupremeLevels[((Integer A) x (Integer B))] + 1)
Collapse Else - Actions
Do nothing
This one is the main trigger that sets up for the actual spawning:
Trigger:
No More Units
Collapse Events
Time - Every 5.00 seconds of game time
Conditions
Collapse Actions
Collapse For each (Integer A) from 1 to 12, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
Collapse And - All (Conditions) are true
Collapse Conditions
(Number of units in (Units owned by (Player((Integer A))) matching ((((Matching unit) is A Hero) Equal to False) and ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A peon-type unit) Equal to False) and ((((Matching unit) is A structure) Equal to 0
((Player((Integer A))) is in ActivePlayers) Equal to True
ArmyRegen[(Integer A)] Equal to False
SheeotMan[(Integer A)] Equal to False
Collapse Then - Actions
Game - Display to (Player group((Player((Integer A))))) for 10.00 seconds the text: (|cffff0000Your army is gone! You must wait|r |cffffcc00 + ((String((((Points[(Integer A)] + (TeamKills[(((Integer A) / 4) + 1)] / KillGain)) / 6) + 20))) + |r |cffff0000seconds before a new one is made.|r))
Set SheeotMan[(Integer A)] = True
Countdown Timer - Start TimerToGetArmy[(Integer A)] as a One-shot timer that will expire in ((Real(((Points[(Integer A)] + (TeamKills[(((Integer A) / 4) + 1)] / KillGain)) / 6))) + 20.00) seconds
Collapse Else - Actions
Do nothing
Collapse For each (Integer A) from 1 to 12, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
ArmyRegen[(Integer A)] Equal to True
ArmyRegen_Copy[(Integer A)] Equal to True
((Player((Integer A))) is in ActivePlayers) Equal to True
Collapse Then - Actions
Set ArmyRegen[(Integer A)] = False
Set ArmyRegen_Copy[(Integer A)] = False
Set NewUnitsBoolean[(Integer A)] = True
Game - Display to (Player group((Player((Integer A))))) for 5.00 seconds the text: |cffffcc00A new arm...
Cinematic - Ping minimap for (Player group((Player((Integer A))))) at ((Player((Integer A))) start location) for 2.00 seconds, using a Simple ping of color (100.00%, 70.00%, 0.00%)
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Set TotalLevels[((Integer A) x (Integer B))] = 0
Set TotalValues[((Integer A) x (Integer B))] = 0
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Collapse For each (Integer C) from 1 to 10, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
HasLevelSpecific[((Integer A) x ((Integer B) x C))] Equal to True
MASTERALLOCATION[((Integer A) x (Integer B))] Greater than or equal to (ValueofUnit[C] x (TotalLevels[((Integer A) x (Integer B))] + 1))
Collapse Then - Actions
Set TotalLevels[((Integer A) x (Integer B))] = (TotalLevels[((Integer A) x (Integer B))] + 1)
Collapse Else - Actions
Do nothing
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Collapse For each (Integer C) from 1 to 10, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
HasLevelSpecific[((Integer A) x ((Integer B) x C))] Equal to True
MASTERALLOCATION[((Integer A) x (Integer B))] Greater than or equal to (ValueofUnit[C] x TotalLevels[((Integer A) x (Integer B))])
Collapse Then - Actions
Set TotalValues[((Integer A) x (Integer B))] = (TotalValues[((Integer A) x (Integer B))] + ValueofUnit[C])
Collapse Else - Actions
Do nothing
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
TotalLevels[((Integer A) x (Integer B))] Greater than or equal to 1
MASTERALLOCATION[((Integer A) x (Integer B))] Greater than or equal to 1
Collapse Then - Actions
Collapse For each (Integer C) from 1 to 10, do (Actions)
Collapse Loop - Actions
Set AvailablePoints[(((Integer A) x (Integer B)) x C)] = (MASTERALLOCATION[((Integer A) x (Integer B))] / TotalLevels[((Integer A) x (Integer B))])
Collapse Else - Actions
Do nothing
Collapse Else - Actions
Do nothing
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
Collapse Or - Any (Conditions) are true
Collapse Conditions
NewUnitsBoolean[1] Equal to True
NewUnitsBoolean[2] Equal to True
NewUnitsBoolean[3] Equal to True
NewUnitsBoolean[4] Equal to True
NewUnitsBoolean[5] Equal to True
NewUnitsBoolean[6] Equal to True
NewUnitsBoolean[7] Equal to True
NewUnitsBoolean[8] Equal to True
NewUnitsBoolean[9] Equal to True
NewUnitsBoolean[10] Equal to True
NewUnitsBoolean[11] Equal to True
NewUnitsBoolean[12] Equal to True
Collapse Then - Actions
Trigger - Run Pick New Unit Set <gen> (ignoring conditions)
Collapse Else - Actions
Do nothing
This one is the actual spawning trigger:
Trigger:
No More Units
Collapse Events
Time - Every 5.00 seconds of game time
Conditions
Collapse Actions
Collapse For each (Integer A) from 1 to 12, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
Collapse And - All (Conditions) are true
Collapse Conditions
(Number of units in (Units owned by (Player((Integer A))) matching ((((Matching unit) is A Hero) Equal to False) and ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A peon-type unit) Equal to False) and ((((Matching unit) is A structure) Equal to 0
((Player((Integer A))) is in ActivePlayers) Equal to True
ArmyRegen[(Integer A)] Equal to False
SheeotMan[(Integer A)] Equal to False
Collapse Then - Actions
Game - Display to (Player group((Player((Integer A))))) for 10.00 seconds the text: (|cffff0000Your army is gone! You must wait|r |cffffcc00 + ((String((((Points[(Integer A)] + (TeamKills[(((Integer A) / 4) + 1)] / KillGain)) / 6) + 20))) + |r |cffff0000seconds before a new one is made.|r))
Set SheeotMan[(Integer A)] = True
Countdown Timer - Start TimerToGetArmy[(Integer A)] as a One-shot timer that will expire in ((Real(((Points[(Integer A)] + (TeamKills[(((Integer A) / 4) + 1)] / KillGain)) / 6))) + 20.00) seconds
Collapse Else - Actions
Do nothing
Collapse For each (Integer A) from 1 to 12, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
ArmyRegen[(Integer A)] Equal to True
ArmyRegen_Copy[(Integer A)] Equal to True
((Player((Integer A))) is in ActivePlayers) Equal to True
Collapse Then - Actions
Set ArmyRegen[(Integer A)] = False
Set ArmyRegen_Copy[(Integer A)] = False
Set NewUnitsBoolean[(Integer A)] = True
Game - Display to (Player group((Player((Integer A))))) for 5.00 seconds the text: |cffffcc00A new arm...
Cinematic - Ping minimap for (Player group((Player((Integer A))))) at ((Player((Integer A))) start location) for 2.00 seconds, using a Simple ping of color (100.00%, 70.00%, 0.00%)
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Set TotalLevels[((Integer A) x (Integer B))] = 0
Set TotalValues[((Integer A) x (Integer B))] = 0
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Collapse For each (Integer C) from 1 to 10, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
HasLevelSpecific[((Integer A) x ((Integer B) x C))] Equal to True
MASTERALLOCATION[((Integer A) x (Integer B))] Greater than or equal to (ValueofUnit[C] x (TotalLevels[((Integer A) x (Integer B))] + 1))
Collapse Then - Actions
Set TotalLevels[((Integer A) x (Integer B))] = (TotalLevels[((Integer A) x (Integer B))] + 1)
Collapse Else - Actions
Do nothing
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Collapse For each (Integer C) from 1 to 10, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
HasLevelSpecific[((Integer A) x ((Integer B) x C))] Equal to True
MASTERALLOCATION[((Integer A) x (Integer B))] Greater than or equal to (ValueofUnit[C] x TotalLevels[((Integer A) x (Integer B))])
Collapse Then - Actions
Set TotalValues[((Integer A) x (Integer B))] = (TotalValues[((Integer A) x (Integer B))] + ValueofUnit[C])
Collapse Else - Actions
Do nothing
Collapse For each (Integer B) from 1 to 8, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
TotalLevels[((Integer A) x (Integer B))] Greater than or equal to 1
MASTERALLOCATION[((Integer A) x (Integer B))] Greater than or equal to 1
Collapse Then - Actions
Collapse For each (Integer C) from 1 to 10, do (Actions)
Collapse Loop - Actions
Set AvailablePoints[(((Integer A) x (Integer B)) x C)] = (MASTERALLOCATION[((Integer A) x (Integer B))] / TotalLevels[((Integer A) x (Integer B))])
Collapse Else - Actions
Do nothing
Collapse Else - Actions
Do nothing
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
Collapse Or - Any (Conditions) are true
Collapse Conditions
NewUnitsBoolean[1] Equal to True
NewUnitsBoolean[2] Equal to True
NewUnitsBoolean[3] Equal to True
NewUnitsBoolean[4] Equal to True
NewUnitsBoolean[5] Equal to True
NewUnitsBoolean[6] Equal to True
NewUnitsBoolean[7] Equal to True
NewUnitsBoolean[8] Equal to True
NewUnitsBoolean[9] Equal to True
NewUnitsBoolean[10] Equal to True
NewUnitsBoolean[11] Equal to True
NewUnitsBoolean[12] Equal to True
Collapse Then - Actions
Trigger - Run Pick New Unit Set <gen> (ignoring conditions)
Collapse Else - Actions
Do nothing