Предыстория
В те далёкие времена, когда динозавры ходили по планете и изучали gui, внезапно оказалось, что спустя некоторое время карты начинали жутко тормозить. Коллективным разумом были найдены странные зверьки - утечки.
Вариант борьбы с ними был прост - обнулять локальные переменные с типом handle. Только вот узнать на сколько протёк код и стоит ли бежать и полностью его переписывать можно было по косвенным причинам. Пока не изобрели...
Handle Counter
Идея была проста - необходимо посчитать все handle. Но игра напрямую не предоставляла эту возможность, но у handle была интересная особенность - GetHandleId возвращала номер handle который отличался от предыдущего на единицу, а удалённые handle переиспользовались. Посему если создать в игре достаточное количество handle, чтоб перекрыть дырки в последовательности номеров, то вызвав GetHandleId и использовав нехитрую математику, можно узнать их количество.
И все начали дружно считать handle.
Выглядело это примерно так:
library HandleCounter
globals
private constant integer safety = 50
endglobals
function CountHandles takes nothing returns integer
local integer i = 0
local integer i2 = 0
local integer space = 0
local integer space2 = 0
local integer count = 0
local location array loc
local integer hid = 0
local integer hid2
loop
set loc[i] = Location(0., 0.)
set hid2 = GetHandleId(loc[i]) - 0x100000
if hid2 == hid + 1 or hid == 0 then
set space = space + 1
set space2 = space2 + 1
else
set space2 = 0
endif
set hid = hid2
set i = i + 1
set count = hid
exitwhen space2 == safety
endloop
loop
exitwhen i2 > i
call RemoveLocation(loc[i2])
set loc[i2] = null
set i2 = i2 + 1
endloop
return count - space - safety - 1
endfunction
endlibrary
Вы наверно часто встречали такую табличку в публикациях способностей. Но была одна проблема - точность оставляла желать лучшего и позволял понять происходящее только в первом приближении. Да и в карте мог использоваться Leaderboard, что затрудняло тестирование. Пока не изобрели...
UjAPI
Идея была ещё проще предыдущей - создать свой лаунчер и дописать недостающие функции. И одной из первых была реализована GetHandleCount, которая брала значение напрямую из движка игры исключая любые неточности. Что позволило более эффективно тестировать свои карты, чтоб исключить дискомфорт игроков на поздней стадии игры.
Оставалась только одна проблема - JNGP, запущенный без лаунчера, отказывался сохранять карты с активной функцией GetHandleCount, а каждый раз копировать код в карту накладною. Мы ценим ваше время.
Тут на помощь пришёл Warcraft III - Lua и картина сразу сложилась - для его работы в корне карты должен быть файл war3map.lua, который игра без лаунчера просто проигнорирует.
Поэтому просто импортируем в корень карты war3map.lua, удаляем war3mapImported\ из пути и наслаждаемся красивым и аккуратным фреймом:
Слева у него количество handle, а справа количество секунд, прошедших с начала игры.
Если же вы захотите использовать UjAPI + Warcraft III - Lua на постоянной основе, то можете воспользоваться инструкцией, а потом добавить код файла куда вашей душеньке мятежной будет угодно.
war3map.lua
TimerStart(CreateTimer(), 0, false, function()
DestroyTimer(GetExpiredTimer())
local gameUi = GetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local menu = CreateFrame('LoadingPlayerSlot', gameUi, 0, 0)
SetFrameSize(menu, .16, .03)
FRAMEPOINT_BOTTOM = ConvertFramePointType(7);
SetFrameRelativePoint(menu, FRAMEPOINT_BOTTOM, gameUi, FRAMEPOINT_BOTTOM, 0, 0.16)
local left = GetFrameByName('LoadingPlayerSlotName', 0)
local right = GetFrameByName('LoadingPlayerSlotRace', 0)
local seconds = 0
local period = .25
TimerStart(CreateTimer(), period, true, function()
seconds = seconds + period;
SetFrameText(left, tostring(GetHandleCount()))
SetFrameText(right, tostring(math.floor(seconds)))
end)
end)
Послесловие
Проекты активно разрабатываются силами всего лишь нескольких человек и они не всегда успевают вовремя вносить в них правки. Так что не стесняйтесь поддерживать авторов рублём и писать комментарии.
Ваша поддержка очень важна!