Выход нового, 1.24, патча стал проблемой для многих игроков Warcraft’а, они потеряли возможность играть в большинство нестандартных карт. Это случилось из-за фикса старой ошибки близов, называемой Return Bug, благодаря которой мы могли получить Handle любого объекта, а некоторые хакеры открыть окно cmd. Взамен они дали возможность пользоваться хеш-таблицами, которые намного удобнее и быстрее (более подробно про хеш-таблицы можно узнать на страницах Wikipedia). В данную таблицу можно записывать абсолютно любые игровые объекты или переменные. Это может быть использовано для создания оригинальных способностей юнитов или дополнительных характеристик, таких как усталость, сытость, температура и т.д.
Как вы видите функций довольно много и рассказывать про каждую отдельно не имеет смысла, поэтому я расскажу лишь про основные.
Использование
Инициализация
Самой главной функцией из этого списка является функция “InitHashtable”. С помощью неё мы инициализируем хеш-таблицу для последующей работы с ней. В начале создадим глобальную переменную типа “Хеш-таблица (Hashtable)” и назовём её “Hash”, затем присвоим ей нужное значение:
Code
set udg_Hash=InitHashtable()
Получение Handle объекта
Если мы хотим присваивать объектам какие-либо значения, то нам необходим хендл данного объекта. Получить его мы можем с помощью функции “GetHandleId”. В качестве аргумента мы передаём любой игровой объект и получаем число типа “Целочисленное (integer) ”. Пример:
Code
local integer ObjectHadle set ObjectHadle = GetHandleId(udg_Unit)
В данном примере мы присвоили переменной “ObjectHadle” хендл юнита, заранее занесённого в переменную “udg_Unit”
Сохранение значений
Теперь когда таблица создана и мы умеем получать ссылки на объекты в неё можно записывать любые значения. Для записи используются функции с префиксом “Save” (например SaveInteger или SaveUnitHandle) из списка предоставленного выше. Простейшим примером использования данных функций является запись числа для юнита:
В первом аргументе мы передаём функции “SaveReal” хеш-таблицу (“udg_Hash”), во втором хендл юнита “udg_Unit” (созданного ранее и записанного в переменную “udg_Unit”), в третьем “номер ячейки” данного числа(“0”), ну а четвёртым мы передали само число(“1.00”). Если мы захотим записать другие числа, то мы можем либо перезаписать его, использую функцию:
В качестве аргументов принимаются хеш-таблица, хендл объекта и номер ячейки. Если запись в ячейке уже существует, то вернётся значение “true”, если же ячейка свободна, то функция вернёт значение “false”. Пример:
Code
if HaveSavedReal (udg_Hash, GetHandleId(udg_Unit), 0) == true then call BJDebugMsg(“True”) else call BJDebugMsg(“False”) endif
Удаление записи
Бывают ситуации когда необходимо удалить запись из ячейки. Например, стереть запись, содержащую какое-либо число, и записать в эту ячейку ссылку на таймер. Для этого используются функции:
Как и в прошлом примере, в качестве аргументов, мы указываем хеш-таблицу, ссылку на объект и номер ячейки.
Полное удаление записей
Последние 2 функции, которые мы с вами разберём, будут “FlushParentHashtable” и “FlushChildHashtable”. FlushParentHashtable позволяет удалить нам абсолютно все записи из хеш-таблицы. В качестве аргумента указывается только очищаемая хеш-таблица. После использования донной функции хеш-таблицу приходиться инициализировать заново! Пример:
Code
call FlushParentHashtable(udg_Hash)
А вот FlushChildHashtable нужна для удаления записей из одного объекта. Рекомендую использовать данную функцию, например при удалении юнита, так как даже есть вы удалите юнита функцией “RemoveUnit”, то его значения останутся в хеш-таблице. Пример:
Рекомендую вставлять такой код в любую карту, где вы работали с хеш-таблицами, по-моему очень удобно:
Code
function Flush_Unit takes nothing returns nothing local unit u = GetTriggerUnit() call FlushChildHashtable(<Хеш-таблица>, GetHandleId(u)) set u=null endfunction
function InitTrig_Flush_Unit takes nothing returns nothing local trigger t = CreateTrigger() call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DEATH ) call TriggerAddAction( t, function Flush_Unit ) set t=null endfunction
Примеры использования
Взрыв юнита
Примером использования хеш-таблиц может служить простой пример со взрывом юнита. Например мы хотим, что бы юнит взорвался после каста заклинания. Это очень просто скажите вы. Но если нужно чтобы он взорвался через 5 секунд после каста заклинания? Особо остроумные могут конечно использовать действие “Wait”, но работа с таймерами куда лучше, так как wait может повести себя абсолютно не предсказуемо, вплоть до того что действия после него просто не будут выполняться.
Code
function Explode takes nothing returns nothing local timer t=GetExpiredTimer() //Получаем таймер, вызвавший данную ф-цию local unit u=LoadUnitHandle(udg_Hash, GetHandleId(t),1) //Загружаем нужного нам юнита
call ExplodeUnitBJ(u) //И взрываем его <img src="http://s24.ucoz.net/sm/1/smile.gif" border="0" align="absmiddle" alt="smile"> call FlushChildHashtable(udg_Hash, GetHandleId(t)) //Удаляем записи таймера
call DestroyTimer(t) //Обнуляем переменные и “разрушаем” таймер set t=null set u=null endfunction
function Trig_Explode_Actions takes nothing returns nothing local timer t=CreateTimer() //Создаём новый таймер local unit u=GetSpellAbilityUnit() //Заносим в переменную юнита-кастера
set udg_Hash=InitHashtable() //Инициализируем хеш-таблицу, если ранее это действие не выполнялось call SaveUnitHandle(udg_Hash, GetHandleId(t), 1, u) //Сохраняем ссылку на юнита “внутри” таймера call TimerStart(t, 5.00, false, function Explode) //Запускаем таймер
set t=null //Обнуляем переменные set u=null endfunction
function InitTrig_Explode takes nothing returns nothing local trigger t=CreateTrigger() call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST ) call TriggerAddAction( t, function Trig_Explode_Actions ) set t=null endfunction
Если вы уже не плохо знаете жасс и ранее использовали кеш, то для вас не составит труда понять как работает данный пример, ну а для новичков я сделал подсказки и пример, который вы найдёте во вложении.