private function FireBallAction takes nothing returns nothing local FireBallData fb local real xc local real yc local real xt local real yt local real x local real y if fb.maxdis < fb.dis then set xc = GetUnitX(fb.caster) set yc = GetUnitY(fb.caster) set xt = GetUnitX(fb.target) set yt = GetUnitY(fb.target) set x = xc + fb.speed * Cos(fb.angle) set y = yc + fb.speed * Sin(fb.angle) call SetUnitPosition(fb.dummy,x,y) else call RemoveUnit(fb.dummy) call UnitDamageTarget(fb.caster,fb.target,damage(fb.level),true,false,attackType,damageType,weaponType) call PauseTimer(TIMER) call DestroyTimer(TIMER) call fb.destroy() endif set fb.caster = null set fb.dummy = null set fb.target = null endfunction
private function cond takes nothing returns boolean local FireBallData fb local unit caster local unit target local real angle local real maxdis local real speed local real dis local real xc local real xt local real yc local real yt local real x local real y local integer level local unit dummy if GetSpellAbilityId() == SpellId then set caster = GetTriggerUnit() set target = GetSpellTargetUnit() set level = GetUnitAbilityLevel(caster, SpellId) set angle = Atan2(yc-yt,xc-xt)*bj_DEGTORAD set maxdis = SquareRoot((xc-xt) * (xc-xt) + (yc-yt) * (yc-yt)) set dis = 900. set speed = 25. set xc = GetUnitX(caster) set yc = GetUnitY(caster) set xt = GetUnitX(target) set yt = GetUnitY(target) set fb = FireBallData.create() set fb.angle = angle set fb.maxdis = maxdis set fb.speed = speed set fb.dis = dis set x = xc + speed * Cos(angle) set y = yc + speed * Sin(angle) set dummy = CreateUnit(GetOwningPlayer(caster), DummyId, x, y, angle) set fb.dummy = dummy set fb.caster = caster set fb.target = target set fb.level = level call TimerStart(TIMER, Interval, TRUE, function FireBallAction) endif set caster = null set target = null return FALSE endfunction
private function init takes nothing returns nothing local trigger t = CreateTrigger() local integer index = 0 loop call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null) set index = index + 1 exitwhen index == bj_MAX_PLAYER_SLOTS endloop call TriggerAddCondition(t, Condition(function cond)) set t = null endfunction
endscope
Что-то не запускает, не понял до конца, но всё-же, почему?
Во-первых, у тебя не задана переменная FireBallData в обработчике таймера. Нужно либо передавать значение через хэш, либо использовать поиск по структурам. Во-вторых, ты уничтожаешь единый глобальный таймер, чего делать не следует ни в коем случае. Хотя, возможно, имелось в виду, чтобы он был членом структуры, а не глобальным.
[/code]private function FireBallAction takes nothing returns nothing local FireBallData fb local real xc local real yc local real xt local real yt local real x local real y set fb=FB
Code
private function cond takes nothing returns boolean local FireBallData fb local unit caster local unit target local real angle local real maxdis local real speed local real dis local real xc local real xt local real yc local real yt local real x local real y local integer level local unit dummy if GetSpellAbilityId() == SpellId then set caster = GetTriggerUnit() set target = GetSpellTargetUnit() set level = GetUnitAbilityLevel(caster, SpellId) set angle = Atan2(yc-yt,xc-xt)*bj_DEGTORAD set maxdis = SquareRoot((xc-xt) * (xc-xt) + (yc-yt) * (yc-yt)) set dis = 900. set speed = 25. set xc = GetUnitX(caster) set yc = GetUnitY(caster) set xt = GetUnitX(target) set yt = GetUnitY(target) set fb = FireBallData.create() set fb.angle = angle set fb.maxdis = maxdis set fb.speed = speed set fb.dis = dis set x = xc + speed * Cos(angle) set y = yc + speed * Sin(angle) set dummy = CreateUnit(GetOwningPlayer(caster), DummyId, x, y, angle) set fb.dummy = dummy set fb.caster = caster set fb.target = target set fb.level = level set FB=fb call TimerStart(TIMER, Interval, TRUE, function FireBallAction) endif set caster = null set target = null return FALSE endfunction
2. Убрал дестрой, оставил паузу. Таймер всё-равно не тикает.
Добавлено (20 Августа 2012, 14:37:21) --------------------------------------------- Объясните почему не запускается таймер, а то что-то не очень понятно, и я хотел попробовать без хэша.
private constant function damage takes integer level returns real return 25. * level endfunction
private struct FireBallData unit caster unit dummy unit target real angle real maxdis real dis real time real speed integer level endstruct
globals private FireBallData FB endglobals
private function FireBallAction takes nothing returns nothing local timer t=GetExpiredTimer() BJDebugMsg("S-4") local FireBallData fb BJDebugMsg(msg) local real xc local real yc local real xt local real yt local real x local real y set fb=FB if fb.maxdis < fb.dis then BJDebugMsg("S-5") set xc = GetUnitX(fb.caster) set yc = GetUnitY(fb.caster) set xt = GetUnitX(fb.target) set yt = GetUnitY(fb.target) set x = xc + fb.speed * Cos(fb.angle) set y = yc + fb.speed * Sin(fb.angle) call SetUnitPosition(fb.dummy,x,y) else call RemoveUnit(fb.dummy) call UnitDamageTarget(fb.caster,fb.target,damage(fb.level),true,false,attackType,damageType,weaponType) call PauseTimer(t) call DestroyTimer(t) call fb.destroy() endif set fb.caster = null set fb.dummy = null set fb.target = null endfunction
private function cond takes nothing returns boolean BJDebugMsg("S-1") local FireBallData fb local timer t local unit caster local unit target local real angle local real maxdis local real speed local real dis local real xc local real xt local real yc local real yt local real x local real y local integer level local unit dummy if GetSpellAbilityId() == SpellId then BJDebugMsg("S-2") set t=CreateTimer() set caster = GetTriggerUnit() set target = GetSpellTargetUnit() set level = GetUnitAbilityLevel(caster, SpellId) set angle = Atan2(yc-yt,xc-xt)*bj_DEGTORAD set maxdis = SquareRoot((xc-xt) * (xc-xt) + (yc-yt) * (yc-yt)) set dis = 900. set speed = 25. set xc = GetUnitX(caster) set yc = GetUnitY(caster) set xt = GetUnitX(target) set yt = GetUnitY(target) set fb = FireBallData.create() set fb.angle = angle set fb.maxdis = maxdis set fb.speed = speed set fb.dis = dis set x = xc + speed * Cos(angle) set y = yc + speed * Sin(angle) set dummy = CreateUnit(GetOwningPlayer(caster), DummyId, x, y, angle) set fb.dummy = dummy set fb.caster = caster set fb.target = target set fb.level = level call TimerStart(t, Interval, TRUE, function FireBallAction) set FB=fb endif BJDebugMsg("S-3") set caster = null set target = null return FALSE endfunction
private function init takes nothing returns nothing local trigger t = CreateTrigger() local integer index = 0 loop call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null) set index = index + 1 exitwhen index == bj_MAX_PLAYER_SLOTS endloop call TriggerAddCondition(t, Condition(function cond)) set t = null endfunction
Добавлено (20 Августа 2012, 18:15:37) --------------------------------------------- tRu^S, Если ты создаешь локлку с таймером, то ты должен будешь потом ее обнулить.
Добавлено (20 Августа 2012, 18:18:07) ---------------------------------------------
Quote (tRu^S)
local timer t=GetExpiredTimer() BJDebugMsg("S-4") local FireBallData fb BJDebugMsg(msg) local real xc local real yc
А здесь у тебя ошибки нет? Помоему переменные всегда должны быть выше всех функций.
А здесь у тебя ошибки нет? Помоему переменные всегда должны быть выше всех функций.
нет всё норм. Я тут посмотрел на хайве пару спелов без this. Там так
Code
private struct DATA unit target real duration endstruct
globals private constant timer TIMER = CreateTimer() private DATA array ARRAY private integer TOTAL = 0 endglobals
private function action takes nothing returns nothing local DATA D local boolean DESTROY_DATA local integer i = 0 loop exitwhen i >= TOTAL set D = ARRAY[i] set D.duration = D.duration - FPS set DESTROY_DATA = D.duration <= 0 if DESTROY_DATA then call IssueImmediateOrder(D.target, "stop") call UnitRemoveAbility(D.target, ABILITY_INVISIBLE_ID) call UnitRemoveAbility(D.target, BUFF_ID) set ARRAY[i] = ARRAY[TOTAL - 1] set TOTAL = TOTAL - 1 call D.destroy() endif set i = i + 1 endloop if TOTAL == 0 then call PauseTimer(TIMER) endif endfunction
private function run takes nothing returns boolean local DATA D local unit caster local unit dummy local integer level if GetSpellAbilityId() == ABILITY_ID then set D = DATA.create() set caster = GetTriggerUnit() set level = GetUnitAbilityLevel(caster, ABILITY_ID) call UnitAddAbility(caster, ABILITY_INVISIBLE_ID) set D.target = caster set D.duration = DURATION(level) set dummy = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, GetUnitX(caster), GetUnitY(caster), 0) call UnitAddAbility(dummy, REDUCE_ABILITY_ID) call SetUnitAbilityLevel(dummy, REDUCE_ABILITY_ID, level) call IssueTargetOrder(dummy, REDUCE_ABILITY_ORDER, caster) call UnitApplyTimedLife(dummy, 'BTLF', 0.5) if TOTAL == 0 then call TimerStart(TIMER, FPS, true, function action) endif set TOTAL = TOTAL + 1 set ARRAY[TOTAL - 1] = D set caster = null set dummy = null endif return false endfunction
тоесть через array, но чота я разницы особой невижу между датами.
private constant function damage takes integer level returns real return 25. * level endfunction
private struct FireBallData unit caster unit dummy unit target real maxdis real time real speed integer level endstruct
globals private FireBallData ball private integer data endglobals
private function FireBallAction takes nothing returns nothing local timer t=GetExpiredTimer() local FireBallData fb fb=ball real xd = GetUnitX(fb.dummy) real yd = GetUnitY(fb.dummy) real xc = GetUnitX(fb.caster) real yc = GetUnitY(fb.caster) real xt = GetUnitX(fb.target) real yt = GetUnitY(fb.target) real angle = Atan2(yt - yc, xt - xc) real x = xd + fb.speed * Cos(angle) real y = yd + fb.speed * Sin(angle) real dis = SquareRoot((xc-xt) * (xc-xt) + (yc-yt) * (yc-yt)) if fb.maxdis > dis then call RemoveUnit(fb.dummy) call UnitDamageTarget(fb.caster,fb.target,damage(fb.level),true,false,attackType,damageType,weaponType) call PauseTimer(t) call DestroyTimer(t) fb.caster = null fb.target = null fb.dummy = null t = null call fb.destroy() else SetUnitPosition(fb.dummy,x,y) fb.maxdis=fb.maxdis+fb.speed endif endfunction
private function cond takes nothing returns boolean if GetSpellAbilityId() == SpellId then FireBallData fb timer t = CreateTimer() unit caster = GetTriggerUnit() unit dummy = CreateUnit(GetOwningPlayer(caster),DummyId,GetWidgetX(caster),GetWidgetY(caster),GetUnitFacing(caster)) unit target = GetSpellTargetUnit() real maxdis = 0. real speed = 30. integer level = GetUnitAbilityLevel(caster, SpellId) fb=FireBallData.create() fb.caster = caster fb.dummy = dummy fb.target = target fb.maxdis = maxdis fb.speed = speed fb.level = level ball=fb TimerStart(t, Interval, true, function FireBallAction) endif return FALSE endfunction
private function init takes nothing returns nothing local trigger t = CreateTrigger() local integer index = 0 loop call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null) set index = index + 1 exitwhen index == bj_MAX_PLAYER_SLOTS endloop call TriggerAddCondition(t, Condition(function cond)) set t = null endfunction
endscope
Всё работает, но теперь я не обнуляю castera,target,таймер и т.д, потому-что они в ифе, а если обнулять в ифе то код не работает. Это утечно? А если делать по 1-ому то код тоже не работает aka когда всё за ифом, а в нём установка локалок.
private function Timer takes nothing returns nothing local real a static /* */ if USE_HASH then local Data d = LoadInteger(Hash, GetHandleId(GetExpiredTimer()), 0) local real x = GetWidgetX(d.dummy) local real y = GetWidgetY(d.dummy) else local handle h = GetExpiredTimer() local Data d = 1 local real x local real y loop exitwhen h == d.t set d = d + 1 endloop set x = GetWidgetX(d.dummy) set y = GetWidgetY(d.dummy) endif if IsUnitInRange(d.dummy, d.target, EXPLOSION_RANGE) then call UnitDamageTarget(d.dummy, d.target, Damage(d.level), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE) call KillUnit(d.dummy) call PauseTimer(d.t) call DestroyTimer(d.t) static /* */ if USE_HASH then call FlushChildHashtable(Hash, GetHandleId(d.t), 0) endif call d.destroy() else set a = Atan2(GetWidgetY(d.target) - y, GetWidgetX(d.target) - x) call SetUnitX(d.dummy, x + Cos(a) * Speed(d.level) * PERIOD) call SetUnitY(d.dummy, y + Sin(a) * Speed(d.level) * PERIOD) call SetUnitFacing(d.dummy, a * 57.296) endif static /* */ if not USE_HASH then set h = null endif endfunction
private function Actions takes nothing returns nothing local unit u = GetTriggerUnit() local real x = GetWidgetX(u) local real y = GetWidgetY(u) local Data d = Data.create() set d.t = CreateTimer() set d.target = GetSpellTargetUnit() set d.dummy = CreateUnit(GetOwningPlayer(u), DUMMY, x, y, Atan2(GetWidgetY(d.target) - y, GetWidgetX(d.target) - x)) set d.level = GetUnitAbilityLevel(u, ABILITY) static /* */ if USE_HASH then call SaveInteger(Hash, GetHandleId(d.t), 0, d) endif call TimerStart(d.t, PERIOD, true, function Timer) set u = null endfunction
private function Init takes nothing returns nothing local trigger trig = CreateTrigger() local integer i = 0 loop call TriggerRegisterPlayerUnitEvent(trig, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null) exitwhen i == 11 set i = i + 1 endloop call TriggerAddCondition(trig, Condition(function Conditions)) call TriggerAddAction(trig, function Actions) set trig = null endfunction endscope
Добавлено (21 Августа 2012, 11:31:17) --------------------------------------------- Вот. С хэшем и без.