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

[JASS] Stump at timer.

Status
Not open for further replies.
Level 31
Joined
May 3, 2008
Messages
3,155
JASS:
globals
    constant integer TA = 'A004'
    constant integer Ship = 'h002'
    constant integer Iceberg = 'h001'
endglobals

function Titanic_Conditions  takes nothing returns boolean
    return GetSpellAbilityId() == TA
endfunction

function Titanic_Dash_Timer takes nothing returns nothing
local timer TDT = GetExpiredTimer()
call DestroyTimer (TDT)
set TDT = null
endfunction

function Titanic_Fall_Timer takes nothing returns nothing
local timer TFT = GetExpiredTimer()
local timer TDT = CreateTimer()
call TimerStart (TDT, 0.02, true, function Titanic_Dash_Timer)
call DestroyTimer (TFT)
set TFT = null
endfunction

function Titanic_Actions takes nothing returns nothing
    local unit C = GetTriggerUnit()
    local location TL = GetSpellTargetLoc()
    local location UL = GetUnitLoc(C)
    local real FP1 = AngleBetweenPoints(TL, UL)
    local real FP2 = AngleBetweenPoints(UL, TL)
    local unit Tit = CreateUnitAtLoc(GetOwningPlayer(C), Ship, TL, FP1)
    local unit Ice = CreateUnitAtLoc(GetOwningPlayer(C), Iceberg, UL, FP2)
    local timer TFT = CreateTimer()
    call SetUnitPathing(Tit,false)
    call UnitAddAbility(Tit,'Arav')
    call UnitRemoveAbility(Tit,'Arav')
    call SetUnitFlyHeight(Tit,800,0)
    call SetUnitFlyHeight (Tit,1,1)
    call TimerStart (TFT, 0.02, true, function Titanic_Fall_Timer)
    call RemoveLocation(TL)
    call RemoveLocation(UL)
    set C = null
    set TL = null
    set UL = null
endfunction

//===========================================================================

constant function DF takes nothing returns boolean
    return true
endfunction

function InitTrig_Titanic_JASS takes nothing returns nothing
    local trigger T = CreateTrigger()
    local integer TI = 0
    local filterfunc FF = Filter(function DF)
    loop
    exitwhen (TI >= bj_MAX_PLAYER_SLOTS)
    call TriggerRegisterPlayerUnitEvent(T, Player(TI), EVENT_PLAYER_UNIT_SPELL_EFFECT, FF)
    set TI = TI + 1
    endloop
    call DestroyBoolExpr(FF)
    call DestroyFilter(FF)
    call TriggerAddAction(T,function Titanic_Actions)
    call TriggerAddCondition(T,Condition(function Titanic_Conditions))
    set FF = null
    set T = null
endfunction

I been trying to learn JASS/VJASS, but only manage to learn a little of it as I am quite busy with my other schedule.

Currently I been trying to learn how to use timer, condition and loop. Which I have not learn about it yet.

I am stump at how to make the ship fall from the sky and dash forward to the iceberg and crush upon impact while knocking down every enemy that are within it's path.

Of course, this spells was currently using loc instead of x/y/z coordinates. But as I say, I am learning too little of it at this moment.

Note : GUI and VJASS are from other users, they are not from me.
 
Last edited:
Level 17
Joined
Mar 17, 2009
Messages
1,349
You say you're learning vJass eh? Ok so let me start off with a hint (can't go into other details since I gotta go sleep -- got college 2moro from 9am to 7pm -- FML! :p)

So you know that each object has it's own id eh? Ok so then EACH TIMER has it's own ID too (we will be using this for MUI'ness).

JASS:
// this integer global here, will have it array as the Id of the timer (thus specific to each timer)
// it'll be equated to the value of the struct data (you know when you use d.variable, the d is a data integer)
// that way, the function to be called when the timer ends can use that data for it's own structs
// you'll see...
// if you don't understand now, just use it and you'll understand with practice =)
globals
     private integer TimerUserData[8191]
endglobals

// this little function is the function that is gonna give the variable it's value
// you could just manually do it without using the function (since it's only one line)
// but it's neater using functions
private function SetTimerUserData takes timer time, integer whichstruct returns nothing
     set TimerUserData[GetHandleId(time) - 0x100000] = whichstruct
endfunction

// now this is gonna be the function then get the data value when needed
private function GetTimerUserData takes timer time returns integer
     return TimerUserData[GetHandleId(time) - 0x100000]
endfunction


// now as i said, if you don't understand what i just said, just copy paste it, you'll understand some day later :P

// now to using it:
struct DT
    timer time
endstruct

// skip this function to the next one, then come back to it:
private function Loop takes nothing returns nothing
    // now to retrieve that instance data:
    local DT d = DT(GetTimerUserData(GetExpiredTimer()))

    // now use your struct variables freely ;)
endfunction

private function Start takes nothing returns nothing
    // creating instance
    local DT d = DT.create()
    // ... actions ...

    // setting the TimerUserData
    call SetTimerUserData(d.time, integer(d))

    // Timer Start
    call TimerStart(d.time, TIMEOUT, true, function Loop)
endfunction
// now back to the Loop function

This should help for a start, tried my BEST to explain it =)

PS: and oh, the - 0x100000 in the arrays is since the ID's start at a value of 2^20, whose hex is 0x100000, so we subtract that to start from zero ;)
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Break it down into 2 parts.
Part 1, the ship flys down.
Part 2, the ship moves foward.

Part 1 I would use a cast instance dependant timer which basically acts as a delay as the natvies will lower the ship over the duration. Thus I would use a non repeating timer and recycle / destroy it after it expires.

Upon expiry, I would add it to the move system. This would be controled by a static (constant / never destroyed) timer which loops throu all instances of the spell at that stage and does the movement / ending / knocking down of units. When there are no instances, I would pause the timer and resume it when one is added.

Timers basically take a duration for them and a function to execute when it expires. Timers which are set for perodic will execute the passed function every duration time (a perodic timer set to 1 seconds will run the function every second until it is stopped by another trigger or game end).

For effective timer use it is important to know how the functions run will behave.
With static code (code that is not dependant on being passed variable data when run) you can just use a perodic timer on it and let it be. I would advise this behaviour on the movement part, where the 1 timer will deal with all instances of the spell.

The other type of use is dynamic, whereby the code relies on values being passed to it to function. There are 2 main ways to pass values to the function which a timer executes. Firstly are hashtables, which can be used to seemingly attach data to the timer handle like a struct identifier or key handles / values which can then be recalled. Secondly abuse a bug which I can only guess still exists where by you can can enconde an number like a struct identifier onto the timer's time itself and decode it from the timer in the executed function. This kind of coding I would advise for the titanic falling as you have like a 1 - 2 second delay during which there is no need for any code to run for the spell but the timer which will expire when the ship should be on the ground.
 
Status
Not open for further replies.
Top