1955 lines
62 KiB
Lua
Executable File
1955 lines
62 KiB
Lua
Executable File
if SpawnSystem == nil then
|
||
SpawnSystem = {}
|
||
SpawnSystem.Spawner = {} -- 刷怪基本数据
|
||
SpawnSystem.AttackingSpawner = {} -- 刷怪实体
|
||
SpawnSystem.CurWave = 0 -- 当前波数
|
||
SpawnSystem.CurTime = 0 -- 当前时间
|
||
SpawnSystem.IsUnLimited = false -- 是否无尽
|
||
SpawnSystem.ReachToWave = nil --跳关
|
||
SpawnSystem.RankMinWave = 130 --开始计算排行榜的波数
|
||
SpawnSystem.GameOverPlayerId = {} -- 失败玩家id
|
||
|
||
SpawnSystem.SpawnOrigin = -- 玩家出生地点
|
||
{
|
||
[1] = Vector(-3424,2816,144),
|
||
[2] = Vector(3424,2816,144),
|
||
[3] = Vector(3424,-2816,144),
|
||
[4] = Vector(-3424,-2816,144)
|
||
}
|
||
SpawnSystem.ShopOrigin = -- 玩家商店地点
|
||
{
|
||
[1] = Vector(-2454,2989,142),
|
||
[2] = Vector(2227,2922,142),
|
||
[3] = Vector(2259,-2806,142),
|
||
[4] = Vector(-2454,-2867,142)
|
||
}
|
||
SpawnSystem.ShopForward = -- 玩家商店朝向
|
||
{
|
||
[1] = Vector(-math.cos(math.pi/4),-math.sin(math.pi/4),0),
|
||
[2] = Vector(math.cos(math.pi/4),-math.sin(math.pi/4),0),
|
||
[3] = Vector(math.cos(math.pi/4),math.sin(math.pi/4),0),
|
||
[4] = Vector(-math.cos(math.pi/4),math.sin(math.pi/4),0)
|
||
}
|
||
end
|
||
|
||
NORMAL_MODE = 1
|
||
EXTRA_MODE = 2
|
||
UNLIMITED_MODE = 3
|
||
RANDOM_MODE = 4
|
||
CHALLENGE_MODE = 5
|
||
FUNNY_MODE = 6
|
||
PVE_MODE = 7
|
||
|
||
MAX_HEALTH = 2000000000
|
||
|
||
THTD_EntitiesRectInner = { [0] = {}, [1] = {}, [2] = {},[3] = {} } -- 内圈怪按玩家逄
|
||
THTD_EntitiesRectOuter = { } -- 外圈怪统一算
|
||
thtd_bosses_list =
|
||
{
|
||
"alice",
|
||
"aya",
|
||
"hina",
|
||
"kaguya",
|
||
"keine",
|
||
"kisume",
|
||
"marisa",
|
||
"minoriko",
|
||
"mokou",
|
||
"rumia",
|
||
"yuugi",
|
||
}
|
||
|
||
function SpawnSystem:GetCount()
|
||
local spawner = SpawnSystem.AttackingSpawner
|
||
if spawner == nil or #spawner == 0 then return 0 end
|
||
local i = 0
|
||
for _, spawnerLine in pairs(spawner) do
|
||
if spawnerLine.hero.is_game_over ~= true then
|
||
i = i + 1
|
||
end
|
||
end
|
||
return i
|
||
end
|
||
|
||
|
||
function RefreshItemListNetTable(hero)
|
||
if hero == nil or hero.is_game_over == true then return end
|
||
hero.thtd_hero_damage_list = {}
|
||
for k,v in pairs(hero.thtd_hero_tower_list) do
|
||
hero.thtd_hero_damage_list[tostring(v:GetEntityIndex())] = math.floor(v:THTD_GetTowerDamage())
|
||
end
|
||
local steamid = PlayerResource:GetSteamID(hero:GetPlayerOwnerID())
|
||
CustomNetTables:SetTableValue("TowerListInfo", "damagelist"..tostring(steamid), hero.thtd_hero_damage_list)
|
||
CustomNetTables:SetTableValue("CustomGameInfo", "game_info"..tostring(steamid), hero.thtd_game_info)
|
||
end
|
||
|
||
function RefreshItemListNetTableAll()
|
||
if SpawnSystem.AttackingSpawner == nil or #SpawnSystem.AttackingSpawner == 0 then return end
|
||
for k,v in pairs(SpawnSystem.AttackingSpawner) do
|
||
RefreshItemListNetTable(v.hero)
|
||
end
|
||
end
|
||
|
||
|
||
|
||
-- todo 使用buff的think实现
|
||
|
||
function RefreshHeroBuff3011(hero)
|
||
if GameRules.player_bb_buff[hero.thtd_player_id]["item_3011"] <= 0 and GameRules.player_bb_buff[hero.thtd_player_id]["item_3011_effect"] <= 0 then
|
||
return
|
||
end
|
||
|
||
local targets = {}
|
||
local comboCount = 0
|
||
local hasSatori = false
|
||
local hasKoishi = false
|
||
local hasRin = false
|
||
local hasUtsuho = false
|
||
for _,tower in pairs(hero.thtd_hero_tower_list) do
|
||
local unitName = tower:GetUnitName()
|
||
if unitName == "satori" then
|
||
hasSatori = true
|
||
table.insert(targets, tower)
|
||
elseif unitName == "koishi" then
|
||
hasKoishi = true
|
||
table.insert(targets, tower)
|
||
elseif unitName == "rin" then
|
||
hasRin = true
|
||
table.insert(targets, tower)
|
||
elseif unitName == "utsuho" then
|
||
hasUtsuho = true
|
||
table.insert(targets, tower)
|
||
end
|
||
end
|
||
if hasSatori and hasKoishi then
|
||
comboCount = comboCount + 1
|
||
end
|
||
if hasRin and hasUtsuho then
|
||
comboCount = comboCount + 1
|
||
end
|
||
|
||
GameRules.player_bb_buff[hero.thtd_player_id]["item_3011_effect"] = GameRules.player_bb_buff[hero.thtd_player_id]["item_3011"] * comboCount
|
||
|
||
if GameRules.player_bb_buff[hero.thtd_player_id]["item_3011_effect"] > 0 then
|
||
for k,v in pairs(targets) do
|
||
if not v:HasModifier("modifier_bb_buff_3011_effect") then
|
||
v:AddNewModifier(v, nil, "modifier_bb_buff_3011_effect", nil)
|
||
elseif v.thtd_hero_3011_damage_up ~= GameRules.player_bb_buff[hero.thtd_player_id]["item_3011_effect"] then
|
||
v:RemoveModifierByName("modifier_bb_buff_3011_effect")
|
||
v:AddNewModifier(v, nil, "modifier_bb_buff_3011_effect", nil)
|
||
end
|
||
end
|
||
else
|
||
for k,v in pairs(targets) do
|
||
if v:HasModifier("modifier_bb_buff_3011_effect") then
|
||
v:RemoveModifierByName("modifier_bb_buff_3011_effect")
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function RefreshHeroBuff3015(hero)
|
||
if GameRules.player_bb_buff[hero.thtd_player_id]["item_3015"] <= 0 and GameRules.player_bb_buff[hero.thtd_player_id]["item_3015_effect"] <= 0 then
|
||
return
|
||
end
|
||
|
||
local targets = {}
|
||
local count = 0
|
||
local hasEirin = false
|
||
local hasKaguya = false
|
||
local hasReisen = false
|
||
local hasInaba = false
|
||
for _,tower in pairs(hero.thtd_hero_tower_list) do
|
||
local unitName = tower:GetUnitName()
|
||
if unitName == "eirin" then
|
||
hasEirin = true
|
||
table.insert(targets, tower)
|
||
elseif unitName == "kaguya" then
|
||
hasKaguya = true
|
||
table.insert(targets, tower)
|
||
elseif unitName == "reisen" then
|
||
hasReisen = true
|
||
table.insert(targets, tower)
|
||
elseif unitName == "inaba" then
|
||
hasInaba = true
|
||
table.insert(targets, tower)
|
||
end
|
||
end
|
||
if hasEirin then
|
||
count = count + 1
|
||
end
|
||
if hasKaguya then
|
||
count = count + 1
|
||
end
|
||
if hasReisen then
|
||
count = count + 1
|
||
end
|
||
if hasInaba then
|
||
count = count + 1
|
||
end
|
||
|
||
GameRules.player_bb_buff[hero.thtd_player_id]["item_3015_effect"] = GameRules.player_bb_buff[hero.thtd_player_id]["item_3015"] * count
|
||
|
||
if GameRules.player_bb_buff[hero.thtd_player_id]["item_3015_effect"] > 0 then
|
||
for k,v in pairs(targets) do
|
||
if not v:HasModifier("modifier_bb_buff_3015_effect") then
|
||
v:AddNewModifier(v, nil, "modifier_bb_buff_3015_effect", nil)
|
||
elseif v.thtd_hero_3015_damage_up ~= GameRules.player_bb_buff[hero.thtd_player_id]["item_3015_effect"] then
|
||
v:RemoveModifierByName("modifier_bb_buff_3015_effect")
|
||
v:AddNewModifier(v, nil, "modifier_bb_buff_3015_effect", nil)
|
||
end
|
||
end
|
||
else
|
||
for k,v in pairs(targets) do
|
||
if v:HasModifier("modifier_bb_buff_3015_effect") then
|
||
v:RemoveModifierByName("modifier_bb_buff_3015_effect")
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function RefreshHeroBuff3028(hero)
|
||
if GameRules.player_bb_buff[hero.thtd_player_id]["item_3028"] <= 0 and GameRules.player_bb_buff[hero.thtd_player_id]["item_3028_effect"] <= 0 then
|
||
return
|
||
end
|
||
|
||
local targets = {}
|
||
for _,tower in pairs(hero.thtd_hero_tower_list) do
|
||
local unitName = tower:GetUnitName()
|
||
if unitName == "yuugi" or unitName == "suika" then
|
||
table.insert(targets, tower)
|
||
end
|
||
end
|
||
|
||
GameRules.player_bb_buff[hero.thtd_player_id]["item_3028_effect"] = GameRules.player_bb_buff[hero.thtd_player_id]["item_3028"]
|
||
|
||
if GameRules.player_bb_buff[hero.thtd_player_id]["item_3028_effect"] > 0 then
|
||
for k,v in pairs(targets) do
|
||
local ability = v:FindAbilityByName("faceless_void_time_lock")
|
||
if ability == nil then
|
||
ability = v:AddAbility("faceless_void_time_lock")
|
||
end
|
||
if ability:GetLevel() ~= GameRules.player_bb_buff[hero.thtd_player_id]["item_3028_effect"] then
|
||
ability:SetLevel(GameRules.player_bb_buff[hero.thtd_player_id]["item_3028_effect"])
|
||
ability:SetActivated(true)
|
||
end
|
||
end
|
||
else
|
||
for k,v in pairs(targets) do
|
||
if v:HasAbility("faceless_void_time_lock") then
|
||
v:RemoveAbility("faceless_void_time_lock")
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
|
||
-- 刷怪准备,DOTA_GAMERULES_STATE_PRE_GAME 时调用
|
||
function SpawnSystem:PreSpawn()
|
||
-- 载入刷怪数据
|
||
SpawnSystem.Spawner = LoadKeyValues("scripts/npc/Spawner.txt")
|
||
|
||
-- 显示准备倒计时
|
||
local maxTime = math.floor(GameRules:GetGameTime() + 0.5) + 30
|
||
local uiWaveInfo =
|
||
{
|
||
["Wave"] = 0,
|
||
["RemainingTime"] = maxTime
|
||
}
|
||
|
||
GameRules:GetGameModeEntity():SetContextThink(DoUniqueString("PreSpawn") ,
|
||
function()
|
||
if GameRules:IsGamePaused() then return 0.1 end
|
||
if GameRules:State_Get() == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then return nil end
|
||
if uiWaveInfo["RemainingTime"] == 0 then
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="item_locked_tip", duration=60, params={}, color="#ff0"})
|
||
return nil
|
||
end
|
||
uiWaveInfo["RemainingTime"] = math.max(math.floor(maxTime - GameRules:GetGameTime()),0)
|
||
SpawnSystem.CurTime = uiWaveInfo["RemainingTime"]
|
||
CustomNetTables:SetTableValue("CustomGameInfo", "attacking_process", uiWaveInfo)
|
||
RefreshItemListNetTableAll()
|
||
if (GameRules:IsCheatMode() and IsInToolsMode() == false) then -- or SERVER_KEY == "Invalid_NotOnDedicatedServer" then
|
||
SpawnSystem:GameEnd()
|
||
return nil
|
||
end
|
||
|
||
-- 初始化刷怪点
|
||
if uiWaveInfo["RemainingTime"] <= 25 and SpawnSystem:GetCount() == 0 then
|
||
SpawnSystem:SpawnLine()
|
||
SpawnSystem:RefreshCreepMaxCount()
|
||
SpawnSystem:SpawnChest()
|
||
-- SendMsg(0, "test_tip", "总伤害",90)
|
||
-- 通知提示
|
||
local difficulty = GameRules:GetCustomGameDifficulty()
|
||
if difficulty == CHALLENGE_MODE then
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="challenge_game_on", duration=25, params={}, color="#ff0"})
|
||
elseif difficulty >= FUNNY_MODE then
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="funny_game_on", duration=25, params={}, color="#ff0"})
|
||
end
|
||
end
|
||
|
||
-- 同步UI数据
|
||
RefreshItemListNetTableAll()
|
||
|
||
-- 提示
|
||
if SpawnSystem.CurTime == 15 then
|
||
GameRules:SendCustomMessage("#game_keyboard_tip", DOTA_TEAM_GOODGUYS, 0)
|
||
elseif SpawnSystem.CurTime == 8 then
|
||
GameRules:SendCustomMessage("#power_view_tip", DOTA_TEAM_GOODGUYS, 0)
|
||
end
|
||
|
||
return 1
|
||
end,
|
||
0)
|
||
end
|
||
|
||
-- 绑定刷怪点
|
||
function SpawnSystem:SpawnLine()
|
||
local spawner = SpawnSystem.AttackingSpawner
|
||
local heroes = {}
|
||
for k,v in pairs(GameRules.HeroList) do
|
||
if v ~= nil then
|
||
table.insert(heroes, v)
|
||
end
|
||
end
|
||
if heroes == nil or #heroes == 0 then return end
|
||
table.sort(heroes, function(a,b) return (a.thtd_player_id < b.thtd_player_id) end)
|
||
local j = 1
|
||
for _,hero in pairs(heroes) do
|
||
if hero.is_game_over ~= true then
|
||
local entity = Entities:FindByName(nil, "spanwer_player"..tostring(j))
|
||
if entity ~= nil then
|
||
entity.index = j
|
||
entity.hero = hero
|
||
hero.spawn_index = j
|
||
hero.spawn_position = SpawnSystem.SpawnOrigin[j]
|
||
if GetDistanceBetweenTwoVec2D(hero:GetAbsOrigin(), hero.spawn_position) > 1000 then
|
||
hero:SetAbsOrigin(hero.spawn_position)
|
||
hero.shop:SetAbsOrigin(SpawnSystem.ShopOrigin[j])
|
||
hero.shop:MoveToPosition(SpawnSystem.ShopOrigin[j]+SpawnSystem.ShopForward[j])
|
||
end
|
||
|
||
if j == 1 then
|
||
entity.first_point = "corner_M1408_1056"
|
||
entity.first_forward = "left"
|
||
entity.second_point = "corner_M2771_1056"
|
||
entity.second_forward = "up"
|
||
elseif j == 2 then
|
||
entity.first_point = "corner_1408_1056"
|
||
entity.first_forward = "right"
|
||
entity.second_point = "corner_2771_1056"
|
||
entity.second_forward = "up"
|
||
elseif j == 3 then
|
||
entity.first_point = "corner_1408_M1056"
|
||
entity.first_forward = "right"
|
||
entity.second_point = "corner_2771_M1056"
|
||
entity.second_forward = "down"
|
||
elseif j == 4 then
|
||
entity.first_point = "corner_M1408_M1056"
|
||
entity.first_forward = "left"
|
||
entity.second_point = "corner_M2771_M1056"
|
||
entity.second_forward = "down"
|
||
end
|
||
table.insert(spawner, entity)
|
||
j = j + 1
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
-- 刷怪开始,DOTA_GAMERULES_STATE_GAME_IN_PROGRESS 时调用
|
||
function SpawnSystem:InitSpawn()
|
||
local spawner = SpawnSystem.AttackingSpawner
|
||
|
||
local max_time = 0
|
||
local left_time = 0
|
||
local uiWaveInfo =
|
||
{
|
||
["Wave"] = 1,
|
||
["RemainingTime"] = max_time
|
||
}
|
||
local wave = 0
|
||
local difficulty = GameRules:GetCustomGameDifficulty()
|
||
local GameMode = GameRules:GetGameModeEntity()
|
||
GameMode:SetContextThink(DoUniqueString("AttackSpawn"),
|
||
function()
|
||
if GameRules:IsGamePaused() then return 0.1 end
|
||
|
||
-- 每波开始
|
||
if left_time <= 0 then
|
||
SpawnSystem:WaveEndForEach()
|
||
|
||
if SpawnSystem.ReachToWave ~= nil then
|
||
SpawnSystem.CurWave = SpawnSystem.ReachToWave + 50
|
||
SpawnSystem.RankMinWave = SpawnSystem.CurWave + 4
|
||
SpawnSystem.ReachToWave = nil
|
||
elseif SpawnSystem.CurWave == 50 and difficulty >= CHALLENGE_MODE then
|
||
SpawnSystem.CurWave = 50 + 70
|
||
elseif difficulty >= FUNNY_MODE and SpawnSystem.CurWave < 50 then
|
||
SpawnSystem.CurWave = SpawnSystem.CurWave + 2
|
||
else
|
||
SpawnSystem.CurWave = SpawnSystem.CurWave + 1
|
||
end
|
||
wave = SpawnSystem.CurWave
|
||
|
||
if wave > 130 and wave < SpawnSystem.RankMinWave then
|
||
GameRules:SendCustomMessage("#skip_wave_rank_tip", DOTA_TEAM_GOODGUYS, 0)
|
||
end
|
||
|
||
-- 普通和Extra胜利
|
||
if difficulty < UNLIMITED_MODE and wave > 120 then
|
||
SpawnSystem:GameEnd()
|
||
return nil
|
||
end
|
||
|
||
-- 无尽前提示
|
||
if wave == 50 then
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="spawn_unlimited", duration=133, params={count=50}, color="#0ff"})
|
||
end
|
||
|
||
-- 进入无尽
|
||
if wave > 50 and SpawnSystem.IsUnLimited == false then
|
||
SpawnSystem:StartUnlimited()
|
||
end
|
||
|
||
-- 100波以后取消刷文文
|
||
if wave == 151 then
|
||
SpawnSystem:RemoveBoss(true)
|
||
end
|
||
|
||
-- 每波怪的计时
|
||
if wave <= 51 then
|
||
max_time = math.floor(SpawnSystem.Spawner["Attacking"]["Wave".. tostring(wave)]["BreakTime"] +
|
||
SpawnSystem.Spawner["Attacking"]["Wave".. tostring(wave)]["Times"] *
|
||
SpawnSystem.Spawner["Attacking"]["Wave".. tostring(wave)]["Interval"] + 0.5)
|
||
elseif max_time > 30 then
|
||
max_time = math.floor(SpawnSystem.Spawner["Attacking"]["Wave51"]["BreakTime"] +
|
||
SpawnSystem.Spawner["Attacking"]["Wave51"]["Times"] *
|
||
SpawnSystem.Spawner["Attacking"]["Wave51"]["Interval"] + 0.5)
|
||
end
|
||
|
||
left_time = max_time
|
||
|
||
SpawnSystem:ClearRemovedSpawner()
|
||
SpawnSystem:StartSpawn()
|
||
end
|
||
|
||
-- 增加无尽准备时间
|
||
if wave == 50 and SpawnSystem.IsUnLimited == false and left_time == 0.5 then
|
||
SpawnSystem:WaveEndForEach()
|
||
SpawnSystem:StartUnlimited()
|
||
max_time = 180.5
|
||
left_time = max_time
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="start_unlimited", duration=180, params={}, color="#ff0"})
|
||
if difficulty == CHALLENGE_MODE then
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="challenge_game_on", duration=180, params={}, color="#ff0"})
|
||
elseif difficulty >= FUNNY_MODE then
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="funny_game_on", duration=180, params={}, color="#ff0"})
|
||
end
|
||
end
|
||
|
||
-- 更新进度
|
||
left_time = left_time - 0.5
|
||
if wave == 50 and SpawnSystem.IsUnLimited then
|
||
uiWaveInfo["Wave"] = 0
|
||
else
|
||
uiWaveInfo["Wave"] = wave
|
||
end
|
||
uiWaveInfo["RemainingTime"] = math.floor(left_time)
|
||
CustomNetTables:SetTableValue("CustomGameInfo", "attacking_process", uiWaveInfo)
|
||
SpawnSystem.CurTime = uiWaveInfo["RemainingTime"]
|
||
|
||
-- 检查漏怪
|
||
if not SpawnSystem:CreepCheck() then
|
||
return nil
|
||
end
|
||
|
||
-- 同步UI数据
|
||
RefreshItemListNetTableAll()
|
||
|
||
if left_time%5 == 0 then
|
||
SpawnSystem:SpawnChest()
|
||
end
|
||
|
||
return 0.5
|
||
end,
|
||
0)
|
||
|
||
end
|
||
|
||
-- 进入无尽相关设置
|
||
function SpawnSystem:StartUnlimited()
|
||
SpawnSystem.IsUnLimited = true
|
||
local entities = Entities:FindAllByClassname("npc_dota_creature")
|
||
for k,v in pairs(entities) do
|
||
local findNum = string.find(v:GetUnitName(), 'creature')
|
||
if findNum ~= nil and v~=nil and v:IsNull()==false and v:IsAlive() then
|
||
v:ForceKill(false)
|
||
end
|
||
end
|
||
for _,hero in pairs(GameRules.HeroList) do
|
||
if hero~=nil and hero:IsNull()==false and hero.is_game_over ~= true then
|
||
hero.thtd_game_info["creature_kill_count"] = 0
|
||
hero.thtd_minoriko_02_change = 0
|
||
end
|
||
end
|
||
SpawnSystem:RefreshCreepMaxCount()
|
||
end
|
||
|
||
-- 无尽高波移除特定BOSS
|
||
function SpawnSystem:RemoveBoss(showMsg)
|
||
if showMsg then
|
||
GameRules:SendCustomMessage("#one_hundred_wave_tip", DOTA_TEAM_GOODGUYS, 0)
|
||
end
|
||
for k,v in pairs(thtd_bosses_list) do
|
||
if v == "aya" then
|
||
table.remove(thtd_bosses_list, k)
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 漏怪检查,返回是否可接受范围内
|
||
function SpawnSystem:CreepCheck()
|
||
local spawner = SpawnSystem.AttackingSpawner
|
||
if spawner == nil or #spawner == 0 then return true end
|
||
local wave = SpawnSystem.CurWave
|
||
local difficulty = GameRules:GetCustomGameDifficulty()
|
||
|
||
CheckPlayerConnect()
|
||
|
||
-- 无尽前
|
||
if not SpawnSystem.IsUnLimited then
|
||
local count = 0
|
||
for _,inner in pairs(THTD_EntitiesRectInner) do
|
||
if inner ~= nil then count = count + #inner end
|
||
end
|
||
if THTD_EntitiesRectOuter ~= nil then count = count + #THTD_EntitiesRectOuter end
|
||
local isEndGame = false
|
||
for spawnerIndex,spawnerLine in pairs(spawner) do
|
||
local hero = spawnerLine.hero
|
||
if hero.is_game_over ~= true then
|
||
hero.thtd_game_info["creep_count"] = count
|
||
if count > hero.thtd_game_info["creep_count_max"] and isEndGame == false then
|
||
isEndGame = true
|
||
end
|
||
end
|
||
end
|
||
if isEndGame then
|
||
for spawnerIndex,spawnerLine in pairs(spawner) do
|
||
local hero = spawnerLine.hero
|
||
if hero.is_game_over ~= true and hero.reimu_pet ~= nil and hero.reimu_pet.pet_level >= 2 then
|
||
for i=0,5 do
|
||
local targetItem = hero.reimu_pet:GetItemInSlot(i)
|
||
if targetItem~=nil and targetItem:IsNull()==false and targetItem:GetAbilityName() == "item_2001" then
|
||
hero.reimu_pet:CastAbilityNoTarget(targetItem, hero:GetPlayerOwnerID())
|
||
isEndGame = false
|
||
break
|
||
end
|
||
end
|
||
if not isEndGame then break end
|
||
end
|
||
end
|
||
if not isEndGame then
|
||
for spawnerIndex,spawnerLine in pairs(spawner) do
|
||
local hero = spawnerLine.hero
|
||
hero.thtd_game_info["creep_count"] = 0
|
||
end
|
||
return true
|
||
else
|
||
RefreshItemListNetTableAll()
|
||
SpawnSystem:GameEnd()
|
||
return false
|
||
end
|
||
else
|
||
return true
|
||
end
|
||
end
|
||
|
||
-- 无尽波数
|
||
-- local entities = Entities:FindAllByClassname("npc_dota_creature")
|
||
for spawnerIndex,spawnerLine in pairs(spawner) do
|
||
local hero = spawnerLine.hero
|
||
if hero.is_game_over ~= true then
|
||
local count = 0
|
||
|
||
-- for k,v in pairs(entities) do
|
||
-- if v ~= nil and v:IsNull() == false and v:IsAlive() and v.thtd_player_index == hero.thtd_player_id and v:GetHealth() > 0 then
|
||
-- if string.find(v:GetUnitName(), 'creature_unlimited') ~= nil or string.find(v:GetUnitName(), 'creature_bosses') ~= nil then
|
||
-- count = count + 1
|
||
-- end
|
||
-- end
|
||
-- end
|
||
|
||
-- 方法二,可以去掉 entities
|
||
for k,v in pairs(THTD_EntitiesRectInner[hero.thtd_player_id]) do
|
||
if v ~= nil and v:IsNull() == false and v:IsAlive() and v:GetHealth() > 0 then
|
||
count = count + 1
|
||
end
|
||
end
|
||
for k,v in pairs(THTD_EntitiesRectOuter) do
|
||
if v ~= nil and v:IsNull() == false and v:IsAlive() and v.thtd_player_index == hero.thtd_player_id and v:GetHealth() > 0 then
|
||
count = count + 1
|
||
end
|
||
end
|
||
|
||
hero.thtd_game_info["creep_count"] = count
|
||
if count == hero.thtd_game_info["creep_count_max"] and GameRules.player_bb_buff[hero.thtd_player_id]["item_3019"] > 0 and GameRules.player_bb_buff[hero.thtd_player_id]["item_3019_enable"] == false and SpawnSystem.CurWave > 50 and SpawnSystem.CurTime <= 5 then
|
||
GameRules.player_bb_buff[hero.thtd_player_id]["item_3019_enable"] = true
|
||
hero:SetContextThink(DoUniqueString("modifier_bb_buff_3019"),
|
||
function()
|
||
GameRules.player_bb_buff[hero.thtd_player_id]["item_3019_enable"] = false
|
||
return nil
|
||
end,
|
||
5.0)
|
||
end
|
||
if count > hero.thtd_game_info["creep_count_max"] then
|
||
if hero.reimu_pet ~= nil and hero.reimu_pet.pet_level >= 2 then
|
||
for i=0,5 do
|
||
local targetItem = hero.reimu_pet:GetItemInSlot(i)
|
||
if targetItem~=nil and targetItem:IsNull()==false and targetItem:GetAbilityName() == "item_2001" then
|
||
hero.reimu_pet:CastAbilityNoTarget(targetItem, hero:GetPlayerOwnerID())
|
||
hero.thtd_game_info["creep_count"] = 0
|
||
break
|
||
end
|
||
end
|
||
end
|
||
if hero.thtd_game_info["creep_count"] > 0 then
|
||
SpawnSystem:GameOver(hero)
|
||
if SpawnSystem:GetCount() == 0 then return false end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
return true
|
||
end
|
||
|
||
-- 指定玩家游戏结束
|
||
function SpawnSystem:GameOver(hero)
|
||
if hero~=nil and hero:IsNull()==false and hero:IsAlive() and hero.is_game_over ~= true then
|
||
RefreshItemListNetTable(hero)
|
||
hero.is_game_over = true
|
||
table.insert(SpawnSystem.GameOverPlayerId, hero.thtd_player_id)
|
||
|
||
if hero.reimu_pet ~= nil then
|
||
if hero.reimu_pet.pet_tree ~= nil then
|
||
UTIL_Remove(hero.reimu_pet.pet_tree)
|
||
end
|
||
UnitStunTarget(hero.reimu_pet,hero.reimu_pet,-1)
|
||
hero.reimu_pet:SetAbsOrigin(Vector(0,0,0))
|
||
hero.reimu_pet:AddNoDraw()
|
||
end
|
||
UnitStunTarget(hero,hero,-1)
|
||
hero:THTD_DropItemAll()
|
||
hero:SetAbsOrigin(Vector(0,0,0))
|
||
hero:AddNoDraw()
|
||
THTD_EntitiesRectInner[hero.thtd_player_id] = {}
|
||
|
||
local wave = SpawnSystem.CurWave
|
||
local entities = Entities:FindAllByClassname("npc_dota_creature")
|
||
local killed = false
|
||
for k,v in pairs(entities) do
|
||
killed = false
|
||
if SpawnSystem.IsUnLimited then
|
||
local findNum = string.find(v:GetUnitName(), 'creature_unlimited')
|
||
local findNum2 = string.find(v:GetUnitName(), 'creature_bosses')
|
||
if (findNum ~= nil or findNum2 ~= nil) and v~=nil and v:IsNull()==false and v:IsAlive() and v.thtd_player_index == hero.thtd_player_id then
|
||
v.diseble_buff = true
|
||
v:ForceKill(false)
|
||
killed = true
|
||
end
|
||
else
|
||
local findNum = string.find(v:GetUnitName(), 'creature')
|
||
if findNum ~= nil and v~=nil and v:IsNull()==false and v:IsAlive() and v.thtd_player_index == hero.thtd_player_id then
|
||
v:ForceKill(false)
|
||
killed = true
|
||
end
|
||
end
|
||
|
||
if killed==false and SpawnSystem:GetCount() > 0 and v~=nil and v:IsNull()==false and v:IsAlive() and v:THTD_IsTower() and v:GetOwner() == hero then
|
||
v:THTD_DropItemAll()
|
||
v:THTD_DestroyLevelEffect()
|
||
hero:AddItem(v.thtd_item)
|
||
hero:THTD_DropItemAll()
|
||
v:SetAbsOrigin(Vector(0,0,0))
|
||
v:AddNoDraw()
|
||
v:AddNewModifier(hero, nil, "modifier_touhoutd_release_hidden", {})
|
||
for _,u in pairs(entities) do
|
||
if u~=nil and u:IsNull()==false and u:IsAlive() and u.thtd_spawn_unit_owner~=nil and u.thtd_spawn_unit_owner==v then
|
||
u:AddNoDraw()
|
||
u:ForceKill(false)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 过挑战第一波BOSS算上榜
|
||
if wave > 100 then
|
||
CheckRank(hero)
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="power_game_end_info", duration=60, params={wave=hero.thtd_game_info["max_wave"],name=PlayerResource:GetPlayerName(hero:GetPlayerID())}, color="#ff0"})
|
||
ShowDetail(hero)
|
||
elseif wave > 50 then
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="normal_game_end_info", duration=30, params={wave=wave-51,name=PlayerResource:GetPlayerName(hero:GetPlayerID())}, color="#f00"})
|
||
end
|
||
SpawnSystem:RefreshCreepMaxCount()
|
||
end
|
||
|
||
if SpawnSystem:GetCount() == 0 then
|
||
SpawnSystem:GameEnd()
|
||
end
|
||
end
|
||
|
||
-- 全部游戏结束
|
||
function SpawnSystem:GameEnd()
|
||
local difficulty = GameRules:GetCustomGameDifficulty()
|
||
local wave = SpawnSystem.CurWave
|
||
|
||
if difficulty < UNLIMITED_MODE and wave > 100 then
|
||
GameRules:GetGameModeEntity():SetContextThink(DoUniqueString("thtd_end_game"),
|
||
function()
|
||
GameRules:SetGameWinner(DOTA_TEAM_GOODGUYS)
|
||
return nil
|
||
end,
|
||
1)
|
||
return
|
||
end
|
||
|
||
if wave > 100 then
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="game_will_end", duration=60, params={}, color="#ff0"})
|
||
GameRules:GetGameModeEntity():SetContextThink(DoUniqueString("thtd_end_game"),
|
||
function()
|
||
GameRules:SetGameWinner(DOTA_TEAM_GOODGUYS)
|
||
return nil
|
||
end,
|
||
60)
|
||
else
|
||
GameRules:GetGameModeEntity():SetContextThink(DoUniqueString("thtd_end_game"),
|
||
function()
|
||
Entities:FindByName(nil, "dota_goodguys_fort"):ForceKill(false)
|
||
return nil
|
||
end,
|
||
1)
|
||
end
|
||
end
|
||
|
||
-- 检查是否能上排行榜
|
||
function CheckRank(hero)
|
||
if GameRules.players_rank_ok ~= true then return end
|
||
if hero.thtd_game_info["max_wave"] == nil or hero.thtd_game_info["max_wave"] == 0 then return end
|
||
if hero.cards == nil then return end
|
||
|
||
local RANK_COUNT = 50 --排行榜排名人数
|
||
|
||
local playerid = hero:GetPlayerOwnerID()
|
||
local steamid = tostring(PlayerResource:GetSteamID(playerid))
|
||
|
||
local wavedata = {}
|
||
wavedata["wave"] = hero.thtd_game_info["max_wave"]
|
||
wavedata["damage"] = hero.thtd_game_info["max_wave_damage"] / 10000
|
||
for i=0,12 do
|
||
if (i+1) <= #hero.cards then
|
||
wavedata["card"..tostring(i)] = hero.cards[i+1]
|
||
else
|
||
wavedata["card"..tostring(i)] = ""
|
||
end
|
||
end
|
||
|
||
-- 确定上传的排行榜
|
||
local isTeamMode = hero.is_team_mode
|
||
if not isTeamMode then
|
||
for i=1,3 do
|
||
if wavedata["card"..tostring(i)] ~= nil and wavedata["card"..tostring(i)]["itemname"] ~= nil and (towerNameList[wavedata["card"..tostring(i)]["itemname"]]["cardname"] == GameRules.GameData.luck_card or GameRules.GameData.luck_card == "all") then
|
||
isTeamMode = true
|
||
hero.is_team_mode = true
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
if isTeamMode then
|
||
if wavedata["wave"] <= GameRules.PlayerData[playerid].max_team_wave then return end
|
||
if #GameRules.players_team_rank >= RANK_COUNT and wavedata["wave"] <= GameRules.players_team_rank[RANK_COUNT].wave then return end
|
||
else
|
||
if wavedata["wave"] <= GameRules.PlayerData[playerid].max_wave then return end
|
||
if #GameRules.players_rank >= RANK_COUNT and wavedata["wave"] <= GameRules.players_rank[RANK_COUNT].wave then return end
|
||
end
|
||
|
||
local toplist
|
||
if isTeamMode then
|
||
toplist = GameRules.players_team_rank_data
|
||
else
|
||
toplist = GameRules.players_rank_data
|
||
end
|
||
|
||
local toDelList = {}
|
||
local isTop = true
|
||
local rankIndex = 0 --排名
|
||
local bestWave = 0
|
||
|
||
if #toplist > 0 then
|
||
for i=1,#toplist do
|
||
local topdata = toplist[i]
|
||
if rankIndex == 0 and wavedata["wave"] > topdata["wave"] then
|
||
rankIndex = i
|
||
end
|
||
|
||
if steamid ~= topdata["steamid"] then
|
||
local isSameRank = false
|
||
|
||
if wavedata["card1"] ~= "" and topdata["card1"] ~= "" and topdata["card1"] ~= nil and wavedata["card1"]["itemname"] == topdata["card1"]["itemname"] then
|
||
if wavedata["card1"]["damage"] / (10000 * wavedata["damage"]) >= 0.6 and topdata["card1"]["damage"] / (10000 * topdata["damage"]) >= 0.6 then
|
||
isSameRank = true
|
||
end
|
||
end
|
||
|
||
if isSameRank ~= true then
|
||
local topDamage1 = 0
|
||
local topDamage2 = 0
|
||
local topNum = 0
|
||
for x=1,12 do
|
||
if wavedata["card"..tostring(x)] ~= "" then
|
||
topDamage1 = topDamage1 + wavedata["card"..tostring(x)]["damage"]
|
||
end
|
||
if topdata["card"..tostring(x)] ~= "" and topdata["card"..tostring(x)] ~= nil then
|
||
topDamage2 = topDamage2 + topdata["card"..tostring(x)]["damage"]
|
||
end
|
||
if topDamage1 / (10000 * wavedata["damage"]) >= 0.8 and topDamage2 / (10000 * topdata["damage"]) >= 0.8 then
|
||
topNum = x
|
||
break
|
||
end
|
||
end
|
||
if topNum > 0 then
|
||
local usedIndex = ""
|
||
local sameCount = 0
|
||
for x=1,topNum do
|
||
for y=1,topNum do
|
||
if string.find(usedIndex,tostring(y)) == nil and wavedata["card"..tostring(x)] ~= "" and topdata["card"..tostring(y)] ~= "" and topdata["card"..tostring(y)] ~= nil and wavedata["card"..tostring(x)]["itemname"] == topdata["card"..tostring(y)]["itemname"] then
|
||
sameCount = sameCount + 1
|
||
usedIndex = usedIndex..tostring(y)..","
|
||
break
|
||
end
|
||
end
|
||
end
|
||
if sameCount == topNum then isSameRank = true end
|
||
end
|
||
end
|
||
|
||
if isSameRank == true then
|
||
if wavedata["wave"] <= topdata["wave"] then
|
||
if isTop ~= false then isTop = false end
|
||
if bestWave == 0 then bestWave = topdata["wave"] end
|
||
else
|
||
table.insert(toDelList, i)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
for k,v in pairs(toDelList) do
|
||
if isTeamMode then
|
||
Service:ResetRank(v,"D")
|
||
else
|
||
Service:ResetRank(v,"S")
|
||
end
|
||
end
|
||
GameRules:SendCustomMessage("<font color='blue'>clear the same rank : "..json.encode(toDelList).."</font>", DOTA_TEAM_GOODGUYS, 0)
|
||
|
||
if not isTop then
|
||
CustomGameEventManager:Send_ServerToPlayer(hero:GetPlayerOwner(), "thtd_server_msg", {code = "0000", msg = "你打破了自己的历史记录,但没有超过该阵容的最高波数 "..bestWave..",请再接再厉!", duration = 30})
|
||
return
|
||
end
|
||
|
||
if rankIndex == 0 then rankIndex = #toplist + 1 end
|
||
wavedata["rank_index"] = rankIndex
|
||
|
||
if isTeamMode then
|
||
Service:UploadRank(playerid, "D", wavedata)
|
||
else
|
||
Service:UploadRank(playerid, "S", wavedata)
|
||
end
|
||
end
|
||
|
||
-- 显示最大波数信息
|
||
function ShowDetail(hero)
|
||
if hero.cards == nil or #hero.cards == 0 then return end
|
||
|
||
local wavedata = {}
|
||
for i=0,12 do
|
||
if (i+1) <= #hero.cards then
|
||
wavedata["card"..tostring(i)] = hero.cards[i+1]
|
||
else
|
||
wavedata["card"..tostring(i)] = ""
|
||
end
|
||
end
|
||
wavedata['wave'] = hero.thtd_game_info["max_wave"]
|
||
|
||
CustomGameEventManager:Send_ServerToPlayer(hero:GetPlayerOwner(), "thtd_game_over_detail", wavedata)
|
||
end
|
||
|
||
-- 检查玩家是否掉线
|
||
function CheckPlayerConnect()
|
||
local spawner = SpawnSystem.AttackingSpawner
|
||
if spawner == nil or #spawner == 0 then return end
|
||
for spawnerIndex,spawnerLine in pairs(spawner) do
|
||
local hero = spawnerLine.hero
|
||
if (hero:GetPlayerOwner() == nil or hero:GetPlayerOwner():IsNull()) then
|
||
if hero.thtd_game_info["is_player_connected"] then
|
||
hero.thtd_game_info["is_player_connected"] = false
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="player_disconnect", duration=15, params={count=1}, color="#0ff"} )
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="{d:count}", duration=15, params={count=hero.thtd_player_id+1}, color="#ff0"})
|
||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="pause_game", duration=15, params={}, color="#ff0"})
|
||
if GameRules:IsGamePaused() then PauseGame(false) end
|
||
PauseGame(true)
|
||
end
|
||
else
|
||
if not hero.thtd_game_info["is_player_connected"] then hero.thtd_game_info["is_player_connected"] = true end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 每波刷怪结束各线路数据更新,伤害清零,统计更新
|
||
function SpawnSystem:WaveEndForEach()
|
||
local spawner = SpawnSystem.AttackingSpawner
|
||
if spawner == nil or #spawner == 0 then return end
|
||
local wave = SpawnSystem.CurWave
|
||
local difficulty = GameRules:GetCustomGameDifficulty()
|
||
for spawnerIndex,spawnerLine in pairs(spawner) do
|
||
local hero = spawnerLine.hero
|
||
if hero.is_game_over ~= true then
|
||
local isMaxWave = false
|
||
if wave >= SpawnSystem.RankMinWave then
|
||
local totalDamage = 0
|
||
for k,v in pairs(hero.thtd_hero_tower_list) do
|
||
if v~=nil and v:IsNull()==false then
|
||
totalDamage = totalDamage + v:THTD_GetTowerDamage()
|
||
end
|
||
end
|
||
if totalDamage < hero.thtd_wave_total_health * 0.9 then
|
||
CustomGameEventManager:Send_ServerToPlayer(hero:GetPlayerOwner(), "display_chat_msg", {msg="damage_less_rank_tip", params={player_name=PlayerResource:GetPlayerName(hero:GetPlayerOwnerID())}})
|
||
else
|
||
isMaxWave = true
|
||
end
|
||
end
|
||
-- todo test
|
||
-- isMaxWave = true
|
||
if isMaxWave then
|
||
hero.thtd_game_info["max_wave"] = wave - 50
|
||
hero.thtd_game_info["max_wave_damage"] = 0
|
||
hero.cards = {}
|
||
end
|
||
|
||
for k,v in pairs(hero.thtd_hero_tower_list) do
|
||
if v~=nil and v:IsNull()==false and v:IsAlive() then
|
||
if isMaxWave then
|
||
hero.thtd_game_info["max_wave_damage"] = hero.thtd_game_info["max_wave_damage"] + v:THTD_GetTowerDamage()/100
|
||
local card = {}
|
||
card["itemname"] = v.thtd_item:GetAbilityName()
|
||
card["star"] = v:THTD_GetStar()
|
||
card["damage"] = math.floor(v:THTD_GetTowerDamage()/100)
|
||
card["power"] = math.floor(v:THTD_GetPower() or 0)
|
||
card["attack"] = math.floor(v:THTD_GetAttack() or 0)
|
||
card["equip"] = {}
|
||
for i=0,5 do
|
||
local targetItem = v:GetItemInSlot(i)
|
||
if targetItem~=nil and targetItem:IsNull()==false then
|
||
table.insert(card["equip"], targetItem:GetAbilityName())
|
||
end
|
||
end
|
||
if #card["equip"] == 0 then card["equip"] = nil end
|
||
table.insert(hero.cards, card)
|
||
end
|
||
if not SpawnSystem.IsUnLimited then
|
||
if v:GetUnitName() == "toramaru" and GameRules:GetCustomGameDifficulty() < FUNNY_MODE then
|
||
local gold = math.floor(v:THTD_GetTowerDamage() * v:GetAbilityValue("thtd_toramaru_01", "gold_damage_percent"))
|
||
THTD_ModifyGoldEx(v:GetPlayerOwnerID(),gold,true,DOTA_ModifyGold_CreepKill)
|
||
SendOverheadEventMessage(v:GetPlayerOwner(),OVERHEAD_ALERT_GOLD,v,gold,v:GetPlayerOwner() )
|
||
end
|
||
end
|
||
v:THTD_ResetTowerDamage()
|
||
end
|
||
end
|
||
hero.thtd_wave_total_health = 0
|
||
|
||
if isMaxWave then
|
||
hero.thtd_game_info["max_wave_damage"] = math.floor(hero.thtd_game_info["max_wave_damage"] + 0.5)
|
||
table.sort(hero.cards, function(a,b) return a["damage"] > b["damage"] end) --坑:使用 a.damage >= b.damage 会失败
|
||
|
||
local card = {}
|
||
card["itemname"] = "item_0028"
|
||
card["star"] = 0
|
||
card["damage"] = hero.next_boss_name or 0 -- 最后BOSS
|
||
card["power"] = hero.use_item2001_count or 0 --爆弹数量
|
||
card["attack"] = 0 --核心数,js计算
|
||
card["equip"] = hero.bb_buff or {}
|
||
if #card["equip"] == 0 then
|
||
for i=0,5 do
|
||
local targetItem = hero:GetItemInSlot(i)
|
||
if targetItem~=nil and targetItem:IsNull()==false then
|
||
table.insert(card["equip"], targetItem:GetAbilityName())
|
||
end
|
||
end
|
||
end
|
||
if #card["equip"] == 0 then card["equip"] = nil end
|
||
table.insert(hero.cards, 1, card)
|
||
end
|
||
|
||
-- 清空空值
|
||
local inner = THTD_EntitiesRectInner[hero.thtd_player_id]
|
||
if inner ~= nil then
|
||
for i = #inner, 1, -1 do
|
||
if inner[i]==nil or inner[i]:IsNull() or inner[i]:IsAlive()==false then
|
||
table.remove(inner, i)
|
||
end
|
||
end
|
||
end
|
||
|
||
if SpawnSystem.IsUnLimited == false and wave >= 30 and wave < 50 and GameRules:GetCustomGameDifficulty() >= FUNNY_MODE then
|
||
for i=1,4 do
|
||
local item = CreateItem("item_1006", nil, nil)
|
||
item.owner_player_id = hero.thtd_player_id
|
||
item:SetPurchaser(hero)
|
||
item:SetPurchaseTime(1.0)
|
||
local pos = GetSpawnLineOffsetVector(hero.spawn_index, hero.spawn_position, (i-1) * 130, 150)
|
||
CreateItemOnPositionSync(pos, item)
|
||
end
|
||
end
|
||
|
||
-- 战利品奖励关
|
||
SpawnSystem:OnBattleBonusWave(hero)
|
||
|
||
-- 战斗中铸就
|
||
if wave > 50 and wave < 1050 and GameRules.player_bb_buff[hero.thtd_player_id]["item_3014"] > 0 then
|
||
local bonusTargets = {}
|
||
for k,v in pairs(hero.thtd_hero_tower_list) do
|
||
local unitName = v:GetUnitName()
|
||
if unitName == "reimu" or unitName == "marisa" or unitName == "sanae" or unitName == "alice" then
|
||
table.insert(bonusTargets, v)
|
||
end
|
||
end
|
||
if #bonusTargets > 0 then
|
||
local bonusWave = SpawnSystem.CurWave - (hero.bb_buff3014_last_wave or 50)
|
||
hero.bb_buff3014_last_wave = SpawnSystem.CurWave
|
||
local bonusPower = GameRules.player_bb_buff[hero.thtd_player_id]["item_3014"] * bonusWave
|
||
for k,v in pairs(bonusTargets) do
|
||
v:THTD_AddBasePower(bonusPower)
|
||
end
|
||
bonusTargets = {}
|
||
end
|
||
end
|
||
|
||
-- 封兽鵺跳关扣减层数
|
||
if SpawnSystem.ReachToWave ~= nil then
|
||
local deCount = math.max(0, SpawnSystem.ReachToWave + 50 - wave) * 20
|
||
if deCount > 0 then
|
||
for k,v in pairs(hero.thtd_hero_tower_list) do
|
||
local unitName = v:GetUnitName()
|
||
if unitName == "nue" then
|
||
local modifier = v:FindModifierByName("modifier_nue_01_extradamage")
|
||
if modifier ~= nil then
|
||
modifier:SetStackCount(math.max(1, modifier:GetStackCount() - deCount))
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
end
|
||
end
|
||
|
||
-- 清空空值
|
||
if THTD_EntitiesRectOuter ~= nil then
|
||
for i = #THTD_EntitiesRectOuter, 1, -1 do
|
||
if THTD_EntitiesRectOuter[i]==nil or THTD_EntitiesRectOuter[i]:IsNull() or THTD_EntitiesRectOuter[i]:IsAlive()==false then
|
||
table.remove(THTD_EntitiesRectOuter, i)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 代替触发器
|
||
local UnitMoveRect = {
|
||
[0] = {
|
||
[1] = {
|
||
["center"] = {-2200, 1550},
|
||
["radius"] = 200,
|
||
["tag"] = {2}
|
||
},
|
||
[2] = {
|
||
["center"] = {-4100, 1600},
|
||
["radius"] = 100,
|
||
["tag"] = {3}
|
||
},
|
||
[3] = {
|
||
["center"] = {-4100, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 7}
|
||
},
|
||
[4] = {
|
||
["center"] = {6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 7}
|
||
},
|
||
[5] = {
|
||
["center"] = {6750, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 6}
|
||
},
|
||
[6] = {
|
||
["center"] = {-6750, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 7}
|
||
},
|
||
[7] = {
|
||
["center"] = {-6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 6}
|
||
},
|
||
},
|
||
[1] = {
|
||
[1] = {
|
||
["center"] = {2200, 1550},
|
||
["radius"] = 200,
|
||
["tag"] = {2 }
|
||
},
|
||
[2] = {
|
||
["center"] = {4100, 1600},
|
||
["radius"] = 100,
|
||
["tag"] = {3 }
|
||
},
|
||
[3] = {
|
||
["center"] = {4100, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 7}
|
||
},
|
||
[4] = {
|
||
["center"] = {6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 7}
|
||
},
|
||
[5] = {
|
||
["center"] = {6750, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 6}
|
||
},
|
||
[6] = {
|
||
["center"] = {-6750, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 7}
|
||
},
|
||
[7] = {
|
||
["center"] = {-6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 6}
|
||
},
|
||
},
|
||
[2] = {
|
||
[1] = {
|
||
["center"] = {2200, -1550},
|
||
["radius"] = 200,
|
||
["tag"] = {2 }
|
||
},
|
||
[2] = {
|
||
["center"] = {4100, -1600},
|
||
["radius"] = 100,
|
||
["tag"] = {3 }
|
||
},
|
||
[3] = {
|
||
["center"] = {4100, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 6}
|
||
},
|
||
[4] = {
|
||
["center"] = {6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 7}
|
||
},
|
||
[5] = {
|
||
["center"] = {6750, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 6}
|
||
},
|
||
[6] = {
|
||
["center"] = {-6750, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 7}
|
||
},
|
||
[7] = {
|
||
["center"] = {-6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 6}
|
||
},
|
||
},
|
||
[3] = {
|
||
[1] = {
|
||
["center"] = {-2200, -1550},
|
||
["radius"] = 200,
|
||
["tag"] = {2 }
|
||
},
|
||
[2] = {
|
||
["center"] = {-4100, -1600},
|
||
["radius"] = 100,
|
||
["tag"] = {3 }
|
||
},
|
||
[3] = {
|
||
["center"] = {-4100, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 6}
|
||
},
|
||
[4] = {
|
||
["center"] = {6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 7}
|
||
},
|
||
[5] = {
|
||
["center"] = {6750, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 6}
|
||
},
|
||
[6] = {
|
||
["center"] = {-6750, -4120},
|
||
["radius"] = 100,
|
||
["tag"] = {5, 7}
|
||
},
|
||
[7] = {
|
||
["center"] = {-6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {4, 6}
|
||
},
|
||
}
|
||
}
|
||
|
||
-- 代替触发器
|
||
local UnitMoveRectAll = {
|
||
[1] = {
|
||
["center"] = {-2200, 1550},
|
||
["radius"] = 200,
|
||
["tag"] = {
|
||
["left"] = {
|
||
{
|
||
["forward"] = "left",
|
||
["index"] = 2
|
||
},
|
||
},
|
||
}
|
||
},
|
||
[2] = {
|
||
["center"] = {-4100, 1600},
|
||
["radius"] = 100,
|
||
["tag"] = {
|
||
["left"] = {
|
||
{
|
||
["forward"] = "up",
|
||
["index"] = 3
|
||
},
|
||
},
|
||
}
|
||
},
|
||
[3] = {
|
||
["center"] = {-4100, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = {
|
||
["up"] = {
|
||
{
|
||
["forward"] = "left",
|
||
["index"] = 4
|
||
},
|
||
{
|
||
["forward"] = "right",
|
||
["index"] = 5
|
||
},
|
||
},
|
||
}
|
||
},
|
||
[4] = {
|
||
["center"] = {-6750, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = { }
|
||
},
|
||
[5] = {
|
||
["center"] = {10, 4120},
|
||
["radius"] = 100,
|
||
["tag"] = { }
|
||
},
|
||
}
|
||
|
||
-- 随机BOSS自带buff
|
||
local RandomBossBuff = {
|
||
"modifier_bosses_random_aura_dark",
|
||
"modifier_bosses_random_attack_speed_aura",
|
||
"modifier_bosses_random_move_aura",
|
||
"modifier_bosses_random_health_aura",
|
||
"modifier_bosses_random_dead_heal"
|
||
}
|
||
|
||
-- 解决草地问题
|
||
local UnitPathFixRect = {
|
||
[0] = {
|
||
[0] = { -- 靠商店侧
|
||
[1] = Vector(-3600, 1800, 128), --左下角
|
||
[2] = Vector(-2100, 2600, 128), --右上角
|
||
},
|
||
[1] = { -- 靠商店侧
|
||
[1] = Vector(-2100, 1700, 128), --左下角
|
||
[2] = Vector(-1020, 2600, 128), --右上角
|
||
},
|
||
[2] = { -- 拐角
|
||
[1] = Vector(-1900, 1420, 128), --靠内上角
|
||
[2] = Vector(-2700, 100, 128), --靠外下角
|
||
},
|
||
},
|
||
[1] = {
|
||
[0] = { -- 靠商店侧
|
||
[1] = Vector(2100, 1800, 128), --左下角
|
||
[2] = Vector(3600, 2600, 128), --右上角
|
||
},
|
||
[1] = { -- 靠商店侧
|
||
[1] = Vector(1020, 1700, 128),
|
||
[2] = Vector(2100, 2600, 128),
|
||
},
|
||
[2] = { -- 拐角
|
||
[1] = Vector(1900, 1420, 128),
|
||
[2] = Vector(2700, 100, 128),
|
||
},
|
||
},
|
||
[2] = {
|
||
[0] = { -- 靠商店侧
|
||
[1] = Vector(2100, -2600, 128), --左下角
|
||
[2] = Vector(3600, -1800, 128), --右上角
|
||
},
|
||
[1] = { -- 靠商店侧
|
||
[1] = Vector(1020, -2600, 128),
|
||
[2] = Vector(2100, -1700, 128),
|
||
},
|
||
[2] = { -- 拐角
|
||
[1] = Vector(1900, -1420, 128),
|
||
[2] = Vector(2700, -100, 128),
|
||
},
|
||
},
|
||
[3] = {
|
||
[0] = { -- 靠商店侧
|
||
[1] = Vector(-3600, -2600, 128), --左下角
|
||
[2] = Vector(-2100, -1800, 128), --右上角
|
||
},
|
||
[1] = { -- 靠商店侧
|
||
[1] = Vector(-2100, -2600, 128),
|
||
[2] = Vector(-1020, -1700, 128),
|
||
},
|
||
[2] = { -- 拐角
|
||
[1] = Vector(-1900, -1420, 128),
|
||
[2] = Vector(-2700, -100, 128),
|
||
},
|
||
}
|
||
}
|
||
|
||
-- 刷怪
|
||
function SpawnSystem:StartSpawn()
|
||
local spawner = SpawnSystem.AttackingSpawner
|
||
if spawner == nil or #spawner == 0 then return end
|
||
local difficulty = GameRules:GetCustomGameDifficulty()
|
||
|
||
local wave = SpawnSystem.CurWave
|
||
local waveInfo = nil
|
||
if wave <= 51 then
|
||
waveInfo = SpawnSystem.Spawner["Attacking"]["Wave"..tostring(wave)]
|
||
else
|
||
waveInfo = SpawnSystem.Spawner["Attacking"]["Wave51"]
|
||
end
|
||
|
||
local count = waveInfo["Count"]
|
||
local times = waveInfo["Times"]
|
||
local interval = waveInfo["Interval"]
|
||
|
||
for spawnerIndex,spawnerLine in pairs(spawner) do
|
||
local hero = spawnerLine.hero
|
||
if hero.is_game_over ~= true then
|
||
local player = hero:GetPlayerOwner()
|
||
local playerId = hero:GetPlayerOwnerID()
|
||
-- 刷新BOSS信息并重置秋
|
||
if difficulty >= EXTRA_MODE then
|
||
if wave > 50 and wave%4 == 3 then
|
||
hero.thtd_minoriko_02_change = 0
|
||
THTD_ModifyGoldEx(playerId,3500,true,DOTA_ModifyGold_CreepKill)
|
||
for k,v in pairs(hero.thtd_hero_tower_list) do
|
||
if v~=nil and v:IsNull()==false and v:IsAlive() then
|
||
if v:THTD_IsTower() and v:THTD_GetLevel()<THTD_MAX_LEVEL then
|
||
v:THTD_SetLevel(THTD_MAX_LEVEL)
|
||
end
|
||
end
|
||
end
|
||
spawnerLine.nextBossName = thtd_bosses_list[RandomInt(1, #thtd_bosses_list)]
|
||
hero.next_boss_name = spawnerLine.nextBossName
|
||
if player ~= nil then
|
||
CustomGameEventManager:Send_ServerToPlayer(player,"show_message", {msg="extra_bonus_nazrin", duration=60, params={count=1}, color="#0ff"} )
|
||
CustomGameEventManager:Send_ServerToPlayer(player,"show_message", {msg="extra_bonus_minoriko_limit", duration=60, params={count=1}, color="#0ff"} )
|
||
CustomGameEventManager:Send_ServerToPlayer(player,"show_message", {msg="extra_bonus_lily", duration=60, params={count=1}, color="#0ff"} )
|
||
CustomGameEventManager:Send_ServerToPlayer(player,"show_message", {msg="extra_bosses_"..spawnerLine.nextBossName, duration=60, params={count=1}, color="#0ff"} )
|
||
end
|
||
end
|
||
end
|
||
|
||
local curTimes = 1
|
||
local randomBossIndex = RandomInt(1, times-10)
|
||
spawnerLine:SetContextThink(DoUniqueString("SpawnAttackingSpawn"..tostring(spawnerIndex)),
|
||
function()
|
||
if GameRules:IsGamePaused() then return 0.1 end
|
||
if curTimes > times then return nil end
|
||
|
||
for i = 1, count do
|
||
if hero.is_game_over == true then return nil end
|
||
|
||
local spawn_unit = waveInfo["Unit"]
|
||
|
||
if difficulty >= EXTRA_MODE and wave > 50 and wave%4 == 0 and spawnerLine.nextBossName ~= nil then
|
||
spawn_unit = "creature_bosses_"..spawnerLine.nextBossName
|
||
end
|
||
|
||
local unit = CreateUnitByName(spawn_unit, spawnerLine:GetOrigin() + RandomVector(400), true, nil, nil, DOTA_TEAM_BADGUYS )
|
||
if unit ~= nil then
|
||
unit.thtd_player_index = hero.thtd_player_id
|
||
|
||
unit.thtd_damage_incoming_magical_percentage = 0
|
||
unit.thtd_damage_incoming_physical_percentage = 0
|
||
unit.thtd_damage_incoming_pure_percentage = 0
|
||
unit.thtd_damage_block_pure = 0
|
||
unit.thtd_damage_block_physical = 0
|
||
unit.thtd_damage_block_magical = 0
|
||
|
||
unit:AddNewModifier(unit, nil, "modifier_phased", {})
|
||
|
||
if wave > 50 then
|
||
local health = math.min(MAX_HEALTH, unit:GetBaseMaxHealth() * SpawnSystem:GetWaveHpFactor())
|
||
unit:SetBaseMaxHealth(health)
|
||
unit:SetMaxHealth(health)
|
||
unit:SetHealth(health)
|
||
|
||
if difficulty >= EXTRA_MODE then
|
||
if wave%4 == 0 and spawnerLine.nextBossName ~= nil then
|
||
unit:AddNewModifier(unit, nil, "modifier_bosses_"..spawnerLine.nextBossName, nil)
|
||
elseif wave%4 ~= 0 and curTimes == randomBossIndex then
|
||
unit.is_random_boss = true
|
||
health = math.min(MAX_HEALTH, health * 1.5)
|
||
unit:SetBaseMaxHealth(health)
|
||
unit:SetMaxHealth(health)
|
||
unit:SetHealth(health)
|
||
unit:SetModelScale(unit:GetModelScale() * 1.5)
|
||
|
||
-- 随机Buff
|
||
local bossBuffChance = 25
|
||
if wave >= 200 then
|
||
bossBuffChance = 100
|
||
elseif wave >= 150 then
|
||
bossBuffChance = 75
|
||
elseif wave >= 100 then
|
||
bossBuffChance = 50
|
||
end
|
||
if RollPercentage(bossBuffChance) then
|
||
local modifierName = RandomBossBuff[RandomInt(1, #RandomBossBuff)]
|
||
unit:AddNewModifier(unit, nil, modifierName, {})
|
||
if player ~= nil then
|
||
CustomGameEventManager:Send_ServerToPlayer(player,"show_message", {msg="random_boss_has_buff", duration=20, params={}, color="#0ff"})
|
||
CustomGameEventManager:Send_ServerToPlayer(player,"show_message", {msg="DOTA_Tooltip_"..modifierName.."_Description", duration=20, params={}, color="#0ff"})
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if GameRules.player_bb_buff[hero.thtd_player_id]["item_3026"] > 0 then
|
||
local modifier = unit:AddNewModifier(unit, nil, "modifier_move_speed", nil)
|
||
modifier:SetStackCount(800+GameRules.player_bb_buff[hero.thtd_player_id]["item_3026"])
|
||
end
|
||
|
||
-- 少女之抵抗
|
||
if wave >= 50 + 250 + 30 then
|
||
local unlimitedResist = 0
|
||
if wave <= 50 + 3220 then
|
||
unlimitedResist = math.floor((wave - 50 - 250)/30)
|
||
else --max: 无尽5218
|
||
unlimitedResist = 99 + math.min(0.999, 0.001 * math.floor((wave - 50 - 3220) / 2))
|
||
end
|
||
local modifier = unit:AddNewModifier(unit, nil, "modifier_touhoutd_unlimited_resist", {})
|
||
if modifier ~= nil then
|
||
modifier:SetStackCount(math.floor(unlimitedResist))
|
||
end
|
||
unit.unlimited_resist = unlimitedResist
|
||
end
|
||
|
||
hero.thtd_wave_total_health = hero.thtd_wave_total_health + health/100
|
||
else
|
||
local modifier = unit:AddNewModifier(unit, nil, "modifier_move_speed", nil)
|
||
if modifier ~= nil then
|
||
modifier:SetStackCount(math.floor(wave/4)*20)
|
||
end
|
||
if difficulty == NORMAL_MODE then
|
||
unit:AddDamageIncomingAll(30)
|
||
end
|
||
end
|
||
|
||
table.insert(THTD_EntitiesRectInner[hero.thtd_player_id], unit)
|
||
|
||
unit.thtd_first_corner = spawnerLine.first_point
|
||
unit.first_move_forward = spawnerLine.first_forward
|
||
unit.first_move_point = G_path_corner[unit.thtd_first_corner].Vector * 1.5
|
||
|
||
unit.thtd_second_corner = spawnerLine.second_point
|
||
unit.second_move_forward = spawnerLine.second_forward
|
||
unit.second_move_point = G_path_corner[unit.thtd_second_corner].Vector * 1.5
|
||
|
||
unit.thtd_next_corner = unit.thtd_first_corner
|
||
unit.next_move_forward = unit.first_move_forward
|
||
unit.next_move_point = unit.first_move_point
|
||
|
||
unit:SetContextThink(DoUniqueString("AttackingBase"),
|
||
function ()
|
||
if GameRules:IsGamePaused() then return 0.1 end
|
||
if unit == nil or unit:IsNull() or unit:IsAlive() == false then return nil end
|
||
|
||
local origin = unit:GetOrigin()
|
||
if unit.thtd_is_outer ~= true then
|
||
if not(origin.x < 4432 and origin.x > -4432 and origin.y < 3896 and origin.y > -3896) then
|
||
unit.thtd_is_outer = true
|
||
table.insert(THTD_EntitiesRectOuter,unit)
|
||
for k,v in pairs(THTD_EntitiesRectInner[hero.thtd_player_id]) do
|
||
if v == unit then
|
||
table.remove(THTD_EntitiesRectInner[hero.thtd_player_id],k)
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 修正卡怪问题
|
||
if unit.thtd_is_fearing ~= true then
|
||
if math.abs(origin.x) < math.abs(unit.first_move_point.x) - 150 then
|
||
if unit.next_move_point ~= unit.first_move_point then
|
||
unit.thtd_next_corner = unit.thtd_first_corner
|
||
unit.next_move_forward = unit.first_move_forward
|
||
unit.next_move_point = unit.first_move_point
|
||
end
|
||
else
|
||
if math.abs(origin.x) < math.abs(unit.second_move_point.x) - 300 and unit.next_move_point ~= unit.second_move_point then
|
||
unit.thtd_next_corner = unit.thtd_second_corner
|
||
unit.next_move_forward = unit.second_move_forward
|
||
unit.next_move_point = unit.second_move_point
|
||
end
|
||
end
|
||
end
|
||
end
|
||
unit:MoveToPosition(unit.next_move_point)
|
||
|
||
-- 草地路径修正
|
||
if
|
||
origin.x > UnitPathFixRect[unit.thtd_player_index][0][1].x and
|
||
origin.x < UnitPathFixRect[unit.thtd_player_index][0][2].x and
|
||
origin.y > UnitPathFixRect[unit.thtd_player_index][0][1].y and
|
||
origin.y < UnitPathFixRect[unit.thtd_player_index][0][2].y then
|
||
if unit.thtd_player_index <= 1 then
|
||
unit:SetAbsOrigin(Vector(origin.x, UnitPathFixRect[unit.thtd_player_index][0][1].y - 5, UnitPathFixRect[unit.thtd_player_index][0][1].z))
|
||
else
|
||
unit:SetAbsOrigin(Vector(origin.x, UnitPathFixRect[unit.thtd_player_index][0][2].y + 10, UnitPathFixRect[unit.thtd_player_index][0][2].z))
|
||
end
|
||
elseif
|
||
origin.x > UnitPathFixRect[unit.thtd_player_index][1][1].x and
|
||
origin.x < UnitPathFixRect[unit.thtd_player_index][1][2].x and
|
||
origin.y > UnitPathFixRect[unit.thtd_player_index][1][1].y and
|
||
origin.y < UnitPathFixRect[unit.thtd_player_index][1][2].y then
|
||
if unit.thtd_player_index <= 1 then
|
||
unit:SetAbsOrigin(Vector(origin.x, UnitPathFixRect[unit.thtd_player_index][1][1].y - 5, UnitPathFixRect[unit.thtd_player_index][1][1].z))
|
||
else
|
||
unit:SetAbsOrigin(Vector(origin.x, UnitPathFixRect[unit.thtd_player_index][1][2].y + 7, UnitPathFixRect[unit.thtd_player_index][1][2].z))
|
||
end
|
||
elseif unit.thtd_player_index == 0 then
|
||
if origin.x > UnitPathFixRect[unit.thtd_player_index][2][2].x and
|
||
origin.x < UnitPathFixRect[unit.thtd_player_index][2][1].x and
|
||
origin.y > UnitPathFixRect[unit.thtd_player_index][2][2].y and
|
||
origin.y < UnitPathFixRect[unit.thtd_player_index][2][1].y then
|
||
if math.abs(origin.x - UnitPathFixRect[unit.thtd_player_index][2][1].x) > math.abs(origin.y - UnitPathFixRect[unit.thtd_player_index][2][1].y) then
|
||
unit:SetAbsOrigin(Vector(origin.x, UnitPathFixRect[unit.thtd_player_index][2][1].y + 10, UnitPathFixRect[unit.thtd_player_index][2][2].z))
|
||
else --y增量要大于移速,防止已切换移动到第二个点拉回来卡住
|
||
unit:SetAbsOrigin(Vector(UnitPathFixRect[unit.thtd_player_index][2][1].x + 5, origin.y + 100, UnitPathFixRect[unit.thtd_player_index][1][1].z))
|
||
end
|
||
end
|
||
elseif unit.thtd_player_index == 1 then
|
||
if origin.x > UnitPathFixRect[unit.thtd_player_index][2][1].x and
|
||
origin.x < UnitPathFixRect[unit.thtd_player_index][2][2].x and
|
||
origin.y > UnitPathFixRect[unit.thtd_player_index][2][2].y and
|
||
origin.y < UnitPathFixRect[unit.thtd_player_index][2][1].y then
|
||
if math.abs(origin.x - UnitPathFixRect[unit.thtd_player_index][2][1].x) > math.abs(origin.y - UnitPathFixRect[unit.thtd_player_index][2][1].y) then
|
||
unit:SetAbsOrigin(Vector(origin.x, UnitPathFixRect[unit.thtd_player_index][2][1].y + 5, UnitPathFixRect[unit.thtd_player_index][2][2].z))
|
||
else
|
||
unit:SetAbsOrigin(Vector(UnitPathFixRect[unit.thtd_player_index][2][1].x - 5, origin.y + 100, UnitPathFixRect[unit.thtd_player_index][1][1].z))
|
||
end
|
||
end
|
||
elseif unit.thtd_player_index == 2 then
|
||
if origin.x > UnitPathFixRect[unit.thtd_player_index][2][1].x and
|
||
origin.x < UnitPathFixRect[unit.thtd_player_index][2][2].x and
|
||
origin.y > UnitPathFixRect[unit.thtd_player_index][2][1].y and
|
||
origin.y < UnitPathFixRect[unit.thtd_player_index][2][2].y then
|
||
if math.abs(origin.x - UnitPathFixRect[unit.thtd_player_index][2][1].x) > math.abs(origin.y - UnitPathFixRect[unit.thtd_player_index][2][1].y) then
|
||
unit:SetAbsOrigin(Vector(origin.x, UnitPathFixRect[unit.thtd_player_index][2][1].y - 5, UnitPathFixRect[unit.thtd_player_index][2][2].z))
|
||
else
|
||
unit:SetAbsOrigin(Vector(UnitPathFixRect[unit.thtd_player_index][2][1].x - 5, origin.y - 100, UnitPathFixRect[unit.thtd_player_index][1][1].z))
|
||
end
|
||
end
|
||
elseif unit.thtd_player_index == 3 then
|
||
if origin.x > UnitPathFixRect[unit.thtd_player_index][2][2].x and
|
||
origin.x < UnitPathFixRect[unit.thtd_player_index][2][1].x and
|
||
origin.y > UnitPathFixRect[unit.thtd_player_index][2][1].y and
|
||
origin.y < UnitPathFixRect[unit.thtd_player_index][2][2].y then
|
||
if math.abs(origin.x - UnitPathFixRect[unit.thtd_player_index][2][1].x) > math.abs(origin.y - UnitPathFixRect[unit.thtd_player_index][2][1].y) then
|
||
unit:SetAbsOrigin(Vector(origin.x, UnitPathFixRect[unit.thtd_player_index][2][1].y - 5, UnitPathFixRect[unit.thtd_player_index][2][2].z))
|
||
else
|
||
unit:SetAbsOrigin(Vector(UnitPathFixRect[unit.thtd_player_index][2][1].x + 5, origin.y - 100, UnitPathFixRect[unit.thtd_player_index][1][1].z))
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 替代触发器
|
||
-- for k,v in pairs(UnitMoveRect[unit.thtd_player_index]) do
|
||
-- if GetDistanceBetweenTwoVec2D(unit:GetOrigin(), Vector(v["center"][1],v["center"][2]),0) <= v["radius"] then
|
||
-- if unit.current_rect_id ~= k then
|
||
-- unit.current_rect_id = k
|
||
-- local tagIndex = v["tag"][RandomInt(1, #v["tag"])]
|
||
-- unit.next_move_point = Vector(UnitMoveRect[unit.thtd_player_index][tagIndex]["center"][1],UnitMoveRect[unit.thtd_player_index][tagIndex]["center"][2],0)
|
||
-- unit:MoveToPosition(unit.next_move_point)
|
||
-- end
|
||
-- break
|
||
-- end
|
||
-- end
|
||
|
||
UnitDamageApply(unit)
|
||
|
||
return 0.15
|
||
end,
|
||
0)
|
||
end
|
||
end
|
||
|
||
curTimes = curTimes + 1
|
||
return interval
|
||
end,
|
||
0)
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
-- 刷新宝箱
|
||
local chest_list = {
|
||
[1] = {
|
||
["chest"] = nil,
|
||
["pos"] = Vector(-2245, 2866, 0)
|
||
},
|
||
[2] = {
|
||
["chest"] = nil,
|
||
["pos"] = Vector(2320, 3176, 0)
|
||
},
|
||
[3] = {
|
||
["chest"] = nil,
|
||
["pos"] = Vector(2360, -2607, 0)
|
||
},
|
||
[4] = {
|
||
["chest"] = nil,
|
||
["pos"] = Vector(-2230, -3013, 0)
|
||
},
|
||
}
|
||
function SpawnSystem:SpawnChest()
|
||
for i=1,#SpawnSystem.AttackingSpawner do
|
||
if IsValidEntity(chest_list[i]["chest"]) == false then
|
||
local item = CreateItem("item_310"..tostring(RandomInt(1, 3)), nil, nil)
|
||
if item ~= nil then
|
||
local drop = CreateItemOnPositionSync(Vector(0, 0, 0), item)
|
||
if drop ~= nil then
|
||
drop:SetModelScale(drop:GetModelScale() * 2)
|
||
item:LaunchLoot(false, 600, 0.75, chest_list[i]["pos"])
|
||
chest_list[i]["chest"] = item
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 无尽生命成长倍数,addWave为取前后多少波(负前正后),默认为当前波
|
||
function SpawnSystem:GetWaveHpFactor()
|
||
local wave = SpawnSystem.CurWave - 50
|
||
|
||
if wave > 250 then
|
||
return (wave - 250) * 100 + 9700
|
||
elseif wave > 240 then
|
||
return (wave - 240) * 95 + 8750
|
||
elseif wave > 230 then
|
||
return (wave - 230) * 90 + 7850
|
||
elseif wave > 220 then
|
||
return (wave - 220) * 85 + 7000
|
||
elseif wave > 210 then
|
||
return (wave - 210) * 80 + 6200
|
||
elseif wave > 200 then
|
||
return (wave - 200) * 75 + 5450
|
||
elseif wave > 190 then
|
||
return (wave - 190) * 70 + 4750
|
||
elseif wave > 180 then
|
||
return (wave - 180) * 65 + 4100
|
||
elseif wave > 170 then
|
||
return (wave - 170) * 60 + 3500
|
||
elseif wave > 160 then
|
||
return (wave - 160) * 55 + 2950
|
||
elseif wave > 150 then
|
||
return (wave - 150) * 50 + 2450
|
||
elseif wave > 140 then
|
||
return (wave - 140) * 45 + 2000
|
||
elseif wave > 130 then
|
||
return (wave - 130) * 40 + 1600
|
||
elseif wave > 120 then
|
||
return (wave - 120) * 35 + 1250
|
||
elseif wave > 110 then
|
||
return (wave - 110) * 30 + 950
|
||
elseif wave > 100 then
|
||
return (wave - 100) * 25 + 700
|
||
elseif wave > 90 then
|
||
return (wave - 90) * 20 + 500
|
||
elseif wave > 80 then
|
||
return (wave - 80) * 16 + 340
|
||
elseif wave > 70 then
|
||
return (wave - 70) * 12 + 220
|
||
elseif wave > 60 then
|
||
return (wave - 60) * 8 + 140
|
||
elseif wave > 50 then
|
||
return (wave - 50) * 4 + 100
|
||
elseif wave > 0 then
|
||
return wave * 2
|
||
else
|
||
return 1
|
||
end
|
||
end
|
||
|
||
-- 清除已移除刷怪点
|
||
function SpawnSystem:ClearRemovedSpawner()
|
||
local spawner = SpawnSystem.AttackingSpawner
|
||
if spawner == nil or #spawner == 0 then return end
|
||
for i = #spawner, 1, -1 do
|
||
if spawner[i].hero.is_game_over == true then
|
||
THTD_EntitiesRectInner[spawner[i].hero.thtd_player_id] = {}
|
||
table.remove(spawner, i)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 刷新漏怪最大数
|
||
function SpawnSystem:RefreshCreepMaxCount()
|
||
for _,hero in pairs(GameRules.HeroList) do
|
||
if SpawnSystem.IsUnLimited then
|
||
hero.thtd_game_info["creep_count_max"] = 20
|
||
else
|
||
hero.thtd_game_info["creep_count_max"] = 30 * SpawnSystem:GetCount()
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
-- 战利品奖励,同步更新下pet对应技能
|
||
|
||
local T1 = {
|
||
"item_2004",
|
||
"item_3022", --金币满箱
|
||
}
|
||
local T2 = {
|
||
"item_2022",
|
||
"item_2003",
|
||
|
||
"item_3012", --幸运者的烦恼
|
||
"item_3018", --亲友折扣
|
||
"item_3029", --四季馈赠
|
||
}
|
||
local T3 = {
|
||
"item_2002",
|
||
"item_2012",
|
||
"item_2013",
|
||
"item_2014",
|
||
|
||
"item_3017", --一线希望
|
||
"item_3019", --绝望手段
|
||
"item_3020", --扩大阵容
|
||
"item_3026", --口袋细沙
|
||
}
|
||
local T4 = {
|
||
"item_2001",
|
||
|
||
"item_3013", --无敌意识 负页效果降低
|
||
"item_3014", --战斗中铸就 主角
|
||
"item_3016", --召唤神石
|
||
"item_3030", --人多力量大 分身
|
||
"item_3021", --邪恶意念 秒杀
|
||
}
|
||
local T5 = {
|
||
"item_3011", --烁热同盟 地灵殿
|
||
"item_3015", --失去天恩 月之民
|
||
"item_3028", --大力一击 鬼族
|
||
"item_3023", --虹吸意图 神灵庙
|
||
"item_3024", --香火长存 守矢神社
|
||
"item_3025", --终极闪烁 红魔馆
|
||
"item_3027", --鉴宝大师 星莲船
|
||
}
|
||
|
||
local battle_bonus_list =
|
||
{
|
||
[10] = {
|
||
[1] = T1,
|
||
[2] = T2,
|
||
},
|
||
[20] = {
|
||
[1] = T2,
|
||
[2] = T3,
|
||
},
|
||
[30] = {
|
||
[1] = T3,
|
||
[2] = T4,
|
||
},
|
||
[40] = {
|
||
[1] = T4,
|
||
[2] = T5,
|
||
},
|
||
[50] = {
|
||
[1] = T5,
|
||
[2] = {},
|
||
},
|
||
}
|
||
|
||
-- 战利品奖励
|
||
function SpawnSystem:OnBattleBonusWaveOld(hero)
|
||
if SpawnSystem.IsUnLimited then return end
|
||
|
||
local wave = SpawnSystem.CurWave
|
||
if battle_bonus_list[wave] == nil then return end
|
||
|
||
local bonusList1 = {}
|
||
local bonusList2 = {}
|
||
|
||
for k,v in pairs(battle_bonus_list[wave][1]) do
|
||
table.insert(bonusList1, v)
|
||
end
|
||
for k,v in pairs(battle_bonus_list[wave][2]) do
|
||
table.insert(bonusList2, v)
|
||
end
|
||
|
||
local maxCount = 2
|
||
if hero.reimu_pet.pet_level >= 20 then
|
||
maxCount = 4 + math.floor(hero.reimu_pet.pet_level/20)
|
||
elseif hero.reimu_pet.pet_level >= 10 then
|
||
maxCount = 4
|
||
elseif hero.reimu_pet.pet_level >= 5 then
|
||
maxCount = 3
|
||
end
|
||
if GameRules.GameData.is_open_day == 1 then maxCount = math.max(5, maxCount) end
|
||
|
||
local select_cards = {}
|
||
|
||
for i=1,maxCount do
|
||
local chance = RandomInt(1,100)
|
||
if #bonusList2 == 0 then chance = 100 end
|
||
if chance > 30 and #bonusList1 > 0 then
|
||
local k = RandomInt(1, #bonusList1)
|
||
select_cards[bonusList1[k]] = bonusList1[k]
|
||
table.remove(bonusList1, k)
|
||
elseif #bonusList2 > 0 then
|
||
local k = RandomInt(1, #bonusList2)
|
||
select_cards[bonusList2[k]] = bonusList2[k]
|
||
table.remove(bonusList2, k)
|
||
end
|
||
end
|
||
|
||
bonusList1 = {}
|
||
bonusList2 = {}
|
||
|
||
for i=maxCount+1, 5 do
|
||
select_cards["item_3050_"..tostring(i)] = "item_3050"
|
||
end
|
||
|
||
CustomGameEventManager:Send_ServerToPlayer(hero:GetPlayerOwner(), "show_select_bonus_card_panel", {cards=select_cards})
|
||
end
|
||
|
||
-- 战利品奖励
|
||
function SpawnSystem:OnBattleBonusWave(hero)
|
||
if SpawnSystem.IsUnLimited then return end
|
||
|
||
local wave = SpawnSystem.CurWave
|
||
if battle_bonus_list[wave] == nil then return end
|
||
|
||
-- 调整为改善运营
|
||
|
||
local bonusList1 = {}
|
||
local bonusList2 = {}
|
||
local chanceBonusPoint = 30
|
||
|
||
if wave == 10 then
|
||
for k,v in pairs(towerNameList) do
|
||
if v["quality"] == 2 and v["cardname"] ~= "BonusEgg" then
|
||
table.insert(bonusList1, k)
|
||
end
|
||
end
|
||
elseif wave == 20 then
|
||
for k,v in pairs(towerNameList) do
|
||
if v["quality"] == 2 and v["cardname"] ~= "BonusEgg" then
|
||
table.insert(bonusList1, k)
|
||
elseif v["quality"] == 3 and v["cardname"] ~= "BonusEgg" then
|
||
table.insert(bonusList2, k)
|
||
end
|
||
end
|
||
elseif wave == 30 then
|
||
for k,v in pairs(towerNameList) do
|
||
if v["quality"] == 3 and v["cardname"] ~= "BonusEgg" then
|
||
table.insert(bonusList1, k)
|
||
elseif v["quality"] == 4 and v["cardname"] ~= "BonusEgg" then
|
||
table.insert(bonusList2, k)
|
||
end
|
||
end
|
||
elseif wave == 40 then
|
||
chanceBonusPoint = 50
|
||
for k,v in pairs(towerNameList) do
|
||
if v["quality"] == 3 and v["cardname"] ~= "BonusEgg" then
|
||
table.insert(bonusList1, k)
|
||
elseif v["quality"] == 4 and v["cardname"] ~= "BonusEgg" then
|
||
table.insert(bonusList2, k)
|
||
end
|
||
end
|
||
elseif wave == 50 then
|
||
for k,v in pairs(towerNameList) do
|
||
if v["quality"] == 4 and v["cardname"] ~= "BonusEgg" then
|
||
table.insert(bonusList1, k)
|
||
end
|
||
end
|
||
end
|
||
|
||
local maxCount = 3
|
||
if hero.reimu_pet.pet_level >= 5 then
|
||
maxCount = 3 + math.floor(hero.reimu_pet.pet_level/5)
|
||
end
|
||
if GameRules.GameData.is_open_day == 1 then maxCount = math.max(6, maxCount) end
|
||
|
||
local select_cards = {}
|
||
|
||
for i=1,maxCount do
|
||
local chance = RandomInt(1,100)
|
||
if #bonusList2 == 0 then chance = 100 end
|
||
if chance > chanceBonusPoint and #bonusList1 > 0 then
|
||
local k = RandomInt(1, #bonusList1)
|
||
select_cards[bonusList1[k]] = bonusList1[k]
|
||
table.remove(bonusList1, k)
|
||
elseif #bonusList2 > 0 then
|
||
local k = RandomInt(1, #bonusList2)
|
||
select_cards[bonusList2[k]] = bonusList2[k]
|
||
table.remove(bonusList2, k)
|
||
end
|
||
end
|
||
|
||
if maxCount < #bonusList1 + #bonusList2 then
|
||
select_cards["item_3050"] = "item_3050"
|
||
end
|
||
|
||
bonusList1 = {}
|
||
bonusList2 = {}
|
||
|
||
CustomGameEventManager:Send_ServerToPlayer(hero:GetPlayerOwner(), "show_select_bonus_card_panel", {cards=select_cards})
|
||
end |