219 lines
8.6 KiB
Lua
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
|