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