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

[Trigger] Complex Spawning

Status
Not open for further replies.
Level 6
Joined
Jun 30, 2006
Messages
230
For all of those familiar with Footmen vs Grunts, I'm properly redoing the map. The ones floating around right now have so many leaks after 30 mins of gameplay one or two players lag out. Not to mention the spawning...
They do the spawns for units is like this.
/* ::::: Rifles for Player One ::::: */
Detects if "Summon Rifle" is researched for Player One, then enables "Bring Rifle For Player1" trigger
/* ::::: Rifles for Player Two ::::: */
Detects if "Summon Rifle" is researched for Player Two, then enables "Bring Rifle For Player2" trigger

So, there are two triggers for every unit for each player. I'm not sure of how many units you can have spawning, but I think it is 24 for each player. So we have a potential of 480 triggers just to summon units on the map. Also there are TONS of timers on the map, plus a lot of triggers to edit if you want to change the time it takes for each unit to spawn. In the Footmen vs Grunts I looked at for the triggers, they never cleaned up points, either.

What I would like is to be able to have one trigger, maybe two for each type of unit. I'm very inexperienced in this kind of trigger, so I need help. I was thinking that it could loop through the players to see if they have the research required to bring the unit being spawned, and then spawn the rifles at the respective start locations for each player. This way you could eliminate four timers per unit, which would drastically reduce lag later in the game. But I don't have a clue how to do it.

And more than likely this will have to be done in JASS to do it the way I want to, but I was hoping not to....
 
Last edited:
Level 21
Joined
Jan 5, 2005
Messages
3,515
oh my goodness yeh this can be simiplified! have those people never heard of loops before?!?!?!?!

attatch the map or post an example of two triggers, one for footman team and one for grunt team (so im ugessing players red and orange?) and we might be able to fix
 
Level 6
Joined
Jun 30, 2006
Messages
230
Sure thing, hang on and I'll upload some stuff...

Footmen vs Grunts 7.12

Don't try to save it, you'll hate yourself :) You have to hold down enter for a long time because of errors due to the map protection used. It'll give errors on EVERY trigger and there are a lot of them.
Edit: fixed it so you can save it, but why would you want to?

Oh yeah, the triggers look like JASS because I had to recover triggers and because Newbie-w3 tampered with the .j file, I can't recover the GUI, but it's obvious that it was made with GUI.

The map I am testing everything on is test.w3x. I recreated the Rifleman trigger in the GUI for you, except I just realized I forgot to register an event lol.

Do you think the boys over at the terraining forums would spiff up my terrain just a little? I don't want it as 'nice' as the 7.12 version, it's too much and it gets in the way of playing.

Umm... I don't know what happened but... somehow I lost trigger data... anyways my map won't open...
I know how to 'steal' my terrain and unit data back, but it'll take some time to remember exactly how it's done...
 
Last edited:
Level 2
Joined
May 31, 2007
Messages
20
I took a look in your map and it's obvious why it laggs.
You didn't clean even 1 location leak. give me some time to rewrite all spawn triggers, i propably can cut it down to 1 - 3 triggers and without leaks.
 
Level 21
Joined
Jan 5, 2005
Messages
3,515
well i cant read jass, and i know you said you wanted it in GUI, i know it can be done in GUI and it can probably done in. there are at least 3 ways i know of doing this in less than 3 triggers, but here is what i would do just because it is the simplest...as for leaks, well im not sure...:

First declare each unit in a unit type array and each region as a region type array:

  • Oh Noes
    • Events
      • Time - Elapsed game time is 0.01 seconds
    • Conditions
    • Actions
      • Set UnitToSpawn[1] = Footman
      • Set UnitToSpawn[2] = Knight
      • Set UnitToSpawn[3] = Rifleman
      • Set UnitToSpawn[4] = Mortar Team
      • Etc - for every unit to be spawned
      • Set Region[1] = Region 001 <gen>
      • Set Region[2] = Region 002 <gen>
      • Set Region[3] = Region 003 <gen>
      • Set Region[4] = Region 004 <gen>
      • For every region for players 1-12.

second have a dedicated building selling only unit upgrades and have this trigger:

  • Oh Noes
    • Events
      • Unit - A unit Finishes research
    • Conditions
      • ((Triggering unit) is A structure) Equal to True
      • (Unit-type of (Triggering unit)) Equal to Arcane Vault
    • Actions
      • Set ResearchLevel[(Player number of (Owner of (Triggering unit)))] = (ResearchLevel[(Player number of (Owner of (Triggering unit)))] + 1)
if the building where u buy the upgrade is not dedicated to that one upgrade, and other upgrades such as armour or weapons can be bought there, u should make conditions to counter this.

then i would have this to spawn the units:

  • Oh Noes
    • Events
      • Time - Every 60.00 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 10, do (Actions)
        • Loop - Actions
          • Unit - Create 1 UnitToSpawn[ResearchLevel[(Integer A)]] for (Player((Integer A))) at (Center of Region[(Integer A)]) facing Default building facing degrees
as i said, this might not be the most leak-free version, but its easy...
 
Level 6
Joined
Jun 30, 2006
Messages
230
Thanks for your help, both of you. And FireEye, it's not my map you looked at, it's some noob version of the original. I want to clean it up, but don't have the Know-How to do it properly. All I can do is clean up the leaks, but it would still be inefficient. Thanks Nemisis, but I'd still like to see how FireEye does it.

So many noobs have edited it that it is a nightmare. And the unit data is done retarded. The creator and the noobs editing it didn't know about <A001,DataA1> and such. They wrote out EVERY data.
 
Last edited:
Level 2
Joined
May 31, 2007
Messages
20
Mine is working with x and y coords.
Didn't really check for any bugs right now, but however, here's what i wrote.
uhm..., to stupid to read the comments? I'll add a globals block.
JASS:
globals
    real array udg_SpawnX
    real array udg_SpawnY
    integer array udg_Interval
    integer array udg_CreepId
    integer array udg_ResearchId
    integer udg_CurrentInterval
endglobals

function CreepSpawnPreload takes nothing returns nothing
    //there are some globals at all
    //udg_SpawnX = real + array
    //udg_SpawnY = real + array
    //udg_Interval = integer + array
    //udg_CreepId = integer + array
    //udg_ResearchId = integer + array
    //udg_CurrentInterval = integer
    //Just setting the CurrentInterval = 0 at start up, not really needed, but i want to make sure it starts with 0
    set udg_CurrentInterval = 0
    //Spawn Position for Player(0)
    set udg_SpawnX[0] = -512.0
    set udg_SpawnY[0] = 512.0
    //And so on for all Players
    //...
    //Now for the creeps
    set udg_CreepId[0] = 'h000' //In this example custom human unit nr. 1
    set udg_ResearchId[0] = 'R000' //In this case the id for a custom research can also be anything else, e.g. ability, unit or what you want, but you have to change the constant function CreepSpawnCondition
    set udg_Interval[0] = 5 //In this case we have a 5 sec timer, meaning every 25 sec this unit will spawn
    set udg_CreepId[1] = 'h001' //Custom human unit nr. 2
    set udg_ResearchId[1] = 'R001' //The needed condition for unit 2
    set udg_Interval[1] = 30 //This unit will spawn every 150 sec
    //And so on
    //Well this was the preload, pretty long for many units, but hey, only 1 trigger
endfunction

constant function CreepSpawnTimerTimeOut takes nothing returns real
    return 5.00 //How fast the timer should expire, SpawnTime = this value * udg_Interval[x]
endfunction

function CreepSpawnCondition takes integer ResearchId, integer PlayerId returns boolean
    local integer CheckI = udg_CurrentInterval/udg_Interval[ResearchId]
    return CheckI*udg_Interval[ResearchId] == udg_CurrentInterval and GetPlayerTechCountSimple(ResearchId, Player(PlayerId)) > 0 //Only spawn Creeps when the condition is true
endfunction

constant function CreepSpawnPlayerAmount takes nothing returns integer
    return 9 //In this case for 10 Player
endfunction

constant function CreepSpawnTypeAmount takes nothing returns integer
    return 1 //The max array index you got for the research ids
endfunction

constant function CreepSpawnMaxInterval takes nothing returns integer
                 //This is a tricky part
                 //If i would use e.g. 15 unit-type 2 won't spawn
                 //But if i use 45 it would need 45 Seconds between the spawns
    return 30    //In this case 30 because 30/5 == 6 => 6*5 == 30
endfunction

function Trig_CreepSpawn_Actions takes nothing returns nothing
    local integer PlayerId = 0
    local integer ResearchLoop
    set udg_CurrentInterval = udg_CurrentInterval + 1
    loop
        exitwhen PlayerId > CreepSpawnPlayerAmount()
        set ResearchLoop = 0
        loop
            exitwhen ResearchLoop > CreepSpawnTypeAmount()
            if CreepSpawnCondition(udg_ResearchId[ResearchLoop],PlayerId) then
                if udg_CreepId[ResearchLoop] > 0 then
                    call CreateUnit(Player(PlayerId),udg_CreepId[ResearchLoop],udg_SpawnX[PlayerId],udg_SpawnY[PlayerId],270.0)
                else
                    call BJDebugMsg("Unit @ index: "+I2S(ResearchLoop)+" is equal 0!")
                endif
            endif
            set ResearchLoop = ResearchLoop + 1
        endloop
        set PlayerId = PlayerId + 1
    endloop
    if udg_CurrentInterval >= CreepSpawnMaxInterval() then
        set udg_CurrentInterval = 0
    endif
endfunction

//===========================================================================
function InitTrig_CreepSpawn takes nothing returns nothing
    //To initiate all variables
    call CreepSpawnPreload()
    //Now creating the trigger and adding the timer to it
    set gg_trg_CreepSpawn = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic(gg_trg_CreepSpawn,CreepSpawnTimerTimeOut())
    call TriggerAddAction(gg_trg_CreepSpawn,function Trig_CreepSpawn_Actions)
endfunction
 
Last edited:
Level 6
Joined
Jun 30, 2006
Messages
230
FireEye, was that all of what you intended to do and leave the rest to me? Just asking, I'm not lazy, merely energy efficient. No sense in reinventing the wheel, as my father always says.

Oh and, you never declared your variables, you merely tried to set values without saying that they exist first.
 
Level 21
Joined
Jan 5, 2005
Messages
3,515
to get rid of leaks in urs gst

uuuggghhh i cant be bothered.... if blue jeans is going to use it i will but by the looks of this its not gunna be used to i wont worry about it.


also if you have a region variable does it still leak? because it stores the spawn point in the memory as the variable not as a place so there is no point destroying it because its not actually getting rid of anything, because the spawn is already saved in the memory by the variable...if you see what i mean?
 
Level 18
Joined
May 27, 2007
Messages
1,689
it wasnt really aimed at u gst, i was just saying that for blue jeans benefit but i guess ur right and its not the region variable its in ur third trigger where it says "Create Whatever Unit-At (Center of Region[Integer A])-Its the Center of Region that leaks, even though the region is already placed the point will leak which is why you need to first set a point variable to the Center of Region then have the units spawn at that point and use the custom script afterwards
 
Level 21
Joined
Jan 5, 2005
Messages
3,515
do u know what the leaks would be like if you had this:

  • Set RegionPoint[1] = (Center of Region 001 <gen>)
RegionPoint is a poin variable

because you are saving the point within region 001, only the variable, which would be saved in the memory anyways, would be able to leak...but if it is preset and saved in the memory surely it isnt taking up to much space?

i dunno im just trying to understand this.
 
Level 18
Joined
May 27, 2007
Messages
1,689
well see im not sure but what happens I think, cus i dont fully understand why they leak, i just know when they leak and how to fix it, basically a plumber that doesnt know anything about rust. But i think what happens is when you use a point, and only use it temporarily, it creates a number referencing to the point, but the game does not kno you only need it temporarily, and then stores this, which after time and more points and things it just builds up a whole bunch of unused references, then it leaks
 
Level 2
Joined
May 31, 2007
Messages
20
Blue_Jeans you're really lazy, well however, i have insert all unit-types, added a new option which prevents too many loops and btw. i said at the very first comments which variables are used, what type of variable and if it's an array.
I just though you're intelligent enough to understand what i'm writing.
I added a global variable part, so even you can not say that i use any undeclared variable.
JASS:
globals
    integer array udg_ResearchId
    integer array udg_CreepId
    integer array udg_Interval
    real array udg_SpawnX
    real array udg_SpawnY
    integer udg_CurrentInterval = 0
    trigger gg_trg_CreepSpawn = null
endglobals
function CreepSpawnPreload takes nothing returns nothing
    //Spawn Locations
    //Player(0)
    set udg_SpawnX[0] = - 6400.0
    set udg_SpawnY[0] = 2240.0
    //Player(1)
    set udg_SpawnX[1] = - 6400.0
    set udg_SpawnY[1] = 960.0
    //Player(2)
    set udg_SpawnX[2] = - 6400.0
    set udg_SpawnY[2] = - 256.0
    //Player(3)
    set udg_SpawnX[3] = - 6400.0
    set udg_SpawnY[3] = - 1600.0
    //Player(4)
    set udg_SpawnX[4] = - 6400.0
    set udg_SpawnY[4] = - 2880.0
    //Player(5)
    set udg_SpawnX[5] = 6400.0
    set udg_SpawnY[5] = 2304.0
    //Player(6)
    set udg_SpawnX[6] = 6400.0
    set udg_SpawnY[6] = 960.0
    //Player(7)
    set udg_SpawnX[7] = 6400.0
    set udg_SpawnY[7] = - 256.0
    //Player(8)
    set udg_SpawnX[8] = 6400.0
    set udg_SpawnY[8] = - 1536.0
    //Player(9)
    set udg_SpawnX[9] = 6400.0
    set udg_SpawnY[9] = - 2880.0
    //Rifleman
    set udg_ResearchId[0]='R007'
    set udg_CreepId[0]='hrif'
    set udg_Interval[0]=6
    //Sorc
    set udg_ResearchId[1]='R00G'
    set udg_CreepId[ 1]='hsor'
    set udg_Interval[1]=10
    //Priest
    set udg_ResearchId[2]='R004'
    set udg_CreepId[2]='hmpr'
    set udg_Interval[2]=9
    //Spellbreaker
    set udg_ResearchId[3]='R005'
    set udg_CreepId[3]='hspt'
    set udg_Interval[3]=10
    //Mortar
    set udg_ResearchId[4]='R008'
    set udg_CreepId[4]='hmtm'
    set udg_Interval[4]=31
    //Knight
    set udg_ResearchId[5]='R009'
    set udg_CreepId[5]='hkni'
    set udg_Interval[5]=10
    //Gryphon
    set udg_ResearchId[6]='R00A'
    set udg_CreepId[6]='hgry'
    set udg_Interval[6]=23
    //Noble Knight
    set udg_ResearchId[7]='R018'
    set udg_CreepId[7]='hbld'
    set udg_Interval[7]=33
    //Bronze Dragon
    set udg_ResearchId[8]='R01E'
    set udg_CreepId[8]='nbzd'
    set udg_Interval[8]=60
    //Archer
    set udg_ResearchId[9]='R00B'
    set udg_CreepId[9]='earc'
    set udg_Interval[9]=3
    //Huntress
    set udg_ResearchId[10]='R00V'
    set udg_CreepId[10]='esen'
    set udg_Interval[10]=6
    //Dryad
    set udg_ResearchId[11]='R00C'
    set udg_CreepId[11]='edry'
    set udg_Interval[11]=6
    //Druid of Talon
    set udg_ResearchId[12]='R00E'
    set udg_CreepId[12]='edot'
    set udg_Interval[12]=9
    //Druid of Claw
    set udg_ResearchId[13]='R00F'
    set udg_CreepId[13]='edoc'
    set udg_Interval[13]=15
    //Mountain Giant
    set udg_ResearchId[14]='R00D'
    set udg_CreepId[14]='emtg'
    set udg_Interval[14]=24
    //Chimera
    set udg_ResearchId[15]='R00H'
    set udg_CreepId[15]='echm'
    set udg_Interval[15]=25
    //Dragon Hawk Rider
    set udg_ResearchId[16]='R00W'
    set udg_CreepId[16]='hdhw'
    set udg_Interval[16]=21
    //Siege Engine
    set udg_ResearchId[17]='R014'
    set udg_CreepId[17]='hrtt'
    set udg_Interval[17]=33
    //Flying Machine
    set udg_ResearchId[18]='R013'
    set udg_CreepId[18]='hgyr'
    set udg_Interval[18]=11
    //Hipporyph
    set udg_ResearchId[19]='R00Y'
    set udg_CreepId[19]='ehip'
    set udg_Interval[19]=10
    //Ancient Protector
    set udg_ResearchId[20]='R019'
    set udg_CreepId[20]='etrp'
    set udg_Interval[20]=31
    //Glaive Thrower
    set udg_ResearchId[21]='R011'
    set udg_CreepId[21]='ebal'
    set udg_Interval[21]=27
    //Faerie Dragon
    set udg_ResearchId[22]='R012'
    set udg_CreepId[22]='efdr'
    set udg_Interval[22]=13
    //Green Dragon
    set udg_ResearchId[23]='R01F'
    set udg_CreepId[23]='ngrd'
    set udg_Interval[23]=60
    //Spirit Walker
    set udg_ResearchId[24]='R00I'
    set udg_CreepId[24]='ospw'
    set udg_Interval[24]=13
    //Shaman
    set udg_ResearchId[25]='R00J'
    set udg_CreepId[25]='oshm'
    set udg_Interval[25]=10
    //Witch Doctor
    set udg_ResearchId[26]='R00K'
    set udg_CreepId[26]='odoc'
    set udg_Interval[26]=9
    //Headhunter
    set udg_ResearchId[27]='R00L'
    set udg_CreepId[27]='ohun'
    set udg_Interval[27]=4
    //Tauren
    set udg_ResearchId[28]='R00M'
    set udg_CreepId[28]='otau'
    set udg_Interval[28]=11
    //Demolisher
    set udg_ResearchId[29]='R00N'
    set udg_CreepId[29]='ocat'
    set udg_Interval[29]=31
    //Wind Rider
    set udg_ResearchId[30]='R00O'
    set udg_CreepId[30]='owyv'
    set udg_Interval[30]=12
    //Bat
    set udg_ResearchId[31]='R00Z'
    set udg_CreepId[31]='otbr'
    set udg_Interval[31]=19
    //Red Dragon
    set udg_ResearchId[32]='R01H'
    set udg_CreepId[32]='nrwm'
    set udg_Interval[32]=60
    //Ogre Lord
    set udg_ResearchId[33]='R01A'
    set udg_CreepId[33]='nogl'
    set udg_Interval[33]=32
    //Raider
    set udg_ResearchId[34]='R010'
    set udg_CreepId[34]='orai'
    set udg_Interval[34]=9
    //Kodo Beast
    set udg_ResearchId[35]='R015'
    set udg_CreepId[35]='okod'
    set udg_Interval[35]=23
    //Kodo Beast
    set udg_ResearchId[36]='R015'
    set udg_CreepId[36]='okod'
    set udg_Interval[36]=23
    //Abomination
    set udg_ResearchId[37]='R00P'
    set udg_CreepId[37]='uabo'
    set udg_Interval[37]=15
    //Banshee
    set udg_ResearchId[38]='R00R'
    set udg_CreepId[38]='uban'
    set udg_Interval[38]=9
    //Necromancer
    set udg_ResearchId[39]='R00Q'
    set udg_CreepId[39]='unec'
    set udg_Interval[39]=9
    //Crypt Fiend
    set udg_ResearchId[40]='R00S'
    set udg_CreepId[40]='ucry'
    set udg_Interval[40]=9
    //Ghoul
    set udg_ResearchId[41]='R00T'
    set udg_CreepId[41]='ugho'
    set udg_Interval[41]=2
    //Meat Wagon
    set udg_ResearchId[42]='R00U'
    set udg_CreepId[42]='umtw'
    set udg_Interval[42]=27
    //Frost Wyrm
    set udg_ResearchId[43]='R006'
    set udg_CreepId[43]='ufro'
    set udg_Interval[43]=27
    //Obsidian Destroyer
    set udg_ResearchId[44]='R00X'
    set udg_CreepId[44]='ubsp'
    set udg_Interval[44]=25
    //Gargoyle
    set udg_ResearchId[45]='R017'
    set udg_CreepId[45]='ugar'
    set udg_Interval[45]=10
    //Obsidian Statue
    set udg_ResearchId[46]='R016'
    set udg_CreepId[46]='uobs'
    set udg_Interval[46]=23
    //Black Dragon
    set udg_ResearchId[47]='R01G'
    set udg_CreepId[47]='nbwm'
    set udg_Interval[47]=60    
endfunction
constant function CreepSpawnTimerTimeOut takes nothing returns real
    return 5.00 //How fast the timer should expire, SpawnTime = this value * udg_Interval[x]
endfunction
function CreepSpawnCondition takes integer ResearchId, integer PlayerId returns boolean
    local integer CheckI = udg_CurrentInterval/udg_Interval[ResearchId]
    return CheckI*udg_Interval[ResearchId] == udg_CurrentInterval and GetPlayerTechCountSimple(ResearchId, Player(PlayerId)) > 0 //Only spawn Creeps when the condition is true
endfunction
constant function CreepSpawnPlayerAmount takes nothing returns integer
    return 9 //In this case for 10 Player
endfunction
constant function CreepSpawnMaxInterval takes nothing returns integer
    return 32400 //Due the different values of the spawn times i choosed a high value none will ever reach during 1 game    
endfunction
function Trig_CreepSpawn_Actions takes nothing returns nothing
    local integer PlayerId = 0
    local integer ResearchLoop
    local integer ExitResearch = 47 //The max array index
    set udg_CurrentInterval = udg_CurrentInterval + 1
    loop
        exitwhen PlayerId > CreepSpawnPlayerAmount()
        set ResearchLoop = 0
        //if PlayerId <= 4 then     //I only recommend using this if you don't plan to
        //    set ResearchLoop = 0  //add many new creeps, so this'll save 
        //    set ExitResearch = 23 //some un-needed loops
        //else
        //    set ResearchLoop = 24
        //    set ExitResearch = 47
        //endif    
        loop
            exitwhen ResearchLoop > ExitResearch
            if CreepSpawnCondition(udg_ResearchId[ResearchLoop],PlayerId) then
                if udg_CreepId[ResearchLoop] > 0 then
                    call CreateUnit(Player(PlayerId),udg_CreepId[ResearchLoop],udg_SpawnX[PlayerId],udg_SpawnY[PlayerId],270.0)
                else
                    call BJDebugMsg("Unit @ index: "+I2S(ResearchLoop)+" is equal 0!")
                endif
            endif
            set ResearchLoop = ResearchLoop + 1
        endloop
        set PlayerId = PlayerId + 1
    endloop
    if udg_CurrentInterval >= CreepSpawnMaxInterval() then
        set udg_CurrentInterval = 0
    endif
endfunction
//===========================================================================
function InitTrig_CreepSpawn takes nothing returns nothing
    //To initiate all variables
    call CreepSpawnPreload()
    //Now creating the trigger and adding the timer to it
    set gg_trg_CreepSpawn = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic(gg_trg_CreepSpawn,CreepSpawnTimerTimeOut())
    call TriggerAddAction(gg_trg_CreepSpawn,function Trig_CreepSpawn_Actions)
endfunction
 
Last edited:
Level 6
Joined
Jun 30, 2006
Messages
230
Dude, thank you so much. And btw, I KNOW that you went back and added the globals in the first post. I copy and pasted your original post into JASS Craft :). So don't try to pull the "thought you were smart enough".
It's seriously appreciated, though. I can do all that but I'm so pushed for time these days. Plus, I haven't had time to play with loops enough to be confident doing them for a working map. Work is getting longer each day, so this is extremely appreciated. You will get a big thank you when the map loads.
In my last post I was merely curious if I needed to finish it or if that was all you were going to do. I didn't mean for you to do them all if you didn't want to. I was willing to finish it after you had fleshed out the basics, but I didn't want to do it myself if you were already doing it. I couldn't understand from your previous post what you planned on doing, so I asked...
I would rep you if I could... but I can't. When I can, you'll get it. You saved me a lot of time, dude. Thank you.
 
Status
Not open for further replies.
Top