Files
Dota-Zombie-Invasion/scripts/vscripts/abilities/invul_box.lua
T
2026-05-29 15:11:31 +07:00

219 lines
8.6 KiB
Lua

local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local ____exports = {}
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
local BaseAbility = ____dota_ts_adapter.BaseAbility
local BaseModifier = ____dota_ts_adapter.BaseModifier
local registerAbility = ____dota_ts_adapter.registerAbility
local registerModifier = ____dota_ts_adapter.registerModifier
____exports.invul_box = __TS__Class()
local invul_box = ____exports.invul_box
invul_box.name = "invul_box"
invul_box.____file_path = "scripts/vscripts/abilities/invul_box.lua"
__TS__ClassExtends(invul_box, BaseAbility)
function invul_box.prototype.GetIntrinsicModifierName(self)
return "modifier_invul_box"
end
invul_box = __TS__Decorate(
invul_box,
invul_box,
{registerAbility(nil)},
{kind = "class", name = "invul_box"}
)
____exports.invul_box = invul_box
____exports.modifier_invul_box = __TS__Class()
local modifier_invul_box = ____exports.modifier_invul_box
modifier_invul_box.name = "modifier_invul_box"
modifier_invul_box.____file_path = "scripts/vscripts/abilities/invul_box.lua"
__TS__ClassExtends(modifier_invul_box, BaseModifier)
function modifier_invul_box.prototype.IsHidden(self)
return true
end
function modifier_invul_box.prototype.IsPurgable(self)
return false
end
function modifier_invul_box.prototype.IsDebuff(self)
return false
end
function modifier_invul_box.prototype.CheckState(self)
return {[MODIFIER_STATE_NO_HEALTH_BAR] = true, [MODIFIER_STATE_UNSELECTABLE] = false, [MODIFIER_STATE_SPECIALLY_DENIABLE] = true}
end
function modifier_invul_box.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MIN_HEALTH, MODIFIER_EVENT_ON_ATTACKED}
end
function modifier_invul_box.prototype.GetMinHealth(self)
return 1
end
function modifier_invul_box.prototype.OnCreated(self)
if IsServer() then
self:StartIntervalThink(0.1)
end
end
function modifier_invul_box.prototype.OnIntervalThink(self)
if IsServer() then
self:CheckForNearbyHeroes()
end
end
function modifier_invul_box.prototype.CheckForNearbyHeroes(self)
local target = self:GetParent()
local nearbyHeroes = FindUnitsInRadius(
target:GetTeamNumber(),
target:GetAbsOrigin(),
nil,
40,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, hero in ipairs(nearbyHeroes) do
if hero and hero:IsAlive() then
local direction = target:GetAbsOrigin() - hero:GetAbsOrigin()
direction.z = 0
local normalizedDirection = direction:Normalized()
self:StartKnockback(target, normalizedDirection, 30, 0.2)
self:CheckForChainKnockback(
target,
target:GetAbsOrigin(),
15,
0.2
)
end
end
end
function modifier_invul_box.prototype.OnAttacked(self, event)
if event.target ~= self:GetParent() then
return
end
local attacker = event.attacker
local target = event.target
if not attacker or not target or attacker == target then
return
end
local direction = target:GetAbsOrigin() - attacker:GetAbsOrigin()
direction.z = 0
local normalizedDirection = direction:Normalized()
local knockbackForce = 50
local knockbackDuration = 0.3
local startPosition = target:GetAbsOrigin()
local startTime = GameRules:GetGameTime()
local totalDuration = knockbackDuration
local knockbackTimer = Timers:CreateTimer(
0.01,
function()
local currentTime = GameRules:GetGameTime()
local elapsed = currentTime - startTime
local progress = elapsed / totalDuration
if progress >= 1 then
return
end
local easeOutProgress = 1 - (1 - progress) ^ 3
local currentDistance = knockbackForce * easeOutProgress
local newPosition = Vector(startPosition.x + normalizedDirection.x * currentDistance, startPosition.y + normalizedDirection.y * currentDistance, startPosition.z)
local groundPosition = GetGroundPosition(newPosition, target)
local finalPosition = Vector(newPosition.x, newPosition.y, groundPosition.z)
local oldPosition = target:GetAbsOrigin()
target:SetAbsOrigin(finalPosition)
local currentPos = target:GetAbsOrigin()
local distanceFromTarget = currentPos - finalPosition
local distance = distanceFromTarget:Length2D()
if distance > 10 then
target:SetAbsOrigin(oldPosition)
local foundSafePosition = false
local searchRadius = 50
do
local angle = 0
while angle < 360 do
local testDirection = Vector(
math.cos(angle * math.pi / 180),
math.sin(angle * math.pi / 180),
0
)
local testPosition = Vector(startPosition.x + testDirection.x * currentDistance * 0.5, startPosition.y + testDirection.y * currentDistance * 0.5, startPosition.z)
local testGroundPosition = GetGroundPosition(testPosition, target)
local testFinalPosition = Vector(testPosition.x, testPosition.y, testGroundPosition.z)
local testOldPos = target:GetAbsOrigin()
target:SetAbsOrigin(testFinalPosition)
local testCurrentPos = target:GetAbsOrigin()
local testDistanceVector = testCurrentPos - testFinalPosition
local testDistance = testDistanceVector:Length2D()
if testDistance <= 10 then
foundSafePosition = true
break
else
target:SetAbsOrigin(testOldPos)
end
angle = angle + 45
end
end
if not foundSafePosition then
return
end
else
self:CheckForChainKnockback(target, finalPosition, knockbackForce * 0.5, knockbackDuration)
end
return 0.01
end
)
end
function modifier_invul_box.prototype.CheckForChainKnockback(self, originalTarget, position, chainForce, chainDuration)
local nearbyUnits = FindUnitsInRadius(
originalTarget:GetTeamNumber(),
position,
nil,
100,
DOTA_UNIT_TARGET_TEAM_BOTH,
DOTA_UNIT_TARGET_ALL,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, unit in ipairs(nearbyUnits) do
do
if unit == originalTarget then
goto __continue29
end
if unit:HasModifier("modifier_invul_box") then
local direction = unit:GetAbsOrigin() - position
direction.z = 0
local normalizedDirection = direction:Normalized()
self:StartKnockback(unit, normalizedDirection, chainForce, chainDuration)
end
end
::__continue29::
end
end
function modifier_invul_box.prototype.StartKnockback(self, target, direction, force, duration)
local startPosition = target:GetAbsOrigin()
local startTime = GameRules:GetGameTime()
local knockbackTimer = Timers:CreateTimer(
0.01,
function()
local currentTime = GameRules:GetGameTime()
local elapsed = currentTime - startTime
local progress = elapsed / duration
if progress >= 1 then
return
end
local easeOutProgress = 1 - (1 - progress) ^ 3
local currentDistance = force * easeOutProgress
local newPosition = Vector(startPosition.x + direction.x * currentDistance, startPosition.y + direction.y * currentDistance, startPosition.z)
local groundPosition = GetGroundPosition(newPosition, target)
local finalPosition = Vector(newPosition.x, newPosition.y, groundPosition.z)
target:SetAbsOrigin(finalPosition)
return 0.01
end
)
end
modifier_invul_box = __TS__Decorate(
modifier_invul_box,
modifier_invul_box,
{registerModifier(nil)},
{kind = "class", name = "modifier_invul_box"}
)
____exports.modifier_invul_box = modifier_invul_box
return ____exports