HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

JASS Question

09-14-2007, 03:23 AM#1
StRoNgFoE_2000
Hi everyone, I am still new to the world of programming and JASS Is the first close to anything language i ever attempted to learn, so one thing I am confused on that needs to be made clear to me.

I understand slightly that all your script uses processor time, and the cleaner your script the faster or more efficient it is. So, I've been wondering for awhile which of the below examples would be faster, slower, or if they are equal to each other.

Lets say I have 3 JASS "triggers" (they are simple, I'm still learning)...
Collapse JASS:
//trigger 1
function RockGolemCond takes nothing returns boolean
    local unit u = GetAttacker()
    local integer id = GetUnitTypeId(u)
    if (id=='o02X') or (id=='o03T') then
        set u = null
        return true
    endif
    set u = null
    return false
endfunction
function RockGolem takes nothing returns nothing
    local unit u = GetAttacker()
    call IssueImmediateOrder(u, "thunderclap")
    set u = null
endfunction
function InitTrig_RockGolems takes nothing returns nothing
    set gg_trg_RockGolems = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_RockGolems, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddCondition(gg_trg_RockGolems, Condition(function RockGolemCond))
    call TriggerAddAction(gg_trg_RockGolems, function RockGolem)
endfunction

//trigger 2
function RootTowerCond takes nothing returns boolean
    local unit u = GetAttacker()
    local integer int = GetUnitTypeId(u)
    if (int=='h03U') then
        set u = null
        return true
    endif
    set u = null
    return false
endfunction
function RootTower takes nothing returns nothing
    local unit a = GetAttacker()
    local unit t = GetTriggerUnit()
    call IssueTargetOrder(a, "entanglingroots", t)
    set a = null
    set t = null
endfunction
function InitTrig_RootTower takes nothing returns nothing
    set gg_trg_RootTower = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_RootTower, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddCondition(gg_trg_RootTower, Condition(function RootTowerCond))
    call TriggerAddAction(gg_trg_RootTower, function RootTower)
endfunction

//trigger 3
function StormCloudCond takes nothing returns boolean
    local unit u = GetAttacker()
    local integer int = GetUnitTypeId(u)
    if (int=='h06E') or (int=='h06F') then
        set u = null
        return true
    endif
    set u = null
    return false
endfunction
function StormCloud takes nothing returns nothing
    local unit a = GetAttacker()
    local unit t = GetTriggerUnit()
    local real r = GetUnitState(a, UNIT_STATE_MAX_MANA)
    call SetUnitState(a, UNIT_STATE_MANA, r * RMaxBJ(0,100) * 0.01)
    call IssueTargetOrder(a, "forkedlightning", t)
    set a = null
    set t = null
endfunction
function InitTrig_StormClouds takes nothing returns nothing
    set gg_trg_StormClouds = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_StormClouds, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddCondition(gg_trg_StormClouds, Condition(function StormCloudCond))
    call TriggerAddAction(gg_trg_StormClouds, function StormCloud)
endfunction

Now, just by looking at it, the below would look like it would be much easier on your processor, but I'm not one to say so or not, because the logic behind it is the same.

Collapse JASS:
function Merged takes nothing returns nothing
    local unit u = GetAttacker()
    local unit t = GetTriggerUnit()
    local integer id = GetUnitTypeId(u)
    local real r = GetUnitState(a, UNIT_STATE_MAX_MANA)
    if (id=='o02X') or (id=='o03T') then
        call IssueImmediateOrder(u, "thunderclap")
    elseif (id=='h03U') then    
         call IssueTargetOrder(u, "entanglingroots", t)
    elseif (id=='h06E') or (id=='h06F') then
        call SetUnitState(u, UNIT_STATE_MANA, r * RMaxBJ(0,100) * 0.01)
        call IssueTargetOrder(u, "forkedlightning", t)
    endif
    set u = null
    set t = null
endfunction
function InitTrig_Merged takes nothing returns nothing
    set gg_trg_Merged = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Merged, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddAction(gg_trg_Merged, function Merged)
endfunction

I don't know the right term for which is better, so I'll use "faster". My question is, is the three triggers in the first box faster, slower, or equal to the one trigger in the second box?
09-14-2007, 03:56 AM#2
botanic
Ok first things first. Shorter script length doesn't have anything to do with how well it runs.

Now as for some basic tips:

Gamecache is slow

globals are slower then locals

when you have a function "take" something it uses memory

every function you call is generally slower then doing it inside the function for example a

call add(1,2)

function add takes integer a and integer b returns integer
return a + b
endfunction

is slower then just adding a and b in the parent function

Triggerting unit is always slower then any other default thing such as dying unit. Also triggering unit will survive through waits ect where most others wont

Use as few limiters as possible for example

if a = 0 then
w/e
endif
if a = 1 then
w/e
endif

is slower then

if a = 0 then
w/e
elseif a = 1 then
w/e
endif

This is because it is only having to worry about the contents of the second if statement in the event that a <> 0.


PS: Im at work so I dont have time to look at the JASS ill see it in about an hour when I get home. Also I am not a "super JASS pro" so this is all to the best of my knowladge however there are much more qualified people out there. (also I cant use JASS new gen pack so I only know JASS2 and not vJASS)



EDIT: one thing that stuck out was the " local unit u = GetAttacker()" jsut have the function take the unit from the parent function
09-14-2007, 04:22 AM#3
StRoNgFoE_2000
Most of those tips were great, I did not know some if that thank you.

Now, I still have my question from my first post, and a new question.

You ended with "one thing that stuck out was the " local unit u = GetAttacker()" jsut have the function take the unit from the parent function". Could you elaborate on that, it confused me.
09-14-2007, 05:19 AM#4
botanic
ok first off if you have AIM please aim me , botanicvelious. If not ill edit the post in a few mins.

EDIT: in the first JASS trigger i thought it was all one trigger....

Ne ways what I meant was for example if you had one function call another function like this:

Collapse JASS:
function actions takes unit u returns nothing
//actions
endfunction

function initialize takes nothing returns nothing
local unit u = GetAttackingUnit()
call actions(u)
endfunction


you see how it passes the value instade of redeclaring it?

that allows you to include things like waits ect.

so then you could have something like this that would be MUI

Collapse JASS:
function actions takes unit u returns nothing
//actions
endfunction

function actions2 takes unit u returns nothing
//more actions
endfunction

function initialize takes nothing returns nothing
local integer I
local unit u = GetAttackingUnit()

set I = 0
loop
    exitwhen I = 100
    set I = I + 1
    call actions(u)
    PolledWait(2.00)
    call actions2(u)
    PolledWait(2.00)
endloop

endfunction

PS: Use the second one it looks fine to me (dunno what you are trying to accomplish with it but it seems optimized to me) My only comment on that one is that make the first if the most common action and the later ones the less common ones. It is not that important in reality however it would be slightly faster because it would reduce the number of times it has to worry about conditions in the trigger.
09-14-2007, 09:22 PM#5
StRoNgFoE_2000
I understand what you mean now, I just didnt' understand or know the correct terms . I try to do that as often as possible to make less lines of code. An example of one of my functions like that is one I use to swap players. I have many more this one is small so won't take up much space.

Collapse JASS:
function OwnershipChange takes unit u, player x, player y, integer i returns nothing
    if (i==1) then
        call SetUnitOwner(u, x, false)
    elseif (i==2) then
        call SetUnitOwner(u, y, false)
    endif
endfunction

The reason I wanted to know which of the two triggers were faster in my first post is because I have a lot of "special towers" in my map that attack with spells or create special effects. I was wondering if I should have left them all in their own trigger or merge them into one function with a bunch of if/elseifs, because they all fire with the same Event, "EVENT_PLAYER_UNIT_ATTACKED". Here is what I have for the final trigger that contains all my spells. (It's rather large). I'm wondering if this is better than multiple triggers.

Collapse JASS:
function Master takes nothing returns nothing
    local unit u = GetAttacker()
    local unit t = GetTriggerUnit()
    local location l = GetUnitLoc(t)
    local integer id = GetUnitTypeId(u)
    local real r = GetUnitState(u, UNIT_STATE_MAX_MANA)
//THIS SECTION HANDLES ANY SPELL ATTACKS THE TOWERS HAVE
    //RockGolems - Thunderclap
    if (id=='o02X') or (id=='o03T') then
        call IssueImmediateOrder(u, "thunderclap")
    //Root Tower - Entangle
    elseif (id=='h03U') then
        call IssueTargetOrder(u, "entanglingroots", t)
    //Storm Cloud / Thunder Cloud - Forked Lightning
    elseif (id=='h06E') or (id=='h06F') then
        call SetUnitState(u, UNIT_STATE_MANA, r * RMaxBJ(0,100) * 0.01)
        call IssueTargetOrder(u, "forkedlightning", t)
    //Mind Blaster / Mind Waster / The Moon / Lunar Eclipse / Priestess - Starfall
    elseif (id=='h01A') or (id=='h01S') or (id=='h03J') or (id=='h049') or (id=='o02U') then
        call IssueImmediateOrder(u, "starfall")
    //Chain Lightnign Caster / Chain Lightning Blaster - Chain Lightning
    elseif (id=='h00B') or (id=='hC36') then
        call SetUnitState(u, UNIT_STATE_MANA, r * RMaxBJ(0,100) * 0.01)
        call IssueTargetOrder(u, "chainlightning", t)
    //Cloud Strife - Bloodlust
    elseif (id=='e015') then
        call IssueTargetOrder(u, "bloodlust", u)
    //Death Tower - Instant Death
    elseif (id=='h03W') then
        call UnitDamageTarget(u, t, 1000000000, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    //Gravity's Pull - Slow
    elseif (id=='h019') then
        if (not(IsUnitType(t, UNIT_TYPE_ANCIENT))) then
            call UnitAddType(t, UNIT_TYPE_ANCIENT)
            call IssueTargetOrder(u, "slow", t)
            call IssueImmediateOrder(u, "stop")
        endif
        call PolledWait(3)
        call UnitRemoveType(t, UNIT_TYPE_ANCIENT)
    //Soul Reaver Towers - TK Blast
    elseif (id=='oC65') or (id=='o00N') or (id=='o00M') or (id=='o00O') or (id=='o00P') or (id=='o00Q') or (id=='o00E') or (id=='o00I') or (id=='o00G') then
        call IssueTargetOrder(u, "thunderbolt", t)
    //Faerie Mage / Faerie Chansellor - Faerie Fire
    elseif (id=='o016') or (id=='oC26') then
        if (not(IsUnitType(t, UNIT_TYPE_ANCIENT))) then
            call UnitAddType(t, UNIT_TYPE_ANCIENT)
            call IssueTargetOrder(u, "faeriefire", t)
            call IssueImmediateOrder(u, "stop")
        endif
        call PolledWait(10)
        call UnitRemoveType(t, UNIT_TYPE_ANCIENT)
    //Noah - Stampede 1,2,3
    elseif (id=='h06J') then
        call UnitAddAbility(u, 'A007')
        call IssuePointOrderLoc(u, "stampede", l)
        call TriggerSleepAction(2.5)
        call UnitRemoveAbility(u, 'A007')
        call UnitAddAbility(u, 'A017')
        call IssuePointOrderLoc(u, "stampede", l)
        call TriggerSleepAction(2.5)
        call UnitRemoveAbility(u, 'A017')
        call UnitAddAbility(u, 'A018')
        call IssuePointOrderLoc(u, "stampede", l)
        call TriggerSleepAction(2.5)
        call UnitRemoveAbility(u, 'A018')
        call UnitAddAbility(u, 'A007')
    //Overgrown Spike Plant / Warden - Fan of Knives    
    elseif (id=='h036') or (id=='o05A') then    
        call IssueImmediateOrder(u, "fanofknives")
    //Raziel - Earth Reaver Charged - Shock Wave
    elseif (id=='o00J') then   
        call IssuePointOrderLoc(u, "shockwave", l)        
    //Raziel - Fire Reaver Charged - War Stomp
    elseif (id=='o00H') then
        call IssueImmediateOrder(u, "stomp")
    //Raziel - Air Reaver Charged / Storm Mage - Cyclone
    elseif (id=='hC85') or (id=='o00F') then
        if (not(IsUnitType(t, UNIT_TYPE_ANCIENT))) then
            call UnitAddType(t, UNIT_TYPE_ANCIENT)
            call IssueTargetOrder(u, "cyclone", t)
            call IssueImmediateOrder(u, "stop")
        endif
        call PolledWait(6)
        call UnitRemoveType(t, UNIT_TYPE_ANCIENT)
    //The Sun / Solar Eclipse - Rain of Fire
    elseif (id=='h03P') or (id=='h048') then
        call IssuePointOrderLoc(u, "rainoffire", l)
    //The Void - Devour
    elseif (id=='o01W') then
        call IssueTargetOrder(u, "devour", t)
    //Lightning Rod / Telsa Rod - Lightning Shield 
    elseif (id=='o00R') or (id=='oC60') then
        if (not(IsUnitType(t, UNIT_TYPE_ANCIENT))) then
            call UnitAddType(t, UNIT_TYPE_ANCIENT)
            call IssueTargetOrder(u, "lightningshield", t)    
            call IssueImmediateOrder(u, "stop")
        endif
        call PolledWait(12)
        call UnitRemoveType(t, UNIT_TYPE_ANCIENT)
    //Web Tower / Marksman - Web
    elseif (IsUnitType(t, UNIT_TYPE_FLYING)) and (id=='h03T') or (id=='h044') then
        if (not(IsUnitType(t, UNIT_TYPE_ANCIENT))) then
            call UnitAddType(t, UNIT_TYPE_ANCIENT)
            call IssueTargetOrder(u, "web", t)    
            call IssueImmediateOrder(u, "stop")
        endif
        call PolledWait(10)
        call UnitRemoveType(t, UNIT_TYPE_ANCIENT)
//THIS SECTION HANDLES ANY SPECIAL EFFECTS THE TOWERS HAVE
    //Blast Furnace
    elseif (id=='o00Y') then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Demon\\ReviveDemon\\ReviveDemon.mdl", t, "origin"))
    //Blizzard Master
    elseif (id=='o00V') then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\Blizzard\\BlizzardTarget.mdl", t, "origin"))
    //Fusion Canon / Ultra Fusion Canon
    elseif (id=='h01X') or (id=='h05H') then
        call DestroyEffect(AddSpecialEffectLoc("Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl", l))
    //Grave Marker / Grave Master
    elseif (id=='o014') or (id=='o01B') then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Reincarnation\\ReincarnationTarget.mdl", t, "origin"))
    //Ion Canon / Ion Combuster
    elseif (id=='hC55') or (id=='h013') then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\NightElf\\ReviveNightElf\\ReviveNightElf.mdl", t, "origin"))
    //Meteor Watcher / Lunar Watcher
    elseif (id=='o00X') or (id=='o017') then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Demon\\RainOfFire\\RainOfFireTarget.mdl", t, "origin"))
    //Nova Creator
    elseif (id=='o00W') then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", t, "origin"))
    //Nuclear Missile Silo
    elseif (id=='hC59') then
        call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\Flare\\FlareTarget.mdx", l))
    //Poison Spire / Deadly Spire
    elseif (id=='h00N') or (id=='h00R') then
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl", t, "origin"))
    //Ursula / Ursula Valkyrie / Berserker / Heavenly ArchAngel
    elseif (id=='h02J') or (id=='h02P') or (id=='oC73') or (id=='o022') or (id=='e00Q') then
        if (IsUnitType(u, UNIT_TYPE_FLYING)) then
            call DestroyEffect(AddSpecialEffectTarget("Units\\NightElf\\Wisp\\WispExplode.mdl", t, "origin"))
        endif
    endif
    call RemoveLocation(l)
    set u = null
    set t = null
    set l = null
endfunction
function InitTrig_MasterTrigger takes nothing returns nothing
    set gg_trg_MasterTrigger = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_MasterTrigger, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddAction(gg_trg_MasterTrigger, function Master)
endfunction

Before I had multiple triggers all with the same event. Would it have been better to keep it multiple triggers, or merge it into one function?
09-14-2007, 09:40 PM#6
TaintedReality
Keep it multiple, I would imagine multiple triggers would be faster (at the worst it would be equal), but mainly keep it multiple for the sake of readability.

Btw: Wtf are you doing with this function? oO. Why would you not just use SetUnitOwner?

Collapse JASS:
function OwnershipChange takes unit u, player x, player y, integer i returns nothing
    if (i==1) then
        call SetUnitOwner(u, x, false)
    elseif (i==2) then
        call SetUnitOwner(u, y, false)
    endif
endfunction
09-14-2007, 09:58 PM#7
grim001
You should seriously knock any idea of "speed" out of your head and focus on organization of code. Splitting your spells into their own triggers is much more important than a 0.000000000001 second faster processing time.
09-14-2007, 10:35 PM#8
Toadcop
+ waits are evil *yep*
09-14-2007, 10:37 PM#9
TaintedReality
/agree. The main place where you need to worry about speed is when something is looping on a short interval.
09-15-2007, 07:45 AM#10
StRoNgFoE_2000
That mess of sloppy code was what I made real fast by merging all triggers with the same event, to use as an example to show what I meant by which is better, one function for each "tower", or a ton of if/elseif.

To TaintedReality: The purpose of the function is to swap players when a unit is sent, for the reason if too many units for one player are on the map at any time, moving them becomes a pain because they start to clutter. Using 3 players for units instead of one, makes things much smoother (3x the limit before they begin to clutter).

Collapse JASS:
function OwnershipChange takes unit u, player x, player y, integer i returns nothing
    if (i==1) then
        call SetUnitOwner(u, x, false)
    elseif (i==2) then
        call SetUnitOwner(u, y, false)
    endif
endfunction
function BuildUnitTopActions takes nothing returns nothing
    local location l
    local rect r
    local unit a
    local unit u = GetEnteringUnit()
    local player x = Player(6)
    local player y = Player(8)
    local player z = Player(10)
    local player p = GetOwningPlayer(u)
    local playercolor pc = GetPlayerColor(p)
    local integer pn = GetPlayerId(p)+1
    local integer id = GetUnitTypeId(u)
    local integer pv = GetUnitPointValue(u)
    call RemoveUnit(u)
    if (udg_UnitPlayerTop==3) then
        set udg_UnitPlayerTop = 0
    endif
    set r = gg_rct_Middle_Center_Bottom_Left
    set l = GetRectCenter(r)
    set a = CreateUnitAtLoc(x, id, l, 270)
    call OwnershipChange(a, y, z, udg_UnitPlayerTop)
    call GroupAddUnit(udg_UnitsCenterBottomLeft, a)
    call RemoveLocation(l)
    call SetUnitColor(a, pc)
    set r = gg_rct_Middle_Left_Bottom
    set l = GetRectCenter(r)
    call IssuePointOrderLoc(a, "move", l)
    call RemoveLocation(l)
    set r = gg_rct_Middle_Center_Bottom_Right
    set l = GetRectCenter(r)
    set a = CreateUnitAtLoc(x, id, l, 270)
    call OwnershipChange(a, y, z, udg_UnitPlayerTop)
    call GroupAddUnit(udg_UnitsCenterBottomRight, a)
    call RemoveLocation(l)
    call SetUnitColor(a, pc)
    set r = gg_rct_Middle_Right_Bottom
    set l = GetRectCenter(r)
    call IssuePointOrderLoc(a, "move", l)
    call RemoveLocation(l)
    set udg_UnitPlayerTop = (udg_UnitPlayerTop + 1)
    set udg_Income[pn] = (udg_Income[pn] + pv)
    set udg_TotalIncome1 = (udg_Income[1]+(udg_Income[2]+udg_Income[3]))
    call MultiboardSetItemValueBJ(udg_MB, 2, (pn + 1), I2S(udg_Income[pn]))
    call MultiboardSetItemValueBJ(udg_MB, 2, 5, I2S(udg_TotalIncome1))
    call ConditionalTriggerExecute(gg_trg_UnitKillers)
    set l = null
    set r = null
    set a = null
    set u = null
    set x = null
    set y = null
    set z = null
    set p = null
    set pc = null
endfunction
function InitTrig_BuildUnitTop takes nothing returns nothing
    local region r2 = CreateRegion()
    set gg_trg_BuildUnitTop = CreateTrigger()
    call RegionAddRect(r2, gg_rct_Region_Top)
    call TriggerRegisterEnterRegion(gg_trg_BuildUnitTop, r2, null)
    call TriggerAddCondition(gg_trg_BuildUnitTop, Condition(function BuildUnit))
    call TriggerAddAction(gg_trg_BuildUnitTop, function BuildUnitTopActions)
    set r2 = null
endfunction

It could probably be further optimized with a loop and a rect array but I'm too lazy. Anyway, the global integer variable "udg_UnitPlayerTop" keeps track of the current position of what player to make it next. In the trigger, 0 does nothing and keeps it player 7, 1 makes it player 9, and 2 makes it player 11. Then after it hits 3, it's reset to 0 again to start the cycle over. This is one of two identical triggers, and this method is used 4 times, figured it would be easier to just make one function.

You have all been great help, thank you for all your advice.
09-15-2007, 08:16 PM#11
TaintedReality
Quote:
To TaintedReality: The purpose of the function is to swap players when a unit is sent, for the reason if too many units for one player are on the map at any time, moving them becomes a pain because they start to clutter. Using 3 players for units instead of one, makes things much smoother (3x the limit before they begin to clutter).

But it does *exactly* what SetUnitOwner does, but with extra parameters that have no purpose. So instead of calling OwnershipChange(u,p1,p2,1) you could just call SetUnitOwner(u,p1,false).
09-15-2007, 11:08 PM#12
StRoNgFoE_2000
I could if I put the function inside the trigger but like I said I use this same method 4 times so I just made it one function.

Collapse JASS:
function BuildUnitTopActions takes nothing returns nothing
    local location l
    local rect r
    local unit a
    local unit u = GetEnteringUnit()
    local player x = Player(6)
    local player y = Player(8)
    local player z = Player(10)
    local player p = GetOwningPlayer(u)
    local playercolor pc = GetPlayerColor(p)
    local integer pn = GetPlayerId(p)+1
    local integer id = GetUnitTypeId(u)
    local integer pv = GetUnitPointValue(u)
    call RemoveUnit(u)
    if (udg_UnitPlayerTop==3) then
        set udg_UnitPlayerTop = 0
    endif
    set r = gg_rct_Middle_Center_Bottom_Left
    set l = GetRectCenter(r)
    set a = CreateUnitAtLoc(x, id, l, 270)
    if (udg_UnitPlayerTop==1) then
        call SetUnitOwner(u, y, false)
    elseif (udg_UnitPlayerTop==2) then
        call SetUnitOwner(u, z, false)
    endif
    call GroupAddUnit(udg_UnitsCenterBottomLeft, a)
    call RemoveLocation(l)
    call SetUnitColor(a, pc)
    set r = gg_rct_Middle_Left_Bottom
    set l = GetRectCenter(r)
    call IssuePointOrderLoc(a, "move", l)
    call RemoveLocation(l)
    set r = gg_rct_Middle_Center_Bottom_Right
    set l = GetRectCenter(r)
    set a = CreateUnitAtLoc(x, id, l, 270)
    if (udg_UnitPlayerTop==1) then
        call SetUnitOwner(u, y, false)
    elseif (udg_UnitPlayerTop==2) then
        call SetUnitOwner(u, z, false)
    endif
    call GroupAddUnit(udg_UnitsCenterBottomRight, a)
    call RemoveLocation(l)
    call SetUnitColor(a, pc)
    set r = gg_rct_Middle_Right_Bottom
    set l = GetRectCenter(r)
    call IssuePointOrderLoc(a, "move", l)
    call RemoveLocation(l)
    set udg_UnitPlayerTop = (udg_UnitPlayerTop + 1)
    set udg_Income[pn] = (udg_Income[pn] + pv)
    set udg_TotalIncome1 = (udg_Income[1]+(udg_Income[2]+udg_Income[3]))
    call MultiboardSetItemValueBJ(udg_MB, 2, (pn + 1), I2S(udg_Income[pn]))
    call MultiboardSetItemValueBJ(udg_MB, 2, 5, I2S(udg_TotalIncome1))
    call ConditionalTriggerExecute(gg_trg_UnitKillers)
    set l = null
    set r = null
    set a = null
    set u = null
    set x = null
    set y = null
    set z = null
    set p = null
    set pc = null
endfunction
function InitTrig_BuildUnitTop takes nothing returns nothing
    local region r2 = CreateRegion()
    set gg_trg_BuildUnitTop = CreateTrigger()
    call RegionAddRect(r2, gg_rct_Region_Top)
    call TriggerRegisterEnterRegion(gg_trg_BuildUnitTop, r2, null)
    call TriggerAddCondition(gg_trg_BuildUnitTop, Condition(function BuildUnit))
    call TriggerAddAction(gg_trg_BuildUnitTop, function BuildUnitTopActions)
    set r2 = null
endfunction

The whole idea is to switch players every time its run for 3 times, then reset, because moving 3 players doesn't clutter like moving one. I can't think of a better way to do it, if there is one.
09-15-2007, 11:22 PM#13
TaintedReality
I understand the 3 players thing, but that function has no purpose. It's not really a big deal though and I think we're both misunderstanding each other =p.