HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Units should have to attack Target, but they don't (Berserker's Call from DotA)

04-16-2007, 04:15 PM#1
Just_a°fOol
Hi there
the spell I try to create is similiar to "Berserkers Call" from DotA
for those who don't know it:
All enemy units in an AoE around the caster have to attack him for a few seconds. They should not be able to cast any spells...they are just not able to do anything else but attacking the caster.

So I gave a buff to every attacker and made a trigger that says, everytime a unit with that specific buff is ordered another order but attacking the caster, it will have to attack the caster.
My trigger for that looks like this:
Code:
function Trig_attack_caster_Conditions takes nothing returns boolean
    if ( not ( UnitHasBuffBJ(GetOrderedUnit(), 'B007') == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_attack_caster_Actions takes nothing returns nothing
    local unit caster = GetLinkedUnit( GetTriggeringTrigger(), "BC_Spell", "caster" )
    local group g = GetLinkedGroup( GetTriggeringTrigger(), "BC_Spell", "group" )
    if ( GetOrderTargetUnit() != caster or (GetOrderTargetUnit() == caster and OrderId2StringBJ(GetIssuedOrderIdBJ()) != "attack" and OrderId2StringBJ(GetIssuedOrderIdBJ()) != "smart" )) then
        if IsUnitInGroup( GetOrderedUnit(), g ) then
            call IssueTargetOrderBJ( GetOrderedUnit(), "attack", caster )
        endif
    endif
    call DestroyGroup(g)
    set caster = null
    set g = null
endfunction

function DefineAttackers takes group MyGroup, unit caster returns nothing
    local location loc
    local unit    u
    local group   g = CreateGroup ()

    call GroupAddGroup( MyGroup, g )
    loop
        set u = FirstOfGroup( g )
        exitwhen u == null
        set loc = GetUnitLoc(u)
        call CreateNUnitsAtLocFacingLocBJ( 1, 'e00E', GetOwningPlayer(caster), loc, loc )
        call UnitApplyTimedLifeBJ( 1.00, 'BTLF', GetLastCreatedUnit() )
        call UnitAddAbilityBJ( 'A00J', GetLastCreatedUnit() )
        call SetUnitAbilityLevelSwapped( 'A00J', GetLastCreatedUnit(), GetUnitAbilityLevelSwapped('A00G', caster) )
        call IssueTargetOrderBJ( GetLastCreatedUnit(), "acidbomb", u )
        call RemoveLocation(loc)
        call GroupRemoveUnitSimple( u, g )           
    endloop
    call DestroyGroup( g )

    set loc = null
    set g   = null
    set u   = null
endfunction

function GroupFilter takes nothing returns boolean
    return ( UnitHasBuffBJ(GetFilterUnit(), 'B007') == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == true and IsUnitAliveBJ(GetFilterUnit()) == true )
endfunction
    
function Trig_Berserkers_Call_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A00G' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Berserkers_Call_Actions takes nothing returns nothing
    local unit caster = GetSpellAbilityUnit()
    local location loc = GetUnitLoc(caster)
    local trigger trg_attack_caster = CreateTrigger()
    local group g = GetUnitsInRangeOfLocMatching( 300.00, loc, Condition(function GroupFilter))
    call LinkObject( trg_attack_caster, "BC_Spell", "caster", caster )
    call LinkObject( trg_attack_caster, "BC_Spell", "group", g )

//buffs für caster und attacker 
    call DefineAttackers( g, caster )
      
    call CreateNUnitsAtLoc( 1, 'e00E', GetOwningPlayer(caster), loc, bj_UNIT_FACING )
    call UnitApplyTimedLifeBJ( 1.00, 'BTLF', GetLastCreatedUnit() )
    call UnitAddAbilityBJ( 'A00H', GetLastCreatedUnit() )
    call SetUnitAbilityLevelSwapped( 'A00H', GetLastCreatedUnit(), GetUnitAbilityLevel(caster, 'A00G') )
    call IssueTargetOrderBJ( GetLastCreatedUnit(), "innerfire", caster )

//trg_attack_caster
	call TriggerRegisterAnyUnitEventBJ( trg_attack_caster, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
	call TriggerRegisterAnyUnitEventBJ( trg_attack_caster, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
	call TriggerRegisterAnyUnitEventBJ( trg_attack_caster, EVENT_PLAYER_UNIT_ISSUED_ORDER )
	call TriggerAddCondition( trg_attack_caster, Condition( function Trig_attack_caster_Conditions ) )
    call TriggerAddAction( trg_attack_caster, function Trig_attack_caster_Actions )
    
    call PolledWait( I2R(GetUnitAbilityLevel(caster, 'A00G')) )
	call TriggerClearActions(trg_attack_caster)
	call DestroyTrigger(trg_attack_caster)   
    call RemoveLocation( loc )
    call DestroyGroup(g)
    set g = null
    set caster = null
    set loc = null    
    set trg_attack_caster = null
endfunction

//===========================================================================
function InitTrig_Berserkers_Call takes nothing returns nothing
    set gg_trg_Berserkers_Call = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Berserkers_Call, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Berserkers_Call, Condition( function Trig_Berserkers_Call_Conditions ) )
    call TriggerAddAction( gg_trg_Berserkers_Call, function Trig_Berserkers_Call_Actions )
endfunction

but when I test this with another player and he orders his buffed unit to walk anywhere on the map, his unit CAN WALK AWAY....that should not be
And I just can't find the mistake I obviously made Oo

thanks for every answer!
fOol
04-16-2007, 05:48 PM#2
wantok
That seems very complicated. Try this trigger. It uses a unit's custom value to store the casting unit. I think it should work, but I haven't tested it.
Collapse JASS:
function H2I takes handle h returns integer
    return h
    return 0
endfunction
function I2U takes integer i returns unit
    return i
    return null
endfunction

function GroupFilter takes nothing returns boolean
    return ( UnitHasBuffBJ(GetFilterUnit(), 'B007') == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetSpellAbilityUnit())) == true and IsUnitAliveBJ(GetFilterUnit()) == true )
endfunction

function BCallOrderConditions takes nothing returns boolean
    return UnitHasBuffBJ(GetTriggerUnit(),'B007') == TRUE
endfunction

function BCallCastConditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00G'
endfunction

function BCallCastActions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local unit f
    local unit d
    local integer uhandleid = H2I(u)
    local group g =CreateGroup()
    local boolexpr b = Condition(function GroupFilter)
    call GroupEnumUnitsInRange(g,GetUnitX(u), GetUnitY(u), 300.+32, b)
    loop
        set f = FirstOfGroup(g)
        exitwhen f == null
        call SetUnitUserData(f, uhandleid)
        set d=CreateUnit(GetOwningPlayer(u), 'e00E', GetUnitX(f), GetUnitY(f),0 )
        call UnitApplyTimedLife(d,'BTLF', 1.)
        call UnitAddAbility(d, 'A00J')
        call SetUnitAbilityLevel(d, 'A00J' GetUnitAbilityLevel(u, 'A00G')
        call IssueTargetOrder( d, "acidbomb", f )
        call GroupRemoveUnit(g, f)
    endloop
    call DestroyGroup(g)
    call DestroyBoolExpr(b)
    set b = null
    set u = null
    set f = null
    set g = null
    set d = null
endfunction

function BCallOrderActions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local unit c = I2U(GetUnitUserData(u)))
    if GetOrderTarget() != c then
        call IssueTargetOrder(u, "attack", I2U(GetUnitUserData(u)))
    endif
    set u = null
    set c = null
endfunction

function BCallOrderSetup takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddCondition( t, Condition( function BCallOrderConditions ) )
    call TriggerAddAction( t, function BCallOrderActions )
    set t = null
endfunction

function InitTrig_BCallCast takes nothing returns nothing
    set gg_trg_BCallCast = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_BCallCast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(gg_trg_BCallCast, Condition( function BCallCastConditions ) )
    call TriggerAddAction(gg_trg_BCallCast, function BCallCastActions)
    call BCallOrderSetup()
endfunction
04-17-2007, 12:22 PM#3
Just_a°fOol
well it seems like it works
but I'm not that sure about it...because my trigger also works well against the PC
I will have to test this with a mate
thanks for your work anyways :)
edit after test!
btw
what is the difference between yours and mine but the custom value?
04-17-2007, 12:35 PM#4
wantok
You use LinkObject to attach groups and the casting unit to the trigger. I assume this is some function that stores the info in gamecache. You don't need to do that, since the only thing you need to store is what unit the buffed units should be attacking. In my version there is no need to destroy trigger that intercepts orders since I don't attach anything to it. All the information you need is stored on the units themselves.
04-17-2007, 03:11 PM#5
Just_a°fOol
yey
i used a GameCache system, because I'm not sure if there are any other spells in my map that use the custom value of the unit
As far as I know the custom value is overwritten everytime it is changed

so what happens if a buffed unit gets a totally different custom value ?

And this trigger is multi-instancable, isn't it ? (i hate that word ^^)
04-17-2007, 03:17 PM#6
Toink
Custom Value doesn't do anything, it is just used for triggers.

And yes, that is MUI
04-17-2007, 04:44 PM#7
wantok
The custom value will only change if you change it in some other trigger though. So you don't have to worry about it being overwritten without you directing it to do so. If you're already using custom value for something else, you can use gamecache instead. But just use it to attach the target unit to the buffed unit. There is no need to attach all that stuff to a trigger like you did.
04-17-2007, 05:27 PM#8
Nosferatu
Just one think: all this scipt just for spell that allready exist in warcraft?! Berseeker Call is based on Taunt abiliti from warcraft. Its a night elf abiliti that stone giants use.
04-17-2007, 06:52 PM#9
Just_a°fOol
with the nightelf ability 'taunt' you are not FORCED to attack the casting unit
you have to attack it once but then you can just run away
what I wanted to do is preventing the targets to do anything else but attacking the caster

yea gamecache...in fact I'm not yet that much experienced as you might have already noticed ^^ (and my english sometimes is a bit strange, too xD)

still not tested your idea for the spell :(

edit:
ok it works
thanks alot :)

but I still don't know what was the mistake in my trigger :(