-- 玩家循环代理 local PlayerFightProxy = {} --> Services local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local ServerStorage = game:GetService("ServerStorage") --> Variables local Character = require(ServerStorage.Base.Character) local Utils = require(ReplicatedStorage.Tools.Utils) local LevelProxy = require(ServerStorage.Proxy.LevelProxy) --> Json local JsonCharacter = require(ReplicatedStorage.Json.Character) local JsonAttributes = require(ReplicatedStorage.Json.Attributes) --> Dependencies local LevelLoop = require(script.LevelLoop) local PlayerAI = require(script.PlayerAI) local Communicate = require(ServerStorage.Modules.Tools.Communicate) --> Events local RE_CleanPlayerPerformance = ReplicatedStorage.Events.RE_CleanPlayerPerformance local RE_AbilityPerformance = ReplicatedStorage.Events.RE_AbilityPerformance -------------------------------------------------------------------------------- local function WaitForCharacter(Player: Player) while not Player.Character or not Player.Character.Parent do Player.CharacterAdded:Wait() end return Player.Character end -------------------------------------------------------------------------------- local PlayerRole = {} PlayerRole.__index = PlayerRole setmetatable(PlayerRole, {__index = Character}) function PlayerRole.new(Player: Player, CharacterId: number) local playerCharacter = WaitForCharacter(Player) -- 获取玩家初始数据(临时初始化使用,不是真属性配置部分) local CharacterData = Utils:GetIdDataFromJson(JsonCharacter, CharacterId) if not CharacterData then warn("CharacterId Data not found", CharacterId) return end -- 补充默认没设置的属性,暂时不添加特殊属性,因为特殊属性是系统调用的,添加也没啥用 for _, AttributeData in JsonCharacter do if AttributeData.id < 50 then if not CharacterData[AttributeData.name] then CharacterData[AttributeData.name] = 0 end end end -- 调用父类Character的new方法,初始化通用属性 local self = Character.new(Player, playerCharacter, CharacterData) setmetatable(self, PlayerRole) self.CharacterId = CharacterId -- 玩家放到Character目录下 playerCharacter.Parent = game.Workspace.Characters return self end function PlayerRole:Died() self:ChangeState("Died", true) self.Humanoid.WalkSpeed = 0 LevelProxy:ChallengeEnd(self.Player, false) end function PlayerRole:Respawn() self:ChangeState("Died", false) self.Humanoid.WalkSpeed = self.Config.walkSpeed self:ChangeAttributeValue("hp", self.Config.maxhp) -- TODO: 重置玩家位置 PlayerFightProxy:UpdatePlayerFightData(self.Player) end -------------------------------------------------------------------------------- function PlayerFightProxy:InitPlayer(Player: Player) if not PlayerFightProxy.pData then PlayerFightProxy.pData = {} end if not PlayerFightProxy.pData[Player.UserId] then PlayerFightProxy.pData[Player.UserId] = {} end -- 生成玩家状态 local PlayerRole = PlayerRole.new(Player, 1) PlayerFightProxy.pData[Player.UserId].PlayerRole = PlayerRole -- 生成关卡循环 local LevelLoop = LevelLoop.new(Player, PlayerRole) PlayerFightProxy.pData[Player.UserId].LevelLoop = LevelLoop -- 生成玩家AI local PlayerAI = PlayerAI.new(Player, PlayerRole) PlayerFightProxy.pData[Player.UserId].PlayerAI = PlayerAI -- 更新玩家战斗数据 self:UpdatePlayerFightData(Player) end function PlayerFightProxy:GetPlayerRole(Player: Player) return PlayerFightProxy.pData[Player.UserId].PlayerRole end function PlayerFightProxy:GetPlayerAI(Player: Player) return PlayerFightProxy.pData[Player.UserId].PlayerAI end -- 更新玩家战斗数据(所有变动全部从这调用) function PlayerFightProxy:UpdatePlayerFightData(Player: Player) local PlayerInfoProxy = require(ServerStorage.Proxy.PlayerInfoProxy) local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy) local AbilityProxy = require(ServerStorage.Proxy.AbilityProxy) local GemProxy = require(ServerStorage.Proxy.GemProxy) local AttributesData = {} -- 计算角色基础属性值 + 装备属性值 + 宝石属性值,赋值属性 local PlayerInfoAttributes = PlayerInfoProxy:GetPlayerAttributes(Player) if PlayerInfoAttributes.UpgradeAttributes then Utils:TableSafeAddTableValue(AttributesData, PlayerInfoAttributes.UpgradeAttributes) end local EquipmentAttributes = EquipmentProxy:GetPlayerAttributes(Player) if EquipmentAttributes then Utils:TableSafeAddTableValue(AttributesData, EquipmentAttributes) end local GemAttributes = GemProxy:GetPlayerAttributes(Player) if GemAttributes.GemWearingAttributes then Utils:TableSafeAddTableValue(AttributesData, GemAttributes.GemWearingAttributes) end -- 角色基础数据 local PlayerRole = self:GetPlayerRole(Player) local CharacterData = Utils:GetIdDataFromJson(JsonCharacter, PlayerRole.CharacterId) if not CharacterData then warn("CharacterId Data not found", PlayerRole.CharacterId) return end -- 如果玩家装备的武器里面有了攻击速度属性,就不用默认的攻击属性进行配置 local ExceptAttributes = {"id", "name"} if AttributesData.atkSpeed then table.insert(ExceptAttributes, "atkSpeed") end for AttributeName, AttributeValue in CharacterData do if not table.find(ExceptAttributes, AttributeName) then Utils:TableSafeAddValue(AttributesData, AttributeName, AttributeValue) end end -- 根据汇总更新玩家属性——————实际生效计算部分 local PlayerRole = self:GetPlayerRole(Player) -- 针对百分比特殊属性直接进行计算修改 if AttributesData["hpRate"] then AttributesData["hp"] = math.floor(AttributesData["hp"] * AttributesData["hpRate"] / 100) end if AttributesData["atkRate"] then AttributesData["atk"] = math.floor(AttributesData["atk"] * AttributesData["atkRate"] / 100) end -- 更新玩家属性 for AttributeName, AttributeValue in AttributesData do -- TODO:这里可能涉及到战斗时更换装备的属性处理,还需要再函数内部再根据剩余百分比数值变化 PlayerRole:ChangeAttributeValue(AttributeName, AttributeValue) end -- 根据技能添加玩家AI行为 local abilityIdList, behaviourNameList = AbilityProxy:GetPlayerWearingAbilityData(Player) local playerAI = PlayerFightProxy:GetPlayerAI(Player) -- TODO:设置AI行为(临时清除所有行为,添加新的玩家行为) playerAI:ClearAllBehaviour() for _, behaviourName in behaviourNameList do playerAI:AddBehaviour(behaviourName) end playerAI:AddBehaviour("Move") playerAI:AddBehaviour("SwordWave") -- 给前端发送技能信息 Communicate:SendToClient(RE_AbilityPerformance, "Ability", Player, playerAI:GetClientBehaviourList()) end -- 重置玩家状态,但是不删除 function PlayerFightProxy:CleanPlayer(Player: Player) -- 玩家角色重生 PlayerFightProxy.pData[Player.UserId].PlayerRole:Respawn() -- AI重新生成 PlayerFightProxy.pData[Player.UserId].PlayerAI:Destroy() PlayerFightProxy.pData[Player.UserId].PlayerAI = nil local PlayerAI = PlayerAI.new(PlayerRole) PlayerFightProxy.pData[Player.UserId].PlayerAI = PlayerAI end function PlayerFightProxy:OnPlayerRemoving(Player: Player) -- 玩家离开时,通知其他客户端销毁玩家表现内容 Communicate:SendToClientFree(RE_CleanPlayerPerformance, Player) -- 正常清除玩家该模块下数据 if not PlayerFightProxy.pData[Player.UserId] then warn("PlayerFight Remove Data not found", Player.Name) return end PlayerFightProxy.pData[Player.UserId].PlayerAI:Destroy() PlayerFightProxy.pData[Player.UserId].PlayerAI = nil PlayerFightProxy.pData[Player.UserId] = nil end Players.PlayerRemoving:Connect(function(Player: Player) PlayerFightProxy:OnPlayerRemoving(Player) end) return PlayerFightProxy