• 🏆 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!
  • ✅ Time to vote for the top 3 models! The POLL for Hive's 6th HD Modeling Contest: Mechanical is now open! 📅 Poll close on July 16, 2024! 🔗 Cast your vote now!
  • ✅ The POLL for Hive's Texturing Contest #33 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!

[vJASS] Attaching integer data from TimerUtils than Table

Not open for further replies.
Level 20
Aug 13, 2013
Is there any difference when attaching integer data to the TimerUtils like this?
set tmr = NewTimerEx(this) than Table by Bribe?

I have this systems in my spell.
Table by Bribe

Here is the demo code of my vJASS spell:
Pls if you can tell me if there's any mistake or wrong or problem about coding so that I'll fix it properly ^^.

//                 F I R E  B L O W                                                                    //
//                       v1.0                                                                          //


// Spell Author: jakeZinc
// Spell Purpose: Creating a stampede creature that will travel along to the target Location
//                during stampede creature is running, nearby enemy units to the stampede creature 
//                will be damaged and stunned. When the stampede creature reaches the target location
//                it will cause an area damage and knockbacking nearby units to the target.
// Spell Changelogs:  v1.0: Initial Release
// How to Import:
// Copy and Paste:
// Object Editor - Abilities - Stampede
// Object Editor - Units - Stampede Missile
// Trigger Editor - Folder - Libraries
// Trigger Editor - Folder - Stampede [ vJASS ] v1.0

library FireBlow requires /*      Required Libraries
                                 -*/ AbilityPreload /*
                                 -*/ DelFX /*
                                 -*/ SpellEffectEvent/*
                                 -*/ Table /*
                                 -*/ TimerUtils
    private constant integer ABILITY_ID = 'A000'
    private constant integer MISSILE_ID = 'u000'
    private constant string  EXPLOSION_EFFECT = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
    private constant string  EXPLOSION_EFFECT_ATTACH = "origin"
    private constant string  CASTER_EFFECT = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl"
    private constant real MISSILE_DAMAGE = 100.
    private constant real MISSILE_BASE_SPEED = 10.
    private constant real MISSILE_PER_LEVEL_SPEED = 10.
    private constant real MISSILE_DETECTRANGE = 50
    private constant real INTERVAL = 0.03125000
    private constant real IMPACT_RADIUS = 300.00
    private constant real IMPACT_DAMAGE = 150.00

private function GetMissileDamage takes integer lvl returns real
    return MISSILE_DAMAGE * lvl

private function GetMissileSpeed takes integer lvl returns real

private struct SpellData

    unit caster
    unit target
    unit missile
    real speed
    real detect
    real damage
    real castX
    real castY
    integer level
    static method filterUnit takes unit caster, unit picked returns boolean
         return /*
        */ IsUnitEnemy(picked, GetOwningPlayer(caster)) and /*
        */ not IsUnitType(picked, UNIT_TYPE_DEAD) and GetUnitTypeId(picked) != 0 and /*
        */ not IsUnitType(picked, UNIT_TYPE_STRUCTURE) and /*
        */ not IsUnitType(picked, UNIT_TYPE_MAGIC_IMMUNE) and /*
        */ not IsUnitType(picked, UNIT_TYPE_FLYING)
    // Spell Loop //
    private static method onLoop takes nothing returns nothing
        local timer tmr = GetExpiredTimer ( )
        local thistype this = GetTimerData(tmr)
        local unit p
        local real missileX = GetWidgetX ( this.missile )
        local real missileY = GetWidgetY ( this.missile )
        local real targX = GetWidgetX ( this.target )
        local real targY = GetWidgetY ( this.target )
        local real angle = Atan2( targY - missileY, targX - missileX )         
        call SetUnitX ( this.missile, missileX + this.speed * Cos ( angle ) )
        call SetUnitY ( this.missile, missileY + this.speed * Sin ( angle ) )
        call SetUnitFacing ( this.missile, angle * bj_RADTODEG )
        if SquareRoot ( ( targX - missileX ) * ( targX - missileX ) + ( targY - missileY ) * ( targY - missileY ) ) <= this.detect then
            call CreateDelayedEffectTarget ( EXPLOSION_EFFECT, this.target, EXPLOSION_EFFECT_ATTACH, 0.03, 0.03 )
            call KillUnit ( this.missile )
            call UnitDamageTarget ( this.caster, this.target, this.damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null )
            call GroupEnumUnitsInRange( bj_lastCreatedGroup, targX, targY, IMPACT_RADIUS, null )
                    set p = FirstOfGroup(bj_lastCreatedGroup)
                    exitwhen p == null
                        if thistype.filterUnit ( this.caster, p ) then
                            call UnitDamageTarget ( this.caster, p, IMPACT_DAMAGE, true,false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null ) 
                    call GroupRemoveUnit( bj_lastCreatedGroup, p )

            call this.deallocate()
            call PauseTimer(tmr)
            call DestroyTimer(tmr)
        set tmr = null

    // Spell Execution //

    private static method onCast takes nothing returns boolean
        local timer    tmr
        local thistype this
        local real     angle2
        local real     targX2
        local real     targY2
        if GetSpellAbilityId() == ABILITY_ID then
        set this = thistype.allocate()
        set            this.caster   =  GetTriggerUnit()
        set            this.target   =  GetSpellTargetUnit()
        set            this.level    =  GetUnitAbilityLevel( this.caster, ABILITY_ID )
        set            this.castX    =  GetWidgetX ( this.caster )
        set            this.castY    =  GetWidgetY ( this.caster )
        set            this.speed    =  GetMissileSpeed( this.level )
        set            this.damage   =  GetMissileDamage( this.level )
        set            this.detect   =  MISSILE_DETECTRANGE
        set            targX2        =  GetWidgetX( this.target )
        set            targY2        =  GetWidgetY( this.target )
        set            angle2        =  Atan2( targY2 - this.castY, targX2 - this.castX ) * bj_RADTODEG 
        set            this.missile  =  CreateUnit( GetOwningPlayer ( this.caster ), MISSILE_ID, this.castX, this.castY, angle2 )
        call CreateDelayedEffect(CASTER_EFFECT, this.castX, this.castY, 0.03, 0.03)

        set tmr = NewTimerEx(this)
        call TimerStart( tmr, INTERVAL, true, function thistype.onLoop)
        set            tmr = null
        return false

// Spell Initialization //
    private static method onInit takes nothing returns nothing
        call RegisterSpellEffectEvent( ABILITY_ID , function thistype.onCast  )
        call AbilityPreload ( ABILITY_ID )



Remember that I'm new to vJASS world :D!
Level 8
Feb 3, 2013
i think it looks good man :) except I think timerUtils has had some problems with new versions of Table in my experience

using RegisterSpellEffectEvent function allows you to not have deal with if GetUnitAbilityLevel(x, '') == ABIL_ID then and it also doesn't require returning a boolean value or anything
Level 20
Aug 13, 2013

I'm using TimerUtils (red+blue+orange flavors for 1.24b+) v2.0 ^^


Will try that ;).


Can I use GUI System??? that uses udg_ prefixes??
Example: Knockback System GUI
TimerUtils is for both storage and for timer recycling. Table is just for storage.

What Nes meant by "version" is that the storage system of TimerUtils behaves differently depending on which "flavor" you choose. By default, it is set to blue (USE_HASHTABLE = true), which means that it saves through a hashtable. You could use Table for the same thing if you want.

However, if USE_HASHTABLE is false, then it will use an array and index with the timer's id - some offset. The problem with it is that you have to worry about maps with over 8190 handles because the timer has a chance of getting an offset out of the array's index. It doesn't happen often since TimerUtils initializes timers on init but it is still a risk to take note of. It is a little faster than hashtables, but the speed difference is negligible. I prefer the stability of hashtables. If "use flexible offset" is true (and use hashtable is false), then it will reduce the chance of the index issue by adjusting the "offset" subtracted from the timer id.

You can read more about it in the TimerUtils documentation (in the actual script). Usually I just leave it as it is.

EDIT: Yeah you can use GUI systems.
Level 37
Mar 6, 2006
-Some people recommend x < y*y rather than SquareRoot(x) < y since apparently sqrt is slow
-Shouldn't you use ReleaseTimer from timer utils and not pause/destroy the timer
-I don't think you can pick units that have unit type id of 0 so no need to check it. Only if the same group is enumed later should the id be checked as only then can the group contain such units
-I recommend CTL by Nestharus since the period is so low. Each instance does not need its own timer
Not open for further replies.