Добавлен Берги
Вот есть мой старый код, ну скажем алгоритм на Jass, который вполне себе исправно работает
Jass код
//передаточная функция я просто вызываю её далее по коду если хочу что либо куда либо передвинуть ForceUnit( юнит, угол ,дистанция, скорость за тик 0,04, флаг (дополнительный параметр))
function ForceUnit takes unit u,real a,real d,real s,integer flag returns nothing
if GetUnitMoveSpeed(u) >= 1 and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false then
call GroupAddUnit(gforce, u)
call SaveReal(udg_hash, GetHandleId(u), StringHash("a"), a)
call SaveReal(udg_hash, GetHandleId(u), StringHash("d"), d)
call SaveReal(udg_hash, GetHandleId(u), StringHash("s"), s)
call SaveInteger(udg_hash, GetHandleId(u), StringHash("flag"), flag)
endif
endfunction
//далее просто перебирается группа и делаются действия
function MainForce takes nothing returns nothing
local unit u=GetEnumUnit()
local real a=LoadReal(udg_hash, GetHandleId(u), StringHash("a"))
local real d=LoadReal(udg_hash, GetHandleId(u), StringHash("d"))
local real s=LoadReal(udg_hash, GetHandleId(u), StringHash("s"))
local integer flag=LoadInteger(udg_hash, GetHandleId(u), StringHash("flag"))
local real x=GetUnitX(u)
local real y=GetUnitY(u)
call SaveReal(udg_hash, GetHandleId(u), StringHash("d"), d - s)
//call BJDebugMsg(R2S(s))
//////ДОПОЛНИТЕЛЬНЫЕ флаги при движении
if flag == 1 then // босс эффект воды
//call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",GetUnitX(u),GetUnitY(u)))
endif
if flag == 2 then // стоп
call IssueImmediateOrder(u, "stop")
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", GetUnitX(u), GetUnitY(u)))
//call BJDebugMsg("2")
endif
////Условия прекращения движения
if d <= 0 or Out(MoveX(x , s * 2 , a) , MoveY(y , s * 2 , a)) == false or GetPointZ(x , y) <= GetPointZ(MoveX(x , s * 2 , a) , MoveY(y , s * 2 , a)) - 30 then
if IsUnitType(u, UNIT_TYPE_HERO) == false then
call FlushChildHashtable(udg_hash, GetHandleId(u))
//call BJDebugMsg("BREAK")
endif
call GroupRemoveUnit(gforce, u)
endif //конец условий прекращения движения
// движение выполняется всегда за исключением условий прекращения движения
call SetUnitX(u, MoveX(x , s , a))
call SetUnitY(u, MoveY(y , s , a))
//call killtree(u,x,y,70)
//call BJDebugMsg("3")
set u=null
endfunction
Код можно не смотреть особо там крутится группа на таймере, в группе у юнита извлекаются на хештаблицах параметры для движения, но ОНB висят НА ЮНИТЕ
Как сделать что-то подобное на LUA?
Как сделать каждое толкание на отдельном таймере я понял, а как крутить группу на 1 таймере? (это тоже в принципе понятно)
Но что щас выступает аналогом load*handle?
Как сделать что-то подобное на LUA?
Как сделать каждое толкание на отдельном таймере я понял, а как крутить группу на 1 таймере? (это тоже в принципе понятно)
Но что щас выступает аналогом load*handle?
Принятый ответ
А еще у меня там местами xpcall отладочный висит, там где я ловил косяки и не убрал его потом, без него код чуть проще становится, он нужен только для отлова ошибок и в моем случае вывода их на экран.
Это печально, новые костыли, а я уже обрадовался, что ничего обнулять и чистить не нужно =(
Не нужно обнулять локалки в функциях и все что ограниченного срока жизни, но всякие системы хранения данных они же либо глобальные либо в "локальном" скопе всей карты и, соответственно, живут пока загружена карта - там вручную подчищать надо, естественно. Можно делать это полу-автоматически как у меня, можно вручную когда становится известно что данные уже не нужны. Можно было бы использовать таблицу со слабыми ключами, но тогда возникает вопрос что использовать в качестве ключей - можно прямо на самого юнита вешать, чтобы когда игра его удалит из памяти, таблица почистилась сборщиком мусора, но нет гарантии что это будет работать и не будет вызывать десинки т.к. сборщику мусора синхронизация не указ.
Bergi_Bear:
Bergi_Bear:
но мне можно себе такой вариант забрать или надо ещё что-то дополнительно записать?
У меня библиотека отгорожена только ради того чтобы автоматизировать сборку мусора и создание новых таблиц при обращении по хендлу на который ничего нет.
Минимальный вариант, наверно, такой:
Минимальный вариант, наверно, такой:
local HandleData = {} -- я использую локальные переменные в скопе карты, при этом важен порядок но доступ к ним идет чуть быстрее чем в глобальном скопе
function ForceUnit (u,a,d,s,flag)
local data = HandleData[GetHandleId(u)]
if (data==nil) then data = {} HandleData[GetHandleId(u)] = data end
data.a = a
data.d = d
data.s = s
data.flag = flag
GroupAddUnit(gforce, u)
end
-- --------------
ForGroup(gforce, function()
local u=GetEnumUnit()
local h=GetHandleId(u)
local data = HandleData[h]
local a=data.a
local d=data.d
local s=data.s
local flag=data.flag
...
end
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован prog
1 - массив-таблица с индексами по хендлу и еще одной таблицей в качестве значений
2 - передача переменных через кложуры (не твой случай ведь тебе на юнита данные вязать надо т.к. таймер один на всех)
prog:
prog:
тот самый сборщик о котором все говорят?
пошёл пробовать
prog:
Отредактирован prog
Bergi_Bear:
Минимальный вариант, наверно, такой:
Такс, prog, не получается =(
if (data==nil) then data = {} HandleData[GetHandleId(u)] = data end
prog, просто я раньше начал писать чем ты отправил и я не видел твоего того сообщения =)
Отредактирован prog
Но не только - еще это нужно чтобы создать запись для юнита если её еще нет. И именно поэтому сыпался твой вариант без этой строки - по хендлу мы вынимали nil (он же null если по джасовски) если на хендл еще ничего не было записано и на этом все падало, естественно, т.к. nil это ни разу не таблица. У меня без этой строки работало потому как у меня в библиотеке переопределена операция получения значения из таблицы HandleData - либа сама создает новые таблицы-записи если на хендл еще ничего не записано.
А вот наверное понял
Отредактирован prog
Если данные связаные с системой - обнуляеш те переменные в таблице-записи которые использовал и которые не нужны в других местах. data.s = nil data.a=nil и так далее.
Если все данные на юнита (юнит умер или удаляется) - записываем nil по хендлу. HandleData[GetHandleId(u)] = nil.
У меня в либе для ручной чистки я вызвал бы HandleData:Purge(GetHandleId(u)), если бы не полагался на автоматическую чистку по какой-то причине, но там внутри пока все то-же самое присвоение nil.
data.somebulkdata = { a=42 b=42 c=42}
data.somebulkdata = nil
но вроде понял, спасибо ещё раз
думаю мне достаточно писать nil по хендлу, это ближайший аналог к FlushChildHashatable
надо ковырять, в любом случае не плохо для первого дня знакомства с lua, я очень доволен, весьма удобно