291 lines
11 KiB
Lua
291 lines
11 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 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
|