diff --git a/src/StarterPlayerScripts/ClientMain/TestRuneStateWindow.luau b/src/StarterPlayerScripts/ClientMain/TestRuneStateWindow.luau deleted file mode 100644 index ca20a23..0000000 --- a/src/StarterPlayerScripts/ClientMain/TestRuneStateWindow.luau +++ /dev/null @@ -1,70 +0,0 @@ ---> Services -local Players = game:GetService("Players") -local UserInputService = game:GetService("UserInputService") - ---> Dependencies -local UIManager = require(script.Parent.Parent.UI.UIManager) - --------------------------------------------------------------------------------- - -local LocalPlayer = Players.LocalPlayer - --- 测试执行记录 -local testExecutionRecords = { - { - runeName = "RuneFireDamage", - runeUniqueId = 1, - index = 1, - timestamp = tick(), - action = "Execute", - attributesBefore = {attack = 100, hp = 1000, atkSpeed = 100}, - attributesAfter = {attack = 150, hp = 1000, atkSpeed = 120}, - behaviorListBefore = {"Attack"}, - behaviorListAfter = {"Attack", "FireDamage"}, - nextIndex = 2 - }, - { - runeName = "RuneIceCoffin", - runeUniqueId = 2, - index = 2, - timestamp = tick(), - action = "Execute", - attributesBefore = {attack = 150, hp = 1000, atkSpeed = 120}, - attributesAfter = {attack = 150, hp = 1200, atkSpeed = 120, fireAtk = 50}, - behaviorListBefore = {"Attack", "FireDamage"}, - behaviorListAfter = {"Attack", "FireDamage", "IceCoffin"}, - nextIndex = nil - } -} - --- 键盘输入测试 -UserInputService.InputBegan:Connect(function(input, gameProcessed) - if gameProcessed then return end - - if input.KeyCode == Enum.KeyCode.R then - -- 打开符文状态窗口 - print("打开符文状态窗口") - UIManager:OpenWindow("RuneStateWindow") - - elseif input.KeyCode == Enum.KeyCode.T then - -- 模拟接收符文执行记录 - print("模拟符文执行记录") - local runeStateWindow = UIManager:GetWindow("RuneStateWindow") - if runeStateWindow then - runeStateWindow:OnRuneExecutionRecord(testExecutionRecords) - end - - elseif input.KeyCode == Enum.KeyCode.C then - -- 关闭符文状态窗口 - print("关闭符文状态窗口") - UIManager:CloseWindow("RuneStateWindow") - end -end) - -print("符文状态窗口测试脚本已启动") -print("按 R 键打开符文状态窗口") -print("按 T 键模拟符文执行记录") -print("按 C 键关闭符文状态窗口") - --- 返回一个空表作为模块返回值 -return {} diff --git a/src/StarterPlayerScripts/UI/Windows/AbilityStateWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/AbilityStateWindow/init.luau index d97908e..60ce165 100644 --- a/src/StarterPlayerScripts/UI/Windows/AbilityStateWindow/init.luau +++ b/src/StarterPlayerScripts/UI/Windows/AbilityStateWindow/init.luau @@ -21,7 +21,7 @@ function AbilityStateWindows:Init(UIManager: table, Data: table?) ["__listAbility"] = 0, ["__listWearAbility"] = 0, } - self.UIRootName = "ui_w_abilityState" + self.UIRootName = "ui_w_ability_state" self.UIParentName = UIEnums.UIParent.UIRoot diff --git a/src/StarterPlayerScripts/UI/Windows/RuneStateWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/RuneStateWindow/init.luau index bf62aae..9e29ffc 100644 --- a/src/StarterPlayerScripts/UI/Windows/RuneStateWindow/init.luau +++ b/src/StarterPlayerScripts/UI/Windows/RuneStateWindow/init.luau @@ -6,6 +6,7 @@ local UIWindow = require(ReplicatedStorage.Base.UIWindow) local UIEnums = require(ReplicatedStorage.Base.UIEnums) local Localization = require(ReplicatedStorage.Tools.Localization) local Utils = require(ReplicatedStorage.Tools.Utils) +local FormatNumber = require(ReplicatedStorage.Modules.FormatNumber) --> Json local JsonAttributes = require(ReplicatedStorage.Json.Attributes) @@ -24,6 +25,8 @@ function RuneStateWindow:Init(UIManager: table, Data: table?) setmetatable(self, RuneStateWindow) self.Variables = { ["__listRune"] = 0, + ["_tmpCombatValue"] = 0, + ["_goCombatValue"] = 0, } self.UIRootName = "ui_w_rune_state" self.UIParentName = UIEnums.UIParent.UIRoot @@ -38,6 +41,175 @@ function RuneStateWindow:Init(UIManager: table, Data: table?) return self end +-- 计算战力值 +function RuneStateWindow:CalculateCombatValue(attributes: table): number + if not attributes then return 0 end + + local totalCombatValue = 0 + + for attrName, attrValue in pairs(attributes) do + -- 通过effectAttribute查找对应的属性配置 + local attributeData = Utils:GetSpecialKeyDataFromJson(JsonAttributes, "effectAttribute", attrName) + if attributeData and attributeData.battleValue then + totalCombatValue = math.floor(totalCombatValue + (attrValue / attributeData.battleValue[1]) * attributeData.battleValue[2]) + end + end + + return math.floor(totalCombatValue) +end + +-- 获取当前玩家属性 +function RuneStateWindow:GetCurrentPlayerAttributes(attributesBefore: table?): table + local Players = game:GetService("Players") + local LocalPlayer = Players.LocalPlayer + + -- 获取玩家数据文件夹 + local PlayerDataFolder = ReplicatedStorage:WaitForChild("PlayerData") + local PlayerFolder = PlayerDataFolder:FindFirstChild(LocalPlayer.UserId) + if not PlayerFolder then + return attributesBefore or {} + end + + local attributes = {} + + -- 获取装备属性 + local EquipmentFolder = PlayerFolder:FindFirstChild("Equipment") + if EquipmentFolder then + for _, equipmentInstance in pairs(EquipmentFolder:GetChildren()) do + local wearing = equipmentInstance:GetAttribute("wearing") + if wearing and tonumber(wearing) > 0 then + -- 基础属性 + local baseAttributes = equipmentInstance:GetAttribute("attributes") + if baseAttributes and typeof(baseAttributes) == "table" then + for attrName, attrValue in pairs(baseAttributes) do + attributes[attrName] = (attributes[attrName] or 0) + attrValue + end + end + + -- 额外属性 + local exAttributes = equipmentInstance:GetAttribute("exAttributes") + if exAttributes then + for attrName, attrValue in pairs(exAttributes) do + attributes[attrName] = (attributes[attrName] or 0) + attrValue + end + end + + -- 元素属性 + local elements = equipmentInstance:GetAttribute("elements") + if elements then + for attrName, attrValue in pairs(elements) do + attributes[attrName] = (attributes[attrName] or 0) + attrValue + end + end + + -- 元素抗性 + local elementDef = equipmentInstance:GetAttribute("elementDef") + if elementDef then + for attrName, attrValue in pairs(elementDef) do + attributes[attrName] = (attributes[attrName] or 0) + attrValue + end + end + end + end + end + + -- 获取符文属性 + local RuneFolder = PlayerFolder:FindFirstChild("Rune") + if RuneFolder then + for _, runeInstance in pairs(RuneFolder:GetChildren()) do + local wearing = runeInstance:GetAttribute("wearing") + if wearing and tonumber(wearing) > 0 then + -- 符文属性(这里需要根据符文的具体实现来获取) + -- 暂时跳过符文属性计算 + end + end + end + + -- 获取角色基础属性(从角色配置中获取) + local CharacterFolder = PlayerFolder:FindFirstChild("Character") + if CharacterFolder then + local characterId = CharacterFolder:GetAttribute("characterId") + if characterId then + local JsonCharacter = require(ReplicatedStorage.Json.Character) + local characterData = Utils:GetIdDataFromJson(JsonCharacter, characterId) + if characterData then + for attrName, attrValue in pairs(characterData) do + if type(attrValue) == "number" and attrName ~= "id" and attrName ~= "name" then + attributes[attrName] = (attributes[attrName] or 0) + attrValue + end + end + end + end + end + + -- 如果属性为空,使用传入的attributesBefore作为默认值 + if next(attributes) == nil then + if attributesBefore then + for attrName, attrValue in pairs(attributesBefore) do + attributes[attrName] = attrValue + end + else + -- 如果没有传入attributesBefore,使用硬编码的测试属性 + attributes.attack = 100 + attributes.hp = 1000 + end + end + + return attributes +end + +-- 播放战力值滚动动画 +function RuneStateWindow:PlayCombatValueAnimation(beforeValue: number, afterValue: number) + if beforeValue == afterValue then return end + + local combatValueUI = self.Variables["_goCombatValue"] + local tmpCombatValueUI = self.Variables["_tmpCombatValue"] + + if not combatValueUI or not tmpCombatValueUI then + return + end + + -- 显示动画战力值组件 + combatValueUI.Visible = true + + local duration = 1.0 -- 动画持续时间 + local steps = 30 -- 动画步数 + local stepDuration = duration / steps + local valueDiff = afterValue - beforeValue + local valueStep = valueDiff / steps + + local currentValue = beforeValue + + -- 创建动画协程 + task.spawn(function() + for i = 1, steps do + currentValue = currentValue + valueStep + tmpCombatValueUI.Text = FormatNumber(math.floor(currentValue), "Suffix") + task.wait(stepDuration) + end + + -- 确保最终值正确 + tmpCombatValueUI.Text = FormatNumber(afterValue, "Suffix") + + -- 动画播放完成后隐藏组件 + task.wait(0.5) -- 等待0.5秒让玩家看到最终值 + combatValueUI.Visible = false + end) +end + +-- 更新战力值显示 +function RuneStateWindow:UpdateCombatValueDisplay(attributesBefore: table?) + -- local currentAttributes = self:GetCurrentPlayerAttributes(attributesBefore) + local currentCombatValue = self:CalculateCombatValue(attributesBefore) + + local combatValueUI = self.Variables["_tmpCombatValue"] + if combatValueUI then + combatValueUI.Text = FormatNumber(currentCombatValue, "Suffix") + end + + return currentCombatValue +end + function RuneStateWindow:OnOpenWindow() UIWindow.OnOpenWindow(self) @@ -48,6 +220,11 @@ function RuneStateWindow:OnOpenWindow() -- 初始化符文列表 self:RefreshRuneList() + + -- 更新战力值显示 + self:UpdateCombatValueDisplay() + + end function RuneStateWindow:OnCloseWindow() @@ -57,6 +234,11 @@ function RuneStateWindow:OnCloseWindow() -- 断开符文执行记录事件连接 self:DisconnectRuneExecutionEvent() + + -- 隐藏动画战力值组件 + if self.Variables["_goCombatValue"] then + self.Variables["_goCombatValue"].Visible = false + end end -- 刷新符文列表 @@ -144,6 +326,9 @@ function RuneStateWindow:OnRuneExecutionRecord(executionRecords: table) if not self.isPlayingAnimation then self:PlayRuneAnimation() end + + -- 更新战力值显示 + self:UpdateCombatValueDisplay() end -- 播放符文动画 @@ -155,6 +340,7 @@ function RuneStateWindow:PlayRuneAnimation() self.isPlayingAnimation = true local record = table.remove(self.runeExecutionQueue, 1) + -- 播放小丑牌动画 self:PlayJokerCardAnimation(record) end @@ -171,8 +357,18 @@ function RuneStateWindow:PlayJokerCardAnimation(record: table) return end + -- 计算战力值变化 + local beforeCombatValue = self:UpdateCombatValueDisplay(record.attributesBefore) + -- 创建动画效果 self:CreateJokerCardEffect(runeItem, record) + + -- 等待动画播放一段时间后计算新的战力值 + task.wait(0.3) + local afterCombatValue = self:UpdateCombatValueDisplay(record.attributesAfter) + + -- 播放战力值滚动动画 + self:PlayCombatValueAnimation(beforeCombatValue, afterCombatValue) end -- 查找符文UI元素(通过名称和唯一ID) @@ -198,15 +394,16 @@ function RuneStateWindow:FindRuneItemByName(runeName: string) -- 在符文列表中查找对应的符文 local runeList = self.Variables["__listRune"] - if runeList and runeList.Instances then - for _, component in pairs(runeList.Instances) do - if component.Data then - if component.Data.runeName == runeName then - return component - end - end + if not runeList or not runeList.Instances then + return nil + end + + for _, component in pairs(runeList.Instances) do + if component.Data and component.Data.runeName == runeName then + return component end end + return nil end @@ -294,6 +491,19 @@ function RuneStateWindow:CreateAttributeChangeDisplay(runeUI: Instance, record: end end + -- 计算战力值变化并添加到显示中 + local beforeCombatValue = self:CalculateCombatValue(record.attributesBefore or {}) + local afterCombatValue = self:CalculateCombatValue(record.attributesAfter or {}) + local combatValueChange = afterCombatValue - beforeCombatValue + + if combatValueChange ~= 0 then + table.insert(attributeChanges, { + name = "战力值", + change = combatValueChange, + isCombatValue = true + }) + end + -- 如果没有属性变化,直接返回 if #attributeChanges == 0 then return @@ -306,7 +516,7 @@ end -- 创建属性变化容器 function RuneStateWindow:CreateAttributeChangeContainer(runeUI: Instance, attributeChanges: table) -- 计算容器高度 - local containerHeight = #attributeChanges * 25 + 10 + local containerHeight = #attributeChanges * 30 + 10 -- 创建属性变化显示容器 local changeContainer = Instance.new("Frame") @@ -332,13 +542,23 @@ function RuneStateWindow:CreateAttributeChangeContainer(runeUI: Instance, attrib for i, change in ipairs(attributeChanges) do local changeText = Instance.new("TextLabel") changeText.Size = UDim2.new(1, -10, 0, 20) - changeText.Position = UDim2.new(0, 5, 0, 5 + (i-1) * 25) - changeText.Text = string.format("%s +%d", change.name, change.change) + changeText.Position = UDim2.new(0, 5, 0, 5 + (i-1) * 30) + + -- 格式化显示文本 + local displayValue = change.isCombatValue and FormatNumber(change.change, "Suffix") or tostring(change.change) + changeText.Text = string.format("%s %s%s", change.name, change.change > 0 and "+" or "", displayValue) + changeText.TextColor3 = change.change > 0 and Color3.fromRGB(0, 255, 100) or Color3.fromRGB(255, 100, 100) changeText.TextScaled = true changeText.Font = Enum.Font.SourceSansBold changeText.BackgroundTransparency = 1 changeText.Parent = changeContainer + + -- 如果是战力值,使用特殊颜色 + if change.isCombatValue then + changeText.TextColor3 = Color3.fromRGB(255, 215, 0) -- 金色 + changeText.Font = Enum.Font.SourceSansBold + end end -- 创建向上移动动画 @@ -395,3 +615,4 @@ function RuneStateWindow:Destroy() end return RuneStateWindow +