HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

vJass - A knockfront spell not knocking

01-13-2009, 10:56 PM#1
HyperActive
I've just spent all my free time today on this spell, trying to figure out why the hell it won't work. Well, ok, I've watched South Park .
Anyway, the spell should attract enemies a bit closer to the caster. It's simple, and I thought it would be perfect to practice using structs. Please, any help would be appreciated.

Collapse JASS:
scope PositiveAttraction initializer Init


globals
    private constant integer SPELLID       = 'A002'
    private constant real RANGE            = 600.0
    private constant real DISTANCEBASE     = 150.0
    private constant real DISTANCEINCREASE = 75.0
    private constant real MOVEEACHTIME     = 25.0
    private constant string EFFECT         = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
    //Struct required
    private group Group                    = CreateGroup()
    private integer Counter                = 0
    private timer Timer                    = CreateTimer()
    private constant real TimerPeriod      = 0.04
    private integer array Move
endglobals

private constant function Distance takes integer level returns real
    return (DISTANCEBASE-DISTANCEINCREASE)+(DISTANCEINCREASE*level)
endfunction

private function Check takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_ANCIENT)
    endfunction

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

private struct move
    integer Level
    real X
    real Y
    unit U
    integer Repeat
    static method create takes integer level, real x, real y, unit u returns move
        local move m = move.allocate()
        set m.Level = level
        set m.X = x
        set m.Y = y
        set m.U = u
        set m.Repeat = R2I(Distance(level) / MOVEEACHTIME)
        return m
    endmethod
endstruct

private function Loop takes nothing returns nothing
    local move m = 0
    local unit v
    local unit u
    local integer i = Counter - 1
    local integer lvl
    local real x
    local real y
    local integer level
    local real angle
    local player p
        loop                        
            exitwhen i < Counter
            set m = Move[i]
            set x = m.X
            set y = m.Y
            set level = m.Level
            set u = m.U
            set p = GetOwningPlayer(u)            
            if m.Repeat<0 then
                call m.destroy()
                set Counter = Counter - 1
                if Counter < 0 then
                    call PauseTimer(Timer)
                    set Counter = 0
                else
                    set Move[i] = Move[Counter]
                endif
            else
                loop
                    set v = FirstOfGroup(Group)
                    exitwhen v == null
                    call GroupRemoveUnit(Group, v)
                    if IsUnitEnemy(v, p) then
                        set angle = bj_RADTODEG*Atan2(y-GetUnitY(v), x-GetUnitX(v))
                        call SetUnitPosition(v, GetUnitX(v)+CosBJ(angle)*MOVEEACHTIME, GetUnitY(v)+SinBJ(angle)*MOVEEACHTIME)
                        call DestroyEffect(AddSpecialEffect(EFFECT, GetUnitX(v), GetUnitY(v)))
                    endif
                endloop                
                set p = null
                set u = null
            endif
            set i = i-1             
        endloop   
        set m.Repeat = m.Repeat-1
endfunction

function Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local move m = 0
    local integer level = GetUnitAbilityLevel(caster, SPELLID)
    local real x = GetUnitX(caster)
    local real y = GetUnitY(caster)
    local integer n
    local player p = GetOwningPlayer(caster)
        call GroupEnumUnitsInRange(Group, x, y, RANGE, Condition(function Check))
        set m = m.create(level, x, y, caster)        
        if Counter == 0 then
            call TimerStart(Timer, TimerPeriod, true, function Loop)
        endif
        set Move[Counter] = m
        set Counter = Counter + 1
        set caster = null
endfunction

//===========================================================================
private function Init 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 Actions )
endfunction


endscope
01-14-2009, 12:14 AM#2
ClichesAreSt00pid
Hm, I believe you are modifying the "Group" variable directly, and therefore it stops after 1 execution. To fix it, create a new local variable in the "Loop" function and add the "Group" variable to it with GroupAddGroup(Group, newvar), then modify that one in your loop.

Also make sure you clean up the "v" and "u" unit variables.
01-14-2009, 01:15 AM#3
Zerzax
I'd use radians, the funny thing about JASS is you really don't need to understand using radians, only use a different set of natives and bj_RADTODEG to convert to degrees for unit facing. And store X Speed and Y Speed as struct members ( X Speed would be calculated on creation, Move offset * Cos(angle)) or at least the cosine and sine ratios of the angle at which the unit is projected, you do not need to recalculate the angle or the cos/sin if the unit is projected at a constant angle.
01-14-2009, 01:36 AM#4
Here-b-Trollz
You know, I would not be surprised if this:
Collapse JASS:
local real a=.a
local real x=Cos(a)
local real y=Sin(a)
Were faster than this:
Collapse JASS:
local real x=.x
local real y=.y
01-14-2009, 04:51 AM#5
HyperActive
I fixed it. As usual, it was an idiot's problem.
First I didn't declared the struct properly, then some minor calculations were wrong, and finally group was cleared after the first loop, so it moved only for one period distance instead of total.

Thanks for helping, your suggestions made me look in the right way.