HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Need a solution to a unit forgetting its order problem

01-20-2007, 08:04 PM#1
rain9441
Heres the problem, in a tower defense map:

I order units to move to points. But if a unit becomes entangled, the unit stops. After becoming un-entangled, the unit no longer has the order to move to a certain point.

I'm looking for a solution to solve this problem.

Heres what I've tried:

A) Keep track of all units that are on the map, and periodically force them to move if they are not moving. Didn't work because units that had no order and became damaged automatically would flee from the tower attacking it... Not only that but it seems unrealistic to have a timer that checks possibly 30-150 units' orders every so often. Was quite the lagg'er.

B) Created a trigger, on player owned unit issued order of "stop". Simply force the unit to move again. Didn't work, entangling units does not order a unit to stop (infact, no order is issued at all).

Open to any ideas anyone has.
01-20-2007, 08:29 PM#2
Feroc1ty
Create a tower, with slow attack speed and an ok range doing 0 damage, and every time a unit gets hit by the tower make a trigger for the attacked unit to move his ass.
01-21-2007, 06:41 AM#3
Pyrogasm
Detect when a unit begins casting your entangle ability (so it fires before the spell is actually cast), and save the target of the ability to a local variable. Then, wait until the unit no longer has the entangle buff, and order the unit to move (or attack move, if that's the case) to the point you specify.

Unfortunately, you need a JASS trigger for this because you're using a local variable in a condition (which GUI can't handle). It'd look something like this:
Collapse JASS:
function Trig_Untitled_Trigger_001_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'AEer' ) ) then //set AEer to your entangle ability's raw data ID
        return false
    endif
    return true
endfunction

function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    local unit Entangle_Unit
    set Entangle_Unit = GetSpellTargetUnit()
    loop
        exitwhen ( UnitHasBuffBJ(Entangle_Unit, 'BEer') == false ) //set BEer to your entangle buff's raw data ID
        call TriggerSleepAction(RMaxBJ(bj_WAIT_FOR_COND_MIN_INTERVAL, 0.25))
    endloop
    call IssuePointOrderLocBJ( Entangle_Unit, "move", udg_PointVar ) //set udg_PointVar equal to where the unit should move to, and if you need to make it attack move, change "move" to "attack move"
    set Entangle_Unit = null
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Untitled_Trigger_001, Condition( function Trig_Untitled_Trigger_001_Conditions ) )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction

Now... if someone could clean up those nasty BJ's you'd be set...
01-21-2007, 07:30 AM#4
zeroXD
Here's an optimized version with removed BJ's and stuff.

Collapse JASS:
function Trig_Entangled_Move_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'AEer' //set AEer to your entangle ability's raw data ID
endfunction

function Trig_Entangled_Move_Actions takes nothing returns nothing
    local unit Entangled_Unit = GetSpellTargetUnit()
    local real targetX = GetLocationX( udg_PointVar ) //set udg_PointVar equal to where the unit should move to. I have converted it to real x/y values for optimization
    local real targetY = GetLocationY( udg_PointVar )
    loop
        exitwhen ( GetUnitAbilityLevel( Entangled_Unit, 'BEer' ) == false ) //set BEer to your entangle buff's raw data ID
        call TriggerSleepAction( 0.25 ) 
    endloop
    call IssuePointOrder( Entangled_Unit, "move", targetX, targetY ) , //if you need to make it attack move, change "move" to "attack move"
    set Entangled_Unit = null
endfunction

//===========================================================================
function InitTrig_Entangled_Move takes nothing returns nothing
    set gg_trg_Entangled_Move = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Entangled_Move, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Entangled_Move, Condition( function Entangled_Move_Conditions ) )
    call TriggerAddAction( gg_trg_Entangled_Move, function Entangled_Move_Actions )
endfunction
01-21-2007, 08:44 AM#5
Pyrogasm
Is using X/Y values actually faster? It seems like you need more variables and lines of code. I understand that it's more precise, but why not just move the unit to the point if the point is constant (which it would be in this case)?

EDIT: I don't mean to say that I am a great "jass-er" myself, but I think you misinterpreted my
Collapse JASS:
loop
    exitwhen ( UnitHasBuffBJ(Entangle_Unit, 'BEer') == false ) //set BEer to your entangle buff's raw data ID
    call TriggerSleepAction(RMaxBJ(bj_WAIT_FOR_COND_MIN_INTERVAL, 0.25))
endloop
The GUI equivalent is
Trigger:
Wait unitil (((Entangle_Unit) has buff Entangling Roots) equal to false), checking every 0.25 seconds
Your method of
Collapse JASS:
loop
    exitwhen ( GetUnitAbilityLevel( Entangled_Unit, 'BEer' ) == false ) //set BEer to your entangle buff's raw data ID
    call TriggerSleepAction( 0.25 ) 
endloop
seems like it A) wouldn't perform the wait until the unit didn't have the buff ("GetUnitAbilityLevel" seems... out of place), and B) would wait indefinitely because there is now no end to the loop.

Correct me if I'm wrong.
01-21-2007, 09:00 AM#6
BertTheJasser
zeroXD's code owns yours Pyrogasm.

The UnitHasBuffBJ(u,'buff') is actually GetUnitAbilityLevel(u,'buff')>0 (Note: For buffs it will only return 0 or 1)

Note: Maybe change the event to EVENT_PLAYER_UNIT_SPELL_EFFECT and decrease the TriggerSleepAction intervall to 0.0 (which is actually ~0.09)
01-21-2007, 10:54 AM#7
Pyrogasm
Quote:
Originally Posted by BertTheJasser
zeroXD's code owns yours Pyrogasm.
Yes, I'd imagined it did. Thanks for clarifying, Bert.

Yes, the event should be EVENT_PLAYER_UNIT_SPELL_EFECT, I had it as EVENT_PLAYER_UNIT_SPELL_CAST only because I was screwing around with trying to save and reissue its order earlier, in which case I needed the trigger to fire before the spell was cast.

I would say, however, that a 0.25 interval is fairly accurate and still doesn't lag (something rain9441 said he was having trouble with), as opposed to a 0.00 (~0.09) second wait. It's really a matter of preference; I would leave it as is, but Bert knows more than I do, so I'd listen to him.
01-21-2007, 12:26 PM#8
BertTheJasser
A loop with a ~0.09 wait does not cause any lag. In my current project i use about 100 loops like that and it's stil running as smooth as a 1vs1 melee game. Another point is that 0.25s is noticeable amount of time for the human eye (, so you will see the "runner" standing there). Here I must say like the hp propaganda says: sense and simplicity.
01-21-2007, 12:30 PM#9
zeroXD
Quote:
and decrease the TriggerSleepAction intervall to 0.0 (which is actually ~0.09)
Is it only 0.09?
It feels like something close to 0.3...
EDIT: What could be done is just put the wait as the same as the entangling roots duration, since this is apparently just for one spell.
01-21-2007, 01:40 PM#10
BertTheJasser
Yes, we could, but then we would have to use a timer for accuracy, and so have to take care about the timer set to null bug. Polled wait is no solution either. It hostages the handle index of a timer. So we could use a private polled wait and a timerstack, like Vex does, but I guess for rain9441's purposes this fits and is even scalable in case he creates another entangling ability with a diffrent duration.
01-21-2007, 03:14 PM#11
rain9441
Actually, waiting in increments of 0.25 or even ranges of 0.40-0.60 wouldn't necessarily be that bad. The original idea I tried (timer that checks ALL units and moves them) was set at 0.50 seconds. The entangled unit may still have a short delay before moving, but since the animation for being unentangled also has delay, it is not noticable at all. To be honest it was actually more awkward looking if you time it to 0.10 seconds or less.

What I think i'll do is create a trigger like the above that will order the entangled unit to stop as soon as the buff wears off. The reason is, I already have good triggers that detect unit stopped and make them move. They are reliable.
01-21-2007, 04:03 PM#12
BertTheJasser
Are you still GUI-centered >programmer<?