Добавлен , опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
Прочее
Тип:
Наработка
Версия Warcraft:
1.26a+
Hashtable 8000 | Cool Hashtable

Введение

При сохранении данных в хеш-таблице используется следующая формула:
Объект -> уникальный идентификатор(UID) -> номер ячейки массива
Для получения UID большинства объектов в вакрафте используется функция GetHandleId().
Хеш-таблица очень удобна при построении многих алгоритмов и систем. Но создание встроенных hashtable ограничено 256-ю. Эта наработка призвана обойти сей недостаток.

Описание

Область применения
Постоянное хранилище. Временное хранилище. Передача больших объемов данных в функцию.
Характеристики
  • Количество элементов внутри одной таблицы до 18747.
  • Количество таблиц до 8190.
Наработка добавляет несколько новых vjass типов. Каждый тип является оберткой для удобного обращения к нативной хеш-таблице. Теперь их можно создавать, удалять, хранить и передавать в качестве параметра. Во время конечной оптимизации карты неиспользуемые типы можно отключить, закоментировав вызов макроса так, как это показано на скриншоте.
спойлер
Все названия типов выглядят как h8k_type, где type - название нативного типа для которого создается таблица. Ключем всегда является тип integer.
  • Пример таблицы для типа real
h8k_real var = h8k_real.create() // создать
var[-81] = 15 // сохранить
var[R2I(var[-81])] = 7
var[15] -> 7 // получить
var.remove(15) // освободить
var.destroy() // удалить таблицу
О хранении элементов
Так как эти хеш-таблицы основаны на встроенной, то имеют такие же особенности хранения данных. А именно: если удалить объект ссылочного типа (например, вызвать RemoveUnit() или юнит просто разложится) то его значение автоматически станет null, хотя ячейка не освободится. Если обратиться к несуществующему элементу, то в ответ получите то же, как если бы обратились к стандартной jass hashtable.
Список поддерживаемых типов данных
(string)
(destructable)
(effect)
(integer)
(item)
(lightning)
(multiboard)
(multiboarditem)
(player)
(real)
(rect)
(region)
(timer)
(trigger)
(unit)

Пример

Допустим, у нас есть разные типы юнитов, которые по разному взаимодействуют со способностями персонажа. В моем примере заводятся две глобальные таблицы для хранения существ типа огонь и вода:
globals
  h8k_boolean bdWater
  h8k_boolean bdFire
endglobals
В триггере инициализации прописываем типы существ, которые заранее имеют свой тип. У меня это элеменаль огня и воды соответственно.
  set bdWater = h8k_boolean.create()
  set bdFire = h8k_boolean.create()
  
  set bdWater['hwat'] = true
  // ...
  set bdFire['nlv1'] = true
Далее будет способность "Облить", которая добавляет элемент любому существу:
  if GetSpellAbilityId() == 'A001' then
    set bdWater[GetHandleId(GetSpellTargetUnit())] = true
    // ...
  endif
Теперь мы можем сделать проверку на нахождение юнита или его типа в соответствующей таблице. И, в зависимости от проверки, наносить дополнительный урон при применении нашего особого заклинания. В данном случае заклинание детектится по наличию определенного бафа в событии получения урона:
  local unit tu = GetTriggerUnit()
  local integer hid = GetHandleId(tu)
  local integer typ = GetUnitTypeId(tu)
  // ...
  if GetUnitAbilityLevel(tu, 'BNbf') > 0 and (bdWater[typ] or bdWater[hid]) then
    call UnitRemoveAbility(tu, 'BNbf')
    call UnitDamageTarget(GetEventDamageSource(), tu, 100, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
  endif
Старый пример
Описание
  1. В области применения случайно появляются N предупреждающих знаков.
  2. Через некоторое время в этих местах поочередно происходят электовзрывы.
Реализация
Будем использовать хеш-таблицу как локальный массив.
  1. Создаем хеш-таблицы для хранения координат и эффектов. Сохраняем количество точек и хеш-таблицы на таймер.
  2. Поочередно создаем взрывы в нужных местах.

Установка

Скопировать папку HT8k
В архиве находятся две карты HT8k_vjass_cjass и HT8k_vjass. Для первой требуется поддержка vjass и cjass, для второй только vjass.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
6
4 года назад
0
(string)
(destructable)
(effect)
(integer)
(item)
(multiboard)
(multiboarditem)
(player)
(real)
(rect)
(region)
(timer)
(trigger)
(unit)
Но... но как же (lightning)?
0
17
4 года назад
0
Добавлено (lightning)
0
13
4 года назад
0
Внимание, вопрос может оказаться гулпым
Что насчёт возможности стора кастомных типов (vjass types или struct)?
1
30
4 года назад
1
vjass types
Это же integer
1
17
4 года назад
1
Что насчёт возможности стора кастомных типов (vjass types или struct)?
vJass не типобезопасен. Все типы vJass это псевдонимы для integer, поэтому для сохранения данных этого типа используется integer.
0
17
3 года назад
0
Обновление
Изменен синтаксис обращения к таблицам, теперь можно писать так:
//! runtextmacro HT8k("myInt","integer")
//! runtextmacro HT8k("myStr","string")
myInt i = myInt.create()
myStr s = myStr.create()
i[3] = 8
i[-50] = i[3]
s[i[3]] = "hello"
s.destroy()
1
37
3 года назад
1
Там вроде вся фича была в том, что можно хранить разные типы в одной хешмапе?
2
22
3 года назад
2
256 хэштаблиц шооо?) мне больше одной пока что не приходилось юзать
0
17
3 года назад
Отредактирован Vlod
0
Ну если кто то чем то не пользовался, разве это значит, что это не нужно) В lua, например, все построено на таблицах, и код получается гибким и легким.
ScorpioT1000:
Там вроде вся фича была в том, что можно хранить разные типы в одной хешмапе?
Когда в статических языках можно было класть в переменную значения разных типов.
СмысОл в том, чтобы не указывать тип переменной при каждом обращении:
call SaveUnitHandle(hashtable, _, key, unit)
call SaveEffectHandle(hashtable, _, key, effect)

set target[key] = unit
set baff[key] = effect
0
22
3 года назад
Отредактирован PROSHELDOTU
0
Ну если кто то чем то не пользовался, разве это значит, что это не нужно)
я так и не говорил, просто удивлён )
1
17
3 года назад
1
Обновление
  • Отобрана возможность задавать собственные названия типов для таблиц. Теперь все типы имеют строго определенный синтаксис.
  • Теперь все типы доступны сначала, а пользователь может лишь отключать ненужные для оптимизации.
  • Добавлен новый показательный пример.
  • Наработка разделена на 2 версии: cjass+vjass и vjass only. Обе имею одинаковую установку и синтаксис обращения, а отличаются лишь внутренней реализацией.
0
37
3 года назад
0
Зачем тогда cjass?
0
13
3 года назад
0
ScorpioT1000, так ведь он в принципе не нужен. О_о
0
17
3 года назад
0
Обнаружено, что если использовать эти хештаблицы в library, то все обращения автоматически заменяются на вызов TriggerEvaluate(), потому что код библиотек помещается выше.

Обновление
  • Оптимизирован код, уменьшено его количество.
  • Все собрано в одну библиотеку. Теперь для использования наработки в других библиотеках достаточно указать H8k в requires.

Для обнаружения таких ситуаций вы можете добавить [forcemethodevaluate] в jasshelper.conf (спасибо PT153)
2
17
3 года назад
2
Обновление
  • Исправлена утечка.
  • Для версии vjass_cjass использованы define вместо textmacro, больше нет дополнительного окна консоли во время сохранения карты.
0
9
3 месяца назад
0
Если вдруг вернешься к теме, выложи весь код под спойлер на сайте. Чтобы можно было перед скачиваем смотреть.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.