| 12-12-2004, 12:40 AM | #1 |
Greetings. I have this trigger. It notices when units enter a region and shuffles them off to the next appropriate region. I have four pathways on the map, and previously, I had a separate trigger that did this for each pathway. However, since they all did virtually the same thing, I combined them into one. So, granted, there's more going on in this trigger than before. However, it's not a lot more stuff. Basically it just checks a larger loop of regions now than it did before. Where before the trigger didn't lag at all, now it noticeably lags every few seconds. So, what can be causing this lag? I'll be blunt: it's generally running for around 60 units every several seconds. However, like I mentioned, it didn't lag when it was separate triggers. Code:
//======================
// Functi0ns
//======================
function Trig_Router_Actions takes nothing returns nothing
//== Loc4ls ============
local unit unitEnter = GetEnteringUnit()
local unit unitPicker
local player playerOwner = (GetOwningPlayer(unitEnter))
local integer intLoop
local integer intDirection = 1
local integer intInGroup = 12
local integer intWaves = 0
local integer intCustom
local integer intLoopWave
local group groupInRegion = CreateGroup()
local group groupInLast = CreateGroup()
local group array groupArWave
local location locOrder
//== Ac7ions ===========
if ((playerOwner == Player(PLAYER_NEUTRAL_PASSIVE)) or (playerOwner == Player(bj_PLAYER_NEUTRAL_VICTIM))) then
call DisplayTextToForce(GetPlayersAll(), "Router runs.")
call PolledWait(0.25)
set intLoop = 0
loop
exitwhen intLoop >= 79
if ((RectContainsCoords(udg_rectArPathCollect[intLoop], GetUnitX(unitEnter), GetUnitY(unitEnter)) == true) and (intLoop == GetUnitUserData(unitEnter))) then
if (playerOwner == Player(PLAYER_NEUTRAL_PASSIVE)) then
set intDirection = 1
elseif (playerOwner == Player(bj_PLAYER_NEUTRAL_VICTIM)) then
set intDirection = -1
endif
call DisplayTextToForce(GetPlayersAll(), "Region: " + I2S(intLoop))
call GroupEnumUnitsInRect(groupInRegion, udg_rectArPathCollect[intLoop], null)
call GroupEnumUnitsInRect(groupInLast, udg_rectArPathCollect[intLoop - intDirection], null)
loop
set unitPicker = FirstOfGroup(groupInLast)
exitwhen unitPicker == null
call GroupAddUnit(groupInRegion, unitPicker)
call GroupRemoveUnit(groupInLast, unitPicker)
endloop
call DestroyGroup(groupInLast)
call DisplayTextToForce(GetPlayersAll(), "groupInRegion size: " + I2S(CountUnitsInGroup(groupInRegion)))
loop
set unitPicker = FirstOfGroup(groupInRegion)
exitwhen unitPicker == null
set intCustom = GetUnitUserData(unitPicker)
if ((intCustom == intLoop) and (GetOwningPlayer(unitPicker) == playerOwner) and (GetWidgetLife(unitPicker) > 0)) then
set intInGroup = intInGroup + 1
if (intInGroup >= 13) then
set intInGroup = 0
set intWaves = intWaves + 1
set groupArWave[intWaves] = CreateGroup()
endif
call GroupAddUnit(groupArWave[intWaves],unitPicker)
call SetUnitUserData(unitPicker, (intCustom + intDirection))
endif
call GroupRemoveUnit(groupInRegion, unitPicker)
endloop
call DestroyGroup(groupInRegion)
// call DisplayTextToForce(GetPlayersAll(), "Waves: " + I2S(intWaves))
set locOrder = GetRectCenter(udg_rectArPathEnter[intLoop + intDirection])
set intLoopWave = 1
loop
exitwhen intLoopWave > intWaves
call GroupPointOrderLoc(groupArWave[intLoopWave], "attack", locOrder)
set intLoopWave = intLoopWave + 1
endloop
set intLoop = 79
endif
set intLoop = intLoop + 1
endloop
call DisplayTextToForce(GetPlayersAll(), "Router finishes.")
endif
//== Cl3anup ===========
set unitEnter = null
set unitPicker = null
call DestroyGroup(groupInRegion)
set groupInRegion = null
call DestroyGroup(groupInLast)
set groupInLast = null
set intLoop = 1
loop
exitwhen intLoop > intWaves
call DestroyGroup(groupArWave[intLoop])
set groupArWave[intLoop] = null
endloop
call RemoveLocation(locOrder)
set locOrder = null
endfunction
//======================
// Event5
//======================
function InitTrig_Router takes nothing returns nothing
set gg_trg_Router = CreateTrigger()
call TriggerAddAction(gg_trg_Router, function Trig_Router_Actions)
endfunction |
| 12-13-2004, 07:16 AM | #2 | |
Quote:
You already give the answer yourself. It's because of the program flow. As you mentioned it used to be different threads (because of different triggers) before, meaning that when 1 trigger finished, control returned to another thread (also other things might have been executed between the execution of these different triggers) As it is now, you don't have any statement that gives control away in between (like a TriggerSleepAction(0) or something that would give control to other waiting threads) so it HAS TO execute the whole big loop before other things can be done whereas it only had to execute parts before. |
| 12-13-2004, 08:56 AM | #3 |
So basically, add a line of code which gives control to other waiting threads after each check, or take the easy (and probably more reliable) way out and make it seperate triggers again. Whats the problem with having more than 1 trigger? Actually, it'd probably be easier to set up waygates instead of using triggers, solves lag and pathing problems. |
| 12-13-2004, 05:05 PM | #4 |
PolledWait won't let it move on to another thread? If I used TriggerSleepAction, it might improve performance? |
| 12-13-2004, 07:46 PM | #5 |
I think polled wait would also do the job, provided that you call it from within the loop (which you're not doing atm). |
| 12-13-2004, 07:52 PM | #6 |
TriggerSleepAction(0) would do it |
| 12-13-2004, 08:49 PM | #7 |
Well, PolledWait can't go below 0.25, and it's only in there right now to give time for the triggering unit to get within the rect that it triggered. I'll try throwing a sleep into the loop, then. |
| 12-13-2004, 10:27 PM | #8 |
I still dont see why you cant just use modified waygates. |
| 12-14-2004, 02:54 AM | #9 |
Could you be more specific; what do you mean exactly when you say "waygates"? |
| 12-14-2004, 11:20 AM | #10 |
Panto, would you mind explaining how that trigger works? Because if it does what I think it does, I could really learn from it. Right now I'm using almost 40 triggers to route spawned units from 1 region to the next, but if I understand your trigger correctly it loops through each region in a variable and automatically routes them? |
| 12-14-2004, 01:51 PM | #11 |
It does. Except right now, it's pretty laggy, so the standard method, like yours, will be more playable. |
| 12-14-2004, 09:16 PM | #12 |
Actually, I figured out how to do what I wanted. I took your code, them chopped off the parts I needed and twiddled it down until it worked. At first, sometimes the regions would not see the units inside the rects, until I put a TriggerSleepAction(0.10) at the very start of the actions. Code:
//======================
// Functions
//======================
function Router_Actions takes nothing returns nothing
//== Locals ============
local unit unitEnter=GetEnteringUnit()
local player playerOwner=GetOwningPlayer(unitEnter)
local location loc
//== Actions ===========
call TriggerSleepAction(0.10)
if playerOwner==Player(0) or playerOwner==Player(6) then
//== Top Lane ==========
if (RectContainsCoords(gg_rct_War_N,GetUnitX(unitEnter),GetUnitY(unitEnter)) or RectContainsCoords(gg_rct_Lore_N,GetUnitX(unitEnter),GetUnitY(unitEnter))) and playerOwner==Player(0) then
set loc=GetRectCenter(gg_rct_Attack_Point_N)
elseif (RectContainsCoords(gg_rct_Crypt_W,GetUnitX(unitEnter),GetUnitY(unitEnter)) or RectContainsCoords(gg_rct_Temple_W,GetUnitX(unitEnter),GetUnitY(unitEnter))) and playerOwner==Player(6) then
set loc=GetRectCenter(gg_rct_Attack_Point_N)
elseif RectContainsCoords(gg_rct_Attack_Point_N,GetUnitX(unitEnter),GetUnitY(unitEnter)) then
if playerOwner==Player(0) then
set loc=GetRectCenter(gg_rct_necropolis)
endif
if playerOwner==Player(6) then
set loc=GetRectCenter(gg_rct_tree_of_life)
endif
endif
call TriggerSleepAction(0)
//== Middle Lane =======
if (RectContainsCoords(gg_rct_War_NE,GetUnitX(unitEnter),GetUnitY(unitEnter)) or RectContainsCoords(gg_rct_Lore_NE,GetUnitX(unitEnter),GetUnitY(unitEnter))) and playerOwner==Player(0) then
set loc=GetRectCenter(gg_rct_Attack_Point_Center)
elseif (RectContainsCoords(gg_rct_Crypt_SW,GetUnitX(unitEnter),GetUnitY(unitEnter)) or RectContainsCoords(gg_rct_Temple_SW,GetUnitX(unitEnter),GetUnitY(unitEnter))) and playerOwner==Player(6) then
set loc=GetRectCenter(gg_rct_Attack_Point_Center)
elseif RectContainsCoords(gg_rct_Attack_Point_Center,GetUnitX(unitEnter),GetUnitY(unitEnter)) then
if playerOwner==Player(0) then
set loc=GetRectCenter(gg_rct_necropolis)
endif
if playerOwner==Player(6) then
set loc=GetRectCenter(gg_rct_tree_of_life)
endif
endif
call TriggerSleepAction(0)
//== Bottom Lane =======
if (RectContainsCoords(gg_rct_War_E,GetUnitX(unitEnter),GetUnitY(unitEnter)) or RectContainsCoords(gg_rct_Lore_E,GetUnitX(unitEnter),GetUnitY(unitEnter))) and playerOwner==Player(0) then
set loc=GetRectCenter(gg_rct_Attack_Point_E)
elseif (RectContainsCoords(gg_rct_Crypt_S,GetUnitX(unitEnter),GetUnitY(unitEnter)) or RectContainsCoords(gg_rct_Temple_S,GetUnitX(unitEnter),GetUnitY(unitEnter))) and playerOwner==Player(6) then
set loc=GetRectCenter(gg_rct_Attack_Point_E)
elseif RectContainsCoords(gg_rct_Attack_Point_E,GetUnitX(unitEnter),GetUnitY(unitEnter)) then
if playerOwner==Player(0) then
set loc=GetRectCenter(gg_rct_necropolis)
endif
if playerOwner==Player(6) then
set loc=GetRectCenter(gg_rct_tree_of_life)
endif
endif
call IssuePointOrderLocBJ(unitEnter,"attack",loc)
endif
//== Cleanup ===========
set unitEnter=null
call RemoveLocation(loc)
set loc=null
endfunction
//======================
// Events
//======================
function InitTrig_Router takes nothing returns nothing
set gg_trg_Router = CreateTrigger()
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_War_N )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_War_NE )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_War_E )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Lore_N )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Lore_NE )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Lore_E )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Crypt_W )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Crypt_SW )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Crypt_S )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Temple_W )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Temple_SW )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Temple_S )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Attack_Point_N )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Attack_Point_Center )
call TriggerRegisterEnterRectSimple( gg_trg_Router, gg_rct_Attack_Point_E )
call TriggerAddAction(gg_trg_Router, function Router_Actions)
endfunction |
| 12-14-2004, 11:26 PM | #13 | |
Quote:
I have 2 islands, seperated by a long, twisty land bridge. Each island has a waygate that transports to the other island, i could send my units over the land bridge, but if i tell them to just move to the other island they will automatically take the shorter route and use the waygate. It requires no triggers (waygate destinations can be set in the editor.) and is compatable with WCIII Pathing. |
| 12-14-2004, 11:55 PM | #14 |
I don't think Panto wants the units to teleport around, he wants them simply to walk to the next waypoint. But yeah, the waypoint idea is quite useful in some situations. |
| 12-15-2004, 01:35 AM | #15 |
Ryude, the reason you need the wait is thus: The "Unit Enters Region" event is triggered when a unit's collision intersects a region (or rather, a rect). However, when checking to see if a unit is within a rect, it checks for its center point. So, you need to give the unit just a split second to fully enter the rect so that the check will catch it. At least, this was roughly how it was explained to me, and it holds up to inspection. |
