• 🏆 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!

[vJASS] Allocation or Indexing makes my spell not work

Status
Not open for further replies.
[jass=]library DeathTempest
globals

private constant integer ABIL_CODE = 'A000'
private constant integer DUMMY = 'h000'

private constant real TIMEOUT = 0.03125

//Damage Constants
private constant real DAMAGE_BASE = 100
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_DIVINE
private constant real LIFE_STEAL_CHANCE_BASE = 10
private constant string DAMAGE_SFX = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl"
private constant string ATTACHMENT = "chest"

//Dummy Speed & SFX
private constant real SPEED_BASE = 625
private constant real FADE_TIME = 1//The number of seconds for a dummy to reach its transparency to 100
private constant real MINIMUM_DIST = 100
private constant string DASH_SFX = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
endglobals

//FUNCTIONS

//Get Speed
private function GetSpeed takes integer lvl returns real
return SPEED_BASE * TIMEOUT
endfunction
//Get Damage
private function GetDamage takes integer lvl returns real
return DAMAGE_BASE * I2R(lvl)
endfunction
//Get RandomChance
private function GetChance takes integer lvl returns real
//DUE TO MY TOOLTIP,THIS WILL BE MY FORMULA
return (10 * I2R(lvl)) + 5
//Results:
// LVL 1:15
// LVL 2:25
// LVL 3:35
endfunction
//Get Min Dist
private function GetMinDist takes nothing returns real
return MINIMUM_DIST * MINIMUM_DIST
endfunction


struct DeathTempest
//Struct Globals
private thistype next
private thistype prev

private static timer iterator = CreateTimer()
private static integer count = 0

private unit caster
private unit target
private unit dummy

private integer fade

private boolean isdummytravelling

private player player

private real damage
private real chance
private real speed

private method destroy takes nothing returns nothing
/*
* Deallocate this instance.
*/
call this.deallocate()

/*
* We remove the instance from the linked list.
*/
set this.next.prev = this.prev
set this.prev.next = this.next

/*
* We decrease the count by 1.
* If the count is 0, we pause the timer.
*/
set count = count - 1
if count == 0 then
call PauseTimer(iterator)
endif


endmethod

private static method periodic takes nothing returns nothing
/*
* Starting from the first instance, we loop
* over all the instance in the list until we hit
* a dead-end.
*/
local thistype this = thistype(0).next

local real x
local real y
local real x2
local real y2
local real angle
local real dist

loop
exitwhen this == 0
if this.isdummytravelling == true then
set x = GetUnitX(this.dummy)
set y = GetUnitY(this.dummy)
set x2 = GetUnitX(this.target)
set y2 = GetUnitY(this.target)
set dist = (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)
set angle = Atan2(y2 - y,x2 - x)

if dist >= GetMinDist() then
call SetUnitFacing(this.dummy,angle)
set x = x + this.speed * Cos(angle)
set y = y + this.speed * Sin(angle)
call SetUnitX(this.dummy,x)
call SetUnitY(this.dummy,y)

/*
* We allocate an instance.
* for dummies
*/
set this = thistype.allocate()

/*
* We add the instance to the linked list.
*/
set this.next = 0
set this.prev = thistype(0).prev
set thistype(0).prev.next = this
set thistype(0).prev = this

set this.dummy = CreateUnit(this.player,DUMMY,x,y,angle)
call DestroyEffect(AddSpecialEffect(DASH_SFX,x,y))
set this.isdummytravelling = false
else
call UnitDamageTarget(this.caster,this.target,this.damage,false,false,ATTACK_TYPE,DAMAGE_TYPE,null)
call DestroyEffect(AddSpecialEffectTarget(DAMAGE_SFX,this.target,ATTACHMENT))
call this.destroy()
call RemoveUnit(this.dummy)
set this.dummy = null
// Null data
set this.caster = null
set this.target = null
endif
else
call BJDebugMsg("hello")
set this.fade = this.fade + 3
if this.fade >= 100 then
call this.destroy()
call RemoveUnit(this.dummy)
set this.dummy = null
else
call SetUnitVertexColor(this.dummy,100,100,100,this.fade)
endif
endif

set this = this.next
endloop
endmethod

private static method run takes nothing returns boolean

local integer lvl
local unit caster
/*
* We allocate an instance.
*/
local thistype this = thistype.allocate()

/*
* We add the instance to the linked list.
*/
set this.next = 0
set this.prev = thistype(0).prev
set thistype(0).prev.next = this
set thistype(0).prev = this

/*
* We increase the count by 1.
* If the count is 1, we start the timer to loop through
* the instances. This is because recasting the spell while
* an instance is already running shouldn't restart the timer.
*/
set count = count + 1
if count == 1 then
call TimerStart(iterator, TIMEOUT, true, function thistype.periodic)
endif

/*
* We set our struct data.
*/
set this.caster = GetTriggerUnit()
set this.target = GetSpellTargetUnit()

set this.player = GetTriggerPlayer()

set this.dummy = CreateUnit(this.player,DUMMY,GetUnitX(this.caster),GetUnitY(this.caster),0)
set this.isdummytravelling = true

set lvl = GetUnitAbilityLevel(this.caster,ABIL_CODE)

set this.damage = GetDamage(lvl)
set this.chance = GetChance(lvl)
set this.speed = GetSpeed(lvl)

return false
endmethod

private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function thistype.run))
set t = null
endmethod
endstruct
endlibrary[/code]

Please check the DeathTempest.periodic method.
the second group id doesnt work.
 

Attachments

  • Death Tempest v1.0.w3x
    21.4 KB · Views: 37
Level 7
Joined
Jan 28, 2012
Messages
266
You should turn all of those CONSTANTS into functions so that they will inline.

why are you allocating a new instance?
JASS:
                        /*
                        *   We allocate an instance.
                        *   for dummies
                        */
                        set this = thistype.allocate()
                        
                        /*
                        *   We add the instance to the linked list.
                        */
                        set this.next = 0
                        set this.prev = thistype(0).prev
                        set thistype(0).prev.next = this
                        set thistype(0).prev = this
                        
                        set this.dummy = CreateUnit(this.player,DUMMY,x,y,angle)
                        call DestroyEffect(AddSpecialEffect(DASH_SFX,x,y))
                        set this.isdummytravelling = false
you are changing which index you are on, which is messing with your system, here is a working version.
JASS:
library DeathTempest
    globals
        
        private constant integer ABIL_CODE = 'A000'
        private constant integer DUMMY = 'h000'
        
        private constant real TIMEOUT = 0.03125
        
        //Damage Constants
        private constant real DAMAGE_BASE = 100
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_DIVINE
        private constant real LIFE_STEAL_CHANCE_BASE = 10
        private constant string DAMAGE_SFX = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl"
        private constant string ATTACHMENT = "chest"
        
        //Dummy Speed & SFX
        private constant real SPEED_BASE = 625
        private constant real FADE_TIME = 1//The number of seconds for a dummy to reach its transparency to 100
        private constant real MINIMUM_DIST = 100
        private constant string DASH_SFX = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
    endglobals
    
//FUNCTIONS

    //Get Speed
    private function GetSpeed takes integer lvl returns real
        return SPEED_BASE * TIMEOUT
    endfunction
    //Get Damage
    private function GetDamage takes integer lvl returns real
        return DAMAGE_BASE * I2R(lvl)
    endfunction
    //Get RandomChance
    private function GetChance takes integer lvl returns real
        //DUE TO MY TOOLTIP,THIS WILL BE MY FORMULA
        return (10 * I2R(lvl)) + 5
        //Results:
        // LVL 1:15
        // LVL 2:25
        // LVL 3:35
    endfunction
    //Get Min Dist
    private function GetMinDist takes nothing returns real
        return MINIMUM_DIST * MINIMUM_DIST
    endfunction
    
    
    struct DeathTempest
        //Struct Globals
        private thistype next
        private thistype prev

        private static timer iterator = CreateTimer()
        private static integer count = 0
        
        private unit caster
        private unit target
        private unit dummy
        
        private integer fade
        
        private boolean isdummytravelling
        
        private player player
        
        private real damage
        private real chance
        private real speed
        
        private method destroy takes nothing returns nothing
            /*
            *   Deallocate this instance.
            */
            call this.deallocate()

            /*
            *   We remove the instance from the linked list.
            */
            set this.next.prev = this.prev
            set this.prev.next = this.next
            /*
            *   We decrease the count by 1.
            *   If the count is 0, we pause the timer.
            */
            set count = count - 1
            call BJDebugMsg("DestroyingIndex "+I2S(this)+" Count is "+I2S(count))
        endmethod
        private static method createSFX takes real x, real y, real angle, player p returns nothing
                local thistype this = thistype.allocate()
                    
                /*
                *   We add the instance to the linked list.
                */
                set this.next = 0
                set this.prev = thistype(0).prev
                set thistype(0).prev.next = this
                set thistype(0).prev = this
                set count = count+1
                set this.dummy = CreateUnit(p,DUMMY,x,y,angle)
                call DestroyEffect(AddSpecialEffect(DASH_SFX,x,y))
                set this.isdummytravelling = false
                set p = null
        endmethod
        private static method periodic takes nothing returns nothing
            /*
            *   Starting from the first instance, we loop
            *   over all the instance in the list until we hit
            *   a dead-end.
            */
            local thistype this = thistype(0).next
            
            local real x
            local real y
            local real x2
            local real y2
            local real angle
            local real dist
            
            loop
                exitwhen this == 0
                if this.isdummytravelling == true then
                    set x = GetUnitX(this.dummy)
                    set y = GetUnitY(this.dummy)
                    set x2 = GetUnitX(this.target)
                    set y2 = GetUnitY(this.target)
                    set dist = (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)
                    set angle = Atan2(y2 - y,x2 - x)
                    
                    if dist >= GetMinDist() then
                        call SetUnitFacing(this.dummy,angle)
                        set x = x + this.speed * Cos(angle)
                        set y = y + this.speed * Sin(angle)
                        call SetUnitX(this.dummy,x)
                        call SetUnitY(this.dummy,y)
                        
                        /*
                        *   We allocate an instance.
                        *   for dummies
                        */
                        call createSFX(x,y,angle,this.player)
                    else
                        call UnitDamageTarget(this.caster,this.target,this.damage,false,false,ATTACK_TYPE,DAMAGE_TYPE,null)
                        call DestroyEffect(AddSpecialEffectTarget(DAMAGE_SFX,this.target,ATTACHMENT))
                        call this.destroy()
                        call RemoveUnit(this.dummy)
                        set this.dummy = null
                        // Null data
                        set this.caster = null
                        set this.target = null
                    endif
                else
                    call BJDebugMsg("Runnning for station index "+I2S(this))
                    set this.fade = this.fade + 12
                    if this.fade >= 100 then
                        call this.destroy()
                        call RemoveUnit(this.dummy)
                        set this.dummy = null
                    else
                        call SetUnitVertexColor(this.dummy,100,100,100,this.fade)
                    endif
                endif
                
                set this = this.next
            endloop
            
            if 0 == count then
                call BJDebugMsg("Count is = 0 halting timer")
                return
            endif
            call TimerStart(iterator, TIMEOUT, false, function thistype.periodic)
        endmethod
        
        private static method run takes nothing returns boolean
        
           local integer lvl
           local unit caster
            /*
           *   We allocate an instance.
           */
           local thistype this = thistype.allocate()

           /*
           *   We add the instance to the linked list.
           */
           set this.next = 0
           set this.prev = thistype(0).prev
           set thistype(0).prev.next = this
           set thistype(0).prev = this

           /*
           *   We increase the count by 1.
           *   If the count is 1, we start the timer to loop through 
           *   the instances. This is because recasting the spell while 
           *   an instance is already running shouldn't restart the timer.
           */
            set count = count + 1
            if count == 1 then
                call TimerStart(iterator, TIMEOUT, false, function thistype.periodic)
            endif

            /*
            *   We set our struct data.
            */
            set this.caster = GetTriggerUnit()
            set this.target = GetSpellTargetUnit()
            
            set this.player = GetTriggerPlayer()
            
            set this.dummy = CreateUnit(this.player,DUMMY,GetUnitX(this.caster),GetUnitY(this.caster),0)
            set this.isdummytravelling = true
            
            set lvl = GetUnitAbilityLevel(this.caster,ABIL_CODE)
            
            set this.damage = GetDamage(lvl)
            set this.chance = GetChance(lvl)
            set this.speed = GetSpeed(lvl)
            
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t, Condition(function thistype.run))
            set t = null
        endmethod
    endstruct
endlibrary
EDIT: you need to set this.fade = 0 when you destroy the index.
JASS:
else
                    call BJDebugMsg("Runnning for station index "+I2S(this))
                    set this.fade = this.fade + 3
                    if this.fade >= 100 then
                        call this.destroy()
                        set this.fade = 0
                        call RemoveUnit(this.dummy)
                        set this.dummy = null
                    else
                        call SetUnitVertexColor(this.dummy,100,100,100,this.fade)
                    endif
                endif
                
                set this = this.next
            endloop

Edit2: you also might want to consider using a dummy recycler, because otherwise this spell will create major lagg
 
Last edited:
Status
Not open for further replies.
Top