• 💀 Happy Halloween! 💀 It's time to vote for the best terrain! Check out the entries to Hive's HD Terrain Contest #2 - Vampire Folklore.❗️Poll closes on November 14, 2023. 🔗Click here to cast your vote!
  • 🏆 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!
  • 🏆 HD Level Design Contest #1 is OPEN! Contestants must create a maze with at least one entry point, and at least one exit point. The map should be made in HD mode, and should not be openable in SD. Only custom models from Hive's HD model and texture sections are allowed. The only exceptions are DNC models and omnilights. This is mainly a visual and design oriented contest, not technical. The UI and video walkthrough rules are there to give everyone an equal shot at victory by standardizing how viewers see the terrain. 🔗Click here to enter!

[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