rsfghd, благодаря этому пованивающему мусору я многому научился))) В твоём коде очень много примеров того как делать надо, и как делать категорически НЕНАДО XD
rsfghd, действительно пованивает, утекает и лагает, использует глобалки близард чтобы обойти отсутствие возможности передать аргументы через предикаты, из-за чего половина стрел при малом интервале не обнулится, утекает и юнит и локация ну и т.д. Да и урон через волны такое себе. Фильтр и дамаг в луп засунуть осталось и через firstofgroup обрабатывать чтобы избавиться от приватной глобалки и не было конкурентности. Оно сейчас с 1000 стрел х 12 кастеров плавно едет. В целом спасибо, пока думал как заставить это плавно без тормозов работать написал полезную вспомогательную библиотеку. Ну а это почищеный код с переработаной логикой до моих шаманств с оптимизацией, моя версия сейчас без лагов поддерживает 2000 снарядов с интервалом 0.010, и каждый снаряд гарантированно обрабатывается, но оно уже требует самописную библиотеку.
Открыть
scope ArrowsSc
globals
//=============================== КОНФИГУРАЦИЯ СПОСОБНОСТИ =====================================
private constant integer aID = 'A000' // ID способности
private constant integer dID = 'u000' // ID дамми-юнита для снаряда и источника урона
private constant real Damage = 50 // Базовое значение урона (на стрелу)
private constant real MaxR = 230 // Радиус действия заклинания (спавна стрел)
private constant real MinR = 65 // Минимальный радиус спавна стрел (от центра)
private constant real DmgR = 70 // Радиус урона стрелы
private constant integer ArrowsCount = 1000 // Количество стрел (снарядов)
private constant real SpwnInt = 0.020 // Минимальный интервал между появлением стрел (к нему прибавится рандомный разброс)
private constant real SpwnIntR = 0.020 // Максимальный разброс интервала
private constant real ArrowHeight = 700 // Начальная высота спавна стрел
private constant real ArrowSpeed = 1500 // Скорость падения (SetUnitFlyHeight)
private constant real ArrowGround = 0 // Конечная высота падения (земля)
private constant attacktype AttackType = ATTACK_TYPE_PIERCE
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL
private constant weapontype WeaponType = WEAPON_TYPE_WHOKNOWS
private constant string ArrowEffect = "Objects\\Spawnmodels\\Critters\\Albatross\\CritterBloodAlbatross.mdl"
private constant string ArrowAttachPoint = "chest"
private constant real ArrowEffectRemoveTime = 1.00
// Глобальные переменные
private unit TempArrow = null
endglobals
//==========================================================================
private function IsUnitDead takes unit u returns boolean
return IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) == 0
endfunction
private function filt takes nothing returns boolean
return not IsUnitDead(GetFilterUnit()) and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(TempArrow)) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)
endfunction
private function remeff takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
call DestroyEffect(LoadEffectHandle(udg_Hash,i,0))
call FlushChildHashtable(udg_Hash,i)
call DestroyTimer(t)
set t = null
endfunction
private function dmgf takes nothing returns nothing
local timer t = null
local effect e = null
call UnitDamageTarget(TempArrow,GetEnumUnit(),Damage,false,true,AttackType,DamageType,WeaponType)
set t = CreateTimer()
set e = AddSpecialEffectTarget(ArrowEffect,GetEnumUnit(),ArrowAttachPoint)
call SaveEffectHandle(udg_Hash,GetHandleId(t),0,e)
call TimerStart(t,ArrowEffectRemoveTime,false,function remeff)
set t = null
set e = null
endfunction
private function ArrowDamage takes nothing returns nothing
local timer t = GetExpiredTimer()//Получаем таймер снаряда
local integer apk = GetHandleId(t)//Получаем arrow parent key
local unit u = LoadUnitHandle(udg_Hash, apk, 0) //Получаем снаряд (источник урона)
local player Owner = LoadPlayerHandle(udg_Hash, apk, 1) // Владелец
local group g = null
local real ux
local real uy
// 1. Получаем точные координаты снаряда в момент срабатывания
set ux = GetUnitX(u)
set uy = GetUnitY(u)
// 3. Создаем группу целей
set g = CreateGroup()
set TempArrow = u
// 4. Группируем цели и наносим урон
call GroupEnumUnitsInRange(g, ux, uy, DmgR, Condition(function filt))
call ForGroup(g, function dmgf)
// 5. КРИТИЧЕСКИ ВАЖНО: Очистка
call DestroyGroup(g)
set TempArrow = null
set g = null
set u = null
// 6. Финальная очистка хэш-таблицы и таймера
call FlushChildHashtable(udg_Hash, apk)
call DestroyTimer(t)
set t = null
set Owner = null
endfunction
private function SpawnArrows takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer pk = GetHandleId(t)
local integer apk
local unit Caster
local player Owner
local real x = LoadReal(udg_Hash, pk, 2) //X
local real y = LoadReal(udg_Hash, pk, 3)//Y
local integer AS = LoadInteger(udg_Hash, pk, 4)//Arrows Shooted
local location Tloc = null
local real RandR
local real Interval
local timer FlyTime
local unit u
local real lifetime = (ArrowHeight-ArrowGround)/ArrowSpeed
if AS == ArrowsCount then//Условие выхода из цикла, остановка и очистка.
local location l = LoadLocationHandle(udg_Hash, pk, 5) //Загружаем хендл локации
call PauseTimer(t)
call RemoveLocation(l) //Удаление объекта Location из памяти игры
call FlushChildHashtable(udg_Hash, pk) // Очистка ссылок из хэша
call DestroyTimer(t)
set t = null
set l = null
return
endif
//Инициализируем переменные
set Caster = LoadUnitHandle(udg_Hash,pk,0) //Кастер
set Owner = LoadPlayerHandle(udg_Hash,pk,1) //Овнер
set Tloc = LoadLocationHandle(udg_Hash,pk,5) //TempLocation
set RandR = GetRandomReal(MinR,MaxR) //Рандомный радиус между минимальным и максимальным радиусом
//Получаем рандомную точку в радиусе
call MoveLocation(Tloc, x+RandR*Cos(GetRandomReal(0,360)*bj_DEGTORAD), y+RandR*Sin(GetRandomReal(0,360)*bj_DEGTORAD))
//создание юнита-стрелы
set u = CreateUnitAtLoc(Owner,dID,Tloc,GetRandomReal(0,360))
// Установка TimedLife. Это удалит юнит после lifetime, проиграв звук.
call UnitApplyTimedLife(u,'BTLF',lifetime)
call SetUnitFlyHeight(u,ArrowHeight,0)
call SetUnitFlyHeight(u,ArrowGround,ArrowSpeed)
set FlyTime = CreateTimer() //Таймер для стрелы
set apk = GetHandleId(FlyTime) //arrow parent key
//Что передаём функции урона:
call SaveUnitHandle(udg_Hash,apk,0,u)//apk 0 - стрела
call SavePlayerHandle(udg_Hash,apk,1,Owner)//apk 1 ее владелец
call TimerStart(FlyTime, lifetime - 0.036, false, function ArrowDamage) //нанесение урона и спецэфектов перед "смертью" стрелы.
// снаряд запущен
call SaveInteger(udg_Hash,pk,4,AS+1)//Запущено снарядов +1
set Interval = SpwnInt + GetRandomReal(0.001, SpwnIntR)//Интервал с разбросом
call TimerStart(t, Interval, true, function SpawnArrows)//Таймер запуска снарядов
//утилизация
set Tloc = null
set u = null
set Caster = null
set FlyTime = null
set Owner = null
endfunction
// --- ИНИЦИАЛИЗАЦИЯ ТАБЛИЦЫ ---
private function Actions takes nothing returns nothing
local unit u = GetSpellAbilityUnit()
local timer t = CreateTimer()
local integer pk = GetHandleId(t) //ключ таблицы
local player o = GetOwningPlayer(u)
local location l = Location(0,0)
call SaveUnitHandle(udg_Hash,pk,0,u) //Caster (слот 0)
call SavePlayerHandle(udg_Hash,pk,1,o) //Owner (слот 1)
call SaveReal(udg_Hash,pk,2,GetSpellTargetX()) // X (слот 2)
call SaveReal(udg_Hash,pk,3,GetSpellTargetY()) // Y (слот 3)
call SaveInteger(udg_Hash,pk,4,0) //Выпущено стрел (слот 4)
call SaveLocationHandle(udg_Hash,pk,5,l) //Точка локации используемая для этого каста
call TimerStart(t,0.01,false,function SpawnArrows)
set l = null
set o = null
set u = null
set t = null
endfunction
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == aID
endfunction
function InitTrig_arrows 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 Conditions))
call TriggerAddAction(t,function Actions)
set t = null
endfunction
endscope
ScorpioT1000, ну я не нашёл на сайте ресурса с этой функцией, поэтому пришлось гуглить тестить и создавать запись в блоге, а источник могу удалить, я просто не люблю присваивать чужие заслуги
Комментарии проекта Блог им. rsfghd
Новый мусор, ура!
но впрочем спасибо что увлёкся, я поржал <3
Ред. AnimoMori
какая-то фигня
какая-то фигня х4
Случайная точка в треугольнике
Ред. ScorpioT1000