From b41e4d8b93f4bf86a3526805df97d047bf70ea4e Mon Sep 17 00:00:00 2001 From: gechangfu Date: Thu, 14 Aug 2025 19:28:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0-=E7=AC=A6=E6=96=87=E7=B3=BB?= =?UTF-8?q?=E7=BB=9Fui?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ReplicatedStorage/Tools/Localization.luau | 11 + src/ServerStorage/Proxy/RuneProxy/init.luau | 5 + .../UI/Windows/RuneWindow/PackageShow.luau | 71 +++++ .../UI/Windows/RuneWindow/WearingShow.luau | 78 ++++++ .../UI/Windows/RuneWindow/init.luau | 246 ++++++++++++++++++ 5 files changed, 411 insertions(+) create mode 100644 src/StarterPlayerScripts/UI/Windows/RuneWindow/PackageShow.luau create mode 100644 src/StarterPlayerScripts/UI/Windows/RuneWindow/WearingShow.luau create mode 100644 src/StarterPlayerScripts/UI/Windows/RuneWindow/init.luau diff --git a/src/ReplicatedStorage/Tools/Localization.luau b/src/ReplicatedStorage/Tools/Localization.luau index 853c42f..5e853da 100644 --- a/src/ReplicatedStorage/Tools/Localization.luau +++ b/src/ReplicatedStorage/Tools/Localization.luau @@ -43,6 +43,12 @@ local QUALITY_BG_COLOR = { [8] = Color3.fromRGB(236, 77, 236), -- 粉色 } +local QUALITY_RUNE_BG_COLOR = { + [1] = Color3.fromRGB(159, 71, 221), -- 紫色 + [2] = Color3.fromRGB(223, 159, 71), -- 橙色 + [3] = Color3.fromRGB(233, 78, 78), -- 红色 +} + -- 获取本地Json文件 function Localization:GetLocalizationJson() if SystemLocaleId == "zh-CN" then @@ -70,6 +76,11 @@ function Localization:GetImageData(Id: number) return data.sourceId end +-- 获取符文品质背景颜色 +function Localization:GetRuneQualityBgColor(Quality: number) + return QUALITY_RUNE_BG_COLOR[Quality] +end + -- 获取装备品质描述 function Localization:GetEquipmentQualityDesc(Quality: number) local qualityData = Utils:GetSpecialKeyDataFromJson(JsonParam, "key", "quality_show") diff --git a/src/ServerStorage/Proxy/RuneProxy/init.luau b/src/ServerStorage/Proxy/RuneProxy/init.luau index 003ede8..d7a5596 100644 --- a/src/ServerStorage/Proxy/RuneProxy/init.luau +++ b/src/ServerStorage/Proxy/RuneProxy/init.luau @@ -16,6 +16,7 @@ local JsonRune = require(ReplicatedStorage.Json.Rune) --> Events local RE_PlayerTip = ReplicatedStorage.Events.RE_PlayerTip +local RE_RuneInlay = ReplicatedStorage.Events.RE_RuneInlay --> SubFunctions local RuneCalculation = require(script.RuneCalculation) @@ -287,4 +288,8 @@ ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(Player: Player) RuneProxy:OnPlayerRemoving(Player) end) +RE_RuneInlay.OnServerEvent:Connect(function(Player: Player, RuneUniqueId: number, EquipmentUniqueId: number) + RuneProxy:WearRune(Player, RuneUniqueId, EquipmentUniqueId) +end) + return RuneProxy \ No newline at end of file diff --git a/src/StarterPlayerScripts/UI/Windows/RuneWindow/PackageShow.luau b/src/StarterPlayerScripts/UI/Windows/RuneWindow/PackageShow.luau new file mode 100644 index 0000000..ad9c5ee --- /dev/null +++ b/src/StarterPlayerScripts/UI/Windows/RuneWindow/PackageShow.luau @@ -0,0 +1,71 @@ +local PackageShow = {} +PackageShow.__index = PackageShow + +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Utils = require(ReplicatedStorage.Tools.Utils) +local Localization = require(ReplicatedStorage.Tools.Localization) +local JsonRune = require(ReplicatedStorage.Json.Rune) +local JsonItemProp = require(ReplicatedStorage.Json.ItemProp) + +local FolderRune = ReplicatedStorage:WaitForChild("Prefabs"):WaitForChild("Runes") + +function PackageShow:Init(data: table) + local self = {} + self.Data = data + self.Variables = { + ["_btnClick"] = 0, + ["_imgIcon"] = 0, + ["_tmpName"] = 0, + ["_imgView"] = 0, + } + self.Connections = {} + + setmetatable(self, PackageShow) + + return self +end + +function PackageShow:Refresh() + local itemData = Utils:GetIdDataFromJson(JsonItemProp, self.Data.orgId) + local runeData = Utils:GetIdDataFromJson(JsonRune, self.Data.orgId) + + self.Variables._imgIcon.Image = Localization:GetImageData(runeData.icon) + self.Variables._imgIcon.BackgroundColor3 = Localization:GetRuneQualityBgColor(runeData.quality) + self.Variables._tmpName.Text = Localization:GetLanguageData(itemData.nameId) +end + +function PackageShow:OnInitFinish() + local con = self.Variables._btnClick.MouseButton1Click:Connect(function() + if self.Data == {} then + -- TODO: 之后做提示弹窗 + else + self.TopUI:ShowDetailData(self.Data.id) + 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() + for k, v in pairs(self) do + self[k] = nil + end + self = nil +end + +return PackageShow \ No newline at end of file diff --git a/src/StarterPlayerScripts/UI/Windows/RuneWindow/WearingShow.luau b/src/StarterPlayerScripts/UI/Windows/RuneWindow/WearingShow.luau new file mode 100644 index 0000000..5c82313 --- /dev/null +++ b/src/StarterPlayerScripts/UI/Windows/RuneWindow/WearingShow.luau @@ -0,0 +1,78 @@ +local WearingShow = {} +WearingShow.__index = WearingShow + +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Utils = require(ReplicatedStorage.Tools.Utils) +local Localization = require(ReplicatedStorage.Tools.Localization) +local JsonRune = require(ReplicatedStorage.Json.Rune) +local JsonItemProp = require(ReplicatedStorage.Json.ItemProp) + +local FolderRune = ReplicatedStorage:WaitForChild("Prefabs"):WaitForChild("Runes") + +function WearingShow:Init(data: table) + local self = {} + self.Data = data + self.Variables = { + ["_btnClick"] = 0, + ["_imgIcon"] = 0, + ["_tmpName"] = 0, + ["_imgView"] = 0, + } + self.Connections = {} + + setmetatable(self, WearingShow) + + return self +end + +function WearingShow:Refresh() + if self.Data then + local itemData = Utils:GetIdDataFromJson(JsonItemProp, self.Data.orgId) + local runeData = Utils:GetIdDataFromJson(JsonRune, self.Data.orgId) + + self.Variables._imgIcon.Image = Localization:GetImageData(runeData.icon) + self.Variables._imgIcon.BackgroundColor3 = Localization:GetRuneQualityBgColor(runeData.quality) + self.Variables._tmpName.Text = Localization:GetLanguageData(itemData.nameId) + self.Variables._imgIcon.Visible = true + else + self.Variables._imgIcon.Image = "" + self.Variables._tmpName.Text = "" + self.Variables._imgIcon.Visible = false + end +end + +function WearingShow:OnInitFinish() + local con = self.Variables._btnClick.MouseButton1Click:Connect(function() + if self.Data == {} then + -- TODO: 之后做提示弹窗 + else + self.TopUI:ShowDetailData(self.Data.id) + 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() + for k, v in pairs(self) do + self[k] = nil + end + self = nil +end + +return WearingShow \ No newline at end of file diff --git a/src/StarterPlayerScripts/UI/Windows/RuneWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/RuneWindow/init.luau new file mode 100644 index 0000000..07bd6fa --- /dev/null +++ b/src/StarterPlayerScripts/UI/Windows/RuneWindow/init.luau @@ -0,0 +1,246 @@ +--> Services +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +--> Dependencies +local UIWindow = require(ReplicatedStorage.Base.UIWindow) +local UIEnums = require(ReplicatedStorage.Base.UIEnums) + +--> Components +local WearingShow = require(script.WearingShow) +local PackageShow = require(script.PackageShow) + +--> Dependencies +local Utils = require(ReplicatedStorage.Tools.Utils) +local Localization = require(ReplicatedStorage.Tools.Localization) + +--> Json +local JsonAttributesUpgrade = require(ReplicatedStorage.Json.AttributesUpgrade) +local JsonRune = require(ReplicatedStorage.Json.Rune) + +--> Events +local RE_RuneInlay = ReplicatedStorage.Events.RE_RuneInlay + + +--> Variables +local LocalPlayer = game.Players.LocalPlayer + +-------------------------------------------------------------------------------- + +local ChaWindow = {} +ChaWindow.__index = ChaWindow +setmetatable(ChaWindow, {__index = UIWindow}) + +function ChaWindow:Init(UIManager: table, Data: table?) + local self = UIWindow:Init(UIManager, Data) + setmetatable(self, ChaWindow) + self.Variables = { + ["_goRunePanel"] = 0, + ["_goEquipmentDetail"] = 0, + ["__listRunePackage"] = 0, + ["__listRuneWearing"] = 0, + ["_tmpCombatValue"] = 0, + ["_imgIcon"] = 0, + + ["_bgNowSelectFrame"] = 0, + ["_imgNowRune"] = 0, + ["_tmpNowRuneName"] = 0, + + ["_btnClose"] = 0, + ["_btnBgClose"] = 0, + ["_btnInlay"] = 0, + } + self.UIRootName = "ui_w_rune" + self.UIParentName = UIEnums.UIParent.UIRoot + self.ShowEquipmentId = nil + self.NowSelectRuneId = nil + + return self +end + +function ChaWindow:ShowDetailData(uniqueId: number) + if uniqueId then + self.NowSelectRuneId = uniqueId + local runeData = Utils:GetIdDataFromJson(JsonRune, uniqueId) + self.Variables["_tmpNowRuneName"].Text = Localization:GetLanguageData(runeData.nameId) + self.Variables["_imgNowRune"].Image = Localization:GetImageData(runeData.icon) + self.Variables["_imgNowRune"].BackgroundColor3 = Localization:GetRuneQualityBgColor(runeData.quality) + self.Variables["_imgNowRune"].Transparency = 0 + else + self.NowSelectRuneId = nil + self.Variables["_tmpNowRuneName"].Text = "" + self.Variables["_imgNowRune"].Image = "" + self.Variables["_imgNowRune"].BackgroundColor3 = Color3.fromRGB(0, 0, 0) + self.Variables["_imgNowRune"].Transparency = 1 + end +end + +function ChaWindow:WearRefresh(data: table) + local newSlot = data.instance:GetAttribute("wearing") + self.Variables["__listRuneWearing"]:RemoveData("slot"..newSlot) + self.Variables["__listRunePackage"]:RemoveData(tostring(data.id)) + + -- 更新穿戴数据,要不再点击前端就不好使了 + data.wearing = newSlot + self.Variables["__listRuneWearing"]:AddData("slot"..newSlot, data) + + -- 穿戴后,如果当前穿戴的符文是当前选中的符文,则刷新当前选中的符文为空 + if data.id == self.NowSelectRuneId then self:ShowDetailData() end +end + +function ChaWindow:UnwearRefresh(data: table) + local oldSlot = data.wearing + self.Variables["__listRuneWearing"]:RemoveData("slot"..oldSlot) + data.wearing = 0 + self.Variables["__listRunePackage"]:AddData(tostring(data.id), data) + self.Data.Wearing["slot"..oldSlot] = { + wearing = oldSlot, + } + self.Variables["__listRuneWearing"]:AddData("slot"..oldSlot, self.Data.Wearing["slot"..oldSlot]) +end + +function ChaWindow:InlayRune() + if self.NowSelectRuneId and self.ShowEquipmentId then + RE_RuneInlay:FireClient(self.NowSelectRuneId, self.ShowEquipmentId) + end +end + +function ChaWindow:AddInstanceData(configInstance: Instance, Data: table?) + local data = self.Data + if Data then data = Data end + local attributes = configInstance:GetAttributes() + + -- 归类是否是穿戴的装备 + local parentName, secondName = "PackageRune", configInstance.Name + if attributes.wearing == self.ShowEquipmentId then + parentName = "WearingRune" + secondName = "slot"..attributes.wearingSlot + end + data[parentName][secondName] = {} + + for attributeKey, attributeValue in attributes do + data[parentName][secondName][attributeKey] = attributeValue + end + data[parentName][secondName].instance = configInstance + return data[parentName][secondName], parentName +end + +function ChaWindow:RemoveInstanceData(configInstance: Instance, Data: table?) + for key, data in pairs(self.Data.WearingRune) do + if data.instance == configInstance then + return tostring(key), "WearingRune" + end + end + for key, data in pairs(self.Data.PackageRune) do + if data.instance == configInstance then + return tostring(key), "PackageRune" + end + end + return nil +end + +function ChaWindow:OnOpenWindow() + UIWindow.OnOpenWindow(self) + + -- 自己进行数据处理 + local DataFolder = Utils:WaitPlayerDataFolder(LocalPlayer):FindFirstChild("Rune") + local data = { + WearingRune = {}, + PackageRune = {}, + } + + -- 找到当前穿戴的装备 + local EquipmentFolder = Utils:WaitPlayerDataFolder(LocalPlayer):FindFirstChild("Equipment") + for _, child in EquipmentFolder:GetChildren() do + if child:GetAttribute("wearing") ~= 0 then + self.ShowEquipmentId = child.Name + break + end + end + -- 如果当前没有穿戴的装备,并且没有装备,则报错提示, 并返回内容 + if not self.ShowEquipmentId and #EquipmentFolder:GetChildren() == 0 then + warn("没有找到当前穿戴的装备") + return + end + + -- 如果当前没有穿戴的装备,则默认使用第一个装备 + if not self.ShowEquipmentId then + self.ShowEquipmentId = EquipmentFolder:GetChildren()[1].Name + end + + local equipmentInstance = EquipmentFolder:FindFirstChild(self.ShowEquipmentId) + local maxRuneNumber = equipmentInstance:GetAttribute("maxRuneNumber") + + -- 如果当前最大槽位数为0,刷新至空显示 + if maxRuneNumber <= 0 then + self.Variables["__listRuneWearing"]:SetData({}) + self:ShowDetailData() + return + end + + -- 添加符文数据 + for _, child in DataFolder:GetChildren() do + self:AddInstanceData(child, data) + end + self:SetData(data) + + -- 补充空槽位 + for i = 1, maxRuneNumber do + local isExist = false + for k, data in pairs(self.Data.WearingRune) do + if data.wearingSlot == i then + isExist = true + break + end + end + if not isExist then + self.Data.WearingRune["slot" .. i] = { + wearingSlot = i, + } + end + end + + local addCon = DataFolder.ChildAdded:Connect(function(child) + local data, parentName = self:AddInstanceData(child, data) + if parentName == "WearingRune" then + self.Variables["__listRuneWearing"]:AddData("slot"..data.wearingSlot, data) + else + self.Variables["__listRunePackage"]:AddData(child.Name, data) + end + end) + + local removeCon = DataFolder.ChildRemoved:Connect(function(child) + -- TODO: 这里清除逻辑不清晰,之后优化 + local key, parentName = self:RemoveInstanceData(child, self.Data) + if parentName == "WearingRune" then + local removeIndex = self.Variables["__listRuneWearing"]:RemoveData(key) + else + local removeIndex = self.Variables["__listRunePackage"]:RemoveData(key) + end + end) + + local bgCloseCon = self.Variables["_btnBgClose"].Activated:Connect(function() + self.UIManager:CloseWindow(script.Name) + end) + local closeCon = self.Variables["_btnClose"].Activated:Connect(function() + self.UIManager:CloseWindow(script.Name) + end) + + table.insert(self.Connections, addCon) + table.insert(self.Connections, removeCon) + table.insert(self.Connections, bgCloseCon) + table.insert(self.Connections, closeCon) + + self.Variables["__listRunePackage"]:AddComponent(PackageShow) + self.Variables["__listRuneWearing"]:AddComponent(WearingShow) + self.Variables["__listRunePackage"]:SetData(self.Data.PackageRune) + self.Variables["__listRuneWearing"]:SetData(self.Data.WearingRune) + self.Variables["__listRuneWearing"]:SetLayoutOrder("wearingSlot") +end + +function ChaWindow:OnCloseWindow() + UIWindow.OnCloseWindow(self) +end + + + +return ChaWindow \ No newline at end of file