• 🏆 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] Bugged Spell

Status
Not open for further replies.
Level 4
Joined
Apr 2, 2006
Messages
32
Having issues with a spell.

It basically enables the caster to control the target unit (merely) for a limited duration after which the target is killed by the spell. The caster is given an additional ability to control the target which just orders it to simply move to the chosen point.

This all works fine.
However, sometimes the CASTER is killed once the target's "time" is up.
I'm posting here because I don't have any clue as to why this is happening.
I can't see the flaw in the code.
This only seems to take place when I cast the spell on one of the turtle creeps in the map below.

If anyone would like to help me fix this bug, just take a look at the attachment and cast the spell as much as you can until it kills the caster so you get the full picture of what I am trying to say.
After you do that, read the code and see if you can find the problem, because it has me stuck.

Thanks in advance.

JASS:
scope SoulCripple

globals
    private constant integer SC_Ability_ID = 'A000'  //Raw code of the "Soul Cripple" ability
    private constant integer SC_Sub_Ability_ID = 'A001'  //Raw code of the "Issue Order" ability
    private constant string SC_Effect_Path = "Objects\\Spawnmodels\\Orc\\OrcLargeDeathExplode\\OrcLargeDeathExplode.mdl"  //Exploding-guts effect
    private constant string SC_Effect_Path2 = "Abilities\\Spells\\Undead\\Cripple\\CrippleTarget.mdl"  //Crippled effect
    private constant string SC_Effect_Path3 = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"  //Supernova effect
    private constant integer SC_Supernova_Arc_Count = 6  //Number of arcs/arms/legs/limbs supernova effect contains
    private constant real SC_Supernova_Angle_Size = 9.5  //Harshness of an arc angle; increase to raise harshness
    private constant real SC_Supernova_Size = 35  //Size of supernova; increase to enlarge size
    private constant real SC_Supernova_Speed = 0.1  //Speed of supernova; decrease to increase speed <<<--- read that again
    private constant real SC_Supernova_Time = 0.9  //Time supernova lasts (in seconds)
endglobals

private constant function Cripple_Duration takes real lvl returns real
    return 40 - (lvl * 10)  //Duration of Soul Cripple
endfunction

private struct Data
    unit u = GetTriggerUnit()
    unit t = GetSpellTargetUnit()
    effect e = AddSpecialEffectTarget(SC_Effect_Path2, .t, "chest")
    trigger T = CreateTrigger()
    triggeraction ta
    real X
    real Y
    real array ang[50]
    real dist = 0
    real count = 0
    boolean b = false
endstruct

private function Supernova takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local Data d = Data(GetHandleInt(t, "d"))
    local integer i = 1
    local integer i2 = SC_Supernova_Arc_Count
    local real PX
    local real PY
    
    set d.count = d.count + SC_Supernova_Speed
    set d.dist = d.dist + SC_Supernova_Size
    
    if d.count <= SC_Supernova_Time then
        loop
            exitwhen i > i2
            set PX = d.X + d.dist * Cos(d.ang[i] * bj_DEGTORAD)
            set PY = d.Y + d.dist * Sin(d.ang[i] * bj_DEGTORAD)
            call DestroyEffect(AddSpecialEffect(SC_Effect_Path3, PX, PY))
            set d.ang[i] = d.ang[i] + SC_Supernova_Angle_Size
            set i = i + 1
        endloop
    else
        call d.destroy()
        call FlushHandleLocals(t)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
    
    set t = null
endfunction

private function End takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local Data d = Data(GetHandleInt(t, "d"))
    local integer i = 1
    local integer i2 = SC_Supernova_Arc_Count
    local timer t2
     
    call UnitRemoveAbility(d.u, SC_Sub_Ability_ID) 
    call TriggerRemoveAction(d.T, d.ta)
    call FlushHandleLocals(d.T)
    call DestroyTrigger(d.T)
    call FlushHandleLocals(t)
    call PauseTimer(t)
    call DestroyTimer(t)
    
    if GetWidgetLife(d.t) > 0.405 then
        set t2 = CreateTimer()
        loop
            exitwhen i > i2
            set d.ang[i] = 360/i2 * i
            set i = i + 1
        endloop
        set d.X = GetUnitX(d.t)
        set d.Y = GetUnitY(d.t) 
        call DestroyEffect(d.e)
        call DestroyEffect(AddSpecialEffect(SC_Effect_Path, d.X, d.Y))
        call UnitDamageTarget(d.u, d.t, 999999, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
        call SetHandleInt(t2, "d", d)
        call TimerStart(t2, SC_Supernova_Speed, true, function Supernova)
        set t2 = null
    else
        call d.destroy()
    endif 
    
    set t = null
endfunction

private function Cast_Sub takes nothing returns nothing
    local trigger T = GetTriggeringTrigger()
    local Data d = Data(GetHandleInt(T, "d"))
    local location l = GetSpellTargetLoc()   
    
    if GetSpellAbilityId() == SC_Sub_Ability_ID then
        call IssuePointOrderLoc(d.t, "move", l)
    endif
    
    call RemoveLocation(l)
    
    set l = null
    set T = null
endfunction

private function Cast_Main takes nothing returns nothing
    local Data d = Data.create()
    local timer t = CreateTimer()  
    
    set d.ta = TriggerAddAction(d.T, function Cast_Sub)
    call TriggerRegisterPlayerUnitEvent(d.T, GetOwningPlayer(d.u), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
    call UnitAddAbility(d.u, SC_Sub_Ability_ID)
    call SetHandleInt(t, "d", d)
    call SetHandleInt(d.T, "d", d)
    call TimerStart(t, Cripple_Duration(GetUnitAbilityLevel(d.u, SC_Ability_ID)), false, function End)  
    
    set t = null
endfunction

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == SC_Ability_ID
endfunction

function InitTrig_Soul_Cripple takes nothing returns nothing
    local trigger t = CreateTrigger()    
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Conditions))
    call TriggerAddAction(t, function Cast_Main)    
    set t = null
endfunction

endscope
 

Attachments

  • Buggy Spell.w3x
    47.2 KB · Views: 35
Level 19
Joined
Aug 24, 2007
Messages
2,888
Try setting struct vars in a method

Well
JASS:
struct S
integer i = 50
endstruct
is showed i as 0 to me once
JASS:
struct S
integer i
  method onCreate takes nothing returns nothing // not sure about method name
  set i = 50
  endmethod
endstruct
worked better (Actually I used a custom method that I executed myself)


Am I right Poot ?
 
Status
Not open for further replies.
Top