- 28 Июн 2023
- 25
- 7
Привет всем! Я наткнулся на форуме на реализацию мультикаста Огра, но она показалась мне громоздкой и перегруженной. Поэтому я решил написать свой алгоритм, который кажется мне более простым и понятным.
Допущения, которые упростили реализацию:
Lua:
LinkLuaModifier("modifier_multicast", "additional_abilities/multicast", LUA_MODIFIER_MOTION_NONE)
multicast = multicast or {}
function multicast:GetIntrinsicModifierName()
return "modifier_multicast"
end
function multicast:OnCreated()
end
modifier_multicast = modifier_multicast or {}
function modifier_multicast:IsHidden()
return true
end
function modifier_multicast:IsDebuff()
return false
end
function modifier_multicast:IsPurgable()
return false
end
function modifier_multicast:DeclareFunctions()
return { MODIFIER_EVENT_ON_ABILITY_FULLY_CAST }
end
function modifier_multicast:OnAbilityFullyCast(parameters)
if parameters.unit ~= self:GetCaster() or parameters.ability == self:GetAbility()
or self:GetCaster():PassivesDisabled() or parameters.ability:IsItem() or parameters.ability:IsHidden() then
return
end
local multicast_4_times = self:GetAbility():GetSpecialValueFor("multicast_4_times")
local multicast_3_times = self:GetAbility():GetSpecialValueFor("multicast_3_times")
local multicast_2_times = self:GetAbility():GetSpecialValueFor("multicast_2_times")
local behavior = parameters.ability:GetBehavior()
local forbidden = DOTA_ABILITY_BEHAVIOR_CHANNELLED + DOTA_ABILITY_BEHAVIOR_TOGGLE + DOTA_ABILITY_BEHAVIOR_VECTOR_TARGETING
if bit.band(behavior, forbidden) ~= 0 then
return
end
local random = RandomFloat(0, 100)
local multicast_n_times
if random < multicast_4_times then
multicast_n_times = 4
elseif random < multicast_3_times then
multicast_n_times = 3
elseif random < multicast_2_times then
multicast_n_times = 2
else
return
end
Thinker:New(
parameters.unit,
parameters.ability,
parameters.ability:GetCursorPosition(),
parameters.target,
multicast_n_times,
self:GetAbility():GetSpecialValueFor("delay")
)
end
Thinker = Thinker or {}
function Thinker:New(caster, ability, position, target, multicast_n_times, delay)
local instance = {
caster = caster,
ability = ability,
position = position,
target = target,
multicast_n_times = multicast_n_times,
used_times = 1,
delay = delay
}
GameRules:GetGameModeEntity():SetThink(
function()
return instance:OnThink()
end,
nil,
caster:entindex() .. "$" .. ability:GetAbilityName(), -- interrupt current multicast of the same ability from the same hero
delay
)
return setmetatable(instance, { __index = self })
end
function Thinker:OnThink()
self.caster:SetCursorPosition(self.position)
self.caster:SetCursorCastTarget(self.target)
self.ability:OnSpellStart()
self.used_times = self.used_times + 1
local pfx = ParticleManager:CreateParticle(
"particles/units/heroes/hero_ogre_magi/ogre_magi_multicast.vpcf",
PATTACH_OVERHEAD_FOLLOW,
self.caster
)
ParticleManager:SetParticleControl(pfx, 1, Vector(self.used_times, 1, 0))
if self.used_times < self.multicast_n_times then
return self.delay
else
return nil
end
end
Lua:
"multicast"
{
"BaseClass" "ability_lua"
"ScriptFile" "additional_abilities/multicast"
"AbilityTextureName" "additional/multicast"
"AbilityType" "DOTA_ABILITY_TYPE_ULTIMATE"
"FightRecapLevel" "2"
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_PASSIVE"
"AbilityCastAnimation" "ACT_INVALID"
"MaxLevel" "3"
"AbilitySpecial"
{
"01"
{
"var_type" "FIELD_FLOAT"
"multicast_2_times" "75 75 75"
}
"02"
{
"var_type" "FIELD_FLOAT"
"multicast_3_times" "0 30 30"
}
"03"
{
"var_type" "FIELD_FLOAT"
"multicast_4_times" "0 0 15"
}
"04"
{
"var_type" "FIELD_FLOAT"
"delay" "0.7"
}
}
}
Допущения, которые упростили реализацию:
- Не работает с предметами
- Для скилов с обездвиживающим модификатором на время каста, обороты мультикаста могут крутиться вхолостую (прыжок мираны, прыжок течса)
- Не все переключаемые способности имеют соответствующий флаг [valve moment], поэтому некоторые неочевидные переключаемые способности могут мультикаститься (например, d у феникса)
- Отключен для прерываемых способностей (upheavel, death ward итд)
- Тестировал на ограниченном пуле героев из Dota1x2