From 0d1d5e3e3ecb9844eb72d2840adbe24c76fbcb72 Mon Sep 17 00:00:00 2001 From: Ggafrik <906823881@qq.com> Date: Wed, 23 Jul 2025 01:04:27 +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 --- src/ReplicatedStorage/Base/UIList.luau | 35 ++++-- src/ReplicatedStorage/Base/UIWindow.luau | 1 - src/ReplicatedStorage/Tools/Localization.luau | 2 +- src/ReplicatedStorage/Tools/Utils.luau | 18 ++- src/ServerStorage/Base/Character.luau | 13 +- src/ServerStorage/Proxy/EquipmentProxy.luau | 3 +- .../Proxy/PlayerFightProxy/init.luau | 12 +- .../AttributeLvupShow.luau | 119 ++++++++++++++++++ .../UI/Windows/AttributeLvupWindow/init.luau | 65 ++++++++++ .../UI/Windows/ChaWindow/PackageShow.luau | 16 +++ .../UI/Windows/ChaWindow/WearingShow.luau | 15 +++ .../UI/Windows/ChaWindow/init.luau | 28 +++++ .../UI/Windows/MainWindow/init.luau | 5 + 13 files changed, 309 insertions(+), 23 deletions(-) create mode 100644 src/StarterPlayerScripts/UI/Windows/AttributeLvupWindow/AttributeLvupShow.luau create mode 100644 src/StarterPlayerScripts/UI/Windows/AttributeLvupWindow/init.luau diff --git a/src/ReplicatedStorage/Base/UIList.luau b/src/ReplicatedStorage/Base/UIList.luau index 6d7b6ac..d0d2719 100644 --- a/src/ReplicatedStorage/Base/UIList.luau +++ b/src/ReplicatedStorage/Base/UIList.luau @@ -58,18 +58,34 @@ function UIList:SetData(Data: table) self:Refresh() end -function UIList:AddData(data: table) - self.Data[#self.Data + 1] = data - self:SetSingleInstance(#self.Data, data) +-- 列表添加单个数据 +function UIList:AddData(key: string, data: table) + self.Data[key] = data + self:SetSingleInstance(key, data) end -function UIList:RemoveData(data: table) - for i, v in pairs(self.Data) do - if Utils:CompareTableJson(v, data) then - self.Instances[i]:Destroy() - table.remove(self.Data, i) - return i +-- 列表清除单个数据 +function UIList:RemoveData(key) + if self.Data[key] then + for k, v in pairs(self.Instances) do + if v.Data == self.Data[key] then + for _, connection in pairs(v.Connections) do + connection:Disconnect() + end + v.Connections = nil + if v.UIRoot then v.UIRoot:Destroy() end + if v.Destroy then v:Destroy() end + if type(key) == "number" then + table.remove(self.Instances, k) + else + self.Instances[k] = nil + end + break + end end + self.Data[key] = nil + else + warn("UIList:RemoveData() 数据不存在", key, self.Data) end end @@ -161,6 +177,7 @@ function UIList:Destroy() self.SignalConnections = nil self.Connections = nil self.Org:Destroy() + if self.UIRoot then self.UIRoot:Destroy() end self = nil end diff --git a/src/ReplicatedStorage/Base/UIWindow.luau b/src/ReplicatedStorage/Base/UIWindow.luau index 0475f7b..8a4cc50 100644 --- a/src/ReplicatedStorage/Base/UIWindow.luau +++ b/src/ReplicatedStorage/Base/UIWindow.luau @@ -75,7 +75,6 @@ function UIWindow:OnOpenWindow() -- 创建UI根节点 self.UIRoot = FolderWindows:FindFirstChild(self.UIRootName):Clone() self.UIRoot.Parent = FolderPlayerGui:WaitForChild(self.UIParentName) - print("节点", self.UIRoot, self.UIParentName, FolderPlayerGui, FolderPlayerGui:FindFirstChild(self.UIParentName)) else self.UIRoot.Visible = true self:Refresh() diff --git a/src/ReplicatedStorage/Tools/Localization.luau b/src/ReplicatedStorage/Tools/Localization.luau index 055ad1f..a1e8c8d 100644 --- a/src/ReplicatedStorage/Tools/Localization.luau +++ b/src/ReplicatedStorage/Tools/Localization.luau @@ -39,7 +39,7 @@ end -- 获取图片Id数据 function Localization:GetImageData(Id: number) - if not Id then return end + if not Id then return "" end local data = Utils:GetIdDataFromJson(JsonImage, Id) if not data then return "" end return data.sourceId diff --git a/src/ReplicatedStorage/Tools/Utils.luau b/src/ReplicatedStorage/Tools/Utils.luau index 86f5a62..d1051f5 100644 --- a/src/ReplicatedStorage/Tools/Utils.luau +++ b/src/ReplicatedStorage/Tools/Utils.luau @@ -65,7 +65,7 @@ function Utils:GetIdDataFromJson(JsonData: table, id: number) -- 遍历JsonData,查找id字段等于目标id的项 for _, item in ipairs(JsonData) do if item.id == id then - return item + return Utils:DeepCopyTable(item) end end return nil -- 没有找到对应id @@ -215,9 +215,23 @@ end -- 合并表(加法合并) function Utils:MergeTable(t1: table, t2: table) + -- 检查是否为空表 + local t1Empty = next(t1) == nil + local t2Empty = next(t2) == nil + + -- 如果其中一个为空表,返回不为空的表 + if t1Empty and not t2Empty then + return t2 + elseif not t1Empty and t2Empty then + return t1 + elseif t1Empty and t2Empty then + return t1 -- 全为空表,返回t1 + end + + -- 正常合并逻辑 for k, v in pairs(t2) do if type(v) == "number" then - t1[k] = t1[k] + v + t1[k] = (t1[k] or 0) + v end end return t1 diff --git a/src/ServerStorage/Base/Character.luau b/src/ServerStorage/Base/Character.luau index 8668884..bdf2095 100644 --- a/src/ServerStorage/Base/Character.luau +++ b/src/ServerStorage/Base/Character.luau @@ -34,11 +34,14 @@ function Character.new(Player: Player, CharacterModel: Model, CharacterData: tab Attributes.Name = "Attributes" Attributes.Parent = self.Instance for attributeKey, attributeValue in self.Config do - Attributes:SetAttribute(attributeKey, attributeValue) - -- 设置限制值 - if table.find(LIMIT_ATTRIBUTE, attributeKey) then - self.Config["max" .. attributeKey] = attributeValue - Attributes:SetAttribute("max" .. attributeKey, attributeValue) + -- 只设置非表类型的属性值 + if type(attributeValue) ~= "table" then + Attributes:SetAttribute(attributeKey, attributeValue) + -- 设置限制值 + if table.find(LIMIT_ATTRIBUTE, attributeKey) then + self.Config["max" .. attributeKey] = attributeValue + Attributes:SetAttribute("max" .. attributeKey, attributeValue) + end end end diff --git a/src/ServerStorage/Proxy/EquipmentProxy.luau b/src/ServerStorage/Proxy/EquipmentProxy.luau index 44b13c2..9d8796a 100644 --- a/src/ServerStorage/Proxy/EquipmentProxy.luau +++ b/src/ServerStorage/Proxy/EquipmentProxy.luau @@ -47,7 +47,7 @@ local function ChangeValue(Player: Player, EquipmentUniqueId: number, KeyName: s local ValueInstance = GetPlayerEquipmentFolder(Player):FindFirstChild(EquipmentUniqueId) if not ValueInstance then warn("ValueInstance not found", KeyName) return end - ArchiveProxy.pData[Player.UserId][EquipmentUniqueId][KeyName] = Value + ArchiveProxy.pData[Player.UserId][STORE_NAME][EquipmentUniqueId][KeyName] = Value ValueInstance:SetAttribute(KeyName, Value) end @@ -363,7 +363,6 @@ RE_WearEquipment.OnServerEvent:Connect(function(Player: Player, EquipmentUniqueI if Unwear then EquipmentProxy:UnwearEquipment(Player, EquipmentUniqueId) else - print(Player, EquipmentUniqueId, SlotId) EquipmentProxy:WearEquipment(Player, EquipmentUniqueId, SlotId) end end) diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau index 3e79da5..bd0ecd0 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau @@ -124,13 +124,19 @@ function PlayerFightProxy:UpdatePlayerFightData(Player: Player) -- 计算角色基础属性值 + 装备属性值 + 宝石属性值,赋值属性 local PlayerInfoAttributes = PlayerInfoProxy:GetPlayerAttributes(Player) - AttributesData = Utils:MergeTable(AttributesData, PlayerInfoAttributes) + if PlayerInfoAttributes.UpgradeAttributes then + Utils:TableSafeAddTableValue(AttributesData, PlayerInfoAttributes.UpgradeAttributes) + end local EquipmentAttributes = EquipmentProxy:GetPlayerAttributes(Player) - AttributesData = Utils:MergeTable(AttributesData, EquipmentAttributes) + if EquipmentAttributes then + Utils:TableSafeAddTableValue(AttributesData, EquipmentAttributes) + end local GemAttributes = GemProxy:GetPlayerAttributes(Player) - AttributesData = Utils:MergeTable(AttributesData, GemAttributes) + if GemAttributes.GemWearingAttributes then + Utils:TableSafeAddTableValue(AttributesData, GemAttributes.GemWearingAttributes) + end -- 角色基础数据 local PlayerRole = self:GetPlayerRole(Player) diff --git a/src/StarterPlayerScripts/UI/Windows/AttributeLvupWindow/AttributeLvupShow.luau b/src/StarterPlayerScripts/UI/Windows/AttributeLvupWindow/AttributeLvupShow.luau new file mode 100644 index 0000000..6070115 --- /dev/null +++ b/src/StarterPlayerScripts/UI/Windows/AttributeLvupWindow/AttributeLvupShow.luau @@ -0,0 +1,119 @@ +local AttributeLvupShow = {} +AttributeLvupShow.__index = AttributeLvupShow + +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Utils = require(ReplicatedStorage.Tools.Utils) +local Localization = require(ReplicatedStorage.Tools.Localization) +local JsonAttributesUpgrade = require(ReplicatedStorage.Json.AttributesUpgrade) +local JsonAttributes = require(ReplicatedStorage.Json.Attributes) + +local RE_UpgradeAttributes = ReplicatedStorage.Events.RE_UpgradeAttributes + +local LocalPlayer = game:GetService("Players").LocalPlayer + +function AttributeLvupShow:Init(data: table) + local self = {} + self.Data = data + self.Variables = { + ["_imgIcon"] = 0, + ["_tmpAttributeName"] = 0, + ["_tmpValue"] = 0, + ["_tmpLv"] = 0, + ["_btnUpgrade"] = 0, + } + self.Connections = {} + setmetatable(self, AttributeLvupShow) + return self +end + +function AttributeLvupShow:GetNowLv() + local attributeFolder = Utils:GetPlayerDataFolder(LocalPlayer):FindFirstChild("PlayerInfo"):FindFirstChild("AttributesUpgrade") + local instance = attributeFolder:FindFirstChild(tostring(self.Data.id)) + local nowLv = 0 + if instance then nowLv = instance.Value end + return nowLv +end + +function AttributeLvupShow:Refresh() + -- 如果有实例,,并且之前有监听,则断开添加监听 + if self.instance then + if self.folderCon then + self.folderCon:Disconnect() + self.folderCon = nil + end + end + + if self.instance and not self.instanceCon then + local instanceCon = self.instance.ValueChanged:Connect(function() + self:Refresh() + end) + self.instanceCon = instanceCon + end + + local attributeData = Utils:GetSpecialKeyDataFromJson(JsonAttributes, "effectAttribute", self.Data.attribute) + self.Variables._imgIcon.Image = Localization:GetImageData(attributeData.iconId) + self.Variables._tmpAttributeName.Text = self.Data.id + self.UIRoot.LayoutOrder = 1000 - attributeData.id + + local nowLv = self:GetNowLv() + self.Variables._tmpLv.Text = "Lv." .. nowLv + + -- 花费按钮显示 + if self.Data.maxLv then + self.Variables._btnUpgrade.Text = nowLv >= self.Data.maxLv and "满级" or self.Data.cost[2] + self.Data.cost[3] * (self.Data.maxLv - 1) + + -- 属性值显示 + local caculateValue = self.Data.lvAdd[1] + self.Data.lvAdd[2] * (self.Data.maxLv - 1) + self.Variables._tmpValue.Text = string.format("%.2f%%", caculateValue / 100) + else + self.Variables._btnUpgrade.Text = self.Data.cost[2] + self.Data.cost[3] * nowLv + -- 属性值显示(下一级) + self.Variables._tmpValue.Text = self.Data.lvAdd[1] + self.Data.lvAdd[2] * nowLv + end +end + +function AttributeLvupShow:OnInitFinish() + local con = self.Variables._btnUpgrade.MouseButton1Click:Connect(function() + if self.Data.maxLv then + if self:GetNowLv() >= self.Data.maxLv then + -- TODO: 之后做提示弹窗 + else + RE_UpgradeAttributes:FireServer(self.Data.id) + end + else + -- TODO: 检查货币是否充足 + RE_UpgradeAttributes:FireServer(self.Data.id) + end + end) + table.insert(self.Connections, con) + + -- 没有实例时,监听文件夹,有实例时,监听实例 + if not self.instance then + local attributeFolder = Utils:GetPlayerDataFolder(LocalPlayer):FindFirstChild("PlayerInfo"):FindFirstChild("AttributesUpgrade") + local folderCon = attributeFolder.ChildAdded:Connect(function(child) + if child.Name == tostring(self.Data.id) then + self.instance = child + self:Refresh() + end + end) + self.folderCon = folderCon + end +end + +function AttributeLvupShow:Destroy() + if self.instanceCon then + self.instanceCon:Disconnect() + self.instanceCon = nil + end + if self.folderCon then + self.folderCon:Disconnect() + self.folderCon = nil + end + for k, v in pairs(self) do + self[k] = nil + end + self = nil +end + +return AttributeLvupShow \ No newline at end of file diff --git a/src/StarterPlayerScripts/UI/Windows/AttributeLvupWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/AttributeLvupWindow/init.luau new file mode 100644 index 0000000..d6198c0 --- /dev/null +++ b/src/StarterPlayerScripts/UI/Windows/AttributeLvupWindow/init.luau @@ -0,0 +1,65 @@ +--> Services +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +--> Dependencies +local UIWindow = require(ReplicatedStorage.Base.UIWindow) +local UIEnums = require(ReplicatedStorage.Base.UIEnums) +local Utils = require(ReplicatedStorage.Tools.Utils) + +--> Components +local AttributeLvupShow = require(script.AttributeLvupShow) + +--> Json +local JsonAttributesUpgrade = require(ReplicatedStorage.Json.AttributesUpgrade) + +-------------------------------------------------------------------------------- + +local AttributeLvupWindow = {} +AttributeLvupWindow.__index = AttributeLvupWindow +setmetatable(AttributeLvupWindow, {__index = UIWindow}) + +function AttributeLvupWindow:Init(UIManager: table, Data: table?) + local self = UIWindow:Init(UIManager, Data) + setmetatable(self, AttributeLvupWindow) + self.Variables = { + ["_goSpecaialPanel"] = 0, + ["_goBasePanel"] = 0, + ["__listSpecialAttributes"] = 0, + ["__listBaseAttributes"] = 0, + ["_tmpSpecialTitle"] = 0, + ["_tmpBaseTitle"] = 0, + } + self.UIRootName = "ui_w_attribute_lvup" + self.UIParentName = UIEnums.UIParent.UIRoot + + return self +end + +function AttributeLvupWindow:OnOpenWindow() + UIWindow.OnOpenWindow(self) + + local orgData = Utils:DeepCopyTable(JsonAttributesUpgrade) + local data = { + Special = {}, + Base = {}, + } + + for key, value in pairs(orgData) do + local secondKey = "Base" + if value.type == 2 then secondKey = "Special" end + table.insert(data[secondKey], value) + end + + self:SetData(data) + + + self.Variables["__listSpecialAttributes"]:AddComponent(AttributeLvupShow) + self.Variables["__listBaseAttributes"]:AddComponent(AttributeLvupShow) + self.Variables["__listSpecialAttributes"]:SetData(self.Data.Special) + self.Variables["__listBaseAttributes"]:SetData(self.Data.Base) + self.Variables["__listSpecialAttributes"]:SetLayoutOrder("id") + self.Variables["__listBaseAttributes"]:SetLayoutOrder("id") +end + + +return AttributeLvupWindow \ No newline at end of file diff --git a/src/StarterPlayerScripts/UI/Windows/ChaWindow/PackageShow.luau b/src/StarterPlayerScripts/UI/Windows/ChaWindow/PackageShow.luau index 2b2e914..b91bcb3 100644 --- a/src/StarterPlayerScripts/UI/Windows/ChaWindow/PackageShow.luau +++ b/src/StarterPlayerScripts/UI/Windows/ChaWindow/PackageShow.luau @@ -19,6 +19,7 @@ function PackageShow:Init(data: table) self.Connections = {} setmetatable(self, PackageShow) + return self end @@ -38,6 +39,21 @@ function PackageShow:OnInitFinish() end end) table.insert(self.Connections, con) + + if self.Data.instance then + local wearingCon = self.Data.instance:GetAttributeChangedSignal("wearing"):Connect(function() + local oldWearing = self.Data.wearing + local newWearing = self.Data.instance:GetAttribute("wearing") + if oldWearing ~= newWearing then + if newWearing > 0 then + self.TopUI:WearRefresh(self.Data) + else + self.TopUI:UnwearRefresh(self.Data) + end + end + end) + table.insert(self.Connections, wearingCon) + end end function PackageShow:Destroy() diff --git a/src/StarterPlayerScripts/UI/Windows/ChaWindow/WearingShow.luau b/src/StarterPlayerScripts/UI/Windows/ChaWindow/WearingShow.luau index ed9b7ed..4af9fa0 100644 --- a/src/StarterPlayerScripts/UI/Windows/ChaWindow/WearingShow.luau +++ b/src/StarterPlayerScripts/UI/Windows/ChaWindow/WearingShow.luau @@ -49,6 +49,21 @@ function WearingShow:OnInitFinish() end end) table.insert(self.Connections, con) + + if self.Data.instance then + local wearingCon = self.Data.instance:GetAttributeChangedSignal("wearing"):Connect(function() + local oldWearing = self.Data.wearing + local newWearing = self.Data.instance:GetAttribute("wearing") + if oldWearing ~= newWearing then + if newWearing > 0 then + self.TopUI:WearRefresh(self.Data) + else + self.TopUI:UnwearRefresh(self.Data) + end + end + end) + table.insert(self.Connections, wearingCon) + end end function WearingShow:Destroy() diff --git a/src/StarterPlayerScripts/UI/Windows/ChaWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/ChaWindow/init.luau index f50976a..b11bb7b 100644 --- a/src/StarterPlayerScripts/UI/Windows/ChaWindow/init.luau +++ b/src/StarterPlayerScripts/UI/Windows/ChaWindow/init.luau @@ -48,6 +48,33 @@ function ChaWindow:ShowDetailData(uniqueId: number) self.UIManager:OpenWindow("EquipmentDetailWindow", data) end +function ChaWindow:WearRefresh(data: table) + local newSlot = data.instance:GetAttribute("wearing") + self.Variables["__listWeaing"]:RemoveData("slot"..newSlot) + self.Variables["__listWeaponPackage"]:RemoveData(tostring(data.id)) + + -- 更新穿戴数据,要不再点击前端就不好使了 + data.wearing = newSlot + self.Variables["__listWeaing"]:AddData("slot"..newSlot, data) + + -- 关闭装备详情窗口 + self.UIManager:CloseWindow("EquipmentDetailWindow") +end + +function ChaWindow:UnwearRefresh(data: table) + local oldSlot = data.wearing + self.Variables["__listWeaing"]:RemoveData("slot"..oldSlot) + data.wearing = 0 + self.Variables["__listWeaponPackage"]:AddData(tostring(data.id), data) + self.Data.Wearing["slot"..oldSlot] = { + wearing = oldSlot, + } + self.Variables["__listWeaing"]:AddData("slot"..oldSlot, self.Data.Wearing["slot"..oldSlot]) + + -- 关闭装备详情窗口 + self.UIManager:CloseWindow("EquipmentDetailWindow") +end + function ChaWindow:AddInstanceData(configInstance: Instance, Data: table?) local data = self.Data if Data then data = Data end @@ -61,6 +88,7 @@ function ChaWindow:AddInstanceData(configInstance: Instance, Data: table?) for attributeKey, attributeValue in attributes do data[parentName][configInstance.Name][attributeKey] = attributeValue end + data[parentName][configInstance.Name].instance = configInstance return data[parentName][configInstance.Name], parentName end diff --git a/src/StarterPlayerScripts/UI/Windows/MainWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/MainWindow/init.luau index 06392dd..0e1b309 100644 --- a/src/StarterPlayerScripts/UI/Windows/MainWindow/init.luau +++ b/src/StarterPlayerScripts/UI/Windows/MainWindow/init.luau @@ -17,6 +17,7 @@ function MainWindow:Init(UIManager: table, Data: table?) self.Variables = { ["_btnMainCreate"] = 0, ["_btnMainCha"] = 0, + ["_btnMainAttributeUpgrade"] = 0, } self.UIRootName = "ui_w_main" self.UIParentName = UIEnums.UIParent.UIRoot @@ -33,9 +34,13 @@ function MainWindow:OnOpenWindow() local chaCon = self.Variables["_btnMainCha"].Activated:Connect(function() self.UIManager:OpenWindow("ChaWindow") end) + local attributeUpgradeCon = self.Variables["_btnMainAttributeUpgrade"].Activated:Connect(function() + self.UIManager:OpenWindow("AttributeLvupWindow") + end) table.insert(self.Connections, createCon) table.insert(self.Connections, chaCon) + table.insert(self.Connections, attributeUpgradeCon) end