Добавлен quq_CCCP
Есть задача крепить к обьекту ссылки на множество триггеров, точное кол-во которых не известно. Своего рода "Group", только для триггеров.
Собственно структуры vJass позволяют создавать структуры с массивами на N элементов, а так же есть хештаблицы с ключам id + N.
Хотелось бы послушать народ о способах реализации этой задачи, мб я что-нибудь упустил?
Собственно структуры vJass позволяют создавать структуры с массивами на N элементов, а так же есть хештаблицы с ключам id + N.
Хотелось бы послушать народ о способах реализации этой задачи, мб я что-нибудь упустил?
Принятый ответ
У меня к каждому юниту крепится ссылка на объект структуры, в которой есть отдельные списки для разных типов баффов. Если же бафф имеет два разных эффекта, то ссылка на него хранится в двух списках. При удалении конфликтов не возникает, потому что при удалении бафф удаляет все ячейки, которые были к нему привязаны, а ячейки удаляются линейно.
Ячейка списка
struct MBSNode
readonly MinionBuff buf
readonly integer number
thistype prev = 0
thistype next = 0
method basicInit takes MinionBuff buf, integer number returns nothing
static if ErrorDetectionEnabled_MBSNode then
if this == 0 then
call ErrorOccurred("Error: MBSNode struct has run out of indexes. Current amount of indexes is 8190", "MBSNodeError")
endif
endif
set this.buf = buf
set this.number = number
endmethod
method removeFromList takes nothing returns nothing
if prev != 0 then
set prev.next = next
endif
if next != 0 then
set next.prev = prev
endif
endmethod
endstruct
struct MBSNodeReal extends MBSNode
real value = 0.
endstruct
struct MBSNodeInt extends MBSNode
integer value = 0
endstruct
struct MBSNodeIntNReal extends MBSNode
integer value = 0
real rvalue = 0.
endstruct
Структура, в которой содержится списки, называется MBS, в ней есть счётчик количества баффов, это нужно для определения, какой бафф был добавлен раньше.
Списки в основном задаются таким макросом.
Списки в основном задаются таким макросом.
Список
// Name - имя типа баффа
// ntyp - тип ячейки
// values - если есть значения у баффа
// bool - если значения типа boolean
// null - нуль для заданного типа значений.
//! textmacro MBSList takes Name, ntyp, values, type, bool, null
private MBSNode$ntyp$ head$Name$
readonly integer buffsAmount$Name$ = 0
method add$Name$Buff takes MinionBuff obj returns MBSNode$ntyp$
local MBSNode$ntyp$ node = MBSNode$ntyp$.create()
if buffsAmount$Name$ == 0 then
set head$Name$ = node
else
set node.next = head$Name$
set head$Name$.prev = node
set head$Name$ = node
endif
set BuffCounter = BuffCounter + 1
set buffsAmount$Name$ = buffsAmount$Name$ + 1
call node.basicInit(obj, BuffCounter)
//call DebugMsg("Current amount of $Name$ buffs is " + I2S(buffsAmount$Name$) + ".")
return node
endmethod
method remove$Name$Buff takes MBSNode$ntyp$ node returns nothing
set buffsAmount$Name$ = buffsAmount$Name$ - 1
if head$Name$ == node then
set head$Name$ = node.next
endif
static if $values$ then
static if $bool$ then
set booleanAmount$Name$ = booleanAmount$Name$ - node.value
set total$Name$Bonus = booleanAmount$Name$ > 0
else
set total$Name$Bonus = total$Name$Bonus - node.value
endif
endif
call node.removeFromList()
call node.destroy()
//call DebugMsg("Current amount of $Name$ buffs is " + I2S(buffsAmount$Name$) + ".")
endmethod
static if $values$ then
static if $bool$ then
private integer booleanAmount$Name$ = 0
readonly boolean total$Name$Bonus = false
else
readonly $type$ total$Name$Bonus = $null$
endif
method change$Name$Value takes MBSNode$ntyp$ node, $type$ value returns nothing
static if $bool$ then
local integer v = B2I(value)
set booleanAmount$Name$ = booleanAmount$Name$ - node.value + v
set total$Name$Bonus = booleanAmount$Name$ > 0
set node.value = v
else
set total$Name$Bonus = total$Name$Bonus - node.value + value
set node.value = value
endif
endmethod
endif
//! endtextmacro
В этой же системе определяется текущее кол-во брони, уязвимый ли он или нет, уровень замедления или ускорения, и пр.
При удалении объекта системы удаляются и все навешанные баффы.
При удалении объекта системы удаляются и все навешанные баффы.
Удаление
// Макрос ниже также используется для удаления баффов конкретного типа при каких-то обстоятельствах.
// pos - бафф положительный.
// Ячейки удаляются с удалением баффа.
//! textmacro DeleteBuffs takes Name, first, pos
static if $first$ then
local MBSNode node = head$Name$
local MBSNode temp
else
set node = head$Name$
endif
loop
exitwhen node == 0
set temp = node.next
$pos$if node.buf.buffdata.negative then
call node.buf.destroy()
$pos$endif
set node = temp
endloop
//! endtextmacro
...
method onDestroy takes nothing returns nothing
//! runtextmacro DeleteBuffs("EoT", "true", "//# ")
//! runtextmacro DeleteBuffs("Shield", "false", "//# ")
//! runtextmacro DeleteBuffs("MoveSpeed", "false", "//# ")
//! runtextmacro DeleteBuffs("Stun", "false", "//# ")
//! runtextmacro DeleteBuffs("Persistence", "false", "//# ")
//! runtextmacro DeleteBuffs("PhysArmor", "false", "//# ")
//! runtextmacro DeleteBuffs("MagcArmor", "false", "//# ")
//! runtextmacro DeleteBuffs("Armor", "false", "//# ")
//! runtextmacro DeleteBuffs("PhysImmune", "false", "//# ")
//! runtextmacro DeleteBuffs("MagcImmune", "false", "//# ")
//! runtextmacro DeleteBuffs("Protection", "false", "//# ")
//! runtextmacro DeleteBuffs("Invul", "false", "//# ")
call DebugMsg("MinionBuffStorage " + I2S(this) + " is deleted.")
endmethod
Сами баффы.
Каждый бафф - отдельная структура, которая наследуется от общей.
Каждый бафф - отдельная структура, которая наследуется от общей.
Бафф
struct MinionBuff
integer typ
Minion target
unit source
CustomPlayer owner
MinionBuffData buffdata
integer currticks = 0
boolean isRunning = false
MBSNode node1
MBSNode node2
MBSNode node3
//! runtextmacro CustomTimer("t", "Timer", "MinionBuff", "false")
method onDestroy takes nothing returns nothing
call DeleteTimer()
call RemoveSavedInteger(Hash, target.id, typ)
call UnitRemoveAbility(target.minion, buffdata.effectid)
set source = null
call DebugMsg("MinionBuff " + I2S(this) + " is deleted.")
endmethod
method basicInit takes Minion host, unit src, CustomPlayer p, integer T returns nothing
static if ErrorDetectionEnabled_MinionBuff then
if this == 0 then
call ErrorOccurred("Error: MinionBuff struct has run out of indexes. Current amount of indexes is 8190", "MinionBuffError")
endif
endif
set typ = T
set target = host
set source = src
set owner = p
set buffdata = p.minion_buffdata[T]
call InitTimer()
call SaveInteger(Hash, target.id, T, this)
//call DebugMsg("MinionBuff " + I2S(this) + " is created.")
endmethod
...
endstruct
Может быть всего 3 разных типа эффекта у баффа, пока максимум было 2.
Примеры баффов
struct BuffMultishotDoT extends MinionBuff
method onCreate takes nothing returns nothing
set node1 = target.addEoTBuff(this)
endmethod
method onDestroy takes nothing returns nothing
call target.removeEoTBuff(node1)
endmethod
method tickAction takes nothing returns boolean
local Tower dd
if UnitExists(source) then
set dd = GetUnitUserData(source)
call dd.dealDamage(target, AbilMultishot(dd.abil).dot, AbilMultishot.dottype, false)
return currticks == 0
endif
return true
endmethod
static method launch takes Minion m, Tower caster returns nothing
// target, sourceunit, owner, name, neg, disabl, chkowne, args
//! runtextmacro InitBuff("m", "caster.tower", "caster.owner", "MultishotDoT", "true", "false", "false", "")
call startPeriodic(buffdata.startticks)
endmethod
endstruct
struct BuffMultishotSlow extends MinionBuff
method onCreate takes real slow returns nothing
set node1 = target.addMoveSpeedBuff(this, slow)
endmethod
method onDestroy takes nothing returns nothing
call target.removeMoveSpeedBuff(node1)
endmethod
static method launch takes Minion m, Tower caster, real slow returns nothing
//! runtextmacro InitBuff("m", "caster.tower", "caster.owner", "MultishotSlow", "true", "true", "false", "slow")
call start()
endmethod
endstruct
Макрос InitBuff инициализирует любой бафф, но вопрос не об устройстве баффов, потому опустим его полное устройство. При вызове баффа (метод launch) делаются некоторые проверки, если всё хорошо, то создаётся объект и вызывается его метод onCreate, где сохраняются ссылки на его ячейки.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Ред. Пушистый
По надобности добавляешь в структуру методы для манипуляций с массивом
Есть в краце - есть много, баффов\дебафов реазизованных на мемхаке, и требуется единая бд для работы с ними, чтобы реализовать сложение\подавление\рассеивание эффектов. До пока их было мало я просто делал ифами, но щяс их стало уже довольно много, и я решил привести все это дело в порядок, предварительно я решил посоветоваться с людьми, мб кто то уже делал что то подобное и реализовал это как-нибудь иначе?
На таймер крепятся все бафы/дебафы, когда он истекает = статы пропадают
Отдельная ХТ под всю эту систему, пока хз, как будет проседать под сильной нагрузкой
На хендл юнита крепятся таймеры (в свободные ячейки(пока всего лишь 30))
Каждый новый баф кидается в новую ячейку, и потом лупом перебираются те, что ещё есть.
Скрины:
Ред. nazarpunk
Для того же стана - не годятся таймеры, не говоря про псевдоконтроль. Идея хранить все эти триггеры-баффы в одном месте и удобно взаимодействовать с ними.