Мои первые MUI способности на Jass. Критика приветствуется.
Список изменений:
1.4.1
Исправлены значения из глобального обновления.
Немного переработаны способности.
Убран талант.
Бар каста над Келем теперь локальный.
У "Феникса" приоритетной целью стали герои, даже если они "беззащитные".
Исправлено описание баффа "Зеленеющие сферы".
Дамми живут 0.10 сек. вместо 1.00.
Добавлено измерение урона для теста.
Немного переработаны способности.
Убран талант.
Бар каста над Келем теперь локальный.
У "Феникса" приоритетной целью стали герои, даже если они "беззащитные".
Исправлено описание баффа "Зеленеющие сферы".
Дамми живут 0.10 сек. вместо 1.00.
Добавлено измерение урона для теста.
1.4
Глобальное обновление: добавлены официальные характеристики урона, здоровья, скорости восстановления и т.д. Теперь требуется версия Warcraft 1.29+
Изменено описание.
Исправлена и оптимизирована "Живая бомба".
Добавлен недостающий скрипт для "Феникса".
Изменено описание.
Исправлена и оптимизирована "Живая бомба".
Добавлен недостающий скрипт для "Феникса".
1.3
Добавлены недостающие скрипты для "Живой бомбы" и "Феникса":
"Живая бомба" теперь летит в качестве снаряда до цели, после закрепляется.
"Феникс" теперь летит от Келя в указанную точку и после этого встает в боевую позицию (отсчет времени "Феникса" начинается, когда он долетит до указанной точки).
Изменено действие "Живой бомбы".
"Огненному столбу" возвращена 1 секунда срабатывания.
Ускорение движения "Искажения гравитации" (но уменьшен радиус) и "Огненной глыбы".
Снаряды теперь летят от героя до указанной точки (ранее от героя + некоторое расстояние).
Небольшое увеличение модельки "Феникса".
Добавлены иконки из HotS.
"Живая бомба" теперь летит в качестве снаряда до цели, после закрепляется.
"Феникс" теперь летит от Келя в указанную точку и после этого встает в боевую позицию (отсчет времени "Феникса" начинается, когда он долетит до указанной точки).
Изменено действие "Живой бомбы".
"Огненному столбу" возвращена 1 секунда срабатывания.
Ускорение движения "Искажения гравитации" (но уменьшен радиус) и "Огненной глыбы".
Снаряды теперь летят от героя до указанной точки (ранее от героя + некоторое расстояние).
Небольшое увеличение модельки "Феникса".
Добавлены иконки из HotS.
1.2.8
Мелкие правки (плавность анимаций, эффекты).
1.2.7
Живая бомба теперь взрывается при смерти цели с эффектом "Живой бомбы" с задержкой 100мс.
Уменьшен радиус "Живой бомбы".
Правки в области "Огненного столба".
"Огненный столб" больше не накладывает вторую бомбу, если таковой эффект уже есть.
Исправлено применение "Огненной глыбы".
Добавлено видео последней версии наработки героя.
Уменьшен радиус "Живой бомбы".
Правки в области "Огненного столба".
"Огненный столб" больше не накладывает вторую бомбу, если таковой эффект уже есть.
Исправлено применение "Огненной глыбы".
Добавлено видео последней версии наработки героя.
1.2.6
Искажение гравитации теперь оглушает, а не вводит в паузу.
Исправлена визуальная часть Искажения гравитации.
Визуальное улучшение анимаций и способностей.
Правка дистанции/области всех способностей.
Добавлено превью.
Исправлена визуальная часть Искажения гравитации.
Визуальное улучшение анимаций и способностей.
Правка дистанции/области всех способностей.
Добавлено превью.
1.2.5
Оптимизирована "Живая бомба".
Удалены лишние скрипты после оптимизации. При копировании "Огненного столба" теперь необходим триггер со способностью "Живая бомба".
Применение способностей теперь мгновенное.
Удалены лишние скрипты после оптимизации. При копировании "Огненного столба" теперь необходим триггер со способностью "Живая бомба".
Применение способностей теперь мгновенное.
1.2.1
Небольшие правки в перезарядке "Зеленеющих сфер".
Добавлено видео для ознакомления.
Добавлено видео для ознакомления.
1.2
Удалены/заменены некоторые скрипты.
Исправлено наложение "Живой бомбы", если эффект "Живой бомбы" уже присутствовал на цели.
Способность "Зеленеющие сферы" (Канал) заменена на способность "Берсерк", дабы не отменять текущий приказ кастера. Добавлена способность-пустышка для триггерного кулдауна.
Добавлены скрипты для кулдауна способности "Зеленеющие сферы" после применения способностей, которые улучшаются "Зеленеющими сферами".
Снижено время жизни дамми до 1 сек.
Исправлено наложение "Живой бомбы", если эффект "Живой бомбы" уже присутствовал на цели.
Способность "Зеленеющие сферы" (Канал) заменена на способность "Берсерк", дабы не отменять текущий приказ кастера. Добавлена способность-пустышка для триггерного кулдауна.
Добавлены скрипты для кулдауна способности "Зеленеющие сферы" после применения способностей, которые улучшаются "Зеленеющими сферами".
Снижено время жизни дамми до 1 сек.
1.1
Исправлено действие бомбы после первого взрыва.
Добавлена модель, показывающая состояние каста Огненной глыбы.
Добавлена модель, показывающая состояние каста Огненной глыбы.
1.0
Первая версия.
Инструкция по импорту:
- в константах убрать прибавку от характеристик героя, кроме маны (+1 за уровень).
- скопировать импортируемую модель, иконки, баффы, способности, юнитов.
- скопировать код и в нем изменить код юнитов и применяемых способностей. (например: 'A000' на тот, что в РО (редакторе объектов). Название и код переменных можно посмотреть с помощью сочетания клавиш Ctrl + D.
- создавать/нанимать героя, чтобы задействовать инициализацию (можно сделать свою, но я привел оптимальный вариант).
ВНИМАНИЕ! ПРЕДУПРЕЖДЕНИЕ! Версия Warcraft должна быть не ниже 1.29 (возможно, работает и на 1.28)!
Описание:
- Огненный столб: "После 1 сек. наносит 345 (+4% за уровень) ед. урона по области.
Под воздействием «Зеленеющих сфер» радиус действия способности увеличивается на 50%."
- Живая бомба: "Наносит противнику 126 (+4% за уровень) ед. урона в течение 3-х секунд, а затем взрывается, нанося еще 215 (+4% за уровень) ед. урона противникам поблизости. Взрыв «Живой бомбы» накладывает эффект этой способности на всех еще не пораженных ею ближайших героев противника.
Под воздействием "Зеленеющих Сфер" способность не требует затрат маны и не имеет времени восстановления."
- Искажение гравитации: "Оглушает первого пораженного противника на 1 сек.
Под воздействием «Зеленеющих Сфер» оглушает до 3-х противников и продлевает время оглушения на 50%."
- Зеленеющие сферы: "Улучшает первые три способности Кель'таса."
- Феникс (1 ульт): "Выпускает в выбранную область феникса, наносящего 78 (+4% за уровень) ед. урона всеми противникам на пути. Феникс продолжает существовать в течение 7 сек., нанося противникам 78 (+4% за уровень) ед. урона автоатаками и 50% от этого значения в качестве урона по области."
- Огненная глыба (2 ульт): "Спустя 1.5 сек. выпускает во вражеского героя медленно летящий огненный шар, наносящий 810 (+5% за уровень) ед. урона цели и 405 (+5% за уровень) ед. урона ближайшим противникам."
Код
Код способностей и систем характеристик
Огненный столб
function SpellFCCond takes nothing returns boolean
return GetSpellAbilityId()=='A002'
endfunction
function TickFC takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit enemy
local unit caster = LoadUnitHandle(Hash,h,2)
local effect e = LoadEffectHandle(Hash,h,4)
local real xRect = LoadReal(Hash,h,5)
local real yRect = LoadReal(Hash,h,7)
local boolean Gain = LoadBoolean(Hash,h,6)
local real Frect = 150.00
local group G = CreateGroup()
local player PlayerEnemy
local player PlayerCaster = GetOwningPlayer(caster)
local integer data = GetUnitUserData(caster)
local real damage = DamageFlamestrike[0][data]
call DestroyEffect(e)
if Gain == true then
Frect = 225.00
endif
call GroupEnumUnitsInRange(G, xRect, yRect, Frect, null)
loop
set enemy = FirstOfGroup(G)
set PlayerEnemy = GetOwningPlayer(enemy)
if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 then
call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
endif
call GroupRemoveUnit(G,enemy)
exitwhen enemy == null
endloop
call GroupClear(G)
call DestroyGroup(G)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer (t)
set caster = null
set e = null
set G = null
set t = null
endfunction
function SpellFC takes nothing returns nothing
local timer t = CreateTimer()
local integer h = GetHandleId(t)
local unit caster = GetTriggerUnit()
local real locX = GetSpellTargetX()
local real locY = GetSpellTargetY()
local string str = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrike1.mdl"
local effect e = AddSpecialEffect(str,locX,locY)
local boolean Gain = false
if GetUnitAbilityLevel(caster, 'A002') == 2 then
call ExecuteFunc("OrbsCooldown")
set Gain = true
call UnitRemoveAbility(caster, 'Asph' )
call UnitRemoveAbility(caster, 'B001')
call SetUnitAbilityLevel( caster, 'A000', 1 )
call SetUnitAbilityLevel( caster, 'A002', 1 )
call SetUnitAbilityLevel( caster, 'A003', 1 )
endif
call SaveUnitHandle(Hash,h,2,caster)
call SaveEffectHandle(Hash,h,4,e)
call SaveReal(Hash,h,5,locX)
call SaveReal(Hash,h,7,locY)
call SaveBoolean(Hash,h,6,Gain)
TimerStart (t,1, false, function TickFC)
set caster = null
set e = null
set t = null
endfunction
Живая бомба
function SpellBombCond takes nothing returns boolean
return GetSpellAbilityId()=='A000'
endfunction
function TickBombEnd takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit caster = LoadUnitHandle(Hash,h,2)
local integer i = LoadInteger(Hash,h,3)
local unit enemy
local player PlayerEnemy
local player PlayerCaster = GetOwningPlayer(caster)
local real array x
local real array y
local unit array target
local string spell = "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnBirthMissile.mdl"
local string attach = "chest"
local integer data = GetUnitUserData(caster)
local real damage = DamageLifeBombRect[0][data]
local real damageLow = DamageLifeBomb[0][data]
local real Frect = 200.00
local integer nMax = LoadInteger(Hash,h,4)
local integer n = 0
local group G = CreateGroup()
local integer numbGroup = 0
local real timeR = LoadReal(Hash,h,5)
set timeR = timeR + 0.01
call SaveReal(Hash,h,5,timeR)
loop
set n = n + 1
set target[n] = LoadUnitHandle(Hash,h,n+10)
if target[n] != null then
set numbGroup = numbGroup + 1
set x[n] = GetUnitX(target[n])
set y[n] = GetUnitY(target[n])
endif
exitwhen n == nMax
endloop
set n = 0
loop
set n = n + 1
if i == 6 and timeR == 3 or GetWidgetLife( target[n] ) <=.405 then
call GroupEnumUnitsInRange(G, x[n], y[n], Frect, null)
loop
set enemy = FirstOfGroup(G)
set PlayerEnemy = GetOwningPlayer(enemy)
if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 then
call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
call DestroyEffect(AddSpecialEffectTarget(spell, enemy, attach))
endif
call GroupRemoveUnit(G,enemy)
exitwhen enemy == null
endloop
if n == nMax or numbGroup == 0 then
call GroupClear(G)
call DestroyGroup(G)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer (t)
endif
else
if timeR == 1 or timeR == 2 then
call UnitDamageTarget( caster, target[n], damageLow, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
endif
endif
exitwhen n == nMax
endloop
call GroupClear(G)
call DestroyGroup(G)
if timeR == 1 or timeR == 2 then
set i = i + 1
call SaveInteger(Hash,h,3,i)
endif
set n = 0
loop
set n = n + 1
set target[n] = null
exitwhen n == nMax
endloop
set t = null
set caster = null
set G = null
endfunction
function TickBomb takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit target = LoadUnitHandle(Hash,h,1)
local unit caster = LoadUnitHandle(Hash,h,2)
local integer i = LoadInteger(Hash,h,3)
local integer n = 1
local integer data = GetUnitUserData(caster)
local real damage = DamageLifeBombRect[0][data]
local real damageLow = DamageLifeBomb[0][data]
local real timeR = LoadReal(Hash,h,6)
set timeR = timeR + 0.01
call SaveReal(Hash,h,6,timeR)
if (i == 3 and timeR == 3) or (GetWidgetLife( target ) <=.405) then
local group G = CreateGroup()
local unit enemy
local string eff1 = "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnBirthMissile.mdl"
local string attach = "chest"
local string spell = "unholyfrenzy"
local real x = GetUnitX(target)
local real y = GetUnitY(target)
local player PlayerEnemy
local player PlayerCaster = GetOwningPlayer(caster)
local unit array arrayEnemy
local real Frect = 200.00
local timer k = CreateTimer()
local integer g = GetHandleId(k)
local integer nMax = 0
call DestroyEffect(AddSpecialEffectTarget(eff1, target, attach))
set n = 0
set i = i + 1
call GroupEnumUnitsInRange(G, x, y, Frect, null)
call UnitDamageTarget( caster, target, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
loop
set enemy = FirstOfGroup(G)
set PlayerEnemy = GetOwningPlayer(enemy)
if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and enemy != target and GetWidgetLife( enemy ) >.405 then
call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
if GetWidgetLife( enemy ) >.405 and IsUnitType(enemy, UNIT_TYPE_HERO) == true then
local real face = GetUnitFacing(enemy) * -1.00
local real life = 0.1
local real x1 = GetUnitX(enemy)
local real y1 = GetUnitY(enemy)
local unit unitDummy = CreateUnit( PlayerCaster, 'h003', x1, y1, face )
set n = n + 1
set arrayEnemy[n] = enemy
call UnitApplyTimedLife(unitDummy, 'BTFL', life )
call IssueTargetOrder(unitDummy, spell, enemy )
call SaveUnitHandle(Hash,g,n+10,arrayEnemy[n])
call SaveUnitHandle(Hash,g,2,caster)
call SaveInteger(Hash,g,3,i)
call SaveInteger(Hash,g,4,n)
set unitDummy = null
endif
endif
call GroupRemoveUnit(G,enemy)
exitwhen enemy == null
endloop
if n > 0 then
TimerStart (k,0.01, true, function TickBombEnd)
else
call FlushChildHashtable(Hash,g)
call DestroyTimer(k)
endif
call GroupClear(G)
call DestroyGroup(G)
set nMax = n
set n = 0
loop
set n = n + 1
set arrayEnemy[n] = null
exitwhen n == nMax or nMax <= 0
endloop
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
set G = null
set k = null
else
if timeR == 1 or timeR == 2 then
call UnitDamageTarget( caster, target, damageLow, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
set i = i + 1
call SaveInteger(Hash,h,3,i)
endif
endif
set target = null
set caster = null
set t = null
endfunction
function SpellBomb_Move takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit target = LoadUnitHandle(Hash,h,1)
local unit caster = LoadUnitHandle(Hash,h,2)
local integer i = 1
local unit bomb = LoadUnitHandle(Hash,h,4)
local real X1 = GetUnitX(bomb)
local real X2 = GetUnitX(target)
local real Y1 = GetUnitY(bomb)
local real Y2 = GetUnitY(target)
local real angle = Atan2(Y2 - Y1, X2 - X1)
local real dist = SquareRoot((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1))
call SetUnitX(bomb, X1 + 20 * Cos(angle))
call SetUnitY(bomb, Y1 + 20 * Sin(angle))
if dist <= 10.00 then
if GetUnitAbilityLevel(target, 'B000') <= 0 then
local player PlayerCaster = GetOwningPlayer(caster)
local unit dummy = CreateUnit( PlayerCaster, 'h003', X2, Y2, angle )
local integer data = GetUnitUserData(caster)
local real damage = DamageLifeBomb[0][data]
local timer r = CreateTimer()
local integer g = GetHandleId(r)
local real life = 0.1
local string spell = "unholyfrenzy"
call UnitApplyTimedLife(dummy, 'BTLF', life )
call IssueTargetOrder( dummy, spell, target )
call UnitDamageTarget( caster, target, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
call SaveUnitHandle(Hash,g,1,target)
call SaveUnitHandle(Hash,g,2,caster)
call SaveInteger(Hash,g,3,i)
TimerStart (r,0.01, true, function TickBomb)
set r = null
set dummy = null
endif
call KillUnit(bomb)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
endif
set t = null
set target = null
set caster = null
set bomb = null
endfunction
function SpellBomb takes nothing returns nothing
local timer t = CreateTimer()
local integer h = GetHandleId(t)
local unit caster = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real face = GetUnitFacing(caster)
local real life = 0.1
local player PlayerCaster = GetOwningPlayer(caster)
local unit bomb = CreateUnit( PlayerCaster, 'h006', x, y, face )
if GetUnitAbilityLevel(target, 'B000') <= 0 then
if GetUnitAbilityLevel(caster, 'A000') == 2 then
call IssueImmediateOrder(caster, "stop")
call SetUnitAnimation(caster, "Spell")
QueueUnitAnimation(caster, "Stand")
call ExecuteFunc("OrbsCooldown")
call UnitRemoveAbility (caster, 'A000')
call UnitAddAbility (caster, 'A000')
call UnitRemoveAbility(caster, 'Asph' )
call UnitRemoveAbility(caster, 'B001')
call SetUnitAbilityLevel( caster, 'A002', 1 )
call SetUnitAbilityLevel( caster, 'A003', 1 )
endif
call SaveUnitHandle(Hash,h,1,target)
call SaveUnitHandle(Hash,h,2,caster)
call SaveUnitHandle(Hash,h,4,bomb)
TimerStart (t,0.01, true, function SpellBomb_Move)
else
if GetUnitAbilityLevel(caster, 'A000') == 2 then
call IssueImmediateOrder(caster, "stop")
call UnitRemoveAbility (caster, 'A000')
call UnitAddAbility (caster, 'A000')
call SetUnitAbilityLevel( caster, 'A000', 2 )
else
call IssueImmediateOrder(caster, "stop")
call UnitRemoveAbility (caster, 'A000')
call UnitAddAbility (caster, 'A000')
endif
endif
set t = null
set target = null
set caster = null
set bomb = null
endfunction
Искажение гравитации
function Gravity_Cond takes nothing returns boolean
return GetSpellAbilityId()=='A003'
endfunction
function Gravity_Act takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit target = LoadUnitHandle(Hash,h,1)
call UnitRemoveAbility( target, 'Arav' )
call UnitRemoveAbility( target, 'Abun' )
call FlushChildHashtable(Hash,h)
call DestroyTimer(t)
set t = null
set target = null
endfunction
function Gravity_Fly_Off takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit targetGravity = LoadUnitHandle(Hash,h,5)
call SetUnitFlyHeight( targetGravity, GetUnitDefaultFlyHeight(targetGravity) - 175, 800 )
call PauseTimer(t)
call DestroyTimer(t)
set targetGravity = null
set t = null
endfunction
function Gravity_Move takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit gravity = LoadUnitHandle(Hash,h,1)
local unit caster = LoadUnitHandle(Hash,h,10)
local real face = GetUnitFacing(gravity)
local real path = LoadReal(Hash,h, 17)
local group G = CreateGroup()
local unit enemy
local boolean Gain = LoadBoolean(Hash,h,15)
local real time
local player PlayerEnemy
local player PlayerCaster = GetOwningPlayer(caster)
local real distance = 450.00
local real x = GetUnitX(gravity) + 5 * Cos(face* bj_DEGTORAD)
local real y = GetUnitY(gravity) + 5 * Sin(face* bj_DEGTORAD)
local real obl = 60.00
local integer i = LoadInteger(Hash,h,3)
call SetUnitX(gravity, x)
call SetUnitY(gravity, y)
set path = path + 5
call SaveReal(Hash,h,17,path)
call GroupEnumUnitsInRange(G, x, y, obl, null)
loop
set enemy = FirstOfGroup(G)
set PlayerEnemy = GetOwningPlayer(enemy)
if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetUnitAbilityLevel(enemy,'B002') <= 0 and GetUnitAbilityLevel(enemy,'Abun') <= 0 and GetWidgetLife( enemy ) >.405 then
if i < 3 then
local timer k = CreateTimer()
local timer jump = CreateTimer()
local integer g = GetHandleId(k)
local integer v = GetHandleId(jump)
local real m = 0.05
local real x1 = GetUnitX(enemy)
local real y1 = GetUnitY(enemy)
local unit dummy = CreateUnit(PlayerCaster,'h003', x1, y1, face)
local unit e = CreateUnit( PlayerCaster, 'h002', x1, y1, face )
if Gain == true then
set time = 1.5
set i = i + 1
call SetUnitAbilityLevel(dummy,'A009',2)
else
set time = 1.0
set i = 3
endif
call UnitAddAbility(enemy,'Abun')
call UnitApplyTimedLife(e, 'BTFL', time - time*0.50)
call IssueTargetOrder(dummy,"thunderbolt",enemy)
call UnitApplyTimedLife(dummy,'BTFL', 0.1)
call SetUnitFlyHeight( enemy, GetUnitDefaultFlyHeight(enemy) + 175, 800 )
call UnitAddAbility( enemy, 'Arav' )
call SaveUnitHandle(Hash,g,1,enemy)
call SaveUnitHandle(Hash,v,5,enemy)
call SaveInteger(Hash,h,3,i)
call SaveReal(Hash,v,6,m)
call SaveReal(Hash,v,7,time)
call SaveBoolean(Hash,v,8,Gain)
TimerStart(k,time,false,function Gravity_Act)
TimerStart(jump,time - time*0.025,false,function Gravity_Fly_Off)
set e = null
set jump = null
set k = null
set dummy = null
endif
endif
call GroupRemoveUnit(G,enemy)
exitwhen enemy == null
endloop
if path >= distance or i == 3 then
call RemoveUnit(gravity)
call GroupClear(G)
call DestroyGroup(G)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
endif
call GroupClear(G)
call DestroyGroup(G)
set t = null
set gravity = null
set caster = null
set G = null
endfunction
function Gravity takes nothing returns nothing
local timer t = CreateTimer()
local integer h = GetHandleId(t)
local unit caster = GetTriggerUnit()
local player PlayerCaster = GetOwningPlayer(caster)
local real X1 = GetSpellTargetX()
local real X2 = GetUnitX(caster)
local real Y1 = GetSpellTargetY()
local real Y2 = GetUnitY(caster)
local real angle = Atan2(Y1 - Y2, X1 - X2)
local boolean Gain = false
local real x = X2 + 1 * Cos(angle)
local real y = Y2 + 1 * Sin(angle)
local unit gravity = CreateUnit( PlayerCaster, 'h002', x, y, angle*bj_RADTODEG )
call SetUnitX(gravity, x)
call SetUnitY(gravity, y)
if GetUnitAbilityLevel(caster, 'A003') == 2 then
call ExecuteFunc("OrbsCooldown")
set Gain = true
call UnitRemoveAbility(caster, 'Asph' )
call UnitRemoveAbility(caster, 'B001')
call SetUnitAbilityLevel(caster, 'A000', 1 )
call SetUnitAbilityLevel(caster, 'A002', 1 )
call SetUnitAbilityLevel(caster, 'A003', 1 )
endif
call SaveUnitHandle(Hash,h,1,gravity)
call SaveUnitHandle(Hash,h,10,caster)
call SaveBoolean(Hash,h,15,Gain)
call TimerStart(t,.01,true,function Gravity_Move)
set t = null
set gravity = null
set caster = null
endfunction
Зеленеющие сферы
Перезарядка
function OrbsCooldownTime takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit caster = LoadUnitHandle(Hash,h,1)
local integer i = LoadInteger(Hash,h,2)
set i = i + 1
if i == 6 and GetWidgetLife( caster ) >.405 then
call UnitAddAbility (caster, 'A00A')
call UnitRemoveAbility (caster, 'A006')
call FlushChildHashtable(Hash,h)
call DestroyTimer(t)
else
if i >= 6 then
set i = 5
endif
call SaveInteger(Hash,h,2,i)
endif
set t = null
set caster = null
endfunction
function OrbsCooldown takes nothing returns nothing
local timer t = GetExpiredTimer()
local timer y = CreateTimer()
local integer h = GetHandleId(t)
local integer i = GetHandleId(y)
local unit caster = GetTriggerUnit()
call SaveUnitHandle(Hash,i,1,caster)
call TimerStart(y,1,true,function OrbsCooldownTime)
call DestroyTimer(t)
set t = null
set caster = null
endfunction
Код
function Trig_Orbs_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A00A'
endfunction
function Trig_Orbs_Actions takes nothing returns nothing
local unit caster = GetTriggerUnit()
call UnitAddAbility(caster, 'Asph' )
call SetUnitAbilityLevel( caster, 'A000', 2 )
call SetUnitAbilityLevel( caster, 'A002', 2 )
call SetUnitAbilityLevel( caster, 'A003', 2 )
call UnitRemoveAbility (caster, 'A00A')
call UnitAddAbility (caster, 'A006')
set caster = null
endfunction
Феникс
function Trig_Phoenix_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A004'
endfunction
function Phoenix_Orders takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit phoenix = LoadUnitHandle(Hash,h,1)
local unit enemyOrder = LoadUnitHandle(Hash,h,2)
local real X1 = GetUnitX(phoenix)
local real Y1 = GetUnitY(phoenix)
local player PlayerEnemy
local player PlayerCaster = GetOwningPlayer(phoenix)
local group G = CreateGroup()
local boolean order = false
local unit enemy
if phoenix != null and GetWidgetLife(phoenix) >.405 then
if enemyOrder == null or GetWidgetLife(enemyOrder) <=.405 then
set enemyOrder = null
call GroupEnumUnitsInRange(G, X1, Y1, 400, null)
loop
set enemy = FirstOfGroup(G)
set PlayerEnemy = GetOwningPlayer(enemy)
if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 and IsUnitType(enemy, UNIT_TYPE_HERO) == true then
set order = true
call IssueTargetOrder(phoenix, "attack", enemy)
set enemyOrder = enemy
call SaveUnitHandle(Hash,h,2,enemyOrder)
endif
call GroupRemoveUnit(G,enemy)
exitwhen enemy == null or order == true
endloop
endif
else
call GroupClear(G)
call DestroyGroup(G)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
endif
call GroupClear(G)
call DestroyGroup(G)
set t = null
set phoenix = null
set enemyOrder = null
set G = null
endfunction
function Phoenix_Move takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit phoenix = LoadUnitHandle(Hash,h,1)
local unit caster = LoadUnitHandle(Hash,h,2)
local real X1 = GetUnitX(phoenix)
local real X2 = LoadReal(Hash,h,3)
local real Y1 = GetUnitY(phoenix)
local real Y2 = LoadReal(Hash,h,4)
local player PlayerEnemy
local player PlayerCaster = GetOwningPlayer(caster)
local real dist = SquareRoot((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1))
local real angle = Atan2(Y2 - Y1, X2 - X1)
local group G = CreateGroup()
local group DUG = LoadGroupHandle(Hash,h,5)
local integer data = GetUnitUserData(caster)
local real damage = DamagePhoenix[0][data]
local unit enemy
local boolean order = false
call SetUnitFacing(phoenix, angle*bj_RADTODEG)
call SetUnitX(phoenix, X1 + 5 * Cos(angle))
call SetUnitY(phoenix, Y1 + 5 * Sin(angle))
if dist <= 10.00 then
local timer k = CreateTimer()
local integer g = GetHandleId(k)
call GroupEnumUnitsInRange(G, X1, Y1, 400, null)
loop
set enemy = FirstOfGroup(G)
set PlayerEnemy = GetOwningPlayer(enemy)
if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 and IsUnitType(enemy, UNIT_TYPE_HERO) == true and IsUnitInGroup(enemy, DUG) == false then
set order = true
call IssueTargetOrder(phoenix, "attack", enemy)
call SaveUnitHandle(Hash,g,1,phoenix)
call SaveUnitHandle(Hash,g,2,enemy)
endif
call GroupRemoveUnit(G,enemy)
exitwhen enemy == null or order == true
endloop
call TimerStart(k,0.01,true,function Phoenix_Orders)
call GroupClear(G)
call DestroyGroup(G)
call GroupClear(DUG)
call DestroyGroup(DUG)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
call UnitApplyTimedLife(phoenix, 'BTLF', 7.00 )
set k = null
else
call GroupEnumUnitsInRange(G, X1, Y1, 80, null)
loop
set enemy = FirstOfGroup(G)
set PlayerEnemy = GetOwningPlayer(enemy)
if IsPlayerEnemy(PlayerEnemy, PlayerCaster) and GetWidgetLife( enemy ) >.405 and IsUnitInGroup(enemy, DUG) == false then
call UnitDamageTarget( caster, enemy, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
call GroupAddUnit(DUG, enemy)
endif
call GroupRemoveUnit(G,enemy)
exitwhen enemy == null
endloop
endif
call SaveGroupHandle(Hash,h,5, DUG)
call GroupClear(G)
call DestroyGroup(G)
set caster = null
set G = null
set DUG = null
set t = null
set phoenix = null
set enemy = null
endfunction
function Trig_Phoenix_Actions takes nothing returns nothing
local timer t = CreateTimer()
local integer h = GetHandleId(t)
local unit caster = GetTriggerUnit()
local integer data = GetUnitUserData(caster)
local unit j = GetTriggerUnit()
local real X1 = GetSpellTargetX()
local real X2 = GetUnitX(caster)
local real Y1 = GetSpellTargetY()
local real Y2 = GetUnitY(caster)
local real angle = Atan2(Y1 - Y2, X1 - X2)
local player pl = GetOwningPlayer(j)
local unit phoenix = CreateUnit( pl, 'h000', X2, Y2, angle*bj_RADTODEG )
local group G = CreateGroup()
call BlzSetUnitBaseDamage( phoenix, R2I(DamagePhoenix[0][data]), 1 )
call SaveUnitHandle(Hash,h,1,phoenix)
call SaveUnitHandle(Hash,h,2,caster)
call SaveReal(Hash,h,3,X1)
call SaveReal(Hash,h,4,Y1)
call SaveGroupHandle(Hash,h,5,G)
call TimerStart(t,0.01,true,function Phoenix_Move)
set caster = null
set t = null
set phoenix = null
set j = null
set G = null
endfunction
Огненная глыба
function Pyroblast_Cond takes nothing returns boolean
return GetSpellAbilityId()=='A005'
endfunction
function Pyroblast_Move takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit pyroblast = LoadUnitHandle(Hash,h,1)
local unit target = LoadUnitHandle(Hash,h,2)
local unit caster = LoadUnitHandle(Hash,h,3)
local real X1 = GetUnitX(pyroblast)
local real X2 = GetUnitX(target)
local real Y1 = GetUnitY(pyroblast)
local real Y2 = GetUnitY(target)
local real angle = Atan2(Y2 - Y1, X2 - X1)
local player PlayerCaster = GetOwningPlayer(caster)
local integer data = GetUnitUserData(caster)
local real damage = DamagePyroblast[0][data]
local real damageLow = DamagePyroblastRect[0][data]
local real dist = SquareRoot((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1))
local real distance = 200
if GetWidgetLife( target ) >.405 then
call SetUnitFacing(pyroblast, angle*bj_RADTODEG)
call SetUnitFlyHeight(pyroblast,GetUnitFlyHeight(target),dist)
call SetUnitX(pyroblast, X1 + 2.5 * Cos(angle))
call SetUnitY(pyroblast, Y1 + 2.5 * Sin(angle))
if dist <= 10.00 then
local group G = CreateGroup()
local unit enemy
local player player1
call GroupEnumUnitsInRange(G, X1, Y1, distance, null)
loop
set enemy = FirstOfGroup(G)
player1 = GetOwningPlayer(enemy)
if IsPlayerEnemy(player1, PlayerCaster) and enemy != target then
call UnitDamageTarget( caster, enemy, damageLow, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
endif
call GroupRemoveUnit(G,enemy)
exitwhen enemy == null
endloop
call UnitDamageTarget( caster, target, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
call KillUnit(pyroblast)
call GroupClear(G)
call DestroyGroup(G)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
set G = null
set player1 = null
endif
else
call UnitRemoveAbility( caster, 'A005' )
call UnitAddAbility( caster, 'A005' )
call KillUnit(pyroblast)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
endif
set t = null
set pyroblast = null
set caster = null
set target = null
endfunction
function Pyroblast_Scale takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local unit pyroblast = LoadUnitHandle(Hash,h,1)
local unit array dummy
local unit target = LoadUnitHandle(Hash,h,2)
local unit caster = LoadUnitHandle(Hash,h,3)
local real scale = LoadReal(Hash,h,4)
local real face = GetUnitFacing(caster)
local real X1 = GetUnitX(caster) + 75 * Cos(face* bj_DEGTORAD)
local real x1 = GetUnitX(caster)
local real X2 = GetUnitX(target)
local real Y1 = GetUnitY(caster) + 75 * Sin(face* bj_DEGTORAD)
local real Y2 = GetUnitY(target)
local integer n = 0
local boolean spell = GetUnitCurrentOrder(caster) == 852119
if spell == true and IsUnitType(caster, UNIT_TYPE_STUNNED) == false or GetWidgetLife( caster ) >.405 then
local real dist = 1.50
set scale = scale + 0.05
call SetUnitScale( pyroblast, scale, scale, scale )
call SetUnitPosition(pyroblast, X1, Y1)
call SetUnitFacing(pyroblast,face)
if scale >= dist then
local timer tick = CreateTimer()
local integer l = GetHandleId(tick)
call UnitRemoveAbility( caster, 'Amrf' )
loop
exitwhen (n == 11)
set dummy[n] = LoadUnitHandle(Hash,h,5+n)
call KillUnit(dummy[n])
set dummy[n] = null
set n = n + 1
endloop
call SaveUnitHandle(Hash,l,1,pyroblast)
call SaveUnitHandle(Hash,l,2,target)
call SaveUnitHandle(Hash,l,3,caster)
call TimerStart(tick,.01,true,function Pyroblast_Move)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
set tick = null
else
call SaveReal(Hash,h,4,scale)
if scale == 0.65 then
call SetUnitAnimationByIndex(caster,5)
QueueUnitAnimation(caster,"stand")
endif
endif
set pyroblast = null
set target = null
set caster = null
set t = null
else
call UnitRemoveAbility( caster, 'A005' )
call UnitAddAbility( caster, 'A005' )
loop
exitwhen (n == 11)
set dummy[n] = LoadUnitHandle(Hash,h,5+n)
call KillUnit(dummy[n])
set dummy[n] = null
set n = n + 1
endloop
call KillUnit(pyroblast)
call FlushChildHashtable(Hash,h)
call PauseTimer(t)
call DestroyTimer(t)
set pyroblast = null
set target = null
set caster = null
set t = null
endif
endfunction
function Pyroblast takes nothing returns nothing
local unit caster = GetTriggerUnit()
local unit target = GetSpellTargetUnit()
local timer t = CreateTimer()
local integer h = GetHandleId(t)
local real face = GetUnitFacing(caster)
local player PlayerCaster = GetOwningPlayer(caster)
local real scale = 1.0
local real x = GetUnitX(caster) + 75 * Cos(face* bj_DEGTORAD)
local real x1 = GetUnitX(caster)
local real y = GetUnitY(caster) + 75 * Sin(face* bj_DEGTORAD)
local real y1 = GetUnitY(caster)
local unit pyroblast = CreateUnit( PlayerCaster, 'h001', x, y, face )
local unit array dummy
local integer i = 'h007'
local integer l = 0
loop
exitwhen (l == 11)
if (l == GetPlayerId(PlayerCaster) and GetLocalPlayer() == PlayerCaster) then
i = 'h004'
endif
set dummy[l] = CreateUnit( Player(l), i, x, y, face )
call SetUnitTimeScale( dummy[l], 0.50 )
call SetUnitScale( dummy[l], 1.5, 1, 1 )
call SaveUnitHandle(Hash,h,5+l,dummy[l])
set i = 'h007'
set dummy[l] = null
set l = l + 1
endloop
call SetUnitPathing( pyroblast, false )
call SetUnitScale( pyroblast, scale, scale, scale )
call SaveUnitHandle(Hash,h,1,pyroblast)
call SaveUnitHandle(Hash,h,2,target)
call SaveUnitHandle(Hash,h,3,caster)
call TimerStart(t,.05,true,function Pyroblast_Scale)
set t = null
set pyroblast = null
set caster = null
set target = null
endfunction
Визуальное исправление анимаций при мгновенном касте
function Trig_AnimationSpell_Conditions takes nothing returns boolean
return GetUnitTypeId(GetTriggerUnit()) == 'KAEL'
endfunction
function Trig_AnimationSpell_Actions takes nothing returns nothing
local unit caster = GetTriggerUnit()
local integer abil = GetSpellAbilityId()
if abil != 'A005' and abil != 'A00A' then
call SetUnitAnimation(caster,"spell")
QueueUnitAnimation(caster,"stand")
endif
set caster = null
endfunction
//===========================================================================
function InitTrig_AnimationSpell takes nothing returns nothing
set gg_trg_AnimationSpell = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_AnimationSpell, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
call TriggerAddCondition( gg_trg_AnimationSpell, Condition( function Trig_AnimationSpell_Conditions ) )
call TriggerAddAction( gg_trg_AnimationSpell, function Trig_AnimationSpell_Actions )
endfunction
Глобальная инициализация
function Kael_Start takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer n = GetUnitUserData( u )
if GetUnitTypeId(u) == 'KAEL' then
if n <= 0 then
set NumberOfKael = NumberOfKael + 1
set LifeRegen[0][NumberOfKael] = 0.033
set ManaRegen[0][NumberOfKael] = 0.03
set Life[0][NumberOfKael] = GetUnitState(u, UNIT_STATE_MAX_LIFE)
set Mana[0][NumberOfKael] = GetUnitState(u, UNIT_STATE_MAX_MANA)
set DamageLifeBomb[0][NumberOfKael] = 126
set DamageLifeBombRect[0][NumberOfKael] = 215
set DamageFlamestrike[0][NumberOfKael] = 345
set DamagePyroblast[0][NumberOfKael] = 810
set DamagePyroblastRect[0][NumberOfKael] = 405
set DamagePhoenix[0][NumberOfKael] = 78
set Damage[0][NumberOfKael] = BlzGetUnitBaseDamage(u, 1)
call SetUnitUserData( u, NumberOfKael )
set DamageLifeBomb[0][NumberOfKael] = DamageLifeBomb[0][NumberOfKael] + (DamageLifeBomb[0][NumberOfKael] * 0.04)
set DamageLifeBombRect[0][NumberOfKael] = DamageLifeBombRect[0][NumberOfKael] + (DamageLifeBombRect[0][NumberOfKael] * 0.04)
set DamageFlamestrike[0][NumberOfKael] = DamageFlamestrike[0][NumberOfKael] + (DamageFlamestrike[0][NumberOfKael] * 0.04)
set DamagePyroblast[0][NumberOfKael] = DamagePyroblast[0][NumberOfKael] + (DamagePyroblast[0][NumberOfKael] * 0.05)
set DamagePyroblastRect[0][NumberOfKael] = DamagePyroblastRect[0][NumberOfKael] + (DamagePyroblastRect[0][NumberOfKael] * 0.05)
set DamagePhoenix[0][NumberOfKael] = DamagePhoenix[0][NumberOfKael] + (DamagePhoenix[0][NumberOfKael] * 0.04)
set Kael[NumberOfKael] = u
endif
endif
set u = null
endfunction
Регенерация
function Trig_Regen_Actions takes nothing returns nothing
local integer n = 0
loop
set n = n + 1
call SetUnitState( Kael[n], UNIT_STATE_LIFE, GetUnitState(Kael[n], UNIT_STATE_LIFE) + LifeRegen[0][n])
call SetUnitState( Kael[n], UNIT_STATE_MANA, GetUnitState(Kael[n], UNIT_STATE_MANA) + ManaRegen[0][n])
exitwhen n == NumberOfKael or NumberOfKael == 0
endloop
endfunction
Повышение уровня
function Trig_LvlUp_Conditions takes nothing returns boolean
return GetUnitTypeId(GetTriggerUnit()) == 'KAEL'
endfunction
function Trig_LvlUp_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer data = GetUnitUserData(u)
set Life[0][data] = Life[0][data] + (Life[0][data] * 0.04)
set Mana[0][data] = Mana[0][data] + 10
set Damage[0][data] = Damage[0][data] + (Damage[0][data] * 0.04)
set DamageLifeBomb[0][data] = DamageLifeBomb[0][data] + (DamageLifeBomb[0][data] * 0.04)
set DamageLifeBombRect[0][data] = DamageLifeBombRect[0][data] + (DamageLifeBombRect[0][data] * 0.04)
set DamageFlamestrike[0][data] = DamageFlamestrike[0][data] + (DamageFlamestrike[0][data] * 0.04)
set DamagePyroblast[0][data] = DamagePyroblast[0][data] + (DamagePyroblast[0][data] * 0.05)
set DamagePyroblastRect[0][data] = DamagePyroblastRect[0][data] + (DamagePyroblastRect[0][data] * 0.05)
set DamagePhoenix[0][data] = DamagePhoenix[0][data] + (DamagePhoenix[0][data] * 0.04)
set LifeRegen[0][data] = LifeRegen[0][data] + (LifeRegen[0][data] * 0.04 )
set ManaRegen[0][data] = ManaRegen[0][data] + (ManaRegen[0][data] * 0.04 )
call BlzSetUnitMaxHP( u, R2I(Life[0][data] + 0.5))
call BlzSetUnitMaxMana( u, R2I(Mana[0][data]))
call BlzSetUnitBaseDamage( u, R2I(Damage[0][data] + 0.5), 1 )
set u = null
endfunction
Отредактирован nvc123
скорее ближе к java или шарпу
да куда проще то
вот мануал по vjass с описанием структур и библиотек
Отредактирован nvc123
хотя это не рекомендуется т.к. выглядит убого и может вызывать конфликты из за дефайнов
скорее всего у тебя баг из за кривого cj_types.j
убери из него последнюю строчку (ту в которой вайл)
Можно ли на обычном Jass оптимизировать?
но выучить v/cJass и оптимизировать на них будет проще и быстрее
Отредактирован nvc123
начни со 2
также прочти комментарии к ней
если будет непонятно то спрашивай в лс
Отредактирован Diaboliko
А вообще есть хорошая нативка из функций для ИИ UnitAlive. Ее надо явно определить в джасс-скрипте карты, но с ней ни у кого не возникало багов :)
и каждый раз как чтото меняешь пиши об этом в этот список