• 🏆 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] Timer wont start (vjass)

Status
Not open for further replies.
Level 19
Joined
Aug 2, 2008
Messages
442
Hello. Can some one help me out here; the timer in this code doesn't start. Also,
can someone tell me if i coded this properly to have the unit "data.u" follow the targeted unit "data.target" in the same way a projectile spell would? (ex: deathcoil, stormbolt,etc)
JASS:
scope GreenShield initializer Init

private struct GreenShield
    unit u
    integer level
    real cos
    real sin
    unit target
endstruct

globals
    private constant integer ID = 'A0C7'
    private constant integer DummyID = 'h017'
    private constant string Explosion = "Abilities\\Spells\\Undead\\Darksummoning\\DarkSummonTarget.mdl"
    private constant real Interval = 0.02
    private constant real Speed = 700
    private constant real Distance = Speed * Interval
    private constant attacktype AT = ATTACK_TYPE_NORMAL
    private constant damagetype DT = DAMAGE_TYPE_FIRE
    private constant weapontype WT = WEAPON_TYPE_WHOKNOWS
    private boolexpr filter
    private group Group = CreateGroup()
    private timer Tim = CreateTimer()
    private GreenShield array queue
    private integer total = 0
    private player GSOwner
endglobals

private constant function Damage takes integer level returns real
    return level * 60. + 100.
endfunction

private function Timer takes nothing returns nothing
    local integer i = 0
    local GreenShield data
    local unit f
    local real damage
    local real x2 = GetUnitX(data.target)
    local real y2 = GetUnitY(data.target)
    local real x =  GetUnitX(data.u)
    local real y =  GetUnitY(data.u)
    local real dx = x2 - x
    local real dy = y2 - y
    local real atan2 = Atan2(dy, dx)
    set data.cos = Distance * Cos(atan2)
    set data.sin = Distance * Sin(atan2)
    call DisplayTextToForce( GetPlayersAll(), "Made it here" )
    loop
       
        exitwhen i >= total
        call DisplayTextToForce( GetPlayersAll(), "Looping" )
        set data = queue[i]
        
        call SetUnitX(data.u, GetUnitX(data.u) + data.cos)
        call SetUnitY(data.u, GetUnitY(data.u) + data.sin)
        call SetUnitFacing(data.u, atan2 * bj_RADTODEG)
        
        set GSOwner = GetOwningPlayer(data.u)
        call GroupClear(Group)
        call GroupEnumUnitsInRange(Group, GetUnitX(data.u), GetUnitY(data.u), 150, filter)
        if (FirstOfGroup(Group) == data.target) then
            call DestroyEffect(AddSpecialEffect(Explosion, GetUnitX(data.u), GetUnitY(data.u)))
            call KillUnit(data.u)
            set damage = Damage(data.level)
            call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Undead\\UCancelDeath\\UCancelDeath.mdl",f,"origin"))
            call UnitDamageTarget(data.u, data.target, damage, true, false, AT, DT, WT)
            call data.destroy()
            set total = total - 1
            set queue[i] = queue[total]
            set i = i - 1
        endif
        set i = i + 1
    endloop
    if total == 0 then
        call DisplayTextToForce( GetPlayersAll(), "Paused" )
        call PauseTimer(Tim)
    endif
    set f = null
endfunction

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

private function Fireball_Filter takes nothing returns boolean
    return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.405 and IsUnitEnemy(GetFilterUnit(), GSOwner) == true and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) == true
endfunction

private function Actions takes nothing returns nothing
    local GreenShield data = GreenShield.create()
    local unit u = GetTriggerUnit()
    local unit t = GetSpellTargetUnit()
    local location l = GetUnitLoc(t)
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real dx  = GetLocationX(l) - x
    local real dy  = GetLocationY(l) - y
    local real atan2  = Atan2(dy, dx)
    set data.target = GetSpellTargetUnit()
    set data.level = GetUnitAbilityLevel(u, ID)
    set data.u = CreateUnit(GetOwningPlayer(u), DummyID, x, y, atan2*bj_RADTODEG)
    set data.cos = Distance * Cos(atan2)
    set data.sin = Distance * Sin(atan2)
    call SetUnitPathing(data.u, false)
    call PauseUnit(data.u, true)
    call RemoveLocation(l)
    if total == 0 then
          call TimerStart(Tim, Interval, true, function Timer)
          call DisplayTextToForce( GetPlayersAll(), "Timer Started" )
    endif
    set queue[total] = data
    set total = total + 1
    set u = null
    set t = null
    set l = 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)
    call Preload(Explosion)
    set filter = Filter(function Fireball_Filter)
endfunction
endscope

JASS:
call DisplayTextToForce( GetPlayersAll(), "Made it here" )
never gets called :(
PS: I am pretty sure that location l is useless but i am lost here. :p
 
Structs are arrays. Your your not giving data a value. Yet you refrence it.

For example;

JASS:
local somstruct s = 10
set s.x = 50
set s.y = 50

//compiles to
local integer s = 10
set somestruct__x[s] = 50
set somestruct__y[s] = 50

And your not giving data a value so your doing something like this;

JASS:
local integer s
set somestruct__x[s] = 50
set somestruct__y[s] = 50

// s has no value, so how are you going to get an array?

Just use a timer attachment system if you want to store a timer to a struct.
 
Level 19
Joined
Aug 2, 2008
Messages
442
Ok. Can you explain to me how come this trigger works ?
JASS:
scope Fireball initializer Init
//Made by Hvo-busterkomo.

private struct Fireball
    unit u
    real count = 0
    real max
    integer level
    real cos
    real sin
endstruct

globals
    //Configuration
    private constant integer ID = 'A000'
    private constant integer DummyID = 'h000'
    private constant string Explosion = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
    private constant real Interval = 0.02//This is the interval of the spell. Try to find a balance between accuracy and efficiency.
    private constant real Speed = 700
    private constant real Distance = Speed * Interval//This is the the distance the fireball moves per interval.
    private constant attacktype AT = ATTACK_TYPE_NORMAL
    private constant damagetype DT = DAMAGE_TYPE_FIRE
    private constant weapontype WT = WEAPON_TYPE_WHOKNOWS
    //Don't touch this stuff unless you know what you're doing
    private boolexpr filter
    private group Group = CreateGroup()
    private timer Tim = CreateTimer()
    private Fireball array queue
    private integer total = 0
    private player FireballOwner
endglobals

private constant function Damage takes integer level returns real
    return level * 60. + 100.
endfunction

private constant function AoE takes integer level returns real
    return level * 25. + 75.
endfunction

private function Fireball_Timer takes nothing returns nothing
    local integer i = 0
    local Fireball data
    local unit f
    local real damage
    loop
        exitwhen i >= total
        set data = queue[i]
        set data.count =data.count+1//Increases the count. Once it reaches a certain number, the fireball will explode.
       call SetUnitX(data.u, GetUnitX(data.u) + data.cos)
        call SetUnitY(data.u, GetUnitY(data.u) + data.sin)
        set FireballOwner = GetOwningPlayer(data.u)
        call GroupClear(Group)//Clears the global group.
        call GroupEnumUnitsInRange(Group, GetUnitX(data.u), GetUnitY(data.u), AoE(data.level), filter)//Groups all nearby units.
        if FirstOfGroup(Group) != null or data.count>=data.max then
            call DestroyEffect(AddSpecialEffect(Explosion, GetUnitX(data.u), GetUnitY(data.u)))//Creates the effect/
            call KillUnit(data.u)//Kills the fireball.
            set damage = Damage(data.level)
            loop
                set f = FirstOfGroup(Group)
                exitwhen f == null
                call UnitDamageTarget(data.u, f, damage, true, false, AT, DT, WT)//Damages the enemy.
                call GroupRemoveUnit(Group, f)//Removes the unit from the group
            endloop
            call data.destroy()
            set total = total - 1
            set queue[i] = queue[total]
            set i = i - 1
        endif
        set i = i + 1
    endloop
    if total == 0 then
        call PauseTimer(Tim)
    endif
    set f = null
endfunction

private function Fireball_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ID//Makes it only fire for this spell.
endfunction

private function Fireball_Filter takes nothing returns boolean
    return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0. and IsUnitEnemy(GetFilterUnit(), FireballOwner) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)//Makes it only work on units (not structures) and living units.
endfunction

private function Fireball_Actions takes nothing returns nothing
    local Fireball data = Fireball.create()
    local unit u = GetTriggerUnit()//Stores the caster in a variable.
    local location l = GetSpellTargetLoc()//Stores the target location of the spell.
    local real x = GetUnitX(u)//Stores the x of the caster.
    local real y = GetUnitY(u)//Stores the y of the caster.
    local real dx = GetLocationX(l) - x
    local real dy = GetLocationY(l) - y
    local real atan2 = Atan2(dy, dx)
    set data.max = SquareRoot(dx * dx + dy * dy)/Distance//Calculates the number of executions required by the timer.
    set data.level = GetUnitAbilityLevel(u, ID)//Stores the level of the ability in a struct.
    set data.u = CreateUnit(GetOwningPlayer(u), DummyID, x, y, atan2*bj_RADTODEG)//Stores the fireball in a struct.
    set data.cos = Distance * Cos(atan2)
    set data.sin = Distance * Sin(atan2)
    call SetUnitPathing(data.u, false)//Sets the fireball's pathing to none.
    call PauseUnit(data.u, true)
    call RemoveLocation(l)//Prevents the location from leaking.
    if total == 0 then
         call TimerStart(Tim, Interval, true, function Fireball_Timer)
     endif
    set queue[total] = data
    set total = total + 1
    set u = null//local
    set l = null//variables
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()//Creates the trigger.
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)//Adds the event.
    call TriggerAddCondition(t, Condition(function Fireball_Conditions))//Adds the condition.
    call TriggerAddAction(t, function Fireball_Actions)//Adds the action.
    call Preload(Explosion)//Preloads the effect, preventing it from lagging the first time it's cast.
    set filter = Filter(function Fireball_Filter)//Stores a global boolexp. Much faster than creating and destroying one all the time.
endfunction

endscope

This has the same line like mine in the timer:
JASS:
local Fireball data
I appreciate you helping me out
 
Status
Not open for further replies.
Top