а если я создаем локалки в процессе инициализации код, они будут существовать всю игру. Или только существуют в процессе инициализации? И уже перестанут существовать?
Блок кода do/end разделяет те же правила. То есть
Код
do
local a = 10 -- Локальная переменная внутри блока do/end
end
-- Блок кода завершен, локальной переменной "a" больше не существует.
Я распишу твой пример
Код
do -- создаём область видимости, чтоб не конфликтовать с другим кодом
local InitGlobalsOrigin = InitGlobals -- хукаем функцию InitGlobals
-- Переменная InitGlobalsOrigin является локальной и существует
-- только внутри текущего do/end блока
function InitGlobals() -- объявляется глобальной и заменяет собой оригинальный InitGlobal
InitGlobalsOrigin() -- переменная InitGlobalsOrigin продолжает существование внутри текущей функции
local Table = { {},{},{} } -- локальная таблица, которая существует в передлах текущей функции
end
-- Конец функции, здесь Table уже нет.
end
-- Конец блока, локальной переменной InitGlobalsOrigin здесь не существует.
-- Однако, она продолжает свое существование внутри той InitGlobals функции,
-- которая была объявлена внутри do/end блока
Для того же, для чего и локальные переменные - ограничить область видимости (а зачастую и время жизни) объекта текущим блоком кода
Код
function MyFunc()
local a = 10
local function InnerFunc()
print(a)
end
end
Переменная a внутри функции MyFunc объявлена локальной. следовательно, доступ к этой переменной возможен только внутри этой функции. Так как функция InnerFunc так же определена внутри функции MyFunc, она имеет доступ к локальной переменной a.
Поскольку функция InnerFunc так же как и переменная a объявлена локальной, доступ к этой функции возможен только внутри тела функции MyFunc.
При это, функция InnerFunc, конкретно в данном примере, как и переменная a, будучи локальной, существует только до тех пор, пока выполняется код объемлющей функции. То есть, она прекратит свое существование, в момент выхода из функции MyFunc
Но, что важно, если мы уберем слово local при объявлении функции InnerFunc
Код
function MyFunc()
local a = 10
function InnerFunc()
print(a)
end
end
то внутри тела функции MyFunc мы создаем глобальную функцию с именем InnerFunc. То есть, если до момента вызова функции MyFunc в глобальной области видимости не существовало чего-либо с именем InnerFunc, то оно будет создаваться и назначаться (переназначаться) с каждым вызовом MyFunc.
Опять же, не нужна константа MaxLifeBonus. Присвоить этой переменной значение 0, в теле функции проверить, если оно равно 0, то выщитать MaxLifeBonus при добавлении способности.
И хуки с предупреждением в дебаг моде на функции GetUnitState, GetUnitStateSwap, GetUnitStatePercent, GetUnitLife все таки нужны.
Если порядок исполнения зависит от порядка регистрации событий, то можно было бы зарегистрировать свой триггер на олов урона после регистрации всех пользовательских. Код этого триггера исполнялся бы после всех пользовательских и это хороший момент для выдачи способности/запуска таймера.
Но это прокатило бы если бы хуки вызывали хук-функцию после оригинальной, а не перед.
Было бы удобнее хукать TriggerRegisterUnitEvent, но поскольку vJass позволяет хукать функции только до их выполнения, наш хук будет выполнятся перед основной функцией, в то время как нам надо после. Шипко изящного решения что-то не высматривается.
Тем не менее, на данном этапе можно намутить хотя бы это
Код
static if DEBUG_MODE then
private function hook_GetUnitState takes unit u, unitstate state returns nothing
if state == UNIT_STATE_MAX_LIFE and GetUnitAbilityLevel(u, HealthAbility) > 0 then
call BJDebugMsg("WARNING: попытка получить максимальное здоровье юнита, увеличенное библиотекой Negate Damage")
endif
endfunction
hook GetUnitState hook_GetUnitState
endif
По крайней мере пользователь будет знать, где ошибся. Аналогичный хук нужен как минимум для ГУИшного GetUnitStateSwap
PT153, не думаю, что это возможно.
Но!
Но мы вероятно можем контролировать момент, когда мы добавляем макс. хп. Варкрафт ведь линеен, у него нет многопоточности, он не порождает параллельных процессов. Это означает что все триггеры на получение урона юнитом, срабатывают последовательно. Но под влиянием каких правил выстраивается последовательность исполнения триггеров? В порядке назначения им событий? Или в порядке создания триггеров? Зависит ли очередь от величины числового значения хэндла? В порядке регистрации собития (TriggerRegister...Event)? Это очередь или стек?
Зная, как выстраивается последовательность, мы можем хукнуть подходящую функцию таким образом, чтобы максимальное хп юнита увеличивалось не в момент вызова функции, а после того как все пользовательские триггеры отработали.
Ну самый простой вариант уже дали, с хэш-таблицей, там есть конкретная функция проверки наличия записи
Я вообще не понимаю, почему ГУИшники хэш-таблицу так не любят. С одной стороны, это избавляет их от гигантского массива переменных, с другой стороны, можно использовать хоть русский язык для сохранения значений
А что делать, если пользователь использует другие библиотеки, затрагивающие максимальный запас здоровья? Чужие наработки, сделанные на заказ. Да и что делать тогда ГУИшнику, если в его карте уже тонна обращений к дефолным бж-функциям?
А что если пользователь совершает какие-то операции с максимальным запасом здоровья юнита, после вызова твоей функции? Ведь в таком случае, он будет работать с максимальным запасом здоровья, увеличенным способностью из твоей библиотеки.
Например, у пользователя в карте есть такая способность
Карающее воздаяние мстительного возмездия (пассивное)
Всякий урон против героя провоцирует взрывную волну, которая наносит урон всем противникам в размере 20% от максимального запаса здоровья героя. Перезарядка: 10 секунд.
Предположим, у владельца способности 1000 ед. здоровья. Если пользовательский триггер, отвечающий за эту способность, срабатывает ДО вызова твоей функции, то все работает ожидаемо и противникам вокруг наносятся запланированные 200 ед. урона. Однако, если очередь триггеров выстроилась таким образом, что триггер, отвечающий за способность срабатывает ПОСЛЕ вызова твоей функции, то из-за того что твоя функция увеличивает макс. запас здоровья на 1 000 000, владелец способности сеет вокруг кровавый апокалипсис нанося более 200000 урона за раз,
Та же невообразимая хурма может получится со всякими щитами, которые накладываются на юнита в момент получения урона и зависят от макс. запаса здоровья. Да и вообще с этой механикой можно наворотить кучу всего.
То есть, ты исцеляешь юнита на весь миллион, который дает способность. А зачем? С одной стороны, переменная HealthAmount не несет особого смысла, ведь ты можешь просто вычислить то количество здоровья, которое дается юниту. Взять макс. здоровье до вручения способности и макс. здоровье после. Одно вычитаем из другого и вот оно значение. То есть тут открывается простор для ошибок со стороны конечного пользователя, если он решит отредактировать способность но забудет внести соответствующую правку в код.
С другой стороны, библиотека подразумевает уменьшение полученного урона, верно? Соответственно, тебе достаточно добавить юниту текущее здоровье, в размере уменьшенного урона. То есть не
Теперь не ясно назначение функции HealUnits.
Технически, мы даем способность с дополнительным здоровьем только для того чтобы мы могли исцелить юнита, в случае, если необходимое исцеление превышает его максимальный запас здоровья. Следовательно, все, что нам нужно сделать по истечению таймера, это отнять у юнита эту способность. Нас даже не беспокоит, умер ли юнит на тот момент, нам нужно только отнять способность и установить его текущее здоровье равное здоровью до удаления способности, что-то вроде этого
Код
local unit u
local real currentHealth
loop
set u = FirstOfGroup(...)
exithwen u == null
set currentHealth = GetWidgetLife(u)
call UnitRemoveAbiity(...)
call SetWidgetLife(u, currentHealth)
call GroupRemoveUnit(...)
endloop
Первые ответов пятнадцать будет о том что от тебя говной воняет, раз тебя даже в гугле забанили, а там где-то в конце может и затерется маломальски вменяемый ответ.
Потом видосики мало помогают, нужно запоминать Хотя-бы базовые функции и синтаксис, а по видео это не сделать, особенно с такими предметами.
Не могу согласиться. Есть такое понятие как сопроводительный материал. Статьи по Жассу/вЖассу это замечательно, как и процесс зазубривания, но наблюдение какой-то активности другого человека со стороны заставляет тебя осмысливать эту самую чужую активность, углубляя таким образом понимание процессов, просто хотя бы за счет сверки имеющихся знаний с происходящим перед глазами.
Присвоить константе AttackType такой тип атаки, у которого одинаковый бонус ко всем типам брони.
В жассе есть дыра с дополнительным типом атаки, она используется для определения типов брони и ее количества в разных системах. Обсуждение можно найти, например, тут.
Вкратце, базовые типы атаки заданы константами
Нипанаятна.
С одной стороны, юниту необходимо установить его текущее здоровье в момент выдачи способности с дополнительным хп, поскольку, при увеличении максимального запаса здоровья, процент текущего запаса здоровья сохраняется, что изменяет его численное количество (или нет?).
С другой стороны, отхиливать юнита нужно в момент нанесения урона. Если делать это в таймере с нулевой задержкой, то в момент исполнения кода таймера юнит уже может быть мертв от того самого урона, от которого его полагалось отлечить.
» WarCraft 3 / Опрос варкрафтеров XGM
Отредактирован GetLocalPlayer
» WarCraft 3 / зачем в lua нужны локальные функции?
» WarCraft 3 / зачем в lua нужны локальные функции?
Поскольку функция InnerFunc так же как и переменная a объявлена локальной, доступ к этой функции возможен только внутри тела функции MyFunc.
При это, функция InnerFunc, конкретно в данном примере, как и переменная a, будучи локальной, существует только до тех пор, пока выполняется код объемлющей функции. То есть, она прекратит свое существование, в момент выхода из функции MyFunc
Но, что важно, если мы уберем слово local при объявлении функции InnerFunc
» WarCraft 3 / Memory hack API v1.4
» WarCraft 3 / Как работать с картой в виде папки?
» WarCraft 3 / Negate Damage library
И хуки с предупреждением в дебаг моде на функции GetUnitState, GetUnitStateSwap, GetUnitStatePercent, GetUnitLife все таки нужны.
» WarCraft 3 / Negate Damage library
Но это прокатило бы если бы хуки вызывали хук-функцию после оригинальной, а не перед.
Отредактирован GetLocalPlayer
» WarCraft 3 / Negate Damage library
Тем не менее, на данном этапе можно намутить хотя бы это
Отредактирован GetLocalPlayer
» WarCraft 3 / Negate Damage library
Но!
Но мы вероятно можем контролировать момент, когда мы добавляем макс. хп. Варкрафт ведь линеен, у него нет многопоточности, он не порождает параллельных процессов. Это означает что все триггеры на получение урона юнитом, срабатывают последовательно. Но под влиянием каких правил выстраивается последовательность исполнения триггеров? В порядке назначения им событий? Или в порядке создания триггеров? Зависит ли очередь от величины числового значения хэндла? В порядке регистрации собития (TriggerRegister...Event)? Это очередь или стек?
Отредактирован PT153
» WarCraft 3 / Наличие типа юнита в массиве
» WarCraft 3 / Negate Damage library
Отредактирован GetLocalPlayer
» WarCraft 3 / Negate Damage library
Например, у пользователя в карте есть такая способность
Отредактирован GetLocalPlayer
» WarCraft 3 / Negate Damage library
» WarCraft 3 / Negate Damage library
» WarCraft 3 / Negate Damage library
Технически, мы даем способность с дополнительным здоровьем только для того чтобы мы могли исцелить юнита, в случае, если необходимое исцеление превышает его максимальный запас здоровья. Следовательно, все, что нам нужно сделать по истечению таймера, это отнять у юнита эту способность. Нас даже не беспокоит, умер ли юнит на тот момент, нам нужно только отнять способность и установить его текущее здоровье равное здоровью до удаления способности, что-то вроде этого
» WarCraft 3 / Использование ShellExecute
» WarCraft 3 / Друг
» WarCraft 3 / Обучение jass
» WarCraft 3 / Get Unit Armor
» WarCraft 3 / Get Unit Armor
» WarCraft 3 / Get Unit Armor
Вкратце, базовые типы атаки заданы константами
» WarCraft 3 / Negate Damage library
» WarCraft 3 / Negate Damage library
С одной стороны, юниту необходимо установить его текущее здоровье в момент выдачи способности с дополнительным хп, поскольку, при увеличении максимального запаса здоровья, процент текущего запаса здоровья сохраняется, что изменяет его численное количество (или нет?).
С другой стороны, отхиливать юнита нужно в момент нанесения урона. Если делать это в таймере с нулевой задержкой, то в момент исполнения кода таймера юнит уже может быть мертв от того самого урона, от которого его полагалось отлечить.
» WarCraft 3 / Спавн юнита с помощью фрейма