Решил перенести способность Исазама тёмная стая на Wurst, чтобы продемонстрировать насколько проще и короче можно сделать. Скорее всего, можно было упростить ещё больше, но даже в таком варианте разница в 82 строки достаточно внушительна.
Оригинальный код
function CarroinSwarm_Move takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
local real time = LoadReal(H, id, 'time') - 0.02
local integer stop = LoadInteger(H, id, 'stop')
local unit caster = LoadUnitHandle(H, id, 'cast')
local unit casw = LoadUnitHandle(H, id, 'CaSw')
local real x0 = GetUnitX(casw)
local real y0 = GetUnitY(casw)
local real x1 = LoadReal(H, id, 'EndX')
local real y1 = LoadReal(H, id, 'EndY')
local real d = SquareRoot( (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) )
local real a = bj_RADTODEG * Atan2(y1 - y0, x1 - x0)
local group g = CreateGroup()
local unit target
local item test
if GetUnitCurrentOrder(caster) != OrderId("AImove") and time > 0.0 then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H, id)
call RemoveUnit(casw)
endif
call SaveReal(H, id, 'time', time)
if time == 0.0 then
call ShowUnit(casw, true)
call ShowUnit(caster, false)
call PauseUnit(caster, true)
call UnitRemoveAbility(casw, 'Aloc')
call UnitAddAbility(casw, 'Aloc')
endif
if time < 0.0 then
if d < 11.0 then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H, id)
call RemoveUnit(casw)
call ShowUnit(caster, true)
call PauseUnit(caster, false)
call SetUnitPosition(caster, x0, y0)
call SelectUnit(caster, true)
set IsazamHorror = IsazamHorror + 5
call AddHorrorEffect()
else
if stop == 0 then
call SetUnitX(casw, x0 + 10.0 * Cos(bj_DEGTORAD * a))
call SetUnitY(casw, y0 + 10.0 * Sin(bj_DEGTORAD * a))
call SetUnitFacing(casw, a)
else
set test = CreateItem('spsh', x0 + 10.0 * Cos(bj_DEGTORAD * a), y0 + 10.0 * Sin(bj_DEGTORAD * a))
call SetItemPosition(test, x0 + 10.0 * Cos(bj_DEGTORAD * a), y0 + 10.0 * Sin(bj_DEGTORAD * a))
if GetItemX(test) == x0 + 10.0 * Cos(bj_DEGTORAD * a) and GetItemY(test) == y0 + 10.0 * Sin(bj_DEGTORAD * a) then
call SetUnitX(casw, x0 + 10.0 * Cos(bj_DEGTORAD * a))
call SetUnitY(casw, y0 + 10.0 * Sin(bj_DEGTORAD * a))
call SetUnitFacing(casw, a)
else
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(H, id)
call RemoveUnit(casw)
call ShowUnit(caster, true)
call PauseUnit(caster, false)
call SetUnitPosition(caster, x0, y0)
call SelectUnit(caster, true)
set IsazamHorror = IsazamHorror + 5
call AddHorrorEffect()
endif
call RemoveItem(test)
endif
endif
endif
call SaveUnitHandle(H, 'Unit', 'Unit', caster)
call GroupEnumUnitsInRange(g, x0, y0, 100.0, function Enemy)
loop
set target = FirstOfGroup(g)
exitwhen target == null
call UnitDamageTarget(caster, target, 5.0 * GetUnitAbilityLevel(caster, 'A00B'), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
call GroupRemoveUnit(g, target)
endloop
call GroupClear(g)
call DestroyGroup(g)
set t = null
set caster = null
set casw = null
set g = null
set target = null
set test = null
endfunction
function Trig_CarroinSwarm_Actions takes nothing returns nothing
local unit Caster = GetTriggerUnit()
local real x0 = GetUnitX(Caster)
local real y0 = GetUnitY(Caster)
local real x1 = GetSpellTargetX()
local real y1 = GetSpellTargetY()
local item test = CreateItem('spsh', x1, y1)
local unit CaSw = CreateUnit(GetOwningPlayer(Caster), 'u007', x0, y0, GetUnitFacing(Caster))
local timer t = CreateTimer()
local integer id = GetHandleId(t)
call SetItemPosition(test, x1, y1)
if GetItemX(test) == x1 and GetItemY(test) == y1 then
call SaveInteger(H, id, 'stop', 0)
else
call SaveInteger(H, id, 'stop', 1)
endif
if IsTerrainPathable(x1, y1, PATHING_TYPE_WALKABILITY) == true then
call SaveInteger(H, id, 'stop', 1)
endif
call ShowUnit(CaSw, false)
call TimerStart(t, 0.02, true, function CarroinSwarm_Move)
call SaveReal(H, id, 'time', 1.0)
call SaveUnitHandle(H, id, 'cast', Caster)
call SaveUnitHandle(H, id, 'CaSw', CaSw)
call SaveReal(H, id, 'EndX', x1)
call SaveReal(H, id, 'EndY', y1)
call RemoveItem(test)
set IsazamHorror = IsazamHorror + 5
set Caster = null
set test = null
set CaSw = null
set t = null
endfunction
function Trig_CarroinSwarm_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A00B'
endfunction
//===========================================================================
function InitTrig_CarroinSwarm takes nothing returns nothing
set gg_trg_CarroinSwarm = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_CarroinSwarm, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_CarroinSwarm, Condition( function Trig_CarroinSwarm_Conditions ) )
call TriggerAddAction( gg_trg_CarroinSwarm, function Trig_CarroinSwarm_Actions )
endfunction
Код на Wurst Script
init
registerPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT) ->
let caster = GetTriggerUnit()
if caster.getTypeId() == ISAZAM_ID and GetSpellAbilityId() == CARRION_SWARM_ID
let x1 = GetSpellTargetX()
let y1 = GetSpellTargetY()
let t0 = CreateItem('spsh', x1, y1)
let _cs_ = createUnit(caster.getOwner(), CARRION_SWARM_DUMMY_ID, caster.getPos(), caster.getFacingAngle())
bool _stop_
real _time_ = 1.
t0.setPos( vec2(x1, y1) )
if t0.getX() == x1 and t0.getY() == y1
_stop_ = false
else
_stop_ = true
t0.remove()
if IsTerrainPathable(x1, y1, PATHING_TYPE_WALKABILITY) == true
_stop_ = true
_cs_.hide()
doPeriodically(0.02) cb ->
_time_ -= .02
if caster.getCurrentOrder() != OrderId("AImove")
destroy cb
_cs_.remove()
if _time_ == 0
_cs_.show()
caster.hide()
caster.pause()
_cs_.removeAbility('Aloc')
_cs_.addAbility('Aloc')
if _time_ < 0.
let x0 = _cs_.getX()
let y0 = _cs_.getY()
let d = SquareRoot( (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) )
let a = bj_RADTODEG * Atan2(y1 - y0, x1 - x0)
if d < 11.
destroy cb
_cs_.remove()
caster.unpause()
caster.show()
caster.setPos(_cs_.getPos())
SelectUnit(caster, true)
else
if _stop_ == false
_cs_.setPos( vec2( x0 + 10.0 * Cos(bj_DEGTORAD * a), y0 + 10.0 * Sin(bj_DEGTORAD * a) ) )
SetUnitFacing(_cs_, a)
else
let t1 = CreateItem('spsh', x0 + 10.0 * Cos(bj_DEGTORAD * a), y0 + 10.0 * Sin(bj_DEGTORAD * a))
t1.setPos( vec2( x0 + 10.0 * Cos(bj_DEGTORAD * a), y0 + 10.0 * Sin(bj_DEGTORAD * a) ) )
if t1.getX() == x0 + 10.0 * Cos(bj_DEGTORAD * a) and t1.getY() == y0 + 10.0 * Sin(bj_DEGTORAD * a)
_cs_.setPos( vec2( x0 + 10.0 * Cos(bj_DEGTORAD * a), y0 + 10.0 * Sin(bj_DEGTORAD * a) ) )
SetUnitFacing(_cs_, a)
else
destroy cb
_cs_.remove()
caster.unpause()
caster.show()
caster.setPos(_cs_.getPos())
SelectUnit(caster, true)
t1.remove()
let g = CreateGroup()
g.enumUnitsInRange(_cs_.getPos(), 100.)
for u from g
if u.isEnemyNew(_cs_.getOwner())
caster.damageTarget(u, 5. * caster.getAbilityLevel(CARRION_SWARM_ID), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
g.clear()
g.destr()
П.С. думаю это видно и так, но замечу, что код на Wurst пишется сверху вниз, в отличии от Jass
П.П.С. забыл сказать, что на Wurst нет "закрытия" функций, что если и прочего, вместо этого используется табуляция
П.П.С. забыл сказать, что на Wurst нет "закрытия" функций, что если и прочего, вместо этого используется табуляция