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

[Spell] Taunt

Status
Not open for further replies.
Level 7
Joined
Jul 3, 2011
Messages
251
Hey hive, how can i make a taunt spell like DotA's Axe has? For thsoe of you that do not know what it does, all nearby enemies will be forced to attack the hero, however it has a duration, simply right clicking away or casting a spell will not work, you are forced to attack the hero for the full duration, unable to do anything else. How can this be implimented? Simply putting a duration on taunt does not work, and the units are not being spam ordered to stop, since they are attacking. Another example of this is dirge's zombies that spawn from the tombstone, they are completely uncontrollable no matter what happens.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
You can not "taunt" unit completely in case some units have attack point animation big amount to prevent the attack via "stop" order. Even if you use 0.01 periods and additional trigger with event Unit - Is issued order with no target -> action: attack given unit, then "stop" can still prevent the taunt effect.

There only possible way to do that is either change the owner or add 'Aloc' abilit and remove it (with passive transformation) after taunt's duration is gone.

Anyways, the trigger goes like this (requires Unit Indexer):
~consider seting (Triggerin unit)/(Picked unit) into variables for efficiency, I haven't in case it's freshhand.
  • init
    • Events
      • Unit - A unit Starts effect of ability
    • Conditions
      • (Ability being cast) Equal to Taunt
    • Actions
      • Set p = (Position of (Triggering unit))
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 500 of p matching (conditions here) and do Actions
        • Loop - Actions
          • Unit - Add (Picked unit) to TauntGroup
          • Set duration[(Custom value of (Picked unit))] = 5.00
          • Set unit[(Custom value of (Picked unit))] = (Triggering unit)
          • Unit - Order (Picked unit) to Attack (Triggering unit)
      • Trigger - Turn on loop <gen>
      • Custom script: call RemoveLocation(udg_p)
Loop:
  • loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in TauntGroup and do Actions
        • Loop - Actions
          • Set key = (Custom value of (Picked unit))
          • Set duration[key] = duration[key] - 0.03
          • If (All conditions are true) then do (Then - Acitons) else do (Else- Actions)
            • If - Conditions
              • Or - Any Conditions are True
                • Conditions
                  • duration[key] Less or equal to 0.00
                  • (unit[key] is dead) Equal to True
                  • ((Picked unit) is dead) Equal to True
            • Then - Actions
              • Set unit[key] = No unit
              • Unit - Order (Picked unit) to Stop
              • Unit Group - Remove (Picked unit) from TauntGroup
              • If (All conditions are true) then do (Then - Acitons) else do (Else- Actions)
                • If - Conditions
                  • (TauntGroup is Empty) Equal to True
                • Then - Acitons
                  • Trigger - Turn off (this trigger)
                • Else - Actions
          • Else - Actions
            • Custom script: if GetUnitCurrentOrder(GetEnumUnit()) != 851983 then
            • Unit - Order (Picked unit) to Attack unit[key]
            • Custom script: endif
 
Level 16
Joined
Aug 7, 2009
Messages
1,403
I've written something like this:

JASS:
library TauntSystem uses Table 

    globals
        private constant real PERIOD = 0.05
    endglobals
    
    struct Taunt extends array
        implement Alloc
        private unit u
        private unit targetUnit
        private real dur

        private thistype next
        private thistype prev
        
        private static Table table
        
        private method destroy takes nothing returns nothing
            /*
                Taunt buff based on Slow Aura
            call UnitMakeAbilityPermanent(this.u,false,'A50Z')
            call UnitRemoveAbility(this.u,'A50Z')
            */    
            call IssueImmediateOrder(this.u,"stop")
            set this.prev.next = this.next
            set this.next.prev = this.prev
                
            call this.table.remove(GetHandleId(this.u))
            call this.deallocate()
        endmethod
        
        static method iterate takes nothing returns nothing
            local thistype this = thistype(0)
            
            loop
                set this = this.next
                exitwhen this == 0
                if this.dur <= 0 or not UnitAlive(this.u) then
                    call this.destroy()
                else
                    call IssueTargetOrder(this.u, "attack", this.targetUnit)
                    set this.dur = this.dur - PERIOD
                endif
            endloop
        endmethod

        static method remove takes unit u returns nothing
            local integer id = GetHandleId(u)
            
            if thistype.table.has(id) then
                call thistype(thistype.table[id]).destroy()
            endif
        endmethod
        
        static method get takes unit u returns real
            local integer id = GetHandleId(u)
            
            if thistype.table.has(id) then
                return thistype(thistype.table[id]).dur
            else
                return 0.
            endif
        endmethod
        
        static method add takes unit u,unit target, real dur returns nothing
            local thistype this
            local integer id = GetHandleId(u)
            
            if target==null then
                return
            endif
            
            if dur > 0 then
                if thistype.table.has(id) then
                    set this = thistype.table[id]
                else    
                    set this = thistype.allocate()
                    set thistype(0).next.prev = this
                    set this.next = thistype(0).next
                    set thistype(0).next = this
                    set this.prev = thistype(0)
                    set thistype.table[id] = this
                    set this.u = u
                    set this.dur = 0
                    
                    /*
                        Taunt buff based on Slow Aura
                    call UnitAddAbility(this.u,'A50Z')
                    call UnitMakeAbilityPermanent(this.u,true,'A50Z')
                    */
                endif
                
                set this.dur=dur
                set this.targetUnit=target
            endif
        endmethod

        // initialization
        private static method onInit takes nothing returns nothing
            set thistype.table = Table.create()
            call TimerStart(CreateTimer(),PERIOD,true,function thistype.iterate)
        endmethod
    endstruct
    
endlibrary
 
Status
Not open for further replies.
Top