You have to use structs. Think of using a struct as a "container" for whatever you need to pass through. I'll guide you step by step.
Okay, so first we need to make a struct to contain all the variables we need to pass. According to your parameters, we need:
- The Caster ; Type: Unit
- Some Group ; Type: Group
- Time ; Type: Real
- X-Coordinate ; Type: Real
- Y-Coordinate ; Type: Real
- Effect Path ; Type: String
Thus, your members should look like this:
JASS:
struct EffectSpellStuff
unit caster
group aGroup
real time
real EffectX
real EffectY
string EffectPath
endstruct
Now let's basically eliminate what we know won't need to be passed. Assuming the time is constant, we can remove that. Same for the EffectPath. The group can be removed as well since we can just use a normal group.
Okay, so let's say you have a standard spell scope:
JASS:
scope StandardSpell initializer Init
globals
private constant integer RAWCODE = 'A064' //modify this to your spell's rawcode
endglobals
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == RAWCODE then
endif
return false
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))
endfunction
endscope
Now add your struct, and your constants:
JASS:
scope EffectSpellThing initializer Init
globals
private constant integer RAWCODE = 'A064' //modify this to your spell's rawcode
private constant string EFFECT_PATH = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl"
private constant real EFFECT_TIME = 2
private group aGroup = CreateGroup()
private constant boolean DESTROY_DESTRUCTABLE = false
endglobals
private function damage takes nothing returns real
return 150.
endfunction
private struct EffectSpell
unit caster
real EffectX
real EffectY
static method LA takes nothing returns nothing
local unit first
call DestroyEffectTimed(AddSpecialEffect(EFFECT_PATH,.EffectX,.EffectY),EFFECT_TIME)
call GroupEnumUnitsInRange(aGroup,.EffectX,.EffectY,150,null)
loop
set first = FirstOfGroup(aGroup)
exitwhen first == null
if IsUnitEnemy(first,GetOwningPlayer(.caster)) then
call UnitDamageTarget(caster,first,damage(),true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
call GroupRemoveUnit(aGroup,first)
endloop
if DESTROY_DESTRUCTABLE then
endif
endmethod
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
set .caster = GetTriggerUnit()
set .EffectX = GetSpellTargetX()
set .EffectY = GetSpellTargetY()
return this
endmethod
endstruct
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == RAWCODE then
call EffectSpell.create()
endif
return false
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))
endfunction
endscope
Okay, now we are trying to execute LA after 0.10 seconds with transferring the data. At the moment, LA will create syntax errors because we can't refer to them directly like that. "this" doesn't exist yet. Thus, we must use something like TimerUtils:
JASS:
scope EffectSpellThing initializer Init
globals
private constant integer RAWCODE = 'A064' //modify this to your spell's rawcode
private constant string EFFECT_PATH = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl"
private constant real EFFECT_TIME = 2
private group aGroup = CreateGroup()
private constant boolean DESTROY_DESTRUCTABLE = false
endglobals
private function damage takes nothing returns real
return 150.
endfunction
private struct EffectSpell
unit caster
real EffectX
real EffectY
static method LA takes nothing returns nothing
local timer t = GetExpiredTimer() //retrieve the timer
local thistype this = GetTimerData(t) //get the data
local unit first
call DestroyEffectTimed(AddSpecialEffect(EFFECT_PATH,.EffectX,.EffectY),EFFECT_TIME)
call GroupEnumUnitsInRange(aGroup,.EffectX,.EffectY,150,null)
loop
set first = FirstOfGroup(aGroup)
exitwhen first == null
if IsUnitEnemy(first,GetOwningPlayer(.caster)) then
call UnitDamageTarget(caster,first,damage(),true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
call GroupRemoveUnit(aGroup,first)
endloop
if DESTROY_DESTRUCTABLE then
endif
endmethod
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
local timer t = NewTimer() //This will create a new timer, or reuse an old one
set .caster = GetTriggerUnit()
set .EffectX = GetSpellTargetX()
set .EffectY = GetSpellTargetY()
call SetTimerData(t,this) //Attach the struct's data to the timer
call TimerStart(t,0.10,false,function thistype.LA) //Start the timer
return this
endmethod
endstruct
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == RAWCODE then
call EffectSpell.create()
endif
return false
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))
endfunction
endscope
Now you have that, which is something like how you would do it. Although it isn't completely optimized, it should get the job done.
Good luck, hopefully this explains it a bit. =)
NewTimer() - This is a function of TimerUtils, which will check if there are any timers that were recycled to be available for use. If there isn't, then it will create a new timer.
SetTimerData(timer,data) - This is a function of TimerUtils, which will "attach" the struct instance to the timer. This way, you can retrieve the data in the callback using GetTimerData(t).
GetTimerData(timer) - This is a function of TimerUtils, which will retrieve the struct instance attached to the timer. Basically,
GetTimerData(GetExpiredTimer())
.
ReleaseTimer(timer) - This is a function of TimerUtils, which will recycle the timer for later use. If the timer stack is full, it will destroy the timer. (which doesn't happen very often as long as you code well)