• 🏆 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 Like Lightning Shield

Status
Not open for further replies.
Level 16
Joined
Mar 3, 2006
Messages
1,564
Custom value = breaks all other spells/systems using it.

I don't think Table makes things too much more complicated. Anyway, it doesn't really matter IMO how complicated it is as long as it's easy for the user to import and use. More object editor crap = harder to import and use.

I totally agree with you about that coping the spell in a different map with lots of OE data is bothersome problem and I dislike it.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Now that I can use hashtables, I need someone to help me finish this spell.

The spell itself works but its commulative, i.e. when you cast it again it doesn't remove the effect of the first and start a new one, instead it commulates with the previous one. EoW, once showed me how to use the table but I couldn't apply it and his patience was ending :) so someone help me please.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
I need help, please

<< bump >>


I need help with implementing Vexorian's table in this spell.


JASS:
scope FireShield initializer Init
    private keyword Data
    globals
        private constant integer ABIL_ID = 'A002'
        private constant integer UNIT_ID = 'e002'
        private constant integer N = 3
        private constant real SHIFT = 360.00 / N
        private constant real r = 128.00
        private constant real dA = 3
        private constant real INTERVAL = 0.01
        private timer tmr = CreateTimer()
        private integer index = 0
        private Data array temp_data
    endglobals
 
    private function Duration takes integer al_dur returns real
        return 6. + al_dur*6.
    endfunction
 
    private function Damage takes integer al_dam returns real
        return al_dam*10.
    endfunction
    private struct Data
        unit Caster
        unit array Charge[N]
        real A
        real temp_A
        real durtime
        timer dur = CreateTimer()
        static method rotate takes nothing returns nothing
            local Data d
            local integer i = 0
            local integer j
            local real X
            local real Y
            loop
                exitwhen i >= index
                set d = temp_data[i]
                if TimerGetRemaining(d.dur) > 0.00 then
                    set d.A = d.A + dA
                    if d.A >= 360 then
                        set d.A = d.A - 360
                    endif
                    set d.temp_A = d.A
                    set j = 0
                    loop
                        exitwhen j >= N
                        set X = GetUnitX(d.Caster) + r * Cos(d.temp_A * bj_DEGTORAD)
                        set Y = GetUnitY(d.Caster) + r * Sin(d.temp_A * bj_DEGTORAD)
                        call SetUnitPosition(d.Charge[j],X,Y)
                        call SetUnitFacing(d.Charge[j],d.temp_A + 90)
                        set d.temp_A = d.temp_A + SHIFT
                        set j = j + 1
                    endloop
                else
                    set index = index - 1
                    set temp_data[i] = temp_data[index]
                    set i = i - 1
                    call d.destroy()
                endif
                set i = i + 1
            endloop
        endmethod
        static method create takes unit u returns Data
            local Data d = Data.allocate()
            local integer i = 0
            local real temp_A = 0
            local real X
            local real Y
            set d.Caster = u
            set d.durtime = Duration(GetUnitAbilityLevel(d.Caster,ABIL_ID))
            loop    
                exitwhen i >= N
                set X = GetUnitX(d.Caster) + r * Cos(temp_A * bj_DEGTORAD)
                set Y = GetUnitY(d.Caster) + r * Sin(temp_A * bj_DEGTORAD)
                set d.Charge[i] =CreateUnit(GetOwningPlayer(d.Caster),UNIT_ID,X,Y,temp_A + 90)
                set i = i + 1
                set temp_A = temp_A + SHIFT
            endloop
            call TimerStart(d.dur,d.durtime,false,null)
            if index == 0 then
                call TimerStart(tmr,INTERVAL,true,function Data.rotate)
            endif
            set temp_data[index] = d
            set index = index + 1
            return d
        endmethod
 
        method onDestroy takes nothing returns nothing
            local integer i = 0
            if index == 0 then
                call PauseTimer(tmr)
            endif
            loop
                exitwhen i >= N
                call KillUnit(.Charge[i])
                set.Charge[i] = null
                set i = i + 1
            endloop
        endmethod
    endstruct
    private function FS_Conditions takes nothing returns boolean
        return GetSpellAbilityId() == ABIL_ID
    endfunction
    private function FS_Actions takes nothing returns nothing
        call Data.create(GetTriggerUnit())
    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 FS_Conditions))
        call TriggerAddAction(t,function FS_Actions)
    endfunction
endscope


To make it works like the spell 'Lightning Shield', when you cast it another time the first one is removed and start a new one.

Thanks in advance for any help.
 
Level 11
Joined
Apr 6, 2008
Messages
760
JASS:
    private function Duration takes integer al_dur returns real
        return 6. + al_dur*6.
    endfunction

    private function Damage takes integer al_dam returns real
        return al_dam*10.
    endfunction

First of these should be constant functions. (inline)

JASS:
call TimerStart(d.dur,d.durtime,false,null)

This could be replaced with a real in the struct like this

JASS:
struct Data
real Dur

static method rotate takes nothing returns nothing
    local thistype this
    //blah blah
    if this.Dur > 0 then
        set this.Dur = this.Dur - INTERVAL
    else
        //destroy
    endif
endmethod

static method create takes unit u returns thistype
   //Blah Blah
   set this.Dur = Duration(GetUnitAbilityLevel(d.Caster,ABIL_ID))
endmethod

JASS:
local integer j
local real X
local real Y

Could be static globals (abit faster)

JASS:
call SetUnitPosition(d.Charge[j],X,Y)

I wouldnt use this for this, since it wont ignore pathing

JASS:
call SetUnitX(d.Charge[j],X)
call SetUnitX(d.Charge[j],Y)

This ignores pathing atleast

This is all i can see, well there is one more thing i'v said it before and i will say it again :p Use raidance! (Don't be scared to try new things :<)

EDIT:

Hmm missed that you needed help with implementing Tables, Well here it goes :p

JASS:
scope FireShield initializer Init
    private keyword Data
    globals
        private constant integer ABIL_ID = 'A002'
        private constant integer UNIT_ID = 'e002'
        private constant integer N = 3
        private constant real SHIFT = 360.00 / N
        private constant real r = 128.00
        private constant real dA = 3
        private constant real INTERVAL = 0.01
        private timer tmr = CreateTimer()
        private integer index = 0
        private Data array temp_data

        //Create a private HandleTable here
        private HandleTable Table
    endglobals

    private function Duration takes integer al_dur returns real
        return 6. + al_dur*6.
    endfunction

    private function Damage takes integer al_dam returns real
        return al_dam*10.
    endfunction
    private struct Data
        unit Caster
        unit array Charge[N]
        real A
        real temp_A
        real durtime
        timer dur = CreateTimer()
        static method rotate takes nothing returns nothing
            local Data d
            local integer i = 0
            local integer j
            local real X
            local real Y
            loop
                exitwhen i >= index
                set d = temp_data[i]
                if TimerGetRemaining(d.dur) > 0.00 then
                    set d.A = d.A + dA
                    if d.A >= 360 then
                        set d.A = d.A - 360
                    endif
                    set d.temp_A = d.A
                    set j = 0
                    loop
                        exitwhen j >= N
                        set X = GetUnitX(d.Caster) + r * Cos(d.temp_A * bj_DEGTORAD)
                        set Y = GetUnitY(d.Caster) + r * Sin(d.temp_A * bj_DEGTORAD)
                        call SetUnitPosition(d.Charge[j],X,Y)
                        call SetUnitFacing(d.Charge[j],d.temp_A + 90)
                        set d.temp_A = d.temp_A + SHIFT
                        set j = j + 1
                    endloop
                else
                    set index = index - 1
                    set temp_data[i] = temp_data[index]
                    set i = i - 1
                    call d.destroy()
                endif
                set i = i + 1
            endloop
        endmethod
        static method create takes unit u returns Data
            local Data d = Data.allocate()
            local integer i = 0
            local real temp_A = 0
            local real X
            local real Y
            set d.Caster = u
            set d.durtime = Duration(GetUnitAbilityLevel(d.Caster,ABIL_ID))
            loop
                exitwhen i >= N
                set X = GetUnitX(d.Caster) + r * Cos(temp_A * bj_DEGTORAD)
                set Y = GetUnitY(d.Caster) + r * Sin(temp_A * bj_DEGTORAD)
                set d.Charge[i] =CreateUnit(GetOwningPlayer(d.Caster),UNIT_ID,X,Y,temp_A + 90)
                set i = i + 1
                set temp_A = temp_A + SHIFT
            endloop
            call TimerStart(d.dur,d.durtime,false,null)
            if index == 0 then
                call TimerStart(tmr,INTERVAL,true,function Data.rotate)
            endif
            set temp_data[index] = d
            set index = index + 1

            //Here we save the struct to the unit
            set Table[d.Caster] = d
 
            return d
        endmethod

        method onDestroy takes nothing returns nothing
            local integer i = 0
            if index == 0 then
                call PauseTimer(tmr)
            endif
            loop
                exitwhen i >= N
                call KillUnit(.Charge[i])
                set.Charge[i] = null
                set i = i + 1
            endloop
            
            //This removes the caster from table
            call Table.flush(this.Caster)
        endmethod
    endstruct
    private function FS_Conditions takes nothing returns boolean
        return GetSpellAbilityId() == ABIL_ID
    endfunction
    private function FS_Actions takes nothing returns nothing
        local unit u = GetTriggerUnit()
        if Table.exists(u) then
            //Here you can Refresh the old lightning shield if you'd like or destroy the old one
        else
            call Data.create(u)
        endif
        set u = 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 FS_Conditions))
        call TriggerAddAction(t,function FS_Actions)

        //Initialize the table here
        set Table = HandleTable.create()
    endfunction
endscope

How to "load" something from the table

JASS:
local struct this = Table["Handle"]

Tables are basically integer array that get the handle it from stuff

JASS:
globals
    private integer array Table
endglobals

function Save takes handle h,integer i returns nothing
    set Table[GetHandleId(h)] = i
endfunction

function Load takes handle h returns integer
    return Table[GetHandleId(h)]
endfunction

this is kinda how it work (to simplify the code :p)
 
Status
Not open for further replies.
Top