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 BaseModifierMotionBoth = ____dota_ts_adapter.BaseModifierMotionBoth local registerAbility = ____dota_ts_adapter.registerAbility local registerModifier = ____dota_ts_adapter.registerModifier ____exports.frogmen_acid_jump = __TS__Class() local frogmen_acid_jump = ____exports.frogmen_acid_jump frogmen_acid_jump.name = "frogmen_acid_jump" frogmen_acid_jump.____file_path = "scripts/vscripts/abilities/creep/frogmen_acid_jump.lua" __TS__ClassExtends(frogmen_acid_jump, BaseAbility) function frogmen_acid_jump.prototype.____constructor(self, ...) BaseAbility.prototype.____constructor(self, ...) self.radius = 0 self.stun_duration = 0 self.land_damage = 0 end function frogmen_acid_jump.prototype.Precache(self, context) PrecacheResource("particle", "particles/neutral_fx/ogre_bruiser_smash.vpcf", context) end function frogmen_acid_jump.prototype.OnAbilityPhaseStart(self) if not IsServer() then return true end return true end function frogmen_acid_jump.prototype.OnAbilityPhaseInterrupted(self) if not IsServer() then return end end function frogmen_acid_jump.prototype.OnSpellStart(self) if not IsServer() then return end local caster = self:GetCaster() if not caster then return end local cursorPos = self:GetCursorPosition() local kv = {vLocX = cursorPos.x, vLocY = cursorPos.y, vLocZ = cursorPos.z} caster:AddNewModifier(caster, self, "modifier_acid_blob_jump", kv) self.radius = self:GetSpecialValueFor("radius") self.stun_duration = self:GetSpecialValueFor("stun_duration") self.land_damage = self:GetSpecialValueFor("land_damage") end function frogmen_acid_jump.prototype.Smash(self) if not IsServer() then return end local caster = self:GetCaster() if not caster then return end local origin = caster:GetOrigin() EmitSoundOnLocationWithCaster(origin, "OgreTank.GroundSmash", caster) local smashFX = ParticleManager:CreateParticle("particles/neutral_fx/ogre_bruiser_smash.vpcf", PATTACH_WORLDORIGIN, caster) ParticleManager:SetParticleControl(smashFX, 0, origin) ParticleManager:SetParticleControl( smashFX, 1, Vector(self.radius, self.radius, self.radius) ) ParticleManager:ReleaseParticleIndex(smashFX) caster:Interrupt() local enemies = FindUnitsInRadius( caster:GetTeamNumber(), origin, caster, self.radius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_ANY_ORDER, false ) for ____, enemy in ipairs(enemies) do do if not enemy then goto __continue13 end if enemy:IsInvulnerable() then goto __continue13 end ApplyDamage({ victim = enemy, attacker = caster, damage = self.land_damage + self:GetCaster():GetAverageTrueAttackDamage(enemy) * 2, damage_type = DAMAGE_TYPE_PHYSICAL, ability = self }) if not enemy:IsAlive() then local critFX = ParticleManager:CreateParticle("particles/units/heroes/hero_phantom_assassin/phantom_assassin_crit_impact.vpcf", PATTACH_CUSTOMORIGIN, nil) ParticleManager:SetParticleControlEnt( critFX, 0, enemy, PATTACH_POINT_FOLLOW, "attach_hitloc", enemy:GetOrigin(), true ) ParticleManager:SetParticleControl( critFX, 1, enemy:GetOrigin() ) local forward = caster:GetForwardVector() ParticleManager:SetParticleControlForward(critFX, 1, forward * -1) ParticleManager:SetParticleControlEnt( critFX, 10, enemy, PATTACH_ABSORIGIN_FOLLOW, nil, enemy:GetOrigin(), true ) ParticleManager:ReleaseParticleIndex(critFX) EmitSoundOn("Dungeon.BloodSplatterImpact", enemy) else enemy:AddNewModifier(caster, self, "modifier_stunned", {duration = self.stun_duration}) end end ::__continue13:: end end frogmen_acid_jump = __TS__Decorate( frogmen_acid_jump, frogmen_acid_jump, {registerAbility(nil)}, {kind = "class", name = "frogmen_acid_jump"} ) ____exports.frogmen_acid_jump = frogmen_acid_jump local AMOEBA_MINIMUM_HEIGHT_ABOVE_LOWEST = 400 local AMOEBA_MINIMUM_HEIGHT_ABOVE_HIGHEST = 200 local AMOEBA_ACCELERATION_Z = 1500 local AMOEBA_MAX_HORIZONTAL_ACCELERATION = 1500 ____exports.modifier_acid_blob_jump = __TS__Class() local modifier_acid_blob_jump = ____exports.modifier_acid_blob_jump modifier_acid_blob_jump.name = "modifier_acid_blob_jump" modifier_acid_blob_jump.____file_path = "scripts/vscripts/abilities/creep/frogmen_acid_jump.lua" __TS__ClassExtends(modifier_acid_blob_jump, BaseModifierMotionBoth) function modifier_acid_blob_jump.prototype.____constructor(self, ...) BaseModifierMotionBoth.prototype.____constructor(self, ...) self.bHorizontalMotionInterrupted = false self.flCurrentTimeHoriz = 0 self.flCurrentTimeVert = 0 self.flInitialVelocityZ = 0 self.flPredictedTotalTime = 0 end function modifier_acid_blob_jump.prototype.IsHidden(self) return true end function modifier_acid_blob_jump.prototype.IsPurgable(self) return false end function modifier_acid_blob_jump.prototype.RemoveOnDeath(self) return false end function modifier_acid_blob_jump.prototype.OnCreated(self, params) if not IsServer() then return end local parent = self:GetParent() local ability = self:GetAbility() if not parent or not ability then self:Destroy() return end self.bHorizontalMotionInterrupted = false if not self:ApplyHorizontalMotionController() or not self:ApplyVerticalMotionController() then self:Destroy() return end self.vStartPosition = GetGroundPosition( parent:GetOrigin(), parent ) self.flCurrentTimeHoriz = 0 self.flCurrentTimeVert = 0 local x = params.vLocX or parent:GetOrigin().x local y = params.vLocY or parent:GetOrigin().y local z = params.vLocZ or parent:GetOrigin().z self.vLoc = Vector(x, y, z) self.vLastKnownTargetPos = self.vLoc local duration = ability:GetSpecialValueFor("duration") local flDesiredHeight = AMOEBA_MINIMUM_HEIGHT_ABOVE_LOWEST * duration * duration local flLowZ = math.min(self.vLastKnownTargetPos.z, self.vStartPosition.z) local flHighZ = math.max(self.vLastKnownTargetPos.z, self.vStartPosition.z) local flArcTopZ = math.max(flLowZ + flDesiredHeight, flHighZ + AMOEBA_MINIMUM_HEIGHT_ABOVE_HIGHEST) local flArcDeltaZ = flArcTopZ - self.vStartPosition.z self.flInitialVelocityZ = math.sqrt(2 * flArcDeltaZ * AMOEBA_ACCELERATION_Z) local flDeltaZ = self.vLastKnownTargetPos.z - self.vStartPosition.z local flSqrtDet = math.sqrt(math.max(0, self.flInitialVelocityZ * self.flInitialVelocityZ - 2 * AMOEBA_ACCELERATION_Z * flDeltaZ)) self.flPredictedTotalTime = math.max((self.flInitialVelocityZ + flSqrtDet) / AMOEBA_ACCELERATION_Z, (self.flInitialVelocityZ - flSqrtDet) / AMOEBA_ACCELERATION_Z) self.vHorizontalVelocity = (self.vLastKnownTargetPos - self.vStartPosition) / self.flPredictedTotalTime self.vHorizontalVelocity.z = 0 end function modifier_acid_blob_jump.prototype.OnDestroy(self) if not IsServer() then return end local parent = self:GetParent() if parent ~= nil then parent:RemoveHorizontalMotionController(self) parent:RemoveVerticalMotionController(self) end end function modifier_acid_blob_jump.prototype.CheckState(self) return {[MODIFIER_STATE_STUNNED] = true, [MODIFIER_STATE_UNSELECTABLE] = true} end function modifier_acid_blob_jump.prototype.UpdateHorizontalMotion(self, me, dt) if not IsServer() then return end self.flCurrentTimeHoriz = math.min(self.flCurrentTimeHoriz + dt, self.flPredictedTotalTime) local t = self.flCurrentTimeHoriz / self.flPredictedTotalTime local vStartToTarget = self.vLastKnownTargetPos - self.vStartPosition local vDesiredPos = self.vStartPosition + vStartToTarget * t local vOldPos = me:GetOrigin() local vToDesired = vDesiredPos - vOldPos vToDesired.z = 0 local vDesiredVel = vToDesired / dt local vVelDif = vDesiredVel - self.vHorizontalVelocity local flVelDif = vVelDif:Length2D() vVelDif = vVelDif:Normalized() local flVelDelta = math.min(flVelDif, AMOEBA_MAX_HORIZONTAL_ACCELERATION) self.vHorizontalVelocity = self.vHorizontalVelocity + vVelDif * flVelDelta * dt local vNewPos = vOldPos + self.vHorizontalVelocity * dt me:SetOrigin(vNewPos) end function modifier_acid_blob_jump.prototype.UpdateVerticalMotion(self, me, dt) if not IsServer() then return end self.flCurrentTimeVert = self.flCurrentTimeVert + dt local bGoingDown = -AMOEBA_ACCELERATION_Z * self.flCurrentTimeVert + self.flInitialVelocityZ < 0 local vNewPos = me:GetOrigin() vNewPos.z = self.vStartPosition.z + (-0.5 * AMOEBA_ACCELERATION_Z * self.flCurrentTimeVert * self.flCurrentTimeVert + self.flInitialVelocityZ * self.flCurrentTimeVert) local flGroundHeight = GetGroundHeight( vNewPos, self:GetParent() ) local bLanded = false if vNewPos.z < flGroundHeight and bGoingDown then vNewPos.z = flGroundHeight bLanded = true end me:SetOrigin(vNewPos) if bLanded then if not self.bHorizontalMotionInterrupted then local ability = self:GetAbility() if ability then ability:Smash() end end self:Destroy() end end function modifier_acid_blob_jump.prototype.OnHorizontalMotionInterrupted(self) if not IsServer() then return end self.bHorizontalMotionInterrupted = true end function modifier_acid_blob_jump.prototype.OnVerticalMotionInterrupted(self) if not IsServer() then return end self:Destroy() end function modifier_acid_blob_jump.prototype.DeclareFunctions(self) return {MODIFIER_PROPERTY_OVERRIDE_ANIMATION} end function modifier_acid_blob_jump.prototype.GetOverrideAnimation(self) return ACT_DOTA_CAST_ABILITY_1 end modifier_acid_blob_jump = __TS__Decorate( modifier_acid_blob_jump, modifier_acid_blob_jump, {registerModifier(nil)}, {kind = "class", name = "modifier_acid_blob_jump"} ) ____exports.modifier_acid_blob_jump = modifier_acid_blob_jump return ____exports