Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно. Вам необходимо обновить браузер или попробовать использовать другой.
Если герою ближнего боя дать абилку троля Berskers Rage, то при переключении она будет уменьшает радиус атаки до нуля, и он перестанет атаковать вовсе. В стандартном файле доты с абилками стоит значение, на которое уменьшается базовая дальность троля. В SpellLibrary - это же значение, но со знаком минус. Есть какие-нибудь варианты исправить это? Нужно чтобы у мили-героев с этой абилкой и при ее переключении была их обычная дальность атаки. Из SpellLibrary абилка работает не полностью. Модификатор на изменение дальности атаки MODIFIER_PROPERTY_ATTACK_RANGE_BONUS то ли сломан, то ли я криворукий. Рассматривал также вариант с внешним луа-модификатором, но заставить его работать при переключении главной абилки не смог.
Если герою ближнего боя дать абилку троля Berskers Rage, то при переключении она будет уменьшает радиус атаки до нуля, и он перестанет атаковать вовсе. В стандартном файле доты с абилками стоит значение, на которое уменьшается базовая дальность троля. В SpellLibrary - это же значение, но со знаком минус. Есть какие-нибудь варианты исправить это? Нужно чтобы у мили-героев с этой абилкой и при ее переключении была их обычная дальность атаки. Из SpellLibrary абилка работает не полностью. Модификатор на изменение дальности атаки MODIFIER_PROPERTY_ATTACK_RANGE_BONUS то ли сломан, то ли я криворукий. Рассматривал также вариант с внешним луа-модификатором, но заставить его работать при переключении главной абилки не смог.
GetAttackRange крашит доту, если вызывается во внешнем луа-модификаторе, в котором используется через self:GetCaster(). Если прописать это в gamemode, то берется конечный ренж после всех модификаторов, а надо чтобы бралось до, т.е. базовый ренж.
GetBaseAttackRange не распознается нигде. Консоль пишет, что пытается вызвать этот метод (nil value). Бла бла бла.
Тот метод, который мне в итоге нужен, не работает. Кто-нибудь знает функцию, которая может заменить модификатор MODIFIER_PROPERTY_ATTACK_RANGE_BONUS?
Я опробовал GetAttackRange() на self:GetCaster(), у меня никакого краша не было.
Если глянуть GitHub, то становистя понятно, что все пользуются GetAttackRange(), а вот GetBaseAttackRange() почему-то совершенно не в моде. Скорее всего, последний жалуется на неприменимость ко всем классам, кроме "CDOTA_BaseNPC" в следствии проблемы, что была у меня здесь. То есть, у остальных entity попросту нет такого метода и его надо определить в них.
Ну либо отыскать функцию, что даст тебе именно того entity, подобно тому, что я описывал здесь.
Но думаю, легче будет разобраться в GetAttackRange(): скинь текст, что пишет при краше.
И еще на крайняк можно сделать пассивку, где можно прописать "специальную" величину (ability special), которой ты присвоишь заранее значение, равное base range юнита, которому дашь эту пассивку и уже через нее доставать эту величину, т.е. base range))
3. Создал луа-модификатор berserkers_rage_bonus_range_modifier.lua в папке scripts/vscripts/heroes/troll_warlord :
Код:
if berserkers_rage_bonus_range_modifier == nil then
berserkers_rage_bonus_range_modifier = class({})
end
4. Т.к. я не стал использовать дополнительную способность, чтобы определять применять модификатор или нет, то прикрепил я его в gamemode.lua в функции GameMode:InitGameMode()
function GameMode:FilterExecuteOrder( filterTable )
local ability = filterTable[ "entindex_ability" ] --записываем индекс способности из приказа
if ability > 0 then -- если это действительно способность или предмет
local order = filterTable[ "order_type" ] -- записываем тип приказа
if order == DOTA_UNIT_ORDER_CAST_TOGGLE then -- если применилась переключаемая способность
local ab = EntIndexToHScript( ability ) -- запоминаем саму способность вместо ее индекса
local ability_name = "troll_warlord_berserkers_rage" --записываем способность, наличие которой и будет определяющим фактором
if ab:GetAbilityName() == ability_name then -- если использованная способность та, по которой будем проверять
local hero = EntIndexToHScript( filterTable[ "units" ][ "0" ] ) -- запомнить героя, который ее применил
local modifier_name = "modifier_" .. ability_name -- для удобства запомнить модификатор, который появляется у героя именно тогда, когда способность во включенном состоянии (он встроенный и идет вместе со способностью, если ее не переписывать полностью)
local modifier_name_fix = "berserkers_rage_bonus_range_modifier" -- запомнить имя нашего самописного луа-модификатора
-- функция выполняется до применения способности, т.к. фильтр и определяет будет ли она выполнена или нет. Поэтому перед включением способности у героя еще не будет модификатора, а значит ренж атаки еще не поменялся. От этого и отталкиваемся.
if not hero:HasModifier( modifier_name ) then -- если у героя нет модификатора от родной способности
local attack_range = hero:GetAttackRange() -- записываем ренж атаки героя
hero:AddNewModifier( hero, nil, modifier_name_fix, { range = attack_range } ) -- применяем луа-модификатор к герою, передавая в параметр тот самый ренж
else -- если у героя есть модификатор от способности(т.е. способность была включена), то при вЫключении способности, он будет удален
hero:RemoveModifierByName( modifier_name_fix ) -- вместе с луа-модификатором
end
end
end
end
--поскольку сама абилка выполняется в любом случае, как и любой другой приказ, пихаем return в самый конец
return true
end
7. Записал переданный ренж при создании модификатора в файле самого модификатора:
Код:
function berserkers_rage_bonus_range_modifier:OnCreated( kv )
-- kv - { range = attack_range } из пункта 6
if IsServer() then
self.range = kv.range
end
end
Обязательно использовать IsServer(), иначе будет "ругаться на все что только можно и вылетать по поводу и без повода".
8. Для изменения ренжа героя используется модификатор MODIFIER_PROPERTY_ATTACK_RANGE_BONUS. Поскольку для поставленной задачи надо охватить весь пул существующих в доте героев, то значение для этого модификатора должно быть плавающим и зависеть от имеющейся дальности у героя, которую я записал в предыдущем пункте. Это значит, что этот модификатор (он же функция) надо переопределить, т.к. по умолчанию подразумевается, что он будет использоваться в kv-файле со статичным значением. Переопределил в файле модификатора:
Код:
function berserkers_rage_bonus_range_modifier:DeclareFunctions()
local funcs = {
MODIFIER_PROPERTY_ATTACK_RANGE_BONUS
}
return funcs
end
function berserkers_rage_bonus_range_modifier:GetModifierAttackRangeBonus( params )
if IsServer() then
return (( self.range - 128 ) * -1 )
end
return 0
end
Сервер будет использовать для расчетов формулу из переопределенной функции:
Код:
(( self.range - 128 ) * -1 )
где self.range - сохраненный ранее изначальный ренж, 128 - ренж мили героя, -1 - т.к. при использовании модификатора значения складываются, а нам надо вычесть.
Если не делать первых 2 пункта, то эта формула примет вид:
Код:
( 372 - ( self.range - 128) )
где 372 - это то самое значение в AbilitySpecial, которое отвечает за урезание ренжа героя для оригинальной способности в npc_abilities.txt
9. До кучи скрыл модификатор, чтобы глаза не мозолил
Код:
function berserkers_rage_bonus_range_modifier:IsHidden()
return true
end
function berserkers_rage_bonus_range_modifier:IsPurgable()
return false
end
10. В итоге при наличии у любого героя способности Berserkers Rage и при его включении, герой получает милишный ренж атаки равный 128. При выключении - герой получает свой родной ренж обратно. Все бафы, баши и прочие плюшки от оригинальной способности добавляются. На данный момент нашел 2 косяка: первый - т.к. расчет ренжа делается на стороне сервера, то у пользователя этот ренж на панели героя не отображается; второй - сларк (возможно еще кто-то, пока не тестил) каким-то образом после вЫключения способности перестает наносить урон, т.е. он подходит, начинает бить, проигрывается анимация, слышен звук, но урона нет. Иногда он наносится, но я хз при каких обстоятельствах. Есть идеи?
Думаю раз ты изменяешь рейндж на стороне сервера, на стороне клиента он остается старым и соответственно, когда рейндж на сервере станет равным 0, на клиенте он будет равным 128 например. На клиенте будет анимация, звук, и т.д, а с точки зрения сервера он не может бить => урона нет. Зато если юниты находятся друг в други с проходом коллизий(типо фазов) урон нанесется так как разница между ними будет 0.
Думаю раз ты изменяешь рейндж на стороне сервера, на стороне клиента он остается старым и соответственно, когда рейндж на сервере станет равным 0, на клиенте он будет равным 128 например. На клиенте будет анимация, звук, и т.д, а с точки зрения сервера он не может бить => урона нет. Зато если юниты находятся друг в други с проходом коллизий(типо фазов) урон нанесется так как разница между ними будет 0.
В том то и дело, что на стороне сервера ренж никогда нулевым не становится, а у клиента может быть. Но урон то расчитывается у сервера. Или я опять что-то не так понял?
В том то и дело, что на стороне сервера ренж никогда нулевым не становится, а у клиента может быть. Но урон то расчитывается у сервера. Или я опять что-то не так понял?