From c1c22aa963336c63bf355d88d5c5cd5f603cc02e Mon Sep 17 00:00:00 2001 From: Ggafrik <906823881@qq.com> Date: Wed, 9 Jul 2025 23:59:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- excel/cha.xlsx | Bin 8795 -> 10775 bytes .../Json/AttributesUpgrade.json | 13 +++ src/ServerStorage/Base/Behaviour.luau | 11 +- src/ServerStorage/Base/Character.luau | 1 + .../Modules/Behaviours/Move.luau | 5 +- src/ServerStorage/Proxy/ArchiveProxy.luau | 6 ++ src/ServerStorage/Proxy/DamageProxy.luau | 1 + src/ServerStorage/Proxy/HelpProxy.luau | 24 +++++ src/ServerStorage/Proxy/LevelProxy.luau | 23 +++-- src/ServerStorage/Proxy/MobsProxy/AI.luau | 50 ++++----- src/ServerStorage/Proxy/MobsProxy/init.luau | 11 +- .../Proxy/PlayerFightProxy/LevelLoop.luau | 10 +- .../Proxy/PlayerFightProxy/PlayerAI.luau | 11 ++ .../Proxy/PlayerFightProxy/init.luau | 2 + src/ServerStorage/Proxy/PlayerInfoProxy.luau | 97 +++++++++++++++++- .../ClientMain/Helper.luau | 32 ++++++ .../ClientMain/PlayerControl.luau | 31 ++++++ .../ClientMain/init.client.luau | 15 +++ 18 files changed, 296 insertions(+), 47 deletions(-) create mode 100644 src/ReplicatedStorage/Json/AttributesUpgrade.json create mode 100644 src/ServerStorage/Proxy/HelpProxy.luau create mode 100644 src/StarterPlayerScripts/ClientMain/Helper.luau create mode 100644 src/StarterPlayerScripts/ClientMain/PlayerControl.luau diff --git a/excel/cha.xlsx b/excel/cha.xlsx index 5552c548f402960aa74623bd7938f4251f066eb1..cb4048da6fa4fffb00ff6af13cf055d4d65d9eb1 100644 GIT binary patch delta 5847 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 BKU4q! diff --git a/src/ReplicatedStorage/Json/AttributesUpgrade.json b/src/ReplicatedStorage/Json/AttributesUpgrade.json new file mode 100644 index 0000000..c8db73d --- /dev/null +++ b/src/ReplicatedStorage/Json/AttributesUpgrade.json @@ -0,0 +1,13 @@ +[ +{"id":1,"type":1,"effectAttribute":"attack","cost":[1,10,20],"lvAdd":[10,20],"battleValueLimit":[5,20],"maxLv":null}, +{"id":2,"type":1,"effectAttribute":"hp","cost":[1,10,20],"lvAdd":[10,20],"battleValueLimit":[5,20],"maxLv":null}, +{"id":3,"type":1,"effectAttribute":"swordAtk","cost":[1,10,20],"lvAdd":[10,20],"battleValueLimit":[5,20],"maxLv":null}, +{"id":4,"type":1,"effectAttribute":"swordWearBase","cost":[1,10,20],"lvAdd":[10,20],"battleValueLimit":[5,20],"maxLv":null}, +{"id":5,"type":1,"effectAttribute":"swordWearSpe","cost":[1,10,20],"lvAdd":[10,20],"battleValueLimit":[5,20],"maxLv":null}, +{"id":10,"type":2,"effectAttribute":"wearNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":4}, +{"id":11,"type":2,"effectAttribute":"skillNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, +{"id":12,"type":2,"effectAttribute":"extraAttributeNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, +{"id":13,"type":2,"effectAttribute":"elementNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, +{"id":14,"type":2,"effectAttribute":"elementDefNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3}, +{"id":15,"type":2,"effectAttribute":"gemNumber","cost":[1,10,20],"lvAdd":[1,1],"battleValueLimit":[5,20],"maxLv":3} +] \ No newline at end of file diff --git a/src/ServerStorage/Base/Behaviour.luau b/src/ServerStorage/Base/Behaviour.luau index 509c7c7..f61b055 100644 --- a/src/ServerStorage/Base/Behaviour.luau +++ b/src/ServerStorage/Base/Behaviour.luau @@ -40,22 +40,21 @@ end -- 检查当前状态是否可执行 function Behaviour:CheckStat() - if not self.Character then warn("Behaviour Character not found") return false end + if not self.Character then return true end -- 死亡检查 - if self.Character:GetState("Died") then return false end + if self.Character:GetState("Died") then return true end -- 执行状态中检查 local ExecutingState = self.PlayerAI.ExecutingState -- 其他内容执行中,就false - if ExecutingState == true then return false end - return true + if ExecutingState == true then return true end + return false end -- 改变当前执行状态标记 function Behaviour:ChangeExecutingState(State: boolean) if not self.Character then warn("Behaviour Character not found") return end - local ExecutingState = self.PlayerAI.ExecutingState - ExecutingState.Value = State + self.PlayerAI.ExecutingState = State end -- 销毁 diff --git a/src/ServerStorage/Base/Character.luau b/src/ServerStorage/Base/Character.luau index f474012..8a10815 100644 --- a/src/ServerStorage/Base/Character.luau +++ b/src/ServerStorage/Base/Character.luau @@ -20,6 +20,7 @@ function Character.new(Player: Player, CharacterModel: Model, CharacterData: tab self.Root = HumanoidRootPart self.Humanoid = mobHumanoid self.Origin = HumanoidRootPart:GetPivot() + self.Player = Player self.TargetPlayerUserID = Player.UserId self.Connections = {} self.Stats = {} diff --git a/src/ServerStorage/Modules/Behaviours/Move.luau b/src/ServerStorage/Modules/Behaviours/Move.luau index 8e67214..e30f196 100644 --- a/src/ServerStorage/Modules/Behaviours/Move.luau +++ b/src/ServerStorage/Modules/Behaviours/Move.luau @@ -12,6 +12,7 @@ local MobsProxy = require(ServerStorage.Proxy.MobsProxy) local Move = {} Move.__index = Move +setmetatable(Move, {__index = Behaviour}) function Move:Init(PlayerAI, Character: TypeList.Character, Player: Player) local self = Behaviour:Init(PlayerAI, Character) @@ -24,7 +25,7 @@ function Move:Check(CheckInfo: table) if Behaviour.CheckStat(self) then return -1, self.CheckData end local PlayerMobs = MobsProxy:GetPlayerMobs(self.Player) - if not PlayerMobs then warn("PlayerMobs not found") return end + if not PlayerMobs then return end local closestMob, minDistance = nil, math.huge for _, Mob in PlayerMobs do @@ -50,7 +51,7 @@ end function Move:Execute() self.ExeTask = task.spawn(function () self:ChangeExecutingState(true) - self.Character.Humanoid.WalkToPart.CFrame = self.CheckData["ClosestCharacter"].Instance.PrimaryPart.CFrame + self.Character.Humanoid:MoveTo(self.CheckData["ClosestCharacter"].Instance:GetPivot().Position) task.wait(0.5) self:ChangeExecutingState(false) end) diff --git a/src/ServerStorage/Proxy/ArchiveProxy.luau b/src/ServerStorage/Proxy/ArchiveProxy.luau index 3b170d0..9a89920 100644 --- a/src/ServerStorage/Proxy/ArchiveProxy.luau +++ b/src/ServerStorage/Proxy/ArchiveProxy.luau @@ -31,6 +31,12 @@ function ArchiveProxy:IsPlayerDataLoaded(Player: Player) return true -- 成功加载 end +function ArchiveProxy:CleanPlayerData(Player: Player) + if not ArchiveProxy.pData[Player.UserId] then warn('CleanPlayerData: ', Player.Name, '数据不存在') return end + ArchiveProxy.pData[Player.UserId] = {} + print("清除数据成功") +end + -------------------------------------------------------------------------------- local PlayerData = Instance.new("Configuration") diff --git a/src/ServerStorage/Proxy/DamageProxy.luau b/src/ServerStorage/Proxy/DamageProxy.luau index 7c8bf0e..98e0c6c 100644 --- a/src/ServerStorage/Proxy/DamageProxy.luau +++ b/src/ServerStorage/Proxy/DamageProxy.luau @@ -57,6 +57,7 @@ function DamageProxy:TakeDamage(Caster: TypeList.Character, Victim: TypeList.Cha -- 伤害计算 local VictimHealth = Victim:GetAttributeValue("hp") Victim:ChangeAttributeValue("hp", math.max(0, VictimHealth - Damage)) + print("伤害数据打印", Damage, VictimHealth) end end diff --git a/src/ServerStorage/Proxy/HelpProxy.luau b/src/ServerStorage/Proxy/HelpProxy.luau new file mode 100644 index 0000000..8ee0dfa --- /dev/null +++ b/src/ServerStorage/Proxy/HelpProxy.luau @@ -0,0 +1,24 @@ +local HelpProxy = {} + +--> Server +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +--> Events +local RE_PlayerHelper = ReplicatedStorage.Events.RE_PlayerHelper + +function HelpProxy:CleanPlayerData(Player: Player) + local ArchiveProxy = require(script.Parent.ArchiveProxy) + ArchiveProxy:CleanPlayerData(Player) +end + +RE_PlayerHelper.OnServerEvent:Connect(function(Player: Player, EventName: string, EventData: any) + if EventName == "CleanPlayerData" then + HelpProxy:CleanPlayerData(Player) + elseif EventName == "AddItem" then + local PlayerInfoProxy = require(script.Parent.PlayerInfoProxy) + PlayerInfoProxy:ChangeItemCount(Player, EventData[1], EventData[2]) + print("添加物品成功", PlayerInfoProxy:GetItemCount(Player, EventData[1])) + end +end) + +return HelpProxy \ No newline at end of file diff --git a/src/ServerStorage/Proxy/LevelProxy.luau b/src/ServerStorage/Proxy/LevelProxy.luau index 78bb243..c0e96e0 100644 --- a/src/ServerStorage/Proxy/LevelProxy.luau +++ b/src/ServerStorage/Proxy/LevelProxy.luau @@ -15,6 +15,9 @@ local TypeList = require(ServerStorage.Base.TypeList) --> Json local JsonLevel = require(ReplicatedStorage.Json.Level) +--> Events +local BD_ChallengeEnd = ReplicatedStorage.Events.BD_ChallengeEnd + --> Constants local STORE_NAME = "Level" local ENUM_LEVEL_TYPE = { @@ -84,7 +87,7 @@ end local function OnMobDied(Player: Player, Mob: TypeList.Character) for _, mob in LevelProxy.pData[Player.UserId].Mobs do if mob ~= Mob then continue end - table.remove(LevelProxy.pData[Player.UserId].Mobs, mob) + table.remove(LevelProxy.pData[Player.UserId].Mobs, table.find(LevelProxy.pData[Player.UserId].Mobs, mob)) -- 怪物清除判断 local LevelData = Utils:GetJsonData(JsonLevel, LevelProxy.pData[Player.UserId].LevelId) @@ -149,8 +152,6 @@ function LevelProxy:InitPlayer(Player: Player) if key == "Task" or key == "Mobs" then continue end CreateLevelInstance(Player, ChallengeFolder, key, value) end - - -- self:ChallengeLevel(Player, 1) end -- 挑战关卡(挑战副本用另一个函数) @@ -165,7 +166,7 @@ function LevelProxy:ChallengeLevel(Player: Player, LevelId: number) local LevelFolder = GetPlayerLevelWorkspaceFolder(Player.UserId) local ChallengeFolder = LevelFolder:FindFirstChild("Challenge") if not ChallengeFolder then warn("ChallengeFolder not found") return end - local levelTask = task.defer(function() + 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) @@ -218,7 +219,7 @@ function LevelProxy:ChallengeLevel(Player: Player, LevelId: number) end end end) - ChangeValue(Player, ChallengeFolder, "Task", levelTask) + LevelProxy.pData[Player.UserId].Task = levelTask end -- 挑战结束 @@ -226,8 +227,15 @@ function LevelProxy:ChallengeEnd(Player: Player, result: boolean) local pData = Utils:GetPlayerDataFolder(Player) local LevelFolder = Utils:CreateFolder(STORE_NAME, pData) local ProgressFolder = Utils:CreateFolder("Progress", LevelFolder) + + -- 停止关卡循环 + if LevelProxy.pData[Player.UserId].Task then + task.cancel(LevelProxy.pData[Player.UserId].Task) + LevelProxy.pData[Player.UserId].Task = nil + end + -- 清除剩余怪物 - for _, mob in LevelProxy.pData[Player.UserId].Mobs do mob:Died() end + for _, mob in LevelProxy.pData[Player.UserId].Mobs do mob:Died(true) end LevelProxy.pData[Player.UserId].Mobs = {} -- 判断玩家是否通关 @@ -239,6 +247,7 @@ function LevelProxy:ChallengeEnd(Player: Player, result: boolean) ChangeValue(Player, ProgressFolder, "BossFail", LevelProxy.pData[Player.UserId].LevelId) end end + BD_ChallengeEnd:Fire(Player, LevelProxy.pData[Player.UserId].LevelId, result) end function LevelProxy:OnPlayerRemoving(Player: Player) @@ -249,7 +258,7 @@ function LevelProxy:OnPlayerRemoving(Player: Player) end -- 关卡存储数据清除 if LevelProxy.pData[Player.UserId].Task then - LevelProxy.pData[Player.UserId].Task:Cancel() + task.cancel(LevelProxy.pData[Player.UserId].Task) end LevelProxy.pData[Player.UserId] = nil end diff --git a/src/ServerStorage/Proxy/MobsProxy/AI.luau b/src/ServerStorage/Proxy/MobsProxy/AI.luau index 35e4c1a..12fb314 100644 --- a/src/ServerStorage/Proxy/MobsProxy/AI.luau +++ b/src/ServerStorage/Proxy/MobsProxy/AI.luau @@ -20,33 +20,27 @@ function AI:GetModelDistance(Unit1: Model, Unit2: Model): number end function AI:GetClosestPlayer(Mob: TypeList.Character): (Player?, number?) - local Closest = {Player = nil, Magnitude = math.huge} + local Closest = {PlayerRole = nil, Magnitude = math.huge, Player = nil} - local ActivePlayer -- We retain a reference to this, so they have to get further away from the mob to stop following, instead of the usual distance. - if Mob.Humanoid.WalkToPart then - local Player = Players:GetPlayerFromCharacter(Mob.Humanoid.WalkToPart.Parent) - if Player then - ActivePlayer = Player - end - end - - -- 临时的 + local PlayerRole = Mob.PlayerRole + local Character = PlayerRole.Instance + if Character == nil then warn("AI:GetClosestPlayer Character not found", Mob.Name) return end + for _, Player in Players:GetPlayers() do if Mob.TargetPlayerUserID == Player.UserId then - local Character = Player.Character - if not Character then continue end - - local Magnitude = (Character:GetPivot().Position - Mob.Instance:GetPivot().Position).Magnitude - local MaxDistance = (ActivePlayer == Player and (Mob.Config.FollowDistance or 32) * 2) or Mob.Config.FollowDistance or 32 - - if Magnitude <= MaxDistance and Magnitude < Closest.Magnitude then - Closest.Player = Player - Closest.Magnitude = Magnitude - end + Closest.Player = Player end end + + local Magnitude = (Character:GetPivot().Position - Mob.Instance:GetPivot().Position).Magnitude + -- 最大距离暂时设置大值 + local MaxDistance = Mob.Config.FollowDistance or 10000 + if Magnitude <= MaxDistance and Magnitude < Closest.Magnitude then + Closest.PlayerRole = PlayerRole + Closest.Magnitude = Magnitude + end - return Closest.Player, Closest.Player and Closest.Magnitude + return Closest.Player, Closest.PlayerRole, Closest.PlayerRole and Closest.Magnitude end -- Adds the mob to the ActiveMobs table. This table runs a few times per second and updates follow & jump code for active mobs. @@ -66,7 +60,10 @@ task.defer(function() for MobInstance, Mob in ActiveMobs do task.spawn(function() if not Mob.Stats.Died then - local Player, distance = AI:GetClosestPlayer(Mob) + -- 执行其他内容就停止 + if Mob.ExecutingState then return end + + local Player, PlayerRole, distance = AI:GetClosestPlayer(Mob) local Enemy = Mob.Humanoid -- Simulation @@ -79,16 +76,22 @@ task.defer(function() end -- Tracking - if Player and Enemy then + if Player and Enemy and PlayerRole then + if PlayerRole.Stats.Died then return end if distance > 5 then Enemy:MoveTo(Player.Character:GetPivot().Position, Player.Character.PrimaryPart) else + Mob.ExecutingState = true -- 停止移动 Enemy:MoveTo(MobInstance:GetPivot().Position) -- 触发攻击逻辑 task.wait(Mob.Config.attackSpeed) + + -- 攻击间隔后再次判断状态 if Mob.Stats.Died then return end if not Player then return end + if PlayerRole.Stats.Died then return end + if AI:GetModelDistance(MobInstance, Player.Character) <= 5 then -- 调用伤害模块 DamageProxy:TakeDamage(Mob, Mob.PlayerRole, { @@ -99,6 +102,7 @@ task.defer(function() } }) end + Mob.ExecutingState = false end end else diff --git a/src/ServerStorage/Proxy/MobsProxy/init.luau b/src/ServerStorage/Proxy/MobsProxy/init.luau index 37d2899..c1b834a 100644 --- a/src/ServerStorage/Proxy/MobsProxy/init.luau +++ b/src/ServerStorage/Proxy/MobsProxy/init.luau @@ -62,6 +62,7 @@ function Mob.new(Player: Player, MobId: number, OnMobDied: ((Player: Player, Mob setmetatable(self, Mob) -- 继承Mob方法 local PlayerFightProxy = require(ServerStorage.Proxy.PlayerFightProxy) self.PlayerRole = PlayerFightProxy:GetPlayerRole(Player) + self.ExecutingState = false -- 放入关卡中 newMobModel.Parent = playerMobsFolder @@ -80,9 +81,11 @@ function Mob.new(Player: Player, MobId: number, OnMobDied: ((Player: Player, Mob return self end -function Mob:Died() +function Mob:Died(IsSkinOnDied: boolean?) MobsProxy:RemoveMob(self.Player, self.Instance) - if self.OnDied then self.OnDied(self.Player, self) end + if not IsSkinOnDied then + if self.OnDied then self.OnDied(self.Player, self) end + end Character.Died(self) end @@ -93,8 +96,8 @@ function MobsProxy:CreateMob(Player: Player, MobId: number, AtkBonus: number?, H local Mob = Mob.new(Player, MobId, OnMobDied) AI:StartTracking(Mob) -- 关卡系数 - -- if AtkBonus then Mob:ChangeAttributeValue("attack", math.floor(Mob.Config.attack * (AtkBonus / 1000))) end - -- if HpBonus then Mob:ChangeAttributeValue("hp", math.floor(Mob.Config.hp * (HpBonus / 1000))) end + if AtkBonus then Mob:ChangeAttributeValue("attack", math.floor(Mob.Config.attack * (AtkBonus / 1000))) end + if HpBonus then Mob:ChangeAttributeValue("hp", math.floor(Mob.Config.hp * (HpBonus / 1000))) end MobsProxy.pData[Player.UserId][Mob.Instance] = Mob return Mob end diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau index 2542b06..2d739a5 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau @@ -20,12 +20,12 @@ local JsonLevel = require(ReplicatedStorage.Json.Level) local LevelLoop = {} LevelLoop.__index = LevelLoop -function LevelLoop.new(Player: Player, Character: TypeList.Character) +function LevelLoop.new(Player: Player, PlayerRole: TypeList.Character) print("LevelLoop:Init") local self = {} setmetatable(self, LevelLoop) self.Player = Player - self.Character = Character + self.PlayerRole = PlayerRole self.TaskAutoChallenge = nil self.ConChallengeEnd = BD_ChallengeEnd.Event:Connect(function(Player: Player, LevelId: number) @@ -38,7 +38,9 @@ function LevelLoop.new(Player: Player, Character: TypeList.Character) end function LevelLoop:AutoChallenge() - print("AutoChallenge") + -- 重置玩家状态(先临时调用角色复活,之后复杂的内容再说) + self.PlayerRole:Respawn() + local LevelFolder = game.Workspace:WaitForChild("Level"):WaitForChild(self.Player.UserId) local ProgressFolder = LevelFolder:FindFirstChild("Progress") @@ -51,7 +53,7 @@ function LevelLoop:AutoChallenge() LevelProxy:ChallengeLevel(self.Player, LevelId) end -function LevelLoop:OnChallengeEnd(Player: Player, LevelId: number) +function LevelLoop:OnChallengeEnd(Player: Player, LevelId: number, result: boolean) self.TaskAutoChallenge = task.defer(function() task.wait(3) self:AutoChallenge() diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau b/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau index ba08f4c..1389610 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau @@ -5,10 +5,14 @@ PlayerAI.__index = PlayerAI --> Services local Players = game:GetService("Players") local ServerStorage = game:GetService("ServerStorage") +local ReplicatedStorage = game:GetService("ReplicatedStorage") --> Dependencies local TypeList = require(ServerStorage.Base.TypeList) +--> Events +local RE_PlayerAI = ReplicatedStorage.Events.RE_PlayerAI + --> Variables local DamageProxy = require(ServerStorage.Proxy.DamageProxy) local ActivePlayers = {} @@ -42,14 +46,21 @@ function PlayerAI.new(Player: Player, PlayerRole: TypeList.Character) self.Character = PlayerRole self.Player = Player self.ExecutingState = false + self.PlayerControling = false self.BehaviourList = {} self.LoopTask = task.spawn(function() while task.wait(0.25) do + if self.Character.Stats.Died then continue end + if self.PlayerControling then continue end self:Update() end end) + self.PlayerControlCon = RE_PlayerAI.OnServerEvent:Connect(function(Player: Player, ControlState: boolean) + if Player ~= self.Player then return end + self.PlayerControling = ControlState + end) return self end diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau index 87a78aa..3be8a28 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau @@ -48,11 +48,13 @@ 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) -- 重置玩家位置 diff --git a/src/ServerStorage/Proxy/PlayerInfoProxy.luau b/src/ServerStorage/Proxy/PlayerInfoProxy.luau index 0489abe..7118d54 100644 --- a/src/ServerStorage/Proxy/PlayerInfoProxy.luau +++ b/src/ServerStorage/Proxy/PlayerInfoProxy.luau @@ -12,6 +12,11 @@ local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy) --> Json local JsonPlayerLv = require(ReplicatedStorage.Json.PlayerLv) local JsonItem = require(ReplicatedStorage.Json.ItemProp) +local JsonAttributesUpgrade = require(ReplicatedStorage.Json.AttributesUpgrade) + +--> Events +local RE_PlayerTip = ReplicatedStorage.Events.RE_PlayerTip +local RE_UpgradeAttributes = ReplicatedStorage.Events.RE_UpgradeAttributes --> Constants local STORE_NAME = "PlayerInfo" @@ -34,7 +39,7 @@ local function GetPlayerInfoFolder(Player: Player) end -- 创建玩家信息实例 -local function CreateInfoInstance(Player: Player, Folder: any, StateKey: string, StateType: string, StateValue: any) +local function CreateInfoInstance(Player: Player, Folder: any, StateKey: string, StateType: string, StateValue: any?) if not Player and not Folder and not StateKey and not StateType then warn('创建玩家信息实例失败: ' , Player.Name, Folder.Name, StateKey, StateType, StateValue) return @@ -81,21 +86,83 @@ function PlayerInfoProxy:InitPlayer(Player: Player) local PlayerInfoFolder = Utils:CreateFolder("PlayerInfo", pData) local StatsFolder = Utils:CreateFolder("Stats", PlayerInfoFolder) local ItemsFolder = Utils:CreateFolder("Items", PlayerInfoFolder) + local AttributesUpgradeFolder = Utils:CreateFolder("AttributesUpgrade", PlayerInfoFolder) -- 新玩家数据初始化 if not ArchiveProxy.pData[Player.UserId][STORE_NAME] then ArchiveProxy.pData[Player.UserId][STORE_NAME] = {} ArchiveProxy.pData[Player.UserId][STORE_NAME].Stats = {} ArchiveProxy.pData[Player.UserId][STORE_NAME].Items = {} + ArchiveProxy.pData[Player.UserId][STORE_NAME].AttributesUpgrade = {} end -- 放在外面是为了以后系统新增内容方便(同时不用在初始化数据是做写入了) ExtraAddPlayerStats(Player, ArchiveProxy.pData[Player.UserId][STORE_NAME].Stats) -- 创建玩家信息实例 + for ItemId, ItemValue in ArchiveProxy.pData[Player.UserId][STORE_NAME].Items do + CreateInfoInstance(Player, ItemsFolder, ItemId, ENUM_STATE_TYPE.Number, ItemValue) + end for StateKey, StateData in ArchiveProxy.pData[Player.UserId][STORE_NAME].Stats do CreateInfoInstance(Player, StatsFolder, StateKey, StateData.type, StateData.value) end + for AttributeId, AttributeLv in ArchiveProxy.pData[Player.UserId][STORE_NAME].AttributesUpgrade do + CreateInfoInstance(Player, AttributesUpgradeFolder, AttributeId, "NumberValue", AttributeLv) + end +end + +-- 玩家属性升级 +function PlayerInfoProxy:UpgradeAttribute(Player: Player, AttributeId: number) + if not Player or not AttributeId then warn('升级属性失败: ', Player.Name, AttributeId) return end + + local AttributesUpgradeFolder = GetPlayerInfoFolder(Player):FindFirstChild("AttributesUpgrade") + + local upgradeTable = ArchiveProxy.pData[Player.UserId][STORE_NAME].AttributesUpgrade + local nowLv = upgradeTable[AttributeId] + if nowLv == nil then nowLv = 0 end + + local attributeData = Utils:GetIdDataFromJson(JsonAttributesUpgrade, AttributeId) + local requireBattleValue, requireMoney + + if nowLv == 0 then + requireMoney = attributeData["cost"][2] + requireBattleValue = attributeData["battleValueLimit"][1] + else + requireMoney = attributeData["cost"][2] + (nowLv - 1) * attributeData["cost"][3] + requireBattleValue = attributeData["battleValueLimit"][1] + (nowLv - 1) * attributeData["battleValueLimit"][2] + end + + -- TODO 判断战力是否足够(暂无战力计算) + + -- 判断是否到达等级上限 + print(nowLv, attributeData["maxLv"]) + if attributeData["maxLv"] ~= nil then + if nowLv >= attributeData["maxLv"] then + local tip = '升级属性失败: ' .. AttributeId .. ' 已到达等级上限' + RE_PlayerTip:FireClient(Player, tip) + return + end + end + + -- 判断钱是否足够 + if not self:HasEnoughItem(Player, attributeData["cost"][1], requireMoney) then + local tip = '升级属性失败: ' .. AttributeId .. ' 钱不够' + RE_PlayerTip:FireClient(Player, tip) + return + end + -- 扣钱 + self:ChangeItemCount(Player, 1, -requireMoney) + + -- 升级 + if nowLv == 0 then + -- 首次生成属性 + upgradeTable[AttributeId] = 1 + CreateInfoInstance(Player, AttributesUpgradeFolder, AttributeId, "NumberValue", upgradeTable[AttributeId]) + else + -- 更新属性显示 + upgradeTable[AttributeId] = nowLv + 1 + ChangeInfoInstance(Player, AttributesUpgradeFolder, AttributeId, upgradeTable[AttributeId]) + end end -- 添加经验 @@ -161,6 +228,29 @@ function PlayerInfoProxy:GetItemCount(Player: Player, ItemId: number) return playerInfoData[ItemId] end +-------------------------------------------------------------------------------- + +-- 获取升级加点属性 +function PlayerInfoProxy:GetPlayerUpgradeAttributes(Player: Player) + if not Player then warn('获取玩家属性失败: ', Player.Name) return end + local playerInfoData = ArchiveProxy.pData[Player.UserId][STORE_NAME] + local attributes = {} + for AttributeId, AttributeLv in playerInfoData.AttributesUpgrade do + local attributeData = Utils:GetIdDataFromJson(JsonAttributesUpgrade, AttributeId) + attributes[attributeData["effectAttribute"]] = attributeData["lvAdd"][1] + (AttributeLv - 1) * attributeData["lvAdd"][2] + end + return attributes +end + +-- 获取玩家属性 +function PlayerInfoProxy:GetPlayerAttributes(Player: Player) + local attributesList = {} + attributesList.UpgradeAttributes = self:GetPlayerUpgradeAttributes(Player) + return attributesList +end + +-------------------------------------------------------------------------------- + function PlayerInfoProxy:OnPlayerRemoving(Player: Player) end @@ -169,4 +259,9 @@ ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(Player: Player) PlayerInfoProxy:OnPlayerRemoving(Player) end) +RE_UpgradeAttributes.OnServerEvent:Connect(function(Player: Player, AttributeId: number) + PlayerInfoProxy:UpgradeAttribute(Player, AttributeId) + print(ArchiveProxy.pData[Player.UserId][STORE_NAME].AttributesUpgrade) +end) + return PlayerInfoProxy \ No newline at end of file diff --git a/src/StarterPlayerScripts/ClientMain/Helper.luau b/src/StarterPlayerScripts/ClientMain/Helper.luau new file mode 100644 index 0000000..8302612 --- /dev/null +++ b/src/StarterPlayerScripts/ClientMain/Helper.luau @@ -0,0 +1,32 @@ +local Helper = {} + +--> Server +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +--> Events +local RE_PlayerHelper = ReplicatedStorage.Events.RE_PlayerHelper +local RE_UpgradeAttributes = ReplicatedStorage.Events.RE_UpgradeAttributes + +local UserInputService = game:GetService("UserInputService") + +UserInputService.InputBegan:Connect(function(input, gameProcessed) + if gameProcessed then return end + if input.UserInputType == Enum.UserInputType.Keyboard then + if input.KeyCode == Enum.KeyCode.H then + RE_PlayerHelper:FireServer("CleanPlayerData") + elseif input.KeyCode == Enum.KeyCode.J then + print("添加物品") + RE_PlayerHelper:FireServer("AddItem", {1, 100}) + elseif input.KeyCode == Enum.KeyCode.K then + RE_UpgradeAttributes:FireServer(1) + elseif input.KeyCode == Enum.KeyCode.L then + RE_UpgradeAttributes:FireServer(2) + elseif input.KeyCode == Enum.KeyCode.M then + RE_UpgradeAttributes:FireServer(3) + elseif input.KeyCode == Enum.KeyCode.N then + RE_UpgradeAttributes:FireServer(4) + end + end +end) + +return Helper \ No newline at end of file diff --git a/src/StarterPlayerScripts/ClientMain/PlayerControl.luau b/src/StarterPlayerScripts/ClientMain/PlayerControl.luau new file mode 100644 index 0000000..42588c4 --- /dev/null +++ b/src/StarterPlayerScripts/ClientMain/PlayerControl.luau @@ -0,0 +1,31 @@ +local UserInputService = game:GetService("UserInputService") + +local PlayerControl = {} + +-- 监听按键按下 +function PlayerControl.ListenMoveKeyDown(onKeyDown) + UserInputService.InputBegan:Connect(function(input, gameProcessed) + if gameProcessed then return end + if input.UserInputType == Enum.UserInputType.Keyboard then + local key = input.KeyCode + if key == Enum.KeyCode.W or key == Enum.KeyCode.A or key == Enum.KeyCode.S or key == Enum.KeyCode.D then + onKeyDown(key) + end + end + end) +end + +-- 监听按键松开 +function PlayerControl.ListenMoveKeyUp(onKeyUp) + UserInputService.InputEnded:Connect(function(input, gameProcessed) + if gameProcessed then return end + if input.UserInputType == Enum.UserInputType.Keyboard then + local key = input.KeyCode + if key == Enum.KeyCode.W or key == Enum.KeyCode.A or key == Enum.KeyCode.S or key == Enum.KeyCode.D then + onKeyUp(key) + end + end + end) +end + +return PlayerControl \ No newline at end of file diff --git a/src/StarterPlayerScripts/ClientMain/init.client.luau b/src/StarterPlayerScripts/ClientMain/init.client.luau index fe4edb2..d913bd5 100644 --- a/src/StarterPlayerScripts/ClientMain/init.client.luau +++ b/src/StarterPlayerScripts/ClientMain/init.client.luau @@ -19,6 +19,11 @@ local PlayerGui = Player:WaitForChild("PlayerGui") local FormatNumber = require(ReplicatedStorage.Modules.FormatNumber) local Tween = require(ReplicatedStorage.Modules.Tween) local SFX = require(ReplicatedStorage.Modules.SFX) +local PlayerControl = require(script.PlayerControl) +local Helper = require(script.Helper) + +--> Events +local RE_PlayerAI = ReplicatedStorage.Events.RE_PlayerAI --> Variables local Random = Random.new() @@ -28,6 +33,16 @@ local ClientMainPrefabs = Player.PlayerScripts.ClientMainPrefabs -------------------------------------------------------------------------------- +PlayerControl.ListenMoveKeyDown(function(key) + -- print("按下了: ", key.Name) + RE_PlayerAI:FireServer(true) +end) + +PlayerControl.ListenMoveKeyUp(function(key) + -- print("松开了: ", key.Name) + RE_PlayerAI:FireServer(false) +end) + -- Initially require client-sided modules for _, Item in script:GetChildren() do if Item:IsA("ModuleScript") then