Ещё можно отображать сферами, на подобии жезла молний, где каждая сфера, например, поглощает 25/50/75/100/125 урона и количетво сфер равно 1*уровень способности. Когда сферы закончатся, щит спадает.
Посмотрите в этой наработке, там структуры с хэштаблицами а таймерами.
Не используйте точки
local location point1 = GetUnitLoc(u)
local location point2 = GetSpellTargetLoc()
// Где RemoveLocation() ?
Лучше координаты
local real casterX = GetUnitX(caster)
local real casterY = GetUnitY(caster)
local real targetX = GetSpellTargetX()
local real targetY = GetSpellTargetY()
Начал тестить и вообще какая-то магия происходит. Если из другого таймера делать print(timer), то timer не остановится. Но отпадут действия триггеров или новые таймеры не смогут запуститься. Ещё нужно будет попробовать тупо пересоздавать таймер каждые неколько секунд и насыпать оптимизации.
//! beginusercode
do
-- На момент патча 1.31 эта функция всегда возвращает 0. Поэтому создадим её локальный аналог.
local function AbilityId(id)
return id:byte(1) * 0x1000000 + id:byte(2) * 0x10000 + id:byte(3) * 0x100 + id:byte(4)
end
local BULLETS = {}
local TIMER_PERIOD = 0.03125 --> 1/32
local SPEED = 600
local SPEED_INC = SPEED/(1/TIMER_PERIOD)
local DAMAGE_PERIOD = 0.5
local DAMAGE_TIME = 0
local IS_DAMAGE = false
local DAMAGE_GROUP = CreateGroup()
local BOARD
-- Настройки
local ABILITY_ID = AbilityId('SIWh')
local ARC = 0.3
local EFFECT = 'Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl'
-- Код
local GetTerrainZ_location = Location(0, 0)
local function GetTerrainZ(x, y)
MoveLocation(GetTerrainZ_location, x, y);
return GetLocationZ(GetTerrainZ_location);
end
local function InMapXY(x, y)
return
x > GetRectMinX(bj_mapInitialPlayableArea)
and
x < GetRectMaxX(bj_mapInitialPlayableArea)
and
y > GetRectMinY(bj_mapInitialPlayableArea)
and
y < GetRectMaxY(bj_mapInitialPlayableArea)
end
TimerStart(CreateTimer(), TIMER_PERIOD, true, function()
if #BULLETS == 0 then return end
DAMAGE_TIME = DAMAGE_TIME + TIMER_PERIOD
IS_DAMAGE = DAMAGE_TIME >= DAMAGE_PERIOD
if
IS_DAMAGE
then
DAMAGE_TIME = 0
end
for i=#BULLETS, 1, -1
do
BULLETS[i].x = BULLETS[i].x + SPEED_INC*BULLETS[i].cos
BULLETS[i].y = BULLETS[i].y + SPEED_INC*BULLETS[i].sin
if
InMapXY(BULLETS[i].x, BULLETS[i].y)
then
BlzSetSpecialEffectX(BULLETS[i].effect, BULLETS[i].x)
BlzSetSpecialEffectY(BULLETS[i].effect, BULLETS[i].y)
BlzSetSpecialEffectHeight(BULLETS[i].effect, 20)
if
IS_DAMAGE
then
GroupEnumUnitsInRange(DAMAGE_GROUP, BULLETS[i].x, BULLETS[i].y, 100, Filter(function()
local target = GetFilterUnit()
return
UnitAlive(target)
and
IsPlayerEnemy(GetOwningPlayer(BULLETS[i].caster), GetOwningPlayer(target))
end))
ForGroup(DAMAGE_GROUP, function()
UnitDamageTarget(BULLETS[i].caster, GetEnumUnit(), 50, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
end)
GroupClear(DAMAGE_GROUP)
end
else
DestroyEffect(BULLETS[i].effect)
table.remove(BULLETS, i)
end
end
if
BOARD ~= nil
then
LeaderboardSetItemValue(BOARD, 0, #BULLETS)
end
end)
local trigger = CreateTrigger()
for i = 0, bj_MAX_PLAYER_SLOTS - 1, 1 do
TriggerRegisterPlayerUnitEvent(trigger, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT)
end
TriggerAddCondition(trigger, Condition(function() return
GetOwningPlayer(GetTriggerUnit()) == Player(0)
end))
TriggerAddAction(trigger, function()
local caster = GetTriggerUnit()
local x
local y
local angle
UnitRemoveAbility(caster, GetSpellAbilityId())
TimerStart(CreateTimer(), 0.1, true, function()
x = GetUnitX(caster)
y = GetUnitY(caster)
angle = Deg2Rad(GetUnitFacing(caster))
table.insert(BULLETS, {
effect = AddSpecialEffect('units\\nightelf\\Wisp\\Wisp.mdl', x, y),
caster = caster,
x = x,
y = y,
angle = angle,
cos = Cos(angle),
sin = Sin(angle)
})
end)
end)
-- Board
TimerStart(CreateTimer(), 1, false, function()
BOARD = CreateLeaderboard()
PlayerSetLeaderboard(GetLocalPlayer(), BOARD)
LeaderboardSetLabel(BOARD, 'Статистика')
LeaderboardDisplay(BOARD, true)
LeaderboardAddItem(BOARD, "Эффекты", #BULLETS, Player(0))
LeaderboardSetSizeByItemCount(BOARD, 1)
DestroyTimer(GetExpiredTimer())
end)
end
//! endusercode
//! beginusercode
do
-- На момент патча 1.31 эта функция всегда возвращает 0. Поэтому создадим её локальный аналог.
local function AbilityId(id)
return id:byte(1) * 0x1000000 + id:byte(2) * 0x10000 + id:byte(3) * 0x100 + id:byte(4)
end
local BULLETS = {}
local TIMER_PERIOD = 0.03125 --> 1/32
local SPEED = 600
local SPEED_INC = SPEED/(1/TIMER_PERIOD)
-- Настройки
local ABILITY_ID = AbilityId('SIWh')
local ARC = 0.3
local EFFECT = 'Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl'
-- Код
local GetTerrainZ_location = Location(0, 0)
local function GetTerrainZ(x,y)
MoveLocation(GetTerrainZ_location, x, y);
return GetLocationZ(GetTerrainZ_location);
end
local function InMapXY(x, y)
return
x > GetRectMinX(bj_mapInitialPlayableArea)
and
x < GetRectMaxX(bj_mapInitialPlayableArea)
and
y > GetRectMinY(bj_mapInitialPlayableArea)
and
y < GetRectMaxY(bj_mapInitialPlayableArea)
end
TimerStart(CreateTimer(), TIMER_PERIOD, true, function()
if #BULLETS == 0 then return end
for i=#BULLETS, 1, -1
do
BULLETS[i].x = BULLETS[i].x + SPEED_INC*BULLETS[i].cos
BULLETS[i].y = BULLETS[i].y + SPEED_INC*BULLETS[i].sin
if InMapXY(BULLETS[i].x, BULLETS[i].y)
then
BlzSetSpecialEffectX(BULLETS[i].effect, BULLETS[i].x)
BlzSetSpecialEffectY(BULLETS[i].effect, BULLETS[i].y)
else
DestroyEffect(BULLETS[i].effect)
table.remove(BULLETS, i)
end
end
end)
local trigger = CreateTrigger()
for i = 0, bj_MAX_PLAYER_SLOTS - 1, 1 do
TriggerRegisterPlayerUnitEvent(trigger, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT)
end
--TriggerAddCondition(trigger, Condition(function() return true end))
TriggerAddAction(trigger, function()
TimerStart(CreateTimer(), 0.5, true, function()
local caster = GetTriggerUnit()
local x = GetUnitX(caster)
local y = GetUnitY(caster)
local angle = GetUnitFacing(caster)
table.insert(BULLETS, {
effect = AddSpecialEffect('units\\nightelf\\Wisp\\Wisp.mdl', x, y),
x = x,
y = y,
angle = angle,
cos = Cos(angle),
sin = Sin(angle)
})
end)
end)
end
//! endusercode
Bergi_Bear, всё никак немогу привыкнуть, что в новом патче эффекты можно в трёх плокостях вращать. Можно ещё оптимизировать и икать столкновения таймером помедленнее, держа координаты эффектов в таблице.
Из детекта, мне тоже больше нравится аура жара
А таймеры я бы создавал на группу снарядов, например: кольцо снарядов, линия снарядов, змейка и т.д. Так меньше мороки с кодом и по хэндлу таймера например, можно менять поведение всей группе, не заморачиваясь с лишними переборами.
» Защитники Хелерии / Обзор героя: Трейм - Повелитель Бурь
Bergi_Bear:
» WarCraft 3 / allocate возвращает 0
» Администрация XGM / Ошибка кодировки вставки картинки
» Администрация XGM / Ошибка кодировки в лайке поста
» Администрация XGM / Не могу открыть свой профиль и вообщем проблемы с сайтом.
» WarCraft 3 / JASS фаербол
» Защитники Хелерии / Обзор героя: Трейм - Повелитель Бурь
» Защитники Хелерии / Обзор героя: Трейм - Повелитель Бурь
» WarCraft 3 / Самый производительный Bullet Hell
Ред. nazarpunk
» WarCraft 3 / Самый производительный Bullet Hell
Ред. nazarpunk
» WarCraft 3 / Самый производительный Bullet Hell
Ред. nazarpunk
» Администрация XGM / Проблемы с отображением окон пользователей...
Что говорит консоль отладчика?
» WarCraft 3 / Самый производительный Bullet Hell
» WarCraft 3 / Самый производительный Bullet Hell
Ред. nazarpunk
» WarCraft 3 / Самый производительный Bullet Hell
Ред. nazarpunk
» WarCraft 3 / Заклинание: Вихрь Иллюзий
» WarCraft 3 / как создать свой GetUnitUserData
Ред. nazarpunk
» WarCraft 3 / Заклинание: Вихрь Иллюзий
» WarCraft 3 / как создать свой GetUnitUserData
» WarCraft 3 / Заклинание: Вихрь Иллюзий
Ред. nazarpunk
» WarCraft 3 / Заклинание: Вихрь Иллюзий
» WarCraft 3 / Самый производительный Bullet Hell
» WarCraft 3 / Самый производительный Bullet Hell
» WarCraft 3 / Самый производительный Bullet Hell
А таймеры я бы создавал на группу снарядов, например: кольцо снарядов, линия снарядов, змейка и т.д. Так меньше мороки с кодом и по хэндлу таймера например, можно менять поведение всей группе, не заморачиваясь с лишними переборами.
» WarCraft 3 / Как найти наибольшее из нескольких чисел?