function dada takes nothing returns nothing
set udg_count = udg_count + 1
if udg_count == 5 then
call BJDebugMsg("done")
else
call DisplayTextToForce(GetPlayersAll(), ( "Total is " + I2S(udg_count) ) )
endif
endfunction
//===========================================================================
function InitTrig_counttest1 takes nothing returns nothing
local trigger y = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( y, 0.50 )
call TriggerAddAction(y,function dada)
set y = null
endfunction
function dada takes nothing returns nothing
local integer count
set count = count + 1
if count == 5 then
call BJDebugMsg("done")
else
call DisplayTextToForce(GetPlayersAll(), ( "Total is " + I2S(count) ) )
endif
endfunction
//===========================================================================
function InitTrig_counttest2 takes nothing returns nothing
local trigger y = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( y, 0.50 )
call TriggerAddAction(y,function dada)
set y = null
endfunction
function WodSpell takes nothing returns boolean
local unit u
local unit o
local integer spelllevel
local integer spelldam
if GetSpellAbilityId()=='A002' then
set u = GetTriggerUnit()
set o = CreateUnit (GetOwningPlayer(u), 'h000', GetUnitX(u), GetUnitY(u), 0)
set spelllevel = GetUnitAbilityLevel(u, 'A002')
set spelldam = spelllevel * 5
call IssuePointOrder(o, "move", GetSpellTargetX(), GetSpellTargetY())
set u = null
set o = null
call DisplayTextToForce(GetPlayersAll(), ( "Damage is " + I2S(spelldam) ) )
endif
return false
endfunction
//===========================================================================
function InitTrig_Wind_of_Decay takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ (t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition (t, Condition(function WodSpell))
set t = null
endfunction
I mean that the local isn't passed on to the next call of the function.
//! zinc
library Test {
unit tester, killer;
real x;
}
//! endzinc
scope A
/*
put the codes here
*/
endscope
5. Can you save local variables to a hashtable and load latter?...
globals
//===============================================
//= CONFIGURATION GLOBALS =
//===============================================
integer SPELL_ID = 'A001'
real SPELL_DPS = 20.00/4
real SPELL_DUR = 06.00
real UPDATE_RATE = 01.00/4
string SPECIAL_FX = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
string ATTACH_POINT= "chest"
//===============================================
//===============================================
// SYSTEM ONLY GLOBALS - DO NOT EDIT =
//===============================================
integer TIMER = 1 // <<< I just changed this, is it OK?
integer CASTER = 2
integer TARGET = 3
integer DURATION = 4
hashtable HASHTABLE = InitHashtable()
//===============================================
endglobals
//============================================================
//= SPELL MAIN =
//= When creating DoT spells, you must consider the =
//= following: =
//= -caster =
//= -target =
//= -duration =
//= A good DoT spell must be able to distinguish if =
//= the targetted unit already has the DoT debuff, in =
//= order to be able to stack or not stack its effects. =
//============================================================
function onCastCondition takes nothing returns boolean
return (GetSpellAbilityId()==SPELL_ID)
endfunction
function onUpdate takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer childkey=GetHandleId(t)
local unit caster=LoadUnitHandle(HASHTABLE,CASTER,childkey)
local unit target=LoadUnitHandle(HASHTABLE,TARGET,childkey)
local real duration=LoadReal(HASHTABLE,DURATION,childkey)-UPDATE_RATE
// We need to check if the debuff has reached it's
// intended lifetime, if so we remove the data we
// saved in the hashtable. We also do the same if
// the target is already dead.
if (duration<0) or IsUnitType(target,UNIT_TYPE_DEAD) then
// There is no longer any time remaining for the
// debuff, so we clear the hashtable.
debug call BJDebugMsg("Destroy debuff timer")
call RemoveSavedHandle(HASHTABLE,CASTER,childkey)
call RemoveSavedHandle(HASHTABLE,TARGET,childkey)
call RemoveSavedReal(HASHTABLE,DURATION,childkey)
call RemoveSavedHandle(HASHTABLE,TIMER,GetHandleId(target))
call DestroyTimer(t)
else
// There's still timer left for the debuff, so we
// apply the debuff effect.
call SaveReal(HASHTABLE,DURATION,childkey,duration)
call DestroyEffect(AddSpecialEffectTarget(SPECIAL_FX,target,ATTACH_POINT))
call UnitDamageTarget(caster,target,SPELL_DPS,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC,null)
endif
set t=null
set caster=null
set target=null
endfunction
function onCast takes nothing returns nothing
local unit caster=GetTriggerUnit()
local unit target=GetSpellTargetUnit()
local integer childkey=GetHandleId(target)
local timer t
// Check if the unit already has a debuff timer, in
// this spell's case, I wan't the duration to reset
// to the maximum duration if the spell is recast
// on an already debuffed unit.
if (HaveSavedHandle(HASHTABLE,TIMER,childkey)) then
// The target has a debuff already, we know this
// because there is already an existing debuff
// timer for the said unit.
debug call BJDebugMsg("Target already has buff!")
set t=LoadTimerHandle(HASHTABLE,TIMER,childkey)
call SaveReal(HASHTABLE,DURATION,childkey,SPELL_DUR)
else
// The target has no debuff yet because there is
// no beduff timer for it. We create a debuff timer
// and save to the hashtable the necessary data.
// These are the caster, the target, the duration,
// and the debuff timer. You'll notice that the debuff
// timer is attached to the target unit, this is
// because we want to associate the unit with the
// debuff timer, so that when we target an already
// affected unit, we can reset the debuff duration.
debug call BJDebugMsg("Target has no buff yet!")
set t=CreateTimer()
call SaveTimerHandle(HASHTABLE,TIMER,childkey,t)
set childkey=GetHandleId(t)
call SaveReal(HASHTABLE,DURATION,childkey,SPELL_DUR)
call SaveUnitHandle(HASHTABLE,CASTER,childkey,caster)
call SaveUnitHandle(HASHTABLE,TARGET,childkey,target)
call TimerStart(t,UPDATE_RATE,true,function onUpdate)
endif
set t=null
set caster=null
set target=null
endfunction
function InitTrig_Damage_Over_Time takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ (t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition (t,Condition(function onCastCondition))
call TriggerAddAction (t,function onCast)
set t = null
endfunction
library MySpell
private function onCast takes nothing returns nothing
//blah blah blah
endfunction
private function TestCast takes nothing returns nothing
call onCast() //this is legit
endfunction
endlibrary
function TestCast takes nothing returns nothing //this funciton can have the same name
call onCast() //this is not legit, because onCast is private to mySpell.
endfunction
library something requires anotherlibrarywhichhasthisname, thisisanotherlibraryseperatedwithacoma
scope something requires willgiveyouasyntaxerror
3. If onCast is private and inside a scope or a library, having a duplicate onCast function will be valid.
Well I hope one of you guys will update the NewGen for the sake of new users of it...
That was too harsh dude, he's just starting to learn.Or we aren't * enough.
Hmm..since you're discussing vJASS may i ask a question?
What's the difference between public function and just function?
If a function is in a library,you can call it from any trigger so i don't see the difference...
I assume though,that the public functions receive a different name (or a prefix) upon compiling so it doesn't interfere with other functions,but i'm not sure...
Also what's the difference when using libraries and scopes?
1. In GUI when you save using hashtable, you set the ID and then add to a unit group...then set the ID again inside that unit group, then load...so how do you do it in JASS/vJASS?...
2. When using HT, is it not necessary to use "TriggerRegisterTimerEventPeriodic"?...
I don't understand, can you give an example?
HT? I'm assuming you meant a periodic timer. You can just use TimerStart(timer WhichTimer, real Duration, boolean Periodic, function Whichfunction). Which will call the specified function whenever the timer procs.
struct myStruct
real x
real y
unit u
endstruct
//and then make theese functions:
function myCallback takes nothing returns nothing
local myStruct S = LoadInteger(myHash, 0, GetHandleId(GetExpiredTimer()))
//now you can retain your variables through the struct, i.e. "S.u" to get the stored unit!
//Remember to type the following lines once you're done witn the struct, or the struct will not be recycled.
call S.destroy()
call RemoveSavedInteger(myHash, 0, GetHandleId(GetExpiredTimer()))
endfunction
function AttachStructToTimer takes unit u, real x, real y returns nothing
local timer t = CreateTimer()
local myStruct S = myStruct.create()
set S.u = u
set S.x = x
set S.y = y
call SaveInteger(MyHash, 0, GetHandleId(t), S) //This attaches our struct "S" to the timer.
call TimerStart(t, false, false, function myCallback)
endfunction
Usually you don't use hashtables for making spells in vJASS, we got structs.
In plain JASS it's better to use a timer's handle id to attach your data instead of the caster's id thus it will always be a unique id every single time which will never clash with anyother spell instance (as they won't use that timer). That's the easiest way in JASS what I know of. If you remember the pounce spell I made, it uses this technique pretty well.
In plain JASS it's better to use a timer's handle id to attach your data instead of the caster's id...