425 lines
16 KiB
Lua
425 lines
16 KiB
Lua
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
|
|
local ____exports = {}
|
|
local setCouriersBlockedForCutscene, spawnCutsceneBossIfNeeded, CUTSCENE_BOSS_UNIT, BOSS_CUTSCENE_STUN_FULL_DURATION, BOSS_CUTSCENE_STUN_AFTER_SKIP, cutsceneBossUnstunSerial, cutsceneBossTeleportGeneration, CUTSCENE_COURIER_BLOCK_MODIFIER
|
|
local ____SpawnManager = require("SpawnManager")
|
|
local SpawnManager = ____SpawnManager.SpawnManager
|
|
function setCouriersBlockedForCutscene(self, blocked)
|
|
local couriers = Entities:FindAllByClassname("npc_dota_courier")
|
|
if #couriers <= 0 then
|
|
return
|
|
end
|
|
for ____, courier in ipairs(couriers) do
|
|
do
|
|
local courierNpc = courier
|
|
if not courierNpc or not IsValidEntity(courierNpc) then
|
|
goto __continue29
|
|
end
|
|
if blocked then
|
|
if not courierNpc:HasModifier(CUTSCENE_COURIER_BLOCK_MODIFIER) then
|
|
courierNpc:AddNewModifier(
|
|
courierNpc,
|
|
getModifierSourceAbility(nil, courierNpc),
|
|
CUTSCENE_COURIER_BLOCK_MODIFIER,
|
|
{}
|
|
)
|
|
end
|
|
goto __continue29
|
|
end
|
|
if courierNpc:HasModifier(CUTSCENE_COURIER_BLOCK_MODIFIER) then
|
|
courierNpc:RemoveModifierByName(CUTSCENE_COURIER_BLOCK_MODIFIER)
|
|
end
|
|
end
|
|
::__continue29::
|
|
end
|
|
end
|
|
function spawnCutsceneBossIfNeeded(self)
|
|
local existing = Entities:FindByName(nil, CUTSCENE_BOSS_UNIT)
|
|
if existing ~= nil and IsValidEntity(existing) then
|
|
return existing
|
|
end
|
|
local bossSpawn = Entities:FindByName(nil, "point_boss_spawn_point")
|
|
if bossSpawn == nil then
|
|
return nil
|
|
end
|
|
local spawnPos = bossSpawn:GetAbsOrigin()
|
|
local boss = CreateUnitByName(
|
|
CUTSCENE_BOSS_UNIT,
|
|
spawnPos,
|
|
true,
|
|
nil,
|
|
nil,
|
|
DOTA_TEAM_BADGUYS
|
|
)
|
|
if boss ~= nil and IsValidEntity(boss) then
|
|
FindClearSpaceForUnit(boss, spawnPos, true)
|
|
boss:SetEntityName(CUTSCENE_BOSS_UNIT)
|
|
boss:AddNewModifier(
|
|
boss,
|
|
getModifierSourceAbility(nil, boss),
|
|
"modifier_stunned",
|
|
{}
|
|
)
|
|
local spawnGameTime = GameRules:GetGameTime()
|
|
local unstunDone = false
|
|
cutsceneBossUnstunSerial = cutsceneBossUnstunSerial + 1
|
|
local fullTimerName = "cutscene_boss_unstun_" .. tostring(cutsceneBossUnstunSerial)
|
|
local function applyUnstun()
|
|
if unstunDone or boss == nil or not IsValidEntity(boss) then
|
|
return
|
|
end
|
|
unstunDone = true
|
|
Timers:RemoveTimer(fullTimerName)
|
|
boss:RemoveModifierByName("modifier_stunned")
|
|
end
|
|
Timers:CreateTimer(
|
|
fullTimerName,
|
|
{
|
|
endTime = BOSS_CUTSCENE_STUN_FULL_DURATION,
|
|
callback = function()
|
|
applyUnstun(nil)
|
|
return nil
|
|
end
|
|
}
|
|
)
|
|
local pollCutsceneSkipUnstun
|
|
pollCutsceneSkipUnstun = function()
|
|
if unstunDone or boss == nil or not IsValidEntity(boss) then
|
|
return
|
|
end
|
|
local mgr = GameRules.CutsceneManager
|
|
if mgr ~= nil and mgr:isCutsceneActive() then
|
|
Timers:CreateTimer(0.1, pollCutsceneSkipUnstun)
|
|
return
|
|
end
|
|
local elapsed = GameRules:GetGameTime() - spawnGameTime
|
|
if elapsed < BOSS_CUTSCENE_STUN_FULL_DURATION - 0.02 then
|
|
Timers:RemoveTimer(fullTimerName)
|
|
Timers:CreateTimer(
|
|
BOSS_CUTSCENE_STUN_AFTER_SKIP,
|
|
function()
|
|
applyUnstun(nil)
|
|
end
|
|
)
|
|
return
|
|
end
|
|
if not unstunDone then
|
|
applyUnstun(nil)
|
|
end
|
|
end
|
|
Timers:CreateTimer(0.1, pollCutsceneSkipUnstun)
|
|
return boss
|
|
end
|
|
return nil
|
|
end
|
|
function ____exports.teleport_heroes(self, options)
|
|
local cinematic = (options and options.cinematic) ~= false
|
|
local myGen = cutsceneBossTeleportGeneration
|
|
local forwardPoint = Entities:FindByName(nil, "point_forward")
|
|
local bossSpawn = Entities:FindByName(nil, "point_boss_spawn_point")
|
|
local teleportPoints = {}
|
|
do
|
|
local i = 0
|
|
while i < 4 do
|
|
teleportPoints[i + 1] = Entities:FindByName(
|
|
nil,
|
|
"point_boss_player_" .. tostring(i)
|
|
)
|
|
if not teleportPoints[i + 1] then
|
|
return
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
local boss
|
|
if bossSpawn ~= nil then
|
|
boss = spawnCutsceneBossIfNeeded(nil)
|
|
end
|
|
local function faceTowardsForward()
|
|
if forwardPoint == nil then
|
|
return
|
|
end
|
|
if myGen ~= cutsceneBossTeleportGeneration then
|
|
return
|
|
end
|
|
local lookAt = forwardPoint:GetAbsOrigin()
|
|
if boss ~= nil and IsValidEntity(boss) then
|
|
boss:FaceTowards(lookAt)
|
|
end
|
|
do
|
|
local p = 0
|
|
while p < 10 do
|
|
do
|
|
local pl = PlayerResource:GetPlayer(p)
|
|
if not pl then
|
|
goto __continue56
|
|
end
|
|
local hero = pl.GetAssignedHero and pl:GetAssignedHero()
|
|
if hero ~= nil and IsValidEntity(hero) then
|
|
hero:FaceTowards(lookAt)
|
|
end
|
|
end
|
|
::__continue56::
|
|
p = p + 1
|
|
end
|
|
end
|
|
end
|
|
if not cinematic then
|
|
faceTowardsForward(nil)
|
|
do
|
|
local i = 0
|
|
while i < 10 do
|
|
do
|
|
local player = PlayerResource:GetPlayer(i)
|
|
if not player then
|
|
goto __continue60
|
|
end
|
|
local hero = player.GetAssignedHero and player:GetAssignedHero()
|
|
if hero == nil then
|
|
goto __continue60
|
|
end
|
|
local ____temp_2
|
|
if i < 4 then
|
|
____temp_2 = teleportPoints[i + 1]
|
|
else
|
|
____temp_2 = nil
|
|
end
|
|
local point = ____temp_2
|
|
if point ~= nil then
|
|
hero:SetAbsOrigin(point:GetAbsOrigin())
|
|
FindClearSpaceForUnit(
|
|
hero,
|
|
point:GetAbsOrigin(),
|
|
true
|
|
)
|
|
end
|
|
if forwardPoint ~= nil then
|
|
hero:FaceTowards(forwardPoint:GetAbsOrigin())
|
|
end
|
|
end
|
|
::__continue60::
|
|
i = i + 1
|
|
end
|
|
end
|
|
return
|
|
end
|
|
Timers:CreateTimer(
|
|
0.1,
|
|
function()
|
|
faceTowardsForward(nil)
|
|
return nil
|
|
end
|
|
)
|
|
do
|
|
local i = 0
|
|
while i < 10 do
|
|
local slot = i
|
|
local player = PlayerResource:GetPlayer(slot)
|
|
if player then
|
|
local hero = player.GetAssignedHero and player:GetAssignedHero()
|
|
if hero ~= nil then
|
|
local particle = ParticleManager:CreateParticle("particles/items2_fx/teleport_start.vpcf", PATTACH_ABSORIGIN, hero)
|
|
ParticleManager:ReleaseParticleIndex(particle)
|
|
Timers:CreateTimer(
|
|
3,
|
|
function()
|
|
if myGen ~= cutsceneBossTeleportGeneration then
|
|
ParticleManager:DestroyParticle(particle, true)
|
|
return nil
|
|
end
|
|
ParticleManager:DestroyParticle(particle, false)
|
|
local ____temp_3
|
|
if slot < 4 then
|
|
____temp_3 = teleportPoints[slot + 1]
|
|
else
|
|
____temp_3 = nil
|
|
end
|
|
local point = ____temp_3
|
|
if point ~= nil then
|
|
hero:SetAbsOrigin(point:GetAbsOrigin())
|
|
FindClearSpaceForUnit(
|
|
hero,
|
|
point:GetAbsOrigin(),
|
|
true
|
|
)
|
|
end
|
|
if forwardPoint ~= nil then
|
|
hero:FaceTowards(forwardPoint:GetAbsOrigin())
|
|
end
|
|
return nil
|
|
end
|
|
)
|
|
end
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
--- Прекеш партиклов телепорта в camera_heroes_endlap / teleport_heroes
|
|
function ____exports.precacheCutsceneParticles(self, context)
|
|
PrecacheResource("particle", "particles/items2_fx/teleport_start.vpcf", context)
|
|
PrecacheResource("particle", "particles/items2_fx/teleport_end.vpcf", context)
|
|
PrecacheResource("model", "models/items/nevermore/diabolical_fiend_shoulder/diabolical_fiend_shoulder.vmdl", context)
|
|
PrecacheResource("model", "models/items/shadow_fiend/arms_deso/arms_deso.vmdl", context)
|
|
PrecacheResource("model", "models/items/nevermore/sf_souls_tyrant_head/sf_souls_tyrant_head.vmdl", context)
|
|
end
|
|
____exports.CutsceneFunctions = {
|
|
camera_start_ending = function(self)
|
|
SpawnManager:getInstance():RemoveAllSpawnZones()
|
|
setCouriersBlockedForCutscene(nil, true)
|
|
do
|
|
local i = 0
|
|
while i < 4 do
|
|
local point = Entities:FindByName(
|
|
nil,
|
|
"point_player_" .. tostring(i)
|
|
)
|
|
local player = PlayerResource:GetPlayer(i)
|
|
if player and point then
|
|
local hero = player.GetAssignedHero and player:GetAssignedHero()
|
|
if hero ~= nil then
|
|
if not hero:IsAlive() then
|
|
hero:RespawnHero(false, false)
|
|
end
|
|
hero:SetTimeUntilRespawn(-1)
|
|
hero:SetRespawnsDisabled(true)
|
|
hero:SetBuybackCooldownTime(9999999)
|
|
local dennySpawn = Entities:FindByName(nil, "point_denny_spawn"):GetAbsOrigin()
|
|
local randomOffset = Vector(
|
|
RandomFloat(-30, 30),
|
|
RandomFloat(-30, 30),
|
|
0
|
|
)
|
|
Timers:CreateTimer(
|
|
0.1,
|
|
function()
|
|
hero:FaceTowards(dennySpawn:__add(randomOffset))
|
|
end
|
|
)
|
|
do
|
|
local slot = 0
|
|
while slot < 16 do
|
|
local item = hero:GetItemInSlot(slot)
|
|
if item and item.GetName and item:GetName() == "item_tpscroll" then
|
|
hero:RemoveItem(item)
|
|
end
|
|
slot = slot + 1
|
|
end
|
|
end
|
|
hero:SetAbsOrigin(point:GetAbsOrigin())
|
|
FindClearSpaceForUnit(
|
|
hero,
|
|
point:GetAbsOrigin(),
|
|
true
|
|
)
|
|
hero:Stop()
|
|
end
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
local dennySpawnPoint = Entities:FindByName(nil, "point_denny_spawn")
|
|
if dennySpawnPoint then
|
|
local denny = Entities:FindByName(nil, "npc_quest_giver_denny")
|
|
if denny ~= nil then
|
|
local pointDenny = Entities:FindByName(nil, "point_denny_spawn")
|
|
local pointDennyMove = Entities:FindByName(nil, "point_denny")
|
|
if pointDenny and pointDennyMove then
|
|
denny:SetAbsOrigin(pointDenny:GetAbsOrigin())
|
|
FindClearSpaceForUnit(
|
|
denny,
|
|
pointDenny:GetAbsOrigin(),
|
|
true
|
|
)
|
|
denny:MoveToPosition(toVectorWS(
|
|
nil,
|
|
pointDennyMove:GetAbsOrigin()
|
|
))
|
|
end
|
|
end
|
|
end
|
|
end,
|
|
camera_heroes_expedition = function(self)
|
|
do
|
|
local i = 0
|
|
while i < 10 do
|
|
local player = PlayerResource:GetPlayer(i)
|
|
if player then
|
|
local hero = player.GetAssignedHero and player:GetAssignedHero()
|
|
local movePos = Entities:FindByName(
|
|
nil,
|
|
("point_player_" .. tostring(i)) .. "_movepos"
|
|
)
|
|
if hero and movePos then
|
|
hero:MoveToPosition(toVectorWS(
|
|
nil,
|
|
movePos:GetAbsOrigin()
|
|
))
|
|
end
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
end,
|
|
camera_heroes_endlap = function(self)
|
|
local denny = Entities:FindByName(nil, "npc_quest_giver_denny")
|
|
if denny == nil then
|
|
return
|
|
end
|
|
local sumX = 0
|
|
local sumY = 0
|
|
local sumZ = 0
|
|
local count = 0
|
|
do
|
|
local i = 0
|
|
while i < 4 do
|
|
do
|
|
local player = PlayerResource:GetPlayer(i)
|
|
if not player then
|
|
goto __continue20
|
|
end
|
|
local hero = player.GetAssignedHero and player:GetAssignedHero()
|
|
if hero == nil then
|
|
goto __continue20
|
|
end
|
|
local o = hero:GetAbsOrigin()
|
|
sumX = sumX + o.x
|
|
sumY = sumY + o.y
|
|
sumZ = sumZ + o.z
|
|
count = count + 1
|
|
hero:FaceTowards(denny:GetAbsOrigin())
|
|
end
|
|
::__continue20::
|
|
i = i + 1
|
|
end
|
|
end
|
|
if count > 0 then
|
|
local dennyPos = denny:GetAbsOrigin()
|
|
denny:FaceTowards(Vector(sumX / count, sumY / count, dennyPos.z))
|
|
end
|
|
local generationAtSchedule = cutsceneBossTeleportGeneration
|
|
Timers:CreateTimer(
|
|
4,
|
|
function()
|
|
if generationAtSchedule ~= cutsceneBossTeleportGeneration then
|
|
return nil
|
|
end
|
|
____exports.teleport_heroes(nil, {cinematic = true})
|
|
return nil
|
|
end
|
|
)
|
|
end
|
|
}
|
|
CUTSCENE_BOSS_UNIT = "npc_boss_nevermore"
|
|
BOSS_CUTSCENE_STUN_FULL_DURATION = 12.8
|
|
BOSS_CUTSCENE_STUN_AFTER_SKIP = 0.1
|
|
cutsceneBossUnstunSerial = 0
|
|
--- Инкремент отменяет отложенный телепорт из camera_heroes_endlap и колбэки киношного teleport_heroes.
|
|
cutsceneBossTeleportGeneration = 0
|
|
--- Вызов при досрочном завершении camera_start_ending (скип): сразу арена + герои.
|
|
function ____exports.finishCameraStartEndingTeleportNow(self)
|
|
cutsceneBossTeleportGeneration = cutsceneBossTeleportGeneration + 1
|
|
____exports.teleport_heroes(nil, {cinematic = false})
|
|
end
|
|
CUTSCENE_COURIER_BLOCK_MODIFIER = "modifier_stunned"
|
|
return ____exports
|