324 lines
13 KiB
Plaintext
324 lines
13 KiB
Plaintext
-- 关卡代理
|
||
local LevelProxy = {}
|
||
|
||
--> Services
|
||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||
local ServerStorage = game:GetService("ServerStorage")
|
||
local Players = game:GetService("Players")
|
||
|
||
--> Variables
|
||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||
local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy)
|
||
local MobsProxy = require(ServerStorage.Proxy.MobsProxy)
|
||
local ItemProxy = require(ServerStorage.Proxy.ItemProxy)
|
||
local TypeList = require(ServerStorage.Base.TypeList)
|
||
|
||
--> Dependencies
|
||
local Communicate = require(ServerStorage.Modules.Tools.Communicate)
|
||
|
||
--> Json
|
||
local JsonLevel = require(ReplicatedStorage.Json.Level)
|
||
local JsonParam = require(ReplicatedStorage.Json.Param)
|
||
|
||
--> Events
|
||
local BD_ChallengeEnd = ReplicatedStorage.Events.BD_ChallengeEnd
|
||
local RE_CleanPlayerPerformance = ReplicatedStorage.Events.RE_CleanPlayerPerformance
|
||
|
||
|
||
--> Constants
|
||
local STORE_NAME = "Level"
|
||
local ENUM_LEVEL_TYPE = {
|
||
Main = 1,
|
||
BossFail = 0,
|
||
}
|
||
|
||
--------------------------------------------------------------------------------
|
||
|
||
-- 初始化生成关卡目录
|
||
local LevelFolder = Utils:CreateFolder(STORE_NAME, game.Workspace)
|
||
|
||
--------------------------------------------------------------------------------
|
||
|
||
-- 获取玩家关卡文件夹
|
||
local function GetPlayerLevelFolder(Player: Player, ChildFolderName: string?)
|
||
local PlayerFolder = LevelFolder:FindFirstChild(Player.UserId)
|
||
if not PlayerFolder then warn("PlayerFolder not found", Player.UserId) return end
|
||
if ChildFolderName then
|
||
local ChildFolder = PlayerFolder:FindFirstChild(ChildFolderName)
|
||
if not ChildFolder then warn("ChildFolder not found", ChildFolderName) return end
|
||
return ChildFolder
|
||
end
|
||
return PlayerFolder
|
||
end
|
||
|
||
-- 获取玩家关卡Workspace目录
|
||
local function GetPlayerLevelWorkspaceFolder(PlayerUserId: string)
|
||
return LevelFolder:FindFirstChild(PlayerUserId)
|
||
end
|
||
|
||
-- 创建关卡信息实例
|
||
local function CreateLevelInstance(Player: Player, Folder: Instance, LevelKey: string, LevelValue: any)
|
||
if not Player or not Folder or not LevelKey then return end
|
||
local InstanceType
|
||
if type(LevelValue) == "number" then
|
||
InstanceType = "NumberValue"
|
||
elseif type(LevelValue) == "boolean" then
|
||
InstanceType = "BoolValue"
|
||
elseif type(LevelValue) == "string" then
|
||
InstanceType = "StringValue"
|
||
else
|
||
InstanceType = "NumberValue"
|
||
end
|
||
local LevelInstance = Instance.new(InstanceType)
|
||
LevelInstance.Name = LevelKey
|
||
LevelInstance.Parent = Folder
|
||
LevelInstance.Value = LevelValue
|
||
return LevelInstance
|
||
end
|
||
|
||
-- 初始化玩家关卡信息
|
||
local function ExtraAddPlayerLevel(Player: Player, LevelData: table)
|
||
if not Player or not LevelData then return end
|
||
-- 如果列表中不包含信息就添加到表中
|
||
for LevelKey, LevelValue in ENUM_LEVEL_TYPE do
|
||
if not LevelData[LevelKey] then
|
||
LevelData[LevelKey] = LevelValue
|
||
end
|
||
end
|
||
end
|
||
|
||
local EXCEPT_KEY = { "Task", "Mobs"}
|
||
local function ChangeValue(Player: Player, Folder: Instance, LevelKey: string, LevelValue: any)
|
||
if not Player or not Folder or not LevelKey then warn("LevelProxy ChangeValue", Player.UserId, Folder.Name, LevelKey, LevelValue) return end
|
||
if table.find(EXCEPT_KEY, LevelKey) then return end
|
||
|
||
local ValueInstance = Folder:FindFirstChild(LevelKey)
|
||
if not ValueInstance then warn("ValueInstance not found", LevelKey) return end
|
||
|
||
local storeTable
|
||
if Folder.Name == "Challenge" then
|
||
storeTable = LevelProxy.pData[Player.UserId]
|
||
else
|
||
storeTable = ArchiveProxy.pData[Player.UserId][STORE_NAME].Progress
|
||
end
|
||
|
||
storeTable[LevelKey] = LevelValue
|
||
ValueInstance.Value = LevelValue
|
||
end
|
||
|
||
-- 怪物死亡,由初始化时传入
|
||
local function OnMobDied(Player: Player, Mob: TypeList.Character)
|
||
-- 怪物死亡后增加玩家货币
|
||
-- TODO:这里暂时没做对应玩家属性处理
|
||
local mob_died_get = Utils:GetIdDataFromJson(JsonParam, 3)
|
||
local PlayerInfoProxy = require(ServerStorage.Proxy.PlayerInfoProxy)
|
||
local getNumber = math.floor(mob_died_get["intArray"][2] + LevelProxy:GetLevelGetBonus(Player) / 100)
|
||
PlayerInfoProxy:ChangeItemCount(Player, mob_died_get["intArray"][1], getNumber)
|
||
|
||
for _, mob in LevelProxy.pData[Player.UserId].Mobs do
|
||
if mob.Instance ~= Mob.Instance then continue end
|
||
table.remove(LevelProxy.pData[Player.UserId].Mobs, table.find(LevelProxy.pData[Player.UserId].Mobs, mob))
|
||
|
||
-- 怪物被击杀时做关卡数据处理
|
||
local LevelData = Utils:GetIdDataFromJson(JsonLevel, LevelProxy.pData[Player.UserId].LevelId)
|
||
if LevelProxy.pData[Player.UserId].SpawnWaveFinish and #LevelProxy.pData[Player.UserId].Mobs == 0 then
|
||
if LevelProxy.pData[Player.UserId].NowWave < #LevelData["wave"] then
|
||
-- -- 波数增长
|
||
LevelProxy.pData[Player.UserId].ShouldWave = LevelProxy.pData[Player.UserId].ShouldWave + 1
|
||
-- 新波次重置怪物生成状态标记
|
||
local ChallengeFolder = GetPlayerLevelFolder(Player, "Challenge")
|
||
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", false)
|
||
elseif LevelProxy.pData[Player.UserId].NowWave >= #LevelData["wave"] then
|
||
-- 结束判断
|
||
LevelProxy:ChallengeEnd(Player, true)
|
||
end
|
||
end
|
||
break
|
||
end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
|
||
function LevelProxy:InitPlayer(Player: Player)
|
||
local PlayerLevelFolder = Utils:CreateFolder(Player.UserId, LevelFolder)
|
||
local ProgressFolder = Utils:CreateFolder("Progress", PlayerLevelFolder)
|
||
local DungeonFolder = Utils:CreateFolder("Dungeon", PlayerLevelFolder)
|
||
-- 当前关卡状态 不存储
|
||
local ChallengeFolder = Utils:CreateFolder("Challenge", PlayerLevelFolder)
|
||
-- Utils:CreateFolder("Stats", PlayerLevelFolder)
|
||
|
||
-- 新玩家数据初始化
|
||
if not ArchiveProxy.pData[Player.UserId][STORE_NAME] then
|
||
ArchiveProxy.pData[Player.UserId][STORE_NAME] = {}
|
||
ArchiveProxy.pData[Player.UserId][STORE_NAME].Progress = {}
|
||
-- 副本之后再做
|
||
ArchiveProxy.pData[Player.UserId][STORE_NAME].Dungeon = {}
|
||
end
|
||
|
||
ExtraAddPlayerLevel(Player, ArchiveProxy.pData[Player.UserId][STORE_NAME].Progress)
|
||
|
||
-- 前端变化
|
||
for LevelKey, LevelValue in ArchiveProxy.pData[Player.UserId][STORE_NAME].Progress do
|
||
CreateLevelInstance(Player, ProgressFolder, LevelKey, LevelValue)
|
||
end
|
||
|
||
-- 本地内容初始化(关卡挑战信息,不存储)
|
||
if not LevelProxy.pData then LevelProxy.pData = {} end
|
||
if not LevelProxy.pData[Player.UserId] then LevelProxy.pData[Player.UserId] = {} end
|
||
LevelProxy.pData[Player.UserId].Task = nil
|
||
LevelProxy.pData[Player.UserId].Time = 0
|
||
LevelProxy.pData[Player.UserId].LevelId = 0
|
||
LevelProxy.pData[Player.UserId].MaxTime = 0
|
||
LevelProxy.pData[Player.UserId].IsBoss = false
|
||
LevelProxy.pData[Player.UserId].NowWave = 0
|
||
LevelProxy.pData[Player.UserId].ShouldWave = 0
|
||
LevelProxy.pData[Player.UserId].SpawnWaveFinish = false
|
||
LevelProxy.pData[Player.UserId].Mobs = {}
|
||
|
||
-- 关卡挑战信息前端
|
||
for key, value in LevelProxy.pData[Player.UserId] do
|
||
if key == "Task" or key == "Mobs" then continue end
|
||
CreateLevelInstance(Player, ChallengeFolder, key, value)
|
||
end
|
||
end
|
||
|
||
-- 挑战关卡(挑战副本用另一个函数)
|
||
function LevelProxy:ChallengeLevel(Player: Player, LevelId: number)
|
||
local LevelData = Utils:GetIdDataFromJson(JsonLevel, LevelId)
|
||
if not LevelData then warn("Level Data not found", LevelId) return end
|
||
-- 给前端传数据,做表现
|
||
|
||
-- 场景后端生成
|
||
|
||
-- 后端生成当前关卡状态数据
|
||
local ChallengeFolder = GetPlayerLevelFolder(Player,"Challenge")
|
||
if not ChallengeFolder then warn("ChallengeFolder not found") return end
|
||
local levelTask = task.spawn(function()
|
||
ChangeValue(Player, ChallengeFolder, "IsBoss", LevelData.type == 2 and true or false)
|
||
ChangeValue(Player, ChallengeFolder, "LevelId", LevelId)
|
||
ChangeValue(Player, ChallengeFolder, "Time", 0)
|
||
ChangeValue(Player, ChallengeFolder, "NowWave", 0)
|
||
ChangeValue(Player, ChallengeFolder, "ShouldWave", 1)
|
||
ChangeValue(Player, ChallengeFolder, "MaxTime", LevelData.timeLimit or 0)
|
||
ChangeValue(Player, ChallengeFolder, "Mobs", {})
|
||
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", false)
|
||
|
||
while task.wait(1) do
|
||
ChangeValue(Player, ChallengeFolder, "Time", LevelProxy.pData[Player.UserId].Time + 1)
|
||
|
||
-- 关卡生成
|
||
if LevelProxy.pData[Player.UserId].NowWave < #LevelData.wave and
|
||
LevelProxy.pData[Player.UserId].NowWave < LevelProxy.pData[Player.UserId].ShouldWave and
|
||
LevelProxy.pData[Player.UserId].SpawnWaveFinish == false then
|
||
ChangeValue(Player, ChallengeFolder, "NowWave", LevelProxy.pData[Player.UserId].NowWave + 1)
|
||
|
||
local waveData = LevelData.wave[LevelProxy.pData[Player.UserId].NowWave]
|
||
for i = 1, #waveData, 3 do
|
||
local mobId = waveData[i + 1]
|
||
local mobCount = waveData[i + 2]
|
||
for _ = 1, mobCount do
|
||
print("怪物增益", LevelData.atkBonus, LevelData.hpBonus)
|
||
local mob = MobsProxy:CreateMob(Player, mobId, LevelData.atkBonus, LevelData.hpBonus, OnMobDied)
|
||
table.insert(LevelProxy.pData[Player.UserId].Mobs, mob)
|
||
end
|
||
end
|
||
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", true)
|
||
end
|
||
|
||
if LevelProxy.pData[Player.UserId].NowWave >= LevelProxy.pData[Player.UserId].ShouldWave and
|
||
LevelProxy.pData[Player.UserId].SpawnWaveFinish == true and
|
||
#LevelProxy.pData[Player.UserId].Mobs == 0 then
|
||
local maxWave = #LevelData.wave
|
||
if LevelProxy.pData[Player.UserId].NowWave < maxWave then
|
||
-- 下一波
|
||
ChangeValue(Player, ChallengeFolder, "ShouldWave", LevelProxy.pData[Player.UserId].ShouldWave)
|
||
else
|
||
-- 挑战胜利
|
||
self:ChallengeEnd(Player, true)
|
||
end
|
||
end
|
||
|
||
-- 时间结束
|
||
if LevelData.timeLimit then
|
||
if LevelProxy.pData[Player.UserId].Time >= LevelData.timeLimit then
|
||
self:ChallengeEnd(Player, false)
|
||
end
|
||
end
|
||
end
|
||
end)
|
||
LevelProxy.pData[Player.UserId].Task = levelTask
|
||
end
|
||
|
||
-- 挑战结束
|
||
function LevelProxy:ChallengeEnd(Player: Player, result: boolean)
|
||
local ProgressFolder = GetPlayerLevelFolder(Player, "Progress")
|
||
|
||
-- 停止关卡循环
|
||
if LevelProxy.pData[Player.UserId].Task then
|
||
task.cancel(LevelProxy.pData[Player.UserId].Task)
|
||
LevelProxy.pData[Player.UserId].Task = nil
|
||
end
|
||
|
||
-- 清除剩余怪物
|
||
for _, mob in pairs(LevelProxy.pData[Player.UserId].Mobs) do mob:Died(true) end
|
||
LevelProxy.pData[Player.UserId].Mobs = {}
|
||
|
||
-- 清除玩家表现
|
||
Communicate:SendToClientFree(RE_CleanPlayerPerformance, Player)
|
||
|
||
-- 判断玩家是否通关
|
||
if result then
|
||
local levelData = Utils:GetIdDataFromJson(JsonLevel, LevelProxy.pData[Player.UserId].LevelId)
|
||
-- 防止之后失败重复添加奖励
|
||
if ArchiveProxy.pData[Player.UserId][STORE_NAME].Progress.Main == LevelProxy.pData[Player.UserId].LevelId then
|
||
-- 添加首次通关奖励
|
||
if levelData.finishRewards then
|
||
for i = 1, #levelData.finishRewards, 2 do
|
||
local itemId = levelData.finishRewards[i]
|
||
local itemCount = levelData.finishRewards[i + 1]
|
||
ItemProxy:AddItem(Player, itemId, itemCount)
|
||
print("添加首次通关奖励", itemId, itemCount)
|
||
end
|
||
end
|
||
end
|
||
|
||
ChangeValue(Player, ProgressFolder, "Main", LevelProxy.pData[Player.UserId].LevelId + 1)
|
||
else
|
||
local IsBoss = LevelProxy.pData[Player.UserId].IsBoss
|
||
if IsBoss then
|
||
ChangeValue(Player, ProgressFolder, "BossFail", LevelProxy.pData[Player.UserId].LevelId)
|
||
end
|
||
end
|
||
BD_ChallengeEnd:Fire(Player, LevelProxy.pData[Player.UserId].LevelId, result)
|
||
end
|
||
|
||
-- 获得关卡产出货币百分比
|
||
function LevelProxy:GetLevelGetBonus(Player: Player)
|
||
if not Player then warn('获取关卡产出货币百分比失败: ', Player.Name) return end
|
||
local level_get_bonus = Utils:GetIdDataFromJson(JsonParam, 2)
|
||
local level = ArchiveProxy.pData[Player.UserId][STORE_NAME].Progress.Main
|
||
return level_get_bonus["intArray"][1] + (level - 1) * level_get_bonus["intArray"][2]
|
||
end
|
||
|
||
function LevelProxy:OnPlayerRemoving(Player: Player)
|
||
-- 关卡文件夹清除
|
||
local PlayerLevelFolder = GetPlayerLevelWorkspaceFolder(Player.UserId)
|
||
if PlayerLevelFolder then
|
||
PlayerLevelFolder:Destroy()
|
||
end
|
||
-- 关卡存储数据清除
|
||
if LevelProxy.pData[Player.UserId].Task then
|
||
task.cancel(LevelProxy.pData[Player.UserId].Task)
|
||
end
|
||
LevelProxy.pData[Player.UserId] = nil
|
||
end
|
||
|
||
-- ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(PlayerUserId: string)
|
||
-- LevelProxy:OnPlayerRemoving(PlayerUserId)
|
||
-- end)
|
||
|
||
Players.PlayerRemoving:Connect(function(Player: Player)
|
||
LevelProxy:OnPlayerRemoving(Player)
|
||
end)
|
||
|
||
return LevelProxy |