HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Spell Crashes warcraft

05-21-2009, 11:45 AM#1
wraithseeker
Collapse JASS:
scope Whirlpool initializer Init

globals
    private constant integer SPELL = 'A011'
    private boolexpr b
endglobals

private struct data
    static data TEMP
    static timer TIMER = CreateTimer()
    static integer Count = 0
    unit caster
    real lx
    real ly
    
static method WhirlCheck takes nothing returns boolean
    local data this = .TEMP
    return IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(.caster)) and GetWidgetLife(GetFilterUnit()) > 0.0451 
endmethod

static method create takes nothing returns data
    local data d = data.allocate()
    local Unit c
    local unit u
    local location L = GetSpellTargetLoc()
    set d.lx = GetLocationX(L)
    set d.ly = GetLocationY(L)
    set d.caster = GetTriggerUnit()
    set d.TEMP = d
    call GroupClear(ENUM_GROUP)
    call GroupEnumUnitsInRange(ENUM_GROUP,d.lx,d.ly,400,b)
    loop
        set u = FirstOfGroup(ENUM_GROUP)
        exitwhen u == null
        set c = Unit.create(u,GetPointDist(d.lx,d.ly,GetUnitX(u),GetUnitY(u)))
        call GroupRemoveUnit(ENUM_GROUP,u)
    endloop
    return d
endmethod
    
method onDestroy takes nothing returns nothing
    
endmethod
endstruct

struct Unit extends data
    static group Hit
    unit target
    real radius
    real angle
    real cos
    real sin
    
static method create takes unit target, real radius returns Unit
    local Unit c = Unit.allocate()
    local data d
    set c.target = target
    set c.radius = radius
    set c.angle = 0. * bj_DEGTORAD
    set c.cos = Cos(c.angle)
    set c.sin = Sin(c.angle)
    call GroupAddUnit(c.Hit,target)
    if d.Count == 0 then
        call TimerStart(d.TIMER,0.03,true,function Unit.Spiral)
    endif
    set d.Count = d.Count + 1
    set Unit[target] = c
    return c
endmethod

static method Move takes nothing returns nothing
    local data c
    local Unit this = Unit[GetEnumUnit()]
    local unit u = GetEnumUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real cx = 0.
    local real cy = 0.
    set .angle = ((.angle * bj_RADTODEG) + 0.03) * bj_DEGTORAD
    set .cos = Cos(.angle)
    set .sin = Sin(.angle)
    set cx = x + 20 * .cos
    set cy = y + 20 * .sin
    call SetUnitPosition(u,cx,cy)
    if .angle*bj_RADTODEG >= 360 then
        set .radius = .radius - 80
    endif
    if .radius <= 0.00 then
        call .destroy()
        set c.Count = c.Count - 1
        if c.Count < 0 then
            call PauseTimer(c.TIMER)
        endif
    endif
    set u = null
endmethod

static method Spiral takes nothing returns nothing
    local Unit c
    if c.Hit != null then
        call ForGroup(c.Hit,function Unit.Move)
    elseif c.Hit == null then
        call PauseTimer(.TIMER)
    endif
endmethod

method onDestroy takes nothing returns nothing
    call GroupRemoveUnit(.Hit,.target)
endmethod

implement AutoData
endstruct

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

private function Actions takes nothing returns nothing
    local data d = data.create()
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(t, function Actions )
    call TriggerAddCondition(t,Condition(function Conditions))
    set b = Filter(function data.WhirlCheck)
endfunction
endscope

Whenever I cast the spell, wc3 crashes. The spell is a targetting image of 400 AOE.

This spell uses GroupUtils & AutoIndex.

Some might ask why am I using 2 structs because each unit's radius varies from distance between the unit and the target point.

I suspect it has something to do with the struct Unit though.

If possible, can anybody tell me a better approach to this?
05-21-2009, 11:59 AM#2
moyack
What this spell should do??
05-21-2009, 01:09 PM#3
Toadcop
Quote:
What this spell should do??
-> Spell should Crash warcraft. imo
05-21-2009, 01:55 PM#4
wraithseeker
This spell creates a "whirlpool" and then pick every unit within x radius and then spiral them to the centre.

Updated stuffs

Aye, I rewrote the whole crap and tell me if this is good?

Collapse JASS:
scope Whirlpool initializer Init

globals
    private constant integer SPELL = 'A011'
    private boolexpr b
endglobals

private struct data
    static data TEMP
    static timer TIMER = CreateTimer()
    static integer Count = 0
    static data array D
    unit caster
    real lx
    real ly
    group g
    real array angle[8190]
    real array radius[8190]
    
static method WhirlCheck takes nothing returns boolean
    local data this = .TEMP
    return IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(.caster)) and GetWidgetLife(GetFilterUnit()) > 0.0451 
endmethod

static method create takes nothing returns data
    local data d = data.allocate()
    local unit u
    local location L = GetSpellTargetLoc()
    set d.lx = GetLocationX(L)
    set d.ly = GetLocationY(L)
    set d.caster = GetTriggerUnit()
    set d.TEMP = d
    set d.g = NewGroup()
    call GroupClear(ENUM_GROUP)
    call GroupEnumUnitsInRange(ENUM_GROUP,d.lx,d.ly,400,b)
    loop
        set u = FirstOfGroup(ENUM_GROUP)
        exitwhen u == null
        call GroupAddUnit(d.g,u)
        set d.angle[GetUnitId(u)] = 0.
        set d.radius[GetUnitId(u)] = GetPointDist(GetUnitX(u),GetUnitY(u),d.lx,d.ly)
        set data[u] = d
        call GroupRemoveUnit(ENUM_GROUP,u)
    endloop
    if d.Count == 0 then
        call TimerStart(d.TIMER,0.03,true,function data.Periodic)
    endif
    set d.D[d.Count] = d
    set d.Count = d.Count + 1
    return d
endmethod

static method spiral takes nothing returns nothing
    local data this = data[GetEnumUnit()]
    local unit u = GetEnumUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real cos = Cos(.angle[GetUnitId(u)])
    local real sin = Sin(.angle[GetUnitId(u)])
    local real cx = x + 10 * cos
    local real cy = y + 10 * sin
    call SetUnitPosition(u,cx,cy)
    set .angle[GetUnitId(u)] = ((.angle[GetUnitId(u)] * bj_RADTODEG) + 10)* bj_DEGTORAD
    if .radius[GetUnitId(u)] <= 0.00 then
        call GroupRemoveUnit(.g,u)
    endif
        set .radius[GetUnitId(u)] = .radius[GetUnitId(u)] - 2
    set u = null
endmethod
    
static method Periodic takes nothing returns nothing    
    local integer i = 0
    local data this
    loop
        exitwhen i >= .Count
        set this = .D[i]
        call ForGroup(.g,function data.spiral)
        if FirstOfGroup(.g) == null then
            set .Count = .Count - 1
            if .Count > 0 then
                set .D[i] = .D[.Count]
                set i = i - 1
            else
                call PauseTimer(.TIMER)
            endif
        endif
        set i = i + 1
    endloop
endmethod

method onDestroy takes nothing returns nothing
    
endmethod
implement AutoData
endstruct

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

private function Actions takes nothing returns nothing
    local data d = data.create()
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(t, function Actions )
    call TriggerAddCondition(t,Condition(function Conditions))
    set b = Filter(function data.WhirlCheck)
endfunction
endscope

Ok basically right now when the unit complete a circle and they stop which isn't supposed to be untill radius is lesser than or equal to 0. I know those arrays suck but anyone has a better idea?

EDIT: They don't seem to be circling at a radius that I want them to circle, any clues?