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

[JASS] What would be the most efficient way of doing this?

Status
Not open for further replies.
Level 4
Joined
Jan 19, 2008
Messages
69
I'm trying to modify my spell slighty so that every time the caster is attacked the remaining duration of the spell is reduced by 1.00 second while the attacker is damaged and stunned for a short duration.

I initially planned to do this by adding TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_ATTACKED) to the SH_OL_periodic function and then do something like:
JASS:
    if GetAttacker() != null then
        set durationcur = durationcur + 0.8
        // stun and damage here
    endif
However using RegisterAnyUnitEvent with a dynamic trigger is apparently "crazy" (read: http://www.wc3c.net/showthread.php?t=103738)
How should I approach this?


This is the entire code in its current state:
JASS:
//===========================================================================
//CONSTANTS:
//===========================================================================

constant function SH_OL_spellid takes nothing returns integer
    return 'A005'
endfunction

//===========================================================================
//CONFIGURABLES:
//===========================================================================

function SH_OL_duration takes nothing returns real
    return 12.
endfunction

function SH_OL_stats takes integer level returns integer
    return level * 10
endfunction

//===========================================================================
//ACTIONS:
//===========================================================================

function SH_OL_getlevel takes unit caster returns integer
    return GetUnitAbilityLevel(caster, SH_OL_spellid()) 
endfunction

function SH_OL_periodic takes nothing returns nothing 
    local trigger trig = GetTriggeringTrigger()
    local integer trigid = GetHandleId(trig)
    local unit caster = LoadUnitHandle(udg_SH_hashtable, trigid, 1)
    local real durationcur = LoadReal(udg_SH_hashtable, trigid, 2)
    local real durationmax = LoadReal(udg_SH_hashtable, trigid, 3)
    local integer stats

    if durationcur < durationmax and IsUnitType(caster, UNIT_TYPE_DEAD) == false then
        set durationcur = durationcur + 0.2
        call SaveReal(udg_SH_hashtable, trigid, 2, durationcur)
    else
        set stats = LoadInteger(udg_SH_hashtable, trigid, 4)
        call SetHeroInt(caster, (GetHeroInt(caster, false)) - stats, true)
        call SetHeroAgi(caster, (GetHeroAgi(caster, false)) - stats, true)
        call DestroyEffect(LoadEffectHandle(udg_SH_hashtable, trigid, 5))
        call FlushChildHashtable(udg_SH_hashtable, trigid)
        call DisableTrigger(trig)
        call TriggerRemoveAction(trig, LoadTriggerActionHandle(udg_SH_hashtable, trigid, 0))
        call DestroyTrigger(GetTriggeringTrigger())
    endif

    set trig = null 
    set caster = null       
endfunction

function SH_OL_conditions takes nothing returns nothing
    local trigger trig
    local integer trigid
    local unit caster
    local integer stats
    local effect sfx

    if GetSpellAbilityId() == SH_OL_spellid() then
        set caster = GetTriggerUnit()
        set stats = SH_OL_stats(SH_OL_getlevel(caster))
        set sfx = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl", caster, "origin")
        call SetHeroInt(caster, (GetHeroInt(caster, false)) + stats, true)
        call SetHeroAgi(caster, (GetHeroAgi(caster, false)) + stats, true)
        set trig = CreateTrigger()
        set trigid = GetHandleId (trig)
        call TriggerRegisterTimerEvent(trig, 0.2, true)
        call SaveTriggerActionHandle(udg_SH_hashtable , trigid, 0, TriggerAddAction(trig, function SH_OL_periodic))
        call SaveUnitHandle(udg_SH_hashtable, trigid, 1, caster)
        call SaveReal(udg_SH_hashtable, trigid, 2, 0.)
        call SaveReal(udg_SH_hashtable, trigid, 3, SH_OL_duration())
        call SaveInteger(udg_SH_hashtable, trigid, 4, stats)
        call SaveEffectHandle(udg_SH_hashtable, trigid, 5, sfx)
        set trig = null
        set caster = null
        set sfx = null
    endif
endfunction
//===========================================================================
function InitTrig_Overload takes nothing returns nothing
    local trigger SH_OL = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(SH_OL, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(SH_OL, Condition(function SH_OL_conditions))
    set SH_OL = null
endfunction
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
Here is how I think you should do it with 2 independent triggers.

In your save value phase, save a boolean as true with the parent key being the unit handle. It will be your 'identifier'. Then in your attack trigger, check if the identifier boolean is true when loaded with the attacked unit's handle, if yes, save another boolean in a different child key of the unit handle. We will name it 'Attacked'.

In your periodic func, check if Attacked return true when loaded. If yes then do stuffs and set it back to false.

Hope I helped :)

Btw, a condition must return a boolean. Write a return false line just above the endfunc in the cond func.

I still code JASS with this very same style. This feels so nostalgic =))
 
Level 4
Joined
Jan 19, 2008
Messages
69
Alright, I'm currently trying to do as you suggested Doomlord - i'll have it done in a few minutes i think.

Thank you for your help! : )
 
Level 4
Joined
Jan 19, 2008
Messages
69
I have made the second trigger now:

JASS:
function Trig_Overload_Update_conditions takes nothing returns boolean
    if LoadBoolean(udg_SH_hashtable, GetHandleId(GetTriggerUnit()), 0) == true then
        call SaveBoolean(udg_SH_hashtable, GetHandleId(GetTriggerUnit()), 1, true)
    endif
    return false
endfunction

//===========================================================================
function InitTrig_Overload_Update takes nothing returns nothing
    local trigger SH_OL_update = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(SH_OL_update, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddCondition(SH_OL_update, Condition(function Trig_Overload_Update_conditions))
    set SH_OL_update = null
endfunction

I will report back in a few minutes once I've updated the periodic function.
 
Level 4
Joined
Jan 19, 2008
Messages
69
It works! Thank you so much Doomlord!

Here is the result:
JASS:
function Trig_Overload_Update_conditions takes nothing returns boolean
    local unit caster = GetTriggerUnit()
    local integer casterid = GetHandleId(caster)

    if LoadBoolean(udg_SH_hashtable, casterid, 0) then
        call SaveBoolean(udg_SH_hashtable, casterid, 1, true)
    endif

    set caster = null
    return false
endfunction

//===========================================================================
function InitTrig_Overload_Update takes nothing returns nothing
    local trigger SH_OL_update = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(SH_OL_update, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddCondition(SH_OL_update, Condition(function Trig_Overload_Update_conditions))
    set SH_OL_update = null
endfunction
JASS:
//===========================================================================
//CONSTANTS:
//===========================================================================

constant function SH_OL_spellid takes nothing returns integer
    return 'A005' // Raw data value of main spell
endfunction

//===========================================================================
//CONFIGURABLES:
//===========================================================================

function SH_OL_duration takes nothing returns real
    return 12. // Duration of the spell
endfunction

function SH_OL_stats takes integer level returns integer
    return level * 10 // Amount of stats gained
endfunction

//===========================================================================
//ACTIONS:
//===========================================================================

function SH_OL_getlevel takes unit caster returns integer
    return GetUnitAbilityLevel(caster, SH_OL_spellid()) 
endfunction

function SH_OL_periodic takes nothing returns nothing 
    local trigger trig = GetTriggeringTrigger()
    local integer trigid = GetHandleId(trig)
    local unit caster = LoadUnitHandle(udg_SH_hashtable, trigid, 1)
    local real durationcur = LoadReal(udg_SH_hashtable, trigid, 2)
    local real durationmax = LoadReal(udg_SH_hashtable, trigid, 3)
    local integer stats
    local integer casterid = GetHandleId(caster)

    if LoadBoolean(udg_SH_hashtable, casterid, 1) then
        set durationcur = durationcur + 1.
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", caster, "chest"))
        call SaveBoolean(udg_SH_hashtable, casterid, 1, false)
    endif

    if durationcur < durationmax and IsUnitType(caster, UNIT_TYPE_DEAD) == false then
        set durationcur = durationcur + 0.2
        call DestroyEffect(AddSpecialEffectTarget("war3mapImported\\AncestralGuardianMissileBlue.mdx", caster, "chest"))
        call SaveReal(udg_SH_hashtable, trigid, 2, durationcur)
    else
        set stats = LoadInteger(udg_SH_hashtable, trigid, 4)
        call SetHeroInt(caster, (GetHeroInt(caster, false)) - stats, true)
        call SetHeroAgi(caster, (GetHeroAgi(caster, false)) - stats, true)
        call DestroyEffect(LoadEffectHandle(udg_SH_hashtable, trigid, 5))
        call FlushChildHashtable(udg_SH_hashtable, trigid)
        call FlushChildHashtable(udg_SH_hashtable, casterid)
        call DisableTrigger(trig)
        call TriggerRemoveAction(trig, LoadTriggerActionHandle(udg_SH_hashtable, trigid, 0))
        call DestroyTrigger(GetTriggeringTrigger())
    endif

    set trig = null 
    set caster = null       

endfunction

function SH_OL_conditions takes nothing returns boolean
    local trigger trig
    local integer trigid
    local unit caster
    local integer stats
    local effect sfx

    if GetSpellAbilityId() == SH_OL_spellid() then
        set caster = GetTriggerUnit()
        set stats = SH_OL_stats(SH_OL_getlevel(caster))
        set sfx = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl", caster, "origin")
        call SetHeroInt(caster, (GetHeroInt(caster, false)) + stats, true)
        call SetHeroAgi(caster, (GetHeroAgi(caster, false)) + stats, true)
        set trig = CreateTrigger()
        set trigid = GetHandleId(trig)
        call TriggerRegisterTimerEvent(trig, 0.2, true)
        call SaveTriggerActionHandle(udg_SH_hashtable , trigid, 0, TriggerAddAction(trig, function SH_OL_periodic))
        call SaveUnitHandle(udg_SH_hashtable, trigid, 1, caster)
        call SaveReal(udg_SH_hashtable, trigid, 2, 0.)
        call SaveReal(udg_SH_hashtable, trigid, 3, SH_OL_duration())
        call SaveInteger(udg_SH_hashtable, trigid, 4, stats)
        call SaveEffectHandle(udg_SH_hashtable, trigid, 5, sfx)
        call SaveBoolean(udg_SH_hashtable, GetHandleId(caster), 0, true)
        set trig = null
        set caster = null
        set sfx = null
    endif
    return false
endfunction
//===========================================================================
function InitTrig_Overload takes nothing returns nothing
    local trigger SH_OL = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(SH_OL, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(SH_OL, Condition(function SH_OL_conditions))
    set SH_OL = null
endfunction

I'm gonna polish it and add the stun + damage now, thank you once again!
 
Status
Not open for further replies.
Top