310 lines
13 KiB
Plaintext
Raw Normal View History

2025-07-03 01:48:06 +08:00
-- 关卡代理
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)
2025-07-07 00:03:47 +08:00
local MobsProxy = require(ServerStorage.Proxy.MobsProxy)
local TypeList = require(ServerStorage.Base.TypeList)
2025-07-03 01:48:06 +08:00
2025-07-12 05:06:14 +08:00
--> Dependencies
local Communicate = require(ServerStorage.Modules.Tools.Communicate)
2025-07-03 01:48:06 +08:00
--> Json
local JsonLevel = require(ReplicatedStorage.Json.Level)
2025-07-16 00:45:20 +08:00
local JsonParam = require(ReplicatedStorage.Json.Param)
2025-07-03 01:48:06 +08:00
2025-07-09 23:59:56 +08:00
--> Events
local BD_ChallengeEnd = ReplicatedStorage.Events.BD_ChallengeEnd
2025-07-12 05:06:14 +08:00
local RE_CleanPlayerPerformance = ReplicatedStorage.Events.RE_CleanPlayerPerformance
2025-07-09 23:59:56 +08:00
2025-07-03 01:48:06 +08:00
--> Constants
local STORE_NAME = "Level"
local ENUM_LEVEL_TYPE = {
Main = 1,
2025-07-07 23:52:31 +08:00
BossFail = 0,
2025-07-03 01:48:06 +08:00
}
--------------------------------------------------------------------------------
-- 初始化生成关卡目录
local LevelFolder = Utils:CreateFolder(STORE_NAME, game.Workspace)
--------------------------------------------------------------------------------
-- 获取玩家关卡文件夹
2025-07-12 05:06:14 +08:00
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
2025-07-03 01:48:06 +08:00
end
-- 获取玩家关卡Workspace目录
local function GetPlayerLevelWorkspaceFolder(PlayerUserId: string)
return LevelFolder:FindFirstChild(PlayerUserId)
end
-- 创建关卡信息实例
2025-07-12 05:06:14 +08:00
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)
2025-07-03 01:48:06 +08:00
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
2025-07-07 00:03:47 +08:00
local EXCEPT_KEY = { "Task", "Mobs"}
local function ChangeValue(Player: Player, Folder: Instance, LevelKey: string, LevelValue: any)
2025-07-12 05:06:14 +08:00
if not Player or not Folder or not LevelKey then warn("LevelProxy ChangeValue", Player.UserId, Folder.Name, LevelKey, LevelValue) return end
2025-07-15 01:12:05 +08:00
if table.find(EXCEPT_KEY, LevelKey) then return end
2025-07-07 00:03:47 +08:00
local ValueInstance = Folder:FindFirstChild(LevelKey)
2025-07-12 05:06:14 +08:00
if not ValueInstance then warn("ValueInstance not found", LevelKey) return end
2025-07-07 00:03:47 +08:00
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
2025-07-15 01:12:05 +08:00
ValueInstance.Value = LevelValue
2025-07-07 00:03:47 +08:00
end
-- 怪物死亡,由初始化时传入
local function OnMobDied(Player: Player, Mob: TypeList.Character)
2025-07-16 00:45:20 +08:00
-- 怪物死亡后增加玩家货币
-- 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)
2025-07-07 00:03:47 +08:00
for _, mob in LevelProxy.pData[Player.UserId].Mobs do
2025-07-12 05:06:14 +08:00
if mob.Instance ~= Mob.Instance then continue end
2025-07-09 23:59:56 +08:00
table.remove(LevelProxy.pData[Player.UserId].Mobs, table.find(LevelProxy.pData[Player.UserId].Mobs, mob))
2025-07-07 00:03:47 +08:00
2025-07-12 05:06:14 +08:00
-- 怪物被击杀时做关卡数据处理
local LevelData = Utils:GetIdDataFromJson(JsonLevel, LevelProxy.pData[Player.UserId].LevelId)
2025-07-07 00:03:47 +08:00
if LevelProxy.pData[Player.UserId].SpawnWaveFinish and #LevelProxy.pData[Player.UserId].Mobs == 0 then
if LevelProxy.pData[Player.UserId].NowWave < #LevelData["wave"] then
2025-07-12 05:06:14 +08:00
-- -- 波数增长
LevelProxy.pData[Player.UserId].ShouldWave = LevelProxy.pData[Player.UserId].ShouldWave + 1
2025-07-07 00:03:47 +08:00
-- 新波次重置怪物生成状态标记
2025-07-12 05:06:14 +08:00
local ChallengeFolder = GetPlayerLevelFolder(Player, "Challenge")
2025-07-07 00:03:47 +08:00
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", false)
elseif LevelProxy.pData[Player.UserId].NowWave >= #LevelData["wave"] then
-- 结束判断
LevelProxy:ChallengeEnd(Player, true)
end
end
break
end
end
2025-07-03 01:48:06 +08:00
--------------------------------------------------------------------------------
function LevelProxy:InitPlayer(Player: Player)
2025-07-07 00:45:26 +08:00
local PlayerLevelFolder = Utils:CreateFolder(Player.UserId, LevelFolder)
local ProgressFolder = Utils:CreateFolder("Progress", PlayerLevelFolder)
local DungeonFolder = Utils:CreateFolder("Dungeon", PlayerLevelFolder)
2025-07-07 23:52:31 +08:00
-- 当前关卡状态 不存储
2025-07-07 00:45:26 +08:00
local ChallengeFolder = Utils:CreateFolder("Challenge", PlayerLevelFolder)
2025-07-07 23:52:31 +08:00
-- Utils:CreateFolder("Stats", PlayerLevelFolder)
2025-07-03 01:48:06 +08:00
-- 新玩家数据初始化
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
2025-07-07 00:03:47 +08:00
-- 本地内容初始化(关卡挑战信息,不存储)
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
2025-07-03 01:48:06 +08:00
end
-- 挑战关卡(挑战副本用另一个函数)
function LevelProxy:ChallengeLevel(Player: Player, LevelId: number)
2025-07-31 19:36:32 +08:00
print("挑战关卡", LevelId)
2025-07-07 00:45:26 +08:00
local LevelData = Utils:GetIdDataFromJson(JsonLevel, LevelId)
2025-07-07 00:03:47 +08:00
if not LevelData then warn("Level Data not found", LevelId) return end
2025-07-03 01:48:06 +08:00
-- 给前端传数据,做表现
-- 场景后端生成
-- 后端生成当前关卡状态数据
2025-07-12 05:06:14 +08:00
local ChallengeFolder = GetPlayerLevelFolder(Player,"Challenge")
2025-07-07 00:45:26 +08:00
if not ChallengeFolder then warn("ChallengeFolder not found") return end
2025-07-09 23:59:56 +08:00
local levelTask = task.spawn(function()
2025-07-07 23:52:31 +08:00
ChangeValue(Player, ChallengeFolder, "IsBoss", LevelData.type == 2 and true or false)
2025-07-07 00:03:47 +08:00
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", {})
2025-07-07 00:45:26 +08:00
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
2025-07-12 05:06:14 +08:00
print("怪物增益", LevelData.atkBonus, LevelData.hpBonus)
2025-07-07 00:45:26 +08:00
local mob = MobsProxy:CreateMob(Player, mobId, LevelData.atkBonus, LevelData.hpBonus, OnMobDied)
table.insert(LevelProxy.pData[Player.UserId].Mobs, mob)
2025-07-07 00:03:47 +08:00
end
end
2025-07-07 00:45:26 +08:00
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", true)
end
2025-07-07 23:52:31 +08:00
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
-- 下一波
2025-07-12 05:06:14 +08:00
ChangeValue(Player, ChallengeFolder, "ShouldWave", LevelProxy.pData[Player.UserId].ShouldWave)
2025-07-07 23:52:31 +08:00
else
-- 挑战胜利
self:ChallengeEnd(Player, true)
end
end
-- 时间结束
2025-07-07 00:45:26 +08:00
if LevelData.timeLimit then
2025-07-07 00:03:47 +08:00
if LevelProxy.pData[Player.UserId].Time >= LevelData.timeLimit then
self:ChallengeEnd(Player, false)
end
end
end
end)
2025-07-09 23:59:56 +08:00
LevelProxy.pData[Player.UserId].Task = levelTask
2025-07-03 01:48:06 +08:00
end
-- 挑战结束
2025-07-07 00:03:47 +08:00
function LevelProxy:ChallengeEnd(Player: Player, result: boolean)
2025-07-12 05:06:14 +08:00
local ProgressFolder = GetPlayerLevelFolder(Player, "Progress")
2025-07-09 23:59:56 +08:00
-- 停止关卡循环
if LevelProxy.pData[Player.UserId].Task then
task.cancel(LevelProxy.pData[Player.UserId].Task)
LevelProxy.pData[Player.UserId].Task = nil
end
2025-07-07 00:03:47 +08:00
-- 清除剩余怪物
2025-07-31 19:36:32 +08:00
for _, mob in pairs(LevelProxy.pData[Player.UserId].Mobs) do mob:Died(true) end
2025-07-07 00:03:47 +08:00
LevelProxy.pData[Player.UserId].Mobs = {}
2025-07-12 05:06:14 +08:00
-- 清除玩家表现
Communicate:SendToClientFree(RE_CleanPlayerPerformance, Player)
2025-07-03 01:48:06 +08:00
-- 判断玩家是否通关
2025-07-07 00:03:47 +08:00
if result then
2025-07-12 05:06:14 +08:00
ChangeValue(Player, ProgressFolder, "Main", LevelProxy.pData[Player.UserId].LevelId + 1)
2025-07-07 23:52:31 +08:00
else
local IsBoss = LevelProxy.pData[Player.UserId].IsBoss
if IsBoss then
ChangeValue(Player, ProgressFolder, "BossFail", LevelProxy.pData[Player.UserId].LevelId)
end
2025-07-07 00:03:47 +08:00
end
2025-07-09 23:59:56 +08:00
BD_ChallengeEnd:Fire(Player, LevelProxy.pData[Player.UserId].LevelId, result)
2025-07-03 01:48:06 +08:00
end
2025-07-16 00:45:20 +08:00
-- 获得关卡产出货币百分比
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
2025-07-03 01:48:06 +08:00
function LevelProxy:OnPlayerRemoving(Player: Player)
2025-07-07 00:03:47 +08:00
-- 关卡文件夹清除
2025-07-03 01:48:06 +08:00
local PlayerLevelFolder = GetPlayerLevelWorkspaceFolder(Player.UserId)
if PlayerLevelFolder then
PlayerLevelFolder:Destroy()
end
2025-07-07 00:03:47 +08:00
-- 关卡存储数据清除
if LevelProxy.pData[Player.UserId].Task then
2025-07-09 23:59:56 +08:00
task.cancel(LevelProxy.pData[Player.UserId].Task)
2025-07-07 00:03:47 +08:00
end
LevelProxy.pData[Player.UserId] = nil
2025-07-03 01:48:06 +08:00
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