Среда, 15.05.2024, 11:20
   
 
Категории
Триггеры / GUI [3]
Jass / AI скрипты [3]
Текстурирование [3]
Моделлинг [3]
Ландшафтинг [3]
Разные статьи [3]
Поиск
Мини-Профиль
Среда
15.05.2024
11:20

[ Управление профилем ]
Главная » Статьи » Модмейкинг » Jass / AI скрипты

Hashtable - работаем с хеш-таблицей
Хеш-таблица — это структура данных, реализующая интерфейс ассоциативного массива, а именно, она позволяет хранить пары (ключ, значение) и выполнять три операции: операцию добавления новой пары, операцию поиска и операцию удаления пары по ключу.

В статье мы рассмотрим самую распространённую область её применения в wc3: прикрепление данных к объекту, на простейшем примере. Статья предполагает, что читатель знаком с основами работы таймеров. Пример будет только на обычном Jass, для совместимости (да и не все умеют работать c v/cJass).

Если вы знакомы с кэшем в wc3, то принцип работы с ним схож, с принципом работы с хеш-таблицей. Только вместо строковых ключей, хеш-таблица использует целочисленные значения (integer).

Допустим, мы хотим создать спелл, в котором врагу на протяжении некоторого времени с малым периодом постоянно наносится урон (для которого wait не подходит).
Мы создали триггер (в редакторе триггеров, для простоты объяснения) с событием каста, дали ему условия и действия:
Код
function Spell takes nothing returns nothing  
local unit caster = GetSpellAbilityUnit() //Кастер  
local unit target = GetSpellTargetUnit() //Цель  
endfunction  

//Проверка спелла  
function SpellCond takes nothing returns boolean  
return GetSpellAbilityId()=='A000'  
endfunction  

//===========================================================================  
function InitTrig_Spell takes nothing returns nothing  
set gg_trg_Spell = CreateTrigger()  
call TriggerRegisterPlayerUnitEvent(gg_trg_Spell,Player(0),EVENT_PLAYER_UNIT_SPELL_CAST,null)  
call TriggerAddCondition(gg_trg_Spell,Condition(function SpellCond))  
call TriggerAddAction(gg_trg_Spell,function Spell)  
endfunction


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

Код
function SpellDamage takes nothing returns nothing  
call UnitDamageTarget(...)  
endfunction  

function Spell takes nothing returns nothing  
local unit caster = GetSpellAbilityUnit() //Кастер  
local unit target = GetSpellTargetUnit() //Цель  
local timer t = CreateTimer() //Создаём таймер  

call TimerStart(t,0.04,true,function SpellDamage) //Стартуем таймер  
endfunction


Но как передать в функцию, кто кому должен наносить урон, и сколько раз? Тут нам на помощь и приходит хеш-таблица. Перед работой нужно создать и инициализировать глобальную хеш-таблицу, желательно при инициализации карты.

Делать это нужно только один раз, например в этом триггере:

Код
function InitTrig_Spell takes nothing returns nothing  
set gg_trg_Spell = CreateTrigger()  
call TriggerRegisterPlayerUnitEvent(gg_trg_Spell,Player(0),EVENT_PLAYER_UNIT_SPELL_CAST,null)  
call TriggerAddCondition(gg_trg_Spell,Condition(function SpellCond))  
call TriggerAddAction(gg_trg_Spell,function Spell)  

set udg_hash = InitHashtable() //Инициализируем хеш-таблицу  
endfunction


Работает хеш-таблица так: [ключ|значение]. Только как ключ мы используем уникальный id объекта, а точнее - id нашего таймера.

На него и будем сохранять нужные нам данные:

Код
function Spell takes nothing returns nothing  
local unit caster = GetSpellAbilityUnit() //Кастер  
local unit target = GetSpellTargetUnit() //Цель  
local timer t = CreateTimer() //Создаём таймер  
local integer h = GetHandleId(t) //Узнаём id таймера  

//Сохраняем объекты с ключом - id таймера  
call SaveUnitHandle(udg_hash,h,1,caster) //Сохраняем кастера со значением 1  
call SaveUnitHandle(udg_hash,h,2,target) //Сохраняем цель со значением 2  
call SaveInteger(udg_hash,h,3,125) //Сохраняем количество ударов, из расчёта, что урон наносится в течение 5 секунд (5/0.04=125).  

call TimerStart(t,0.04,true,function SpellDamage) //Стартуем таймер  

//Не забываем устранять утечки  
set caster = null  
set target = null  
set t = null  
endfunction


Готово, данные сохранены, теперь их можно будет достать в функции нанесения урона, на которую запущен таймер.
Доставать данные мы будем тоже по id таймера:

Код
function SpellDamage takes nothing returns nothing  
local timer t = GetExpiredTimer() //Наш таймер - истёкший  
local integer h = GetHandleId(t) //Узнаём id таймера  
local unit caster = LoadUnitHandle(udg_hash,h,1) //Достаём кастера из значения 1  
local unit target = LoadUnitHandle(udg_hash,h,2) //Достаём цель из значения 2  
local integer counter = LoadInteger(udg_hash,h,3) //Достаём количество ударов  

if counter>0 then //Если количество ударов больше 0  
call UnitDamageTarget(caster,target,1.0,true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null) //Наносим урон цели  
call SaveInteger(udg_hash,h,3,counter-1) //Сохраняем количество ударов, убавленное на 1  
else //Иначе  
call DestroyTimer(t) //Уничтожаем таймер  
//Очищаем хеш-таблицу, чтобы избежать утечек и наложений  
call FlushChildHashtable(udg_hash,h) //Очищаем ключ по id  
endif  

//Не забываем устранять утечки  
set caster = null  
set target = null  
set t = null  
endfunction


Спелл готов, данные записываются, достаются и удаляются из хеш-таблицы.
Вот что у нас получилось в итоге:

Код
function SpellDamage takes nothing returns nothing  
local timer t = GetExpiredTimer()  
local integer h = GetHandleId(t)  
local unit caster = LoadUnitHandle(udg_hash,h,1)  
local unit target = LoadUnitHandle(udg_hash,h,2)  
local integer counter = LoadInteger(udg_hash,h,3)  

if counter>0 then  
call UnitDamageTarget(caster,target,1.0,true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)  
call SaveInteger(udg_hash,h,3,counter-1)  
else  
call DestroyTimer(t)  
call FlushChildHashtable(udg_hash,h)  
endif  

set caster = null  
set target = null  
set t = null  
endfunction  

function Spell takes nothing returns nothing  
local unit caster = GetSpellAbilityUnit()  
local unit target = GetSpellTargetUnit()  
local timer t = CreateTimer()  
local integer h = GetHandleId(t)  

call SaveUnitHandle(udg_hash,h,1,caster)  
call SaveUnitHandle(udg_hash,h,2,target)  
call SaveInteger(udg_hash,h,3,125)  

call TimerStart(t,0.04,true,function SpellDamage)  

set caster = null  
set target = null  
set t = null  
endfunction  

function SpellCond takes nothing returns boolean  
return GetSpellAbilityId()=='A000'  
endfunction  

//===========================================================================  
function InitTrig_Spell takes nothing returns nothing  
set gg_trg_Spell = CreateTrigger()  
call TriggerRegisterPlayerUnitEvent(gg_trg_Spell,Player(0),EVENT_PLAYER_UNIT_SPELL_CAST,null)  
call TriggerAddCondition(gg_trg_Spell,Condition(function SpellCond))  
call TriggerAddAction(gg_trg_Spell,function Spell)  

set udg_hash = InitHashtable()  
endfunction
Категория: Jass / AI скрипты | Добавил: TrallFace (02.03.2013)
Просмотров: 2071 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Мини-чат
Топ Пользователей
Случайные обои
Случайные картинки
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Кто нас сегодня посетил

Шаблоны для ucoz