Template On Attack Template 1.30

emjlr3

Change can be a good thing
Reaction score
395
I present to you my...

On Attack Template 1.30:
a simple system that allows you do to some great things

What does this do?

In the absence of a better method for damage detection using GUI;

This allows you leverage the event "a unit is attacked", and both efficiently and accurately, detect when the target takes damage, and deal effects to said unit.

Sounds like fun no..??

Ok then hurry up and try it out!!

Version History:
  • 1.30 - Updated for 1.24 compatibility, removed dated CSData and CSSafety requirements, re-arranged and shorten code a bit, optimized trigger execution function, added theoretical destroytrigger() bug aversion configurable
  • 1.20b - Updated to CSData and CSSafety 15.0, added in a new demo ability to showcase usage of the On_Attack_Template_Function call, Demo 3 updated slightly, few minor readme/documentation errors updated
  • 1.2 - Ported to vJASS, slightly updated readme, removed demo 4 ability from test map
  • 1.1 - Added greater functionality
  • 1.0 - Initial Release

JASS:
library OnAttackTemplate initializer Init

//=====On Attack Template 1.30=====\\
                                                                                                     
//==Configurables==\\
globals
    private constant    boolean     AVOID   = true // Experimental method for trying to avoid destroy trigger related handle stack corruption
    private constant    integer     CASTER  = 'n000' // Rawcode of your dummy caster unit (Ctrl+d in object editor)
    private             hashtable   HT      = null // If you have a global hashtable, set it here
    private constant    real        TIME    = 2. // Duration after the attack to disregard effects
endglobals

//==NO TOUCHING PAST THIS POINT!!!==\\
//==========================================================================================
// Needed globals
globals
    private boolexpr B
endglobals

// Needed struct
private struct data
    unit atkr
    timer t
    trigger trig
    string type
    
    integer abilid
    integer lvl
    string order
    
    real dam
    boolean show
    
    string func
    
    // Maybe it works!?!?!
    static method destroytrigger takes trigger trig returns nothing
        call TriggerSleepAction(300.)
        call DestroyTrigger(trig)
    endmethod
    // Clean up
    method destroy takes nothing returns nothing
        call DisableTrigger(.trig)
        call FlushChildHashtable(HT,GetHandleId(.trig))
        static if AVOID then
            call data.destroytrigger.execute(trig)
        else
            call DestroyTrigger(.trig)
        endif
    endmethod
    // Core of the system
    static method effects takes nothing returns boolean
        local data this
        local unit targ
        local unit dum   
        local texttag t       
        
        if GetTriggerEventId()!=EVENT_UNIT_DAMAGED then // Timer expired
            call .destroy()
        elseif GetEventDamage()>.01 then // Negligable damage
            set this=LoadInteger(HT,GetHandleId(GetTriggeringTrigger()),0)
            if GetEventDamageSource()!=.atkr then // Wrong damage do-er
                return false
            endif
            
            set targ=GetTriggerUnit()
            call DisableTrigger(.trig) 
            
            if .type=="spell" then // Spell cast
                set dum = CreateUnit(GetOwningPlayer(.atkr),CASTER,GetUnitX(.atkr),GetUnitY(.atkr),0.) 
                call UnitAddAbility(dum,.abilid)
                call UnitApplyTimedLife(dum,'BTLF',2.)  
                call SetUnitAbilityLevel(dum,.abilid,.lvl) 
                call IssueTargetOrder(dum,.order,targ)            
                set dum = null
            elseif .type=="damage" then // Damage deal
                call UnitDamageTarget(.atkr,targ,.dam,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)     
                if .show then
                    set t = CreateTextTag()                    
                    call SetTextTagText(t, "+"+I2S(R2I(.dam))+"!", 0.025)
                    call SetTextTagPosUnit(t, targ,15)
                    call SetTextTagColor(t, 255, 0, 0, 255)
                    call SetTextTagVelocity(t, 0, .03)
                    call SetTextTagVisibility(t, true)
                    call SetTextTagFadepoint(t, 2.)
                    call SetTextTagLifespan(t, 2.)
                    call SetTextTagPermanent(t, false)        
                    set t = null
                endif
            else // Call function
                call ExecuteFunc(.func)
            endif
            
            set targ = null
        endif
        
        return false
    endmethod
    // Create struct
    static method create takes unit target returns data
        local data this=data.allocate()
        
        set .trig=CreateTrigger()
        call TriggerRegisterUnitEvent(.trig,target,EVENT_UNIT_DAMAGED)
        call TriggerRegisterTimerEvent(.trig,TIME,false)
        call TriggerAddCondition(.trig,B)
        call SaveInteger(HT,GetHandleId(.trig),0,this)
        
        return this
    endmethod
endstruct

//==User Functions==\\
function On_Attack_Template_Function takes unit attacker, unit target, string func returns nothing
    local data d = data.create(target)
    
    set d.atkr = attacker
    set d.func = func
    set d.type = "function"
endfunction
function On_Attack_Template_Damage takes unit attacker, unit target, real damage, boolean show returns nothing
    local data d = data.create(target)    
    
    set d.atkr = attacker
    set d.dam = damage
    set d.show = show
    set d.type = "damage"
endfunction
function On_Attack_Template_Spell takes unit attacker, unit target, integer abil, integer lvl, string order returns nothing 
    local data d = data.create(target)
    
    set d.atkr = attacker
    set d.abilid = abil
    set d.lvl = lvl
    set d.order = order
    set d.type = "spell"
endfunction

//==Initialization==\\
private function Init takes nothing returns nothing
    set B=Condition(function data.effects)
    if HT==null then
        set HT=InitHashtable()
    endif
endfunction

endlibrary

enjoy!
 

Attachments

  • attack temp.JPG
    attack temp.JPG
    178.7 KB · Views: 1,760
  • emjlr3 - On Attack Template 1.30.w3x
    110 KB · Views: 612

ayumilove

Youtube account suspended! youtube.com/ayumilove8
Reaction score
110
could please explain in detail about this on attack system?

i don't really get the point of having it o.o"
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
....

So that you don't have to be like DotA and use orb effect spots that block other on-attack effects.
 

emjlr3

Change can be a good thing
Reaction score
395
normally to do a spell like this is GUI, you would go off the event a unit is attacked

this can be played with and you cna actually pause ur unit and make it attack real fast, so as to never actually attack, but get the effects, this is an abuse

what this allows you to do is, detect whe na unit is attack, go through ur conditions, all in GUI, and if they match up, call this with an ability to be cast

as you can see fro mthe range char. I put into the map, it waits until the damage is done to do the effects, else the spells would be casted before even the projectile left the attacker

how is this better even more so?

well to stop this abuse, in DoTA, for ex., with Spirit Breakers Greater Bash

the main triger is disabled once it fires, and not reenabled unitl after the slide is over

so not only can there not be multiple slides at the same tiem for different spirit breakers, but it there can only be one slide ever in the game, and one that is over a new one can happen

pretty shitty if you ask me
 

lh2705

Just another Helper
Reaction score
111
normally to do a spell like this is GUI, you would go off the event a unit is attacked

this can be played with and you cna actually pause ur unit and make it attack real fast, so as to never actually attack, but get the effects, this is an abuse

what this allows you to do is, detect whe na unit is attack, go through ur conditions, all in GUI, and if they match up, call this with an ability to be cast

as you can see fro mthe range char. I put into the map, it waits until the damage is done to do the effects, else the spells would be casted before even the projectile left the attacker

how is this better even more so?

well to stop this abuse, in DoTA, for ex., with Spirit Breakers Greater Bash

the main triger is disabled once it fires, and not reenabled unitl after the slide is over

so not only can there not be multiple slides at the same tiem for different spirit breakers, but it there can only be one slide ever in the game, and one that is over a new one can happen

pretty shitty if you ask me

Wtf? Are you serious? Thats not fair at all, well only if your playing a samehero game... :D
 

emjlr3

Change can be a good thing
Reaction score
395
i have thought of ways to further improve this and make it be able to do more things

i will add major updates and a better readme next week when I have the time to

until then, more comments please :)
 

elmstfreddie

The Finglonger
Reaction score
203
I don't see what's so special about this though... It's just saying if someone gets attacked and the 30% chance happened, then cast the ability...
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
I don't see what's so special about this though... It's just saying if someone gets attacked and the 30% chance happened, then cast the ability...

The 'unit is attacked' event fires on the attack initialization. AKA it allows you to spam the 'stop' button to spam a triggered spell.
If you use a damage detection trigger w/o proper coding you can make things fire on like, spell casts. Usually not a big deal, but undesireable.



This is a rather good system.
 

emjlr3

Change can be a good thing
Reaction score
395
basically it allows what all JASS users do for their maps, for the most part, since it is better, to be used by GUI ppl as well

do this for me

in the demo map, make a trigger on attack to cast an ability for the ranged hero

and look at the difference there

**UPDATED, now with much more functionality and a better read me

enjoy!
 

gref

New Member
Reaction score
33
That frost spell is one of the coolest spells I have ever seen.

No lag, no ugliness, just perfect. (+Rep)
 

Arkan

Nobody rides for free
Reaction score
92
I have a question.
What would the difference be between using a system like this compared to a system where you have a trigger A that adds all units who enters playable map area (triggering unit takes damage) to trigger B where the actual effect is?
 

emjlr3

Change can be a good thing
Reaction score
395
not sure what you mean there...I guess however that that would leak a good bit more though, and be slower
 

Arkan

Nobody rides for free
Reaction score
92
What I mean:

Detect Trigger:
Code:
function Trig_addevent_Actions takes nothing returns nothing
    call TriggerRegisterUnitEvent( gg_trg_Spell_A, GetTriggerUnit(), EVENT_UNIT_DAMAGED )
    call TriggerRegisterUnitEvent( gg_trg_Spell_B, GetTriggerUnit(), EVENT_UNIT_DAMAGED )
endfunction

//===========================================================================
function InitTrig_addevent takes nothing returns nothing
    set gg_trg_addevent = CreateTrigger(  )
    call TriggerRegisterEnterRectSimple( gg_trg_addevent, GetPlayableMapRect() )
    call TriggerAddAction( gg_trg_addevent, function Trig_addevent_Actions )
endfunction

Spell A:
Code:
function Trig_Spell_A_Conditions takes nothing returns boolean
return GetRandomInt(1,100)>80
endfunction

function Trig_Spell_A_Actions takes nothing returns nothing
    //Spell actions
endfunction

//===========================================================================
function InitTrig_Spell_A takes nothing returns nothing
    set gg_trg_Spell_A = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Spell_A, Condition( function Trig_Spell_A_Conditions ) )
    call TriggerAddAction( gg_trg_Spell_A, function Trig_Spell_A_Actions )
endfunction

Spell B:
Code:
function Trig_Spell_B_Conditions takes nothing returns boolean
return GetRandomInt(1,100)>60
endfunction

function Trig_Spell_B_Actions takes nothing returns nothing
    //Spell actions
endfunction

//===========================================================================
function InitTrig_Spell_B takes nothing returns nothing
    set gg_trg_Spell_B = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Spell_B, Condition( function Trig_Spell_B_Conditions ) )
    call TriggerAddAction( gg_trg_Spell_B, function Trig_Spell_B_Actions )
endfunction

Would this be slower and leak more?
 

emjlr3

Change can be a good thing
Reaction score
395
that is theoretically that optimal way to do it

however, try and get a GUI user to make that work, and then you have issues
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
System coded in GUI or JASS ?
Mind post the code??

I am having slow internet speed now...(At friends house for few days)
So i might need to avoid all uneeded download
 

emjlr3

Change can be a good thing
Reaction score
395
coded in JASS, written with GUIers in mind
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top