• 🏆 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] Spell won't deal damage and doesn't stay for duration. (TimerUtils,GroupUtils,xefx)

Status
Not open for further replies.
Level 13
Joined
Jul 26, 2008
Messages
1,009
Alright I created a spell and am using xefx for the graphic of it. It creates a giant star above an area and deals damage/heals depending on how many units are around. It lasts 10+1per level seconds.

Now, it worked before and did damage, but it wouldn't stay for more than a second after it's first cast. So, I put in the set D.dur = 0 after realizing I forgot it. Now it just dissappears right away.

Any help is appreciated, thanks.

[HIDDEN="Blood Star]
JASS:
scope BloodStar initializer init

globals
    private integer SPELLID         = 'BlSt'
    private integer ECOUNTED
    private integer ACOUNTED
    private constant real TICK      = 1
endglobals

private struct Data

    xefx xf
    unit c
    real dur
    real x
    real y

    static method ApplyEffects takes nothing returns nothing
     local unit e = GetEnumUnit()
        if IsUnitEnemy(e, GetOwningPlayer(TEMP)) then
            call UnitDamageTarget(TEMP, e, 2+1.5*ECOUNTED, true, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, null)
        elseif IsUnitAlly(e, GetOwningPlayer(TEMP)) then
            call SetWidgetLife(e, GetWidgetLife(e)+5+3.5*ACOUNTED)
        endif
     set e = null
    endmethod

    static method GroupEm takes nothing returns boolean
     local unit f = GetFilterUnit()
        if not(IsUnitType(f, UNIT_TYPE_STRUCTURE) or IsUnitType(f, UNIT_TYPE_DEAD))then
            if IsUnitEnemy(f, GetOwningPlayer(TEMP)) then
                set ECOUNTED = ECOUNTED + 1
            elseif IsUnitAlly(f, GetOwningPlayer(TEMP)) then
                set ACOUNTED = ACOUNTED + 1
            endif
         return true
        endif
     set f = null
     return false
    endmethod

    static method Timer takes nothing returns nothing
     local Data D = Data(GetTimerData(GetExpiredTimer()))
     local integer lvl = GetUnitAbilityLevel(D.c, SPELLID)
        if D.dur > 9+1 then
            call D.xf.destroy()
            call ReleaseTimer(GetExpiredTimer())
            call D.destroy()
        else
            set TEMP = D.c
            set ACOUNTED = 0
            set ECOUNTED = 0
            call GroupEnumUnitsInArea(ENUM_GROUP, D.xf.x, D.xf.y, 300+200*lvl, Filter(function Data.GroupEm))
            call ForGroup(ENUM_GROUP, function Data.ApplyEffects)
            set D.dur = D.dur + TICK
        endif
    endmethod

    static method Actions takes unit c, real x, real y returns Data
     local Data D = Data.allocate()
     local timer tim
        set D.dur = 0
        set D.x = x
        set D.y = y
        set D.xf = xefx.create(x,y,GetUnitFacing(c))
        set D.xf.z = 450
        set D.xf.owner = GetOwningPlayer(c)
        set D.xf.abilityid = 'duBS'
        set D.xf.fxpath = GetAbilityEffectById(SPELLID, EFFECT_TYPE_MISSILE, 0)
        set D.xf.abilityLevel = GetUnitAbilityLevel(c, SPELLID)
        set D.c = c
        set tim = NewTimer()
        call SetTimerData(tim,D)
        call TimerStart(tim, TICK, true, function Data.Timer)
     return D
    endmethod

endstruct

private function Conditions takes nothing returns boolean
    if GetSpellAbilityId() == SPELLID then
        call Data.Actions(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
    endif
 return false
endfunction
//===========================================================================
public function init takes nothing returns nothing
 local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(t, function Conditions )
    call XE_PreloadAbility(SPELLID)
 set t=null
endfunction

endscope
[/HIDDEN]
 
Hmm... That is weird. What is the effect's path? Some models only last a few seconds or they fail to appear properly. Try to use something like the peasant model to be sure that it isn't the model's problem.

Also, maybe add the following code in your "Actions" function after setting everything to their respective values.
JASS:
call BJDebugMsg(I2S(xf))
call BJDebugMsg(R2S(D.dur))

And in your timer function right after the locals:
JASS:
call BJDebugMsg(R2S(D.dur))
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
I try not to declare my NewTimer() with it's local declaration as I've been absent minded about it in the past and put them before if statements where not all of the branches used the timer. The end result was catastrophic, as my TimerStack would overflow and fail.

The thing you pointed out with the Timer could go either way I think. I don't know what the advantages of putting GetTimerData in Data() is though.

Something I did worked. No clue what, but the spell works now. My JNGP is fickle from time to time, perhaps it just needed me to save a second time.

Anyways, thanks to all the help and suggestions. :)
 
Status
Not open for further replies.
Top