Сейчас 02:55 Пятница, 3 5, 2024 год
Главная ⇒ Форум ⇐ RSS Файлы Cтатьи Обои В о й т и   или   з а р е г и с т р и р о в а т ь с я
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Live Warcraft - Форум » Разработка карт » GUI и JASS » [Статья] Хеш-таблицы
[Статья] Хеш-таблицы
h0peДата: Воскресенье, 01.08.2010, 22:45 | Сообщение # 1




h0pe
*Король проекта*
Уровень 3
Сообщений: 186  
Репутация: 10  ±
Замечания:  ±
Вступление

Выход нового, 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) из списка предоставленного выше. Простейшим примером использования данных функций является запись числа для юнита:

Code
call SaveReal(udg_Hash, GetHandleId(udg_Unit), 0, 1.00)

В первом аргументе мы передаём функции “SaveReal” хеш-таблицу (“udg_Hash”), во втором хендл юнита “udg_Unit” (созданного ранее и записанного в переменную “udg_Unit”), в третьем “номер ячейки” данного числа(“0”), ну а четвёртым мы передали само число(“1.00”). Если мы захотим записать другие числа, то мы можем либо перезаписать его, использую функцию:

Code
call SaveReal(udg_Hash, GetHandleId(udg_Unit), 0, “2.00”)



Проверка

Что бы проверить занята ли ячейки или нет пользуются функциями:

Code
native  HaveSavedInteger     takes hashtable table, integer parentKey, integer childKey returns boolean  
native  HaveSavedReal      takes hashtable table, integer parentKey, integer childKey returns boolean  
native  HaveSavedBoolean     takes hashtable table, integer parentKey, integer childKey returns boolean  
native  HaveSavedString         takes hashtable table, integer parentKey, integer childKey returns boolean  
native  HaveSavedHandle         takes hashtable table, integer parentKey, integer childKey returns Boolean

В качестве аргументов принимаются хеш-таблица, хендл объекта и номер ячейки. Если запись в ячейке уже существует, то вернётся значение “true”, если же ячейка свободна, то функция вернёт значение “false”. Пример:

Code
if HaveSavedReal (udg_Hash, GetHandleId(udg_Unit), 0) == true then  
      call BJDebugMsg(“True”)  
else  
      call BJDebugMsg(“False”)  
endif



Удаление записи

Бывают ситуации когда необходимо удалить запись из ячейки. Например, стереть запись, содержащую какое-либо число, и записать в эту ячейку ссылку на таймер. Для этого используются функции:

Code
native  RemoveSavedInteger     takes hashtable table, integer parentKey, integer childKey returns nothing  
native  RemoveSavedReal      takes hashtable table, integer parentKey, integer childKey returns nothing  
native  RemoveSavedBoolean     takes hashtable table, integer parentKey, integer childKey returns nothing  
native  RemoveSavedString     takes hashtable table, integer parentKey, integer childKey returns nothing  
native  RemoveSavedHandle     takes hashtable table, integer parentKey, integer childKey returns nothing

Примером очищения ячейки может служить код:

Code

call RemoveSavedReal (udg_Hash, GetHandleId(udg_Unit), 0)

Как и в прошлом примере, в качестве аргументов, мы указываем хеш-таблицу, ссылку на объект и номер ячейки.



Полное удаление записей

Последние 2 функции, которые мы с вами разберём, будут “FlushParentHashtable” и “FlushChildHashtable”. FlushParentHashtable позволяет удалить нам абсолютно все записи из хеш-таблицы. В качестве аргумента указывается только очищаемая хеш-таблица. После использования донной функции хеш-таблицу приходиться инициализировать заново! Пример:

Code
call FlushParentHashtable(udg_Hash)

А вот FlushChildHashtable нужна для удаления записей из одного объекта. Рекомендую использовать данную функцию, например при удалении юнита, так как даже есть вы удалите юнита функцией “RemoveUnit”, то его значения останутся в хеш-таблице. Пример:

Code
call FlushChildHashtable(udg_Hash, GetHandleId(udg_Unit))



Примечания





Примеры использования

Взрыв юнита

Примером использования хеш-таблиц может служить простой пример со взрывом юнита. Например мы хотим, что бы юнит взорвался после каста заклинания. Это очень просто скажите вы. Но если нужно чтобы он взорвался через 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

Если вы уже не плохо знаете жасс и ранее использовали кеш, то для вас не составит труда понять как работает данный пример, ну а для новичков я сделал подсказки и пример, который вы найдёте во вложении.

Автор статьи – RazArt


Live Warcraft - Форум » Разработка карт » GUI и JASS » [Статья] Хеш-таблицы
  • Страница 1 из 1
  • 1
Поиск:
Copyright © 2010 Live Warcraft - Всё для WarCraft, Dota, WoW< World Edit При копировании материалов c сайта ставьте, пожалуйста, активную обратную ссылку на нас!! Теги сайта Карта сайта Хостинг от uCoz ©