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

[Trigger] Efficiency Trouble

Status
Not open for further replies.
Level 2
Joined
Dec 18, 2007
Messages
15
I guess I couldn't satisfy myself just leeching off the tutorials as a guest anymore.

READ NO FURTHER UNLESS YOU WANT TO READ A RATHER LENGTHY POST.

You've been warned.

I'm making a map akin to Footmen Frenzy, but starting from scratch and with a couple of my own little quirks. I was wondering if there's a more efficient (fewer lines, leak free, easy for loop, or something else) way to trigger my spawns. The spawn unit is controlled by a castable ability, and once the spawn is chosen, it's locked (at least for the tiers I've triggered.) I've tested those that I've written and they work great, but it's really getting to be a pain to do 5 triggers for each of 3 tiers for each of 12 players. Any way to compact this but still keep the cast based spawning system would be appreciated.

  • P1 T1
    • Events
      • Unit - A unit owned by Player 1 (Red) Finishes casting an ability
    • Conditions
      • ((Casting unit) is A structure) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Spawn Dragonkin Defender T1 tank
        • Then - Actions
          • Unit - Remove Spawn Dragonkin Defender T1 tank from (Triggering unit)
          • Unit - Remove Spawn Frost Wolf T1 dps from (Triggering unit)
          • Unit - Remove Spawn Raging Ice Troll T1 range from (Triggering unit)
          • Unit - Remove Spawn Murloc Frostweaver T1 caster from (Triggering unit)
          • Multiboard - Set the icon for (Last created multiboard) item in column 2, row 3 to ReplaceableTextures\CommandButtons\BTNFountainOfLifeBlood.blp
          • Trigger - Turn on P1 T1t <gen>
          • Trigger - Turn off P1 T0 <gen>
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Spawn Murloc Frostweaver T1 caster
        • Then - Actions
          • Unit - Remove Spawn Dragonkin Defender T1 tank from (Triggering unit)
          • Unit - Remove Spawn Frost Wolf T1 dps from (Triggering unit)
          • Unit - Remove Spawn Raging Ice Troll T1 range from (Triggering unit)
          • Unit - Remove Spawn Murloc Frostweaver T1 caster from (Triggering unit)
          • Multiboard - Set the icon for (Last created multiboard) item in column 2, row 3 to ReplaceableTextures\CommandButtons\BTNFountainOfLifeBlood.blp
          • Trigger - Turn on P1 T1c <gen>
          • Trigger - Turn off P1 T0 <gen>
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Spawn Frost Wolf T1 dps
        • Then - Actions
          • Unit - Remove Spawn Dragonkin Defender T1 tank from (Triggering unit)
          • Unit - Remove Spawn Frost Wolf T1 dps from (Triggering unit)
          • Unit - Remove Spawn Raging Ice Troll T1 range from (Triggering unit)
          • Unit - Remove Spawn Murloc Frostweaver T1 caster from (Triggering unit)
          • Multiboard - Set the icon for (Last created multiboard) item in column 2, row 3 to ReplaceableTextures\CommandButtons\BTNFountainOfLifeBlood.blp
          • Trigger - Turn on P1 T1d <gen>
          • Trigger - Turn off P1 T0 <gen>
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Spawn Raging Ice Troll T1 range
        • Then - Actions
          • Unit - Remove Spawn Dragonkin Defender T1 tank from (Triggering unit)
          • Unit - Remove Spawn Frost Wolf T1 dps from (Triggering unit)
          • Unit - Remove Spawn Raging Ice Troll T1 range from (Triggering unit)
          • Unit - Remove Spawn Murloc Frostweaver T1 caster from (Triggering unit)
          • Multiboard - Set the icon for (Last created multiboard) item in column 2, row 3 to ReplaceableTextures\CommandButtons\BTNFountainOfLifeBlood.blp
          • Trigger - Turn on P1 T1r <gen>
          • Trigger - Turn off P1 T0 <gen>
        • Else - Actions
      • Trigger - Turn off (This trigger)
      • Trigger - Turn on P1 T2 <gen>
Yeah it's big and messy. This is the trigger for player 1 tier 1, it responds to the spell for unit selection being cast and reacts accordingly. The multiboard stuff I'm ok with because I made a team setup and a multiboard layput that defies all attempts to fill in slots with for loops >.<. P1 T2, the trigger turned on at the bottom, is the same sort of trigger, initially off because it's pointless but turned on once it matters. The spawn triggers themselves are all of the same format so I'll only post one of em.

  • P1 T1t
    • Events
      • Time - Every 12.00 seconds of game time
    • Conditions
      • PlayerHereArray[1] Equal to True
    • Actions
      • Unit - Create 1 Dragonkin Defender for Player 1 (Red) at (Player 1 (Red) start location) facing 270.00 degrees
NOTE: Each unit type has its own spawn timer, so it's not just the "every 12 seconds" event. Most of the times range from 10-15 seconds though, at least the ones I've triggered so far.
This is initially off, and is turned on by the first trigger. PlayerHereArray is a boolean array which is set at map initialization and adjusted when a player leaves.

Any help would be greatly appreciated, as all I really have left is a lot of trigger grunt work and some minor unit work, but the triggers are going to take for ever at this rate.
 
Last edited:
Level 11
Joined
Feb 22, 2006
Messages
752
You could set all your spawn unit types into a global integer array. Then, when you detect a spell being cast, just set the custom value of the casting structure to the appropriate value so that you will only need ONE spawn trigger with an action that goes something like:

Create 1 <SpawnUnitType[Custom Value of <Player 1 Base>]> at...

where SpawnUnitType is your integer array with all of the unit types stored, and Player 1 Base is the the structure that casts the spells and the units spawn next to (I assume).

Of course, you will need an additional trigger at map init to define your SpawnUnitType array values, but it's better than creating a spawn trigger for every unit type.

EDIT: Can't believe I didn't think of this earlier but...you can just have another global integer array called like SpawnUnitIndex or something and save the appropriate integer values in THAT variable instead of Custom Values of the players' bases. So your actions would look like:

Create 1 <SpawnUnitType[SpawnUnitIndex[1]]> at...

Then have one trigger for each player, which it looks like you should already have.
 
Level 2
Joined
Dec 18, 2007
Messages
15
I neglected to mention in the first post that the periodic events are unique to each unit, the units aren't balanced to be on the same spawn interval.

In retrospect that's a pretty big thing to omit when asking for help- Amending the first post.

I've tried to handle spawning with one trigger but I couldn't seem to get around the periodic event. Lemme leaf through the GUI again and see if I missed something.
 
Last edited:
Level 11
Joined
Feb 22, 2006
Messages
752
Lol, yes tht bit of information does change things around a bit.

Ok, well, here's my revised solution:

Create a global timer variable called, let's say RespawnTimer.

Now create an integer array called RespawnType to hold unit type ids, like in my last post, make the array size equal to the number of players in the map.

Finally, make a global unit array called RespawnBase that holds the bases for every player - you will need to define the array at map init or something. I don't know exactly how your map works, but if you ever destroy/replace bases for whatever reason, you need to update the array. IMPORTANT: When you are defining the array, make sure that RespawnBase[0] (not RespawnBase[1] ) points to Player 1's base, and so on.

Now, in your trigger that detects the spell casting, put this in as the very first action(using Custom Script action):

JASS:
local integer i = GetPlayerId( GetOwningPlayer( GetTriggerUnit() ) )


Then, for each spell check, instead of turning on your spawn triggers, put this in (again using Custom Script action):

JASS:
set udg_RespawnType[i] = 'h000'
call PauseTimer( udg_RespawnTimer[i] )
call TimerStart( udg_RespawnTimer[i], 12.00, true, null )


Of course, you will want to change the unit type id to match the appropriate units in your map. The second parameter of the TimerStart() function is the timeout value - how often it expires. Change that value accordingly based on how often you want your units to spawn.

Now, create a trigger that detects Timer Expiration of all of the RespawnTimers. Then, in the actions, input this:

JASS:
local timer t = GetExpiredTimer()
local real x
local real y
local integer i
if ( t == udg_RespawnTimer[0] ) then
    set i = 0
elseif ( t == udg_RespawnTimer[1] ) then
    set i = 1
//keep adding elseif clauses until there is one for each respawn timer (so if there are 12 players, 12 timers in your map, it would go up to elseif( t == udg_RespawnTimer[11] ) )
endif
set x = GetUnitX( RespawnBase[i] )
set y = GetUnitY( RespawnBase[i] )
call CreateUnit( Player(i), udg_RespawnType[i], x, y, 270.00 ) //the last parameter (the 270.00) is the unit facing angle when it spawns; you can change it to w/e you want
set t = null


You can put it in any way you want, but it'll probably be easier just to convert the entire trigger in custom script and just copy-paste the above code into the _Actions function.

If you want to avoid the JASS altogether in this last step, just make one trigger for every player, like you did before, and in have each trigger only detect a specific RespawnTimer, and in the trigger have actions that respawn the correct unit at the correct base (by manipulating the array indexes). This will probably take longer though.

EDIT: THIS IS IMPORTANT - if you have a default unit spawn at the beginning of the map (that does not require the player to cast one of those spells in order to start respawning) you need to call TimerStart() for every RespawnTimer at map initialization (or whenever you want to start the default spawn) with the appropriate timeout values. You ALSO need to define the RespawnType array to hold the correct unit type id for the default spawn. Remember, you ONLY need to do this if you have units spawning at the beginning of your map that don't require players to cast those spells at their bases.
 
Level 2
Joined
Dec 18, 2007
Messages
15
Overall you lost me, I'm absurdly JASStarded except for the basic memory leak patching. But you did give me an idea for a MUCH easier GUI workaround (relative to what I was doing, not relative to JASS.) I'll retrigger the spawns tomorrow and see if I can get something like that running.

Thanks a ton.

*EDIT*
Just retriggered player 1 in about 5 minutes for all 3 tiers. you definately pointed me in the right direction. thanks.
 
Last edited:
Level 2
Joined
Dec 18, 2007
Messages
15
Used a Timer array, with each index belonging to a player, that was redefined depending on the spawn spell cast. Coupled that with a Unit-type array with each index refering to a player, so each slot was that player's spawn unit. So all spawns were handled by a single trigger for each player, plus the ones that detected spellcasts.

Rewrote the spellcast detection to, instead of turning on an individual spawn trigger, just redefine the spawn timer and unit (and deal with the multiboard stuff/)
 
Status
Not open for further replies.
Top