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

[Solved] Prevent Friendly Attack

Status
Not open for further replies.
Level 13
Joined
Mar 19, 2010
Messages
870
hey hivers,

just a question. I wrote some lines of code to prevent friendly attack - It works but did I forget something or taken into account?

Here's the code:

JASS:
scope FriendlyAttackSystem initializer init

    private function Actions takes nothing returns nothing
        call IssueImmediateOrder(GetAttacker(), "stop")
    endfunction
    
    private function Conditions takes nothing returns boolean
        return IsUnitAlly(GetAttacker(), GetOwningPlayer(GetTriggerUnit()))
    endfunction

    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED)
        call TriggerAddCondition(t, Condition( function Conditions ))
        call TriggerAddAction(t, function Actions )
    
        set t = null
    endfunction

endscope
 
Level 14
Joined
Jun 27, 2008
Messages
1,325
Looks good. But you could make the code smaller:

JASS:
scope FriendlyAttackSystem initializer init
    private function Conditions takes nothing returns boolean
        if IsUnitAlly(GetAttacker(), GetOwningPlayer(GetTriggerUnit())) then
            call IssueImmediateOrder(GetAttacker(), "stop")
        endif
        return false
    endfunction

    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED)
        call TriggerAddCondition(t, Condition( function Conditions ))
        set t = null
    endfunction
endscope

Its also faster, but it doesnt make any difference unless your players are trying to attack teammates 1000 times per second :p
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Or like this:
JASS:
scope FriendlyAttackSystem initializer init
    private function Conditions takes nothing returns boolean
        local unit u = GetAttacker()
        /*
        *   TriggerPlayer is the owner of the attacked unit.
        */
        if IsUnitAlly(u, GetTriggerPlayer()) then
            /*
            *   Not much of a difference to "stop".
            *       - If the previous order was a no target order, it will keep it, for instance "holdposition"
            *       - easy to detect/filter because a unit can't get this order, except via trigger.
            *
            *   Use whatever you like.
            */
            call IssueImmediateOrderById(u, 851973)
            //call IssueImmediateOrder(u, "stop")
        endif
        set u = null
        return false
    endfunction

    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED)
        call TriggerAddCondition(t, Condition( function Conditions ))
        set t = null
    endfunction
endscope
As muzzel already mentioned, the speed difference is negligible in this case.

Edit: On a second thought the local unit is an overkill, because the condition will be wrong in more than 99% of all cases. Just use GetAttacker() twice.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Wait what's the difference between a Filter and Condition? Aren't they both just boolexpr? Or are filters "faster?" And the Vjass compiler automatically turns filters Conditions into filters?
 
Level 7
Joined
Sep 9, 2007
Messages
253
I would like to stop a footman from attacking an enemy footman.

I don't know JASS but this was my attempt. Even if this code worked it would work for any unit attacking a footman. I only want it to stop a footman from attacking a footman.

JASS:
scope FriendlyAttackSystem initializer init
    private function Conditions takes nothing returns boolean
        if IsUnitType(GetAttacker(), 'hfoo') == true then
        //if IsUnitAlly(GetAttacker(), GetOwningPlayer(GetTriggerUnit())) then
            call IssueImmediateOrder(GetAttacker(), "stop")
        endif
        return false
    endfunction

    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED)
        call TriggerAddCondition(t, Condition( function Conditions ))
        set t = null
    endfunction
endscope
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
You need to add a second condition which is GetUnitTypeId(GetTriggerUnit()) == 'hfoo'
Btw condition boolean == true is redundant, just boolean is enough.
-->if IsUnitType(GetAttacker(), 'hfoo') then

Also you have to check for GetUnitTypeId and not for IsUnitType. IsUnitType is related to UNIT_TYPE_ANCIENT/GIANT/TAUREN/PEON, ....
 
Status
Not open for further replies.
Top