From fb53aa4305f1a393eb10baa78ee819c26ddb9590 Mon Sep 17 00:00:00 2001 From: gechangfu Date: Tue, 26 Aug 2025 19:25:08 +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/Rune.xlsx | Bin 14797 -> 14775 bytes .../Modules/Behaviours/Attack.luau | 2 +- .../Modules/Runes/RuneAtkSpeed.luau | 2 + .../Modules/Runes/RuneBookQualityYellow.luau | 21 +++++--- .../Modules/Runes/RuneBossAtk.luau | 6 +-- .../Modules/Runes/RuneBossHp.luau | 6 +-- .../Modules/Runes/RuneHpToAtk.luau | 5 +- .../Modules/Runes/RuneKillEnemyHeal.luau | 7 ++- .../Runes/RuneThunderAddDamageTime.luau | 12 ++++- .../Runes/RuneThunderDoubleDamage.luau | 1 + .../Runes/RuneWearElementAttackSpeed.luau | 2 +- .../Runes/RuneWearExAttributeAttack.luau | 4 +- src/ServerStorage/Proxy/DamageProxy.luau | 3 +- src/ServerStorage/Proxy/MobsProxy/init.luau | 2 +- .../Proxy/PlayerFightProxy/LevelLoop.luau | 2 +- .../ClientMain/Helper.luau | 1 + .../PerformanceClient/HealBoard.luau | 50 ++++++++++++++++++ .../ClientMain/PerformanceClient/init.luau | 7 ++- .../UI/Windows/CreateWindow/WeaponItem.luau | 34 +++++++++++- .../UI/Windows/CreateWindow/init.luau | 9 ++++ .../UI/Windows/RuneStateWindow/init.luau | 28 +++++++--- 21 files changed, 168 insertions(+), 36 deletions(-) create mode 100644 src/StarterPlayerScripts/ClientMain/PerformanceClient/HealBoard.luau diff --git a/excel/Rune.xlsx b/excel/Rune.xlsx index 604add4dc553933a9678dfce85d3a1af2d3e4131..fad7d5ba2994ee61f37beb28824f619beb6d4d32 100644 GIT binary patch delta 8863 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 E0d$hwYybcN delta 8893 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
  • -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 diff --git a/src/ServerStorage/Modules/Behaviours/Attack.luau b/src/ServerStorage/Modules/Behaviours/Attack.luau index 4436bec..b94f286 100644 --- a/src/ServerStorage/Modules/Behaviours/Attack.luau +++ b/src/ServerStorage/Modules/Behaviours/Attack.luau @@ -103,9 +103,9 @@ function Attack:Execute() -- 攻击前摇 task.wait(atkSpeed) - -- 暴击判定走通用属性 local critCheckRate = self:GetAttributeValue("critRate") or 0 + -- critCheckRate = 100 local isCrit = Rng:RandomPercent(critCheckRate) local baseAttack = self.PlayerAI:GetBaseAttack() diff --git a/src/ServerStorage/Modules/Runes/RuneAtkSpeed.luau b/src/ServerStorage/Modules/Runes/RuneAtkSpeed.luau index 6a96caf..c1f01ff 100644 --- a/src/ServerStorage/Modules/Runes/RuneAtkSpeed.luau +++ b/src/ServerStorage/Modules/Runes/RuneAtkSpeed.luau @@ -26,7 +26,9 @@ end function RuneAtkSpeed:OnExecute(index: number, AttributesData: table, BehaviorNameList: table) local baseAttribute = AttributesData.atkSpeed or 1 local addAttribute = baseAttribute - math.floor(baseAttribute * 25) / 100 + print("Before RuneAtkSpeed OnExecute", AttributesData.atkSpeed, addAttribute) Utils:TableSafeSetValue(AttributesData, "atkSpeed", addAttribute) + print("After RuneAtkSpeed OnExecute", AttributesData.atkSpeed, addAttribute) return nil end diff --git a/src/ServerStorage/Modules/Runes/RuneBookQualityYellow.luau b/src/ServerStorage/Modules/Runes/RuneBookQualityYellow.luau index a180cca..039c4e2 100644 --- a/src/ServerStorage/Modules/Runes/RuneBookQualityYellow.luau +++ b/src/ServerStorage/Modules/Runes/RuneBookQualityYellow.luau @@ -21,17 +21,26 @@ end function RuneBookQualityYellow:Check(index: number, AttributesData: table, BehaviorNameList: table) local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData") - if not pDataFolder then return nil end + if not pDataFolder then + return false + end + local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId) - if not pData then return nil end + if not pData then + return false + end local bookFolder = pData:FindFirstChild("Book") - if not bookFolder then return nil end + if not bookFolder then + return false + end + local bookList = bookFolder:GetChildren() - if #bookList == 0 then return nil end + if #bookList == 0 then + return false + end self.Data = bookList - return true end @@ -43,7 +52,7 @@ function RuneBookQualityYellow:OnExecute(index: number, AttributesData: table, B qualityNumber = qualityNumber + 1 end end - local attackRate = math.floor(qualityNumber * 50 / 100) + local attackRate = qualityNumber * 50 Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate) return nil diff --git a/src/ServerStorage/Modules/Runes/RuneBossAtk.luau b/src/ServerStorage/Modules/Runes/RuneBossAtk.luau index 82af640..da294d5 100644 --- a/src/ServerStorage/Modules/Runes/RuneBossAtk.luau +++ b/src/ServerStorage/Modules/Runes/RuneBossAtk.luau @@ -36,14 +36,14 @@ function RuneBossAtk:Check(index: number, AttributesData: table, BehaviorNameLis if not pLevelId then return nil end local LevelData = Utils:GetIdDataFromJson(JsonLevel, pLevelId.Value) + if not LevelData then return nil end if tostring(LevelData.type) ~= "2" then return nil end return true end function RuneBossAtk:OnExecute(index: number, AttributesData: table, BehaviorNameList: table) - local baseAttribute = AttributesData.attackRate or 100 - local addAttribute = math.floor(baseAttribute * 50 / 100) - Utils:TableSafeAddValue(AttributesData, "attackRate", addAttribute) + local attackRate = math.floor((100 + AttributesData.attackRate or 0) * (25 / 100)) + Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate) return nil end diff --git a/src/ServerStorage/Modules/Runes/RuneBossHp.luau b/src/ServerStorage/Modules/Runes/RuneBossHp.luau index a4c646f..0ea9dec 100644 --- a/src/ServerStorage/Modules/Runes/RuneBossHp.luau +++ b/src/ServerStorage/Modules/Runes/RuneBossHp.luau @@ -36,14 +36,14 @@ function RuneBossHp:Check(index: number, AttributesData: table, BehaviorNameList if not pLevelId then return nil end local LevelData = Utils:GetIdDataFromJson(JsonLevel, pLevelId.Value) + if not LevelData then return nil end if tostring(LevelData.type) ~= "2" then return nil end return true end function RuneBossHp:OnExecute(index: number, AttributesData: table, BehaviorNameList: table) - local baseAttribute = AttributesData.hpRate or 100 - local addAttribute = math.floor(baseAttribute * 50 / 100) - Utils:TableSafeAddValue(AttributesData, "hpRate", addAttribute) + local hpRate = math.floor((100 + AttributesData.hpRate or 0) * (25 / 100)) + Utils:TableSafeAddValue(AttributesData, "hpRate", hpRate) return nil end diff --git a/src/ServerStorage/Modules/Runes/RuneHpToAtk.luau b/src/ServerStorage/Modules/Runes/RuneHpToAtk.luau index ca038d4..31f1bd6 100644 --- a/src/ServerStorage/Modules/Runes/RuneHpToAtk.luau +++ b/src/ServerStorage/Modules/Runes/RuneHpToAtk.luau @@ -27,9 +27,8 @@ function RuneHpToAtk:Check(index: number, AttributesData: table, BehaviorNameLis end function RuneHpToAtk:OnExecute(index: number, AttributesData: table, BehaviorNameList: table) - local baseAttribute = AttributesData.atkRate or 100 - local addAttribute = math.floor(baseAttribute * AttributesData.hp * 0.035) - Utils:TableSafeAddValue(AttributesData, "atkRate", addAttribute) + local addAttribute = math.floor(AttributesData.maxhp * 0.035) + Utils:TableSafeAddValue(AttributesData, "attack", addAttribute) return nil end diff --git a/src/ServerStorage/Modules/Runes/RuneKillEnemyHeal.luau b/src/ServerStorage/Modules/Runes/RuneKillEnemyHeal.luau index 7527aee..356ec1a 100644 --- a/src/ServerStorage/Modules/Runes/RuneKillEnemyHeal.luau +++ b/src/ServerStorage/Modules/Runes/RuneKillEnemyHeal.luau @@ -23,17 +23,16 @@ setmetatable(RuneKillEnemyHeal, {__index = Rune}) function RuneKillEnemyHeal:Init(PlayerAI, Character: TypeList.Character) local self = Rune:Init(PlayerAI, Character, script.Name) setmetatable(self, RuneKillEnemyHeal) - self.FirstAttack = true return self end function RuneKillEnemyHeal:OnInitFinish() EventFilter.SubscribeGlobalFilter(EventFilterEnum.BEFORE_KILL_MONSTER, function(eventData) - if self.FirstAttack then - self.FirstAttack = false - DamageProxy:Heal(self.PlayerAI, self.PlayerAI, math.floor(self.Character.Config.maxhp * 0.01)) + if eventData.attacker == self.PlayerAI.Player then + DamageProxy:Heal(self.PlayerAI.Character, self.PlayerAI.Character, math.floor(self.Character.Config.maxhp * 0.01)) end + return eventData end, self.TriggerSlot, self) end diff --git a/src/ServerStorage/Modules/Runes/RuneThunderAddDamageTime.luau b/src/ServerStorage/Modules/Runes/RuneThunderAddDamageTime.luau index 3c07054..229b53d 100644 --- a/src/ServerStorage/Modules/Runes/RuneThunderAddDamageTime.luau +++ b/src/ServerStorage/Modules/Runes/RuneThunderAddDamageTime.luau @@ -26,12 +26,20 @@ end function RuneThunderAddDamageTime:OnInitFinish() EventFilter.SubscribeGlobalFilter(EventFilterEnum.BEFORE_ATTACK, function(eventData) + -- 先收集需要添加的光元素伤害数据 + local newDamageDataList = {} for _, damageData in eventData.damageData do - if damageData.ElementType == DamageProxy.ElementType.LIGHT then + if (damageData.ElementType == DamageProxy.ElementType.LIGHT) and (damageData.Tag == DamageProxy.DamageTag.CRIT) then local newDamageData = Utils:DeepCopyTable(damageData) - table.insert(eventData.damageData, newDamageData) + table.insert(newDamageDataList, newDamageData) end end + + -- 然后一次性添加所有新的伤害数据 + for _, newDamageData in ipairs(newDamageDataList) do + table.insert(eventData.damageData, newDamageData) + end + return eventData end, self.TriggerSlot, self) end diff --git a/src/ServerStorage/Modules/Runes/RuneThunderDoubleDamage.luau b/src/ServerStorage/Modules/Runes/RuneThunderDoubleDamage.luau index 09b6bb8..576d840 100644 --- a/src/ServerStorage/Modules/Runes/RuneThunderDoubleDamage.luau +++ b/src/ServerStorage/Modules/Runes/RuneThunderDoubleDamage.luau @@ -38,6 +38,7 @@ function RuneThunderDoubleDamage:OnInitFinish() table.insert(eventData.damageData, newDamageData) end end + return eventData end, self.TriggerSlot, self) end diff --git a/src/ServerStorage/Modules/Runes/RuneWearElementAttackSpeed.luau b/src/ServerStorage/Modules/Runes/RuneWearElementAttackSpeed.luau index f874079..215eb2c 100644 --- a/src/ServerStorage/Modules/Runes/RuneWearElementAttackSpeed.luau +++ b/src/ServerStorage/Modules/Runes/RuneWearElementAttackSpeed.luau @@ -38,7 +38,7 @@ function RuneWearElementAttackSpeed:OnExecute(index: number, AttributesData: tab for _, equipment in equipmentList do local equipmentWearing = equipment:GetAttribute("wearing") if equipmentWearing > 0 then - elementNumber = elementNumber + #equipment:FindFirstChild("Element"):GetAttributes() + elementNumber = elementNumber + Utils:GetTableLength(equipment:FindFirstChild("elements"):GetAttributes()) end end diff --git a/src/ServerStorage/Modules/Runes/RuneWearExAttributeAttack.luau b/src/ServerStorage/Modules/Runes/RuneWearExAttributeAttack.luau index b3e249c..51f3bf2 100644 --- a/src/ServerStorage/Modules/Runes/RuneWearExAttributeAttack.luau +++ b/src/ServerStorage/Modules/Runes/RuneWearExAttributeAttack.luau @@ -38,11 +38,11 @@ function RuneWearExAttributeAttack:OnExecute(index: number, AttributesData: tabl for _, equipment in equipmentList do local equipmentWearing = equipment:GetAttribute("wearing") if equipmentWearing > 0 then - elementNumber = elementNumber + #equipment:FindFirstChild("exAttributes"):GetAttributes() + elementNumber = elementNumber + Utils:GetTableLength(equipment:FindFirstChild("exAttributes"):GetAttributes()) end end - local attackRate = math.floor((AttributesData.attackRate or 100) * elementNumber * 25 / 100) + local attackRate = math.floor((100 + AttributesData.attackRate or 0) * (elementNumber * 25 / 100)) Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate) return nil diff --git a/src/ServerStorage/Proxy/DamageProxy.luau b/src/ServerStorage/Proxy/DamageProxy.luau index e286e3c..d4b9429 100644 --- a/src/ServerStorage/Proxy/DamageProxy.luau +++ b/src/ServerStorage/Proxy/DamageProxy.luau @@ -306,11 +306,12 @@ function DamageProxy:Heal(Caster: TypeList.Character, Victim: TypeList.Character -- 治疗计算 local VictimHealth = Victim:GetAttributeValue("hp") or 0 - local MaxHealth = Victim:GetAttributeValue("maxHp") or 0 + local MaxHealth = Victim:GetAttributeValue("maxhp") or 0 -- 计算实际治疗量(不超过最大生命值) local actualHeal = math.min(Amount, MaxHealth - VictimHealth) local overheal = math.max(0, Amount - actualHeal) + print("actualHeal", actualHeal, overheal, Amount) -- 发送攻击前事件 diff --git a/src/ServerStorage/Proxy/MobsProxy/init.luau b/src/ServerStorage/Proxy/MobsProxy/init.luau index 91baf10..2da27f9 100644 --- a/src/ServerStorage/Proxy/MobsProxy/init.luau +++ b/src/ServerStorage/Proxy/MobsProxy/init.luau @@ -89,9 +89,9 @@ end -- isChallengeFailed 挑战失败清除怪物传参 function Mob:Died(isChallengeFailed: boolean?) MobsProxy:RemoveMob(self.Player, self.Instance) + if not isChallengeFailed then if self.OnDied then self.OnDied(self.Player, self) end - else -- 发送怪物死亡事件 EventFilter.FireGlobalWithFilter(EventFilterEnum.BEFORE_KILL_MONSTER, { attacker = self.Player, diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau index 98b466a..0640482 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau @@ -70,7 +70,6 @@ function LevelLoop:AutoChallenge(ignoreBoss: boolean?) if not self.IsAutoChallenge then return end print("AutoChallenge") - self.PlayerRole:Respawn() LevelProxy:TeleportToLevel(self.Player) -- TODO: 回退有bug,不能一关一关回退 @@ -88,6 +87,7 @@ function LevelLoop:AutoChallenge(ignoreBoss: boolean?) end LevelProxy:ChallengeLevel(self.Player, LevelId) + self.PlayerRole:Respawn() end function LevelLoop:OnChallengeEnd(Player: Player, LevelId: number, result: boolean) diff --git a/src/StarterPlayerScripts/ClientMain/Helper.luau b/src/StarterPlayerScripts/ClientMain/Helper.luau index 82ca310..a13b4fc 100644 --- a/src/StarterPlayerScripts/ClientMain/Helper.luau +++ b/src/StarterPlayerScripts/ClientMain/Helper.luau @@ -28,6 +28,7 @@ UserInputService.InputBegan:Connect(function(input, gameProcessed) -- RE_PlayerHelper:FireServer("AddItem", {60000, 1}) -- RE_PlayerHelper:FireServer("AddItem", {61000, 1}) -- RE_PlayerHelper:FireServer("AddItem", {62000, 1}) + RE_PlayerHelper:FireServer("AddItem", {60023, 1}) elseif input.KeyCode == Enum.KeyCode.L then -- RE_UpgradeAttributes:FireServer(2) for k, v in JsonRune do diff --git a/src/StarterPlayerScripts/ClientMain/PerformanceClient/HealBoard.luau b/src/StarterPlayerScripts/ClientMain/PerformanceClient/HealBoard.luau new file mode 100644 index 0000000..43c739e --- /dev/null +++ b/src/StarterPlayerScripts/ClientMain/PerformanceClient/HealBoard.luau @@ -0,0 +1,50 @@ +local HealBoard = {} + +--> Services +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +--> Variables +local FolderHealBoard = ReplicatedStorage.UI.HealBoard + +-- 治疗颜色定义 +local heal_color = { + ["Normal"] = Color3.fromRGB(0, 255, 0), -- 绿色表示正常治疗 +} + +local LocalPlayer = game.Players.LocalPlayer + +local Boards = {} +for _, data in FolderHealBoard:GetChildren() do + Boards[data.Name] = data +end + + +function HealBoard:GetBoard(Name: string) + return Boards[Name] +end + +function HealBoard:CreateHealBoard(HealDetail: table) + local HealInitPos = HealDetail.HealPosition + local BiasPos = Vector3.new(0, 6, 0) + local MultPos = Vector3.new(0, 1, 0) + + local index = 0 + local BoardInstance = Boards["Board1"]:Clone() + local BoardCanvas = BoardInstance:FindFirstChild("BillboardGui"):FindFirstChild("Canvas") + local HealInstance = BoardCanvas:FindFirstChild("Damage") -- 假设UI结构相同,使用Damage作为基础 + + -- 创建治疗量显示 + local MainHealInstance = HealInstance:Clone() + MainHealInstance.Text = "+" .. tostring(HealDetail.HealAmount) + MainHealInstance.TextColor3 = heal_color["Normal"] + MainHealInstance.Visible = true + MainHealInstance.Parent = BoardCanvas + MainHealInstance.LayoutOrder = 10 - index + + BoardInstance.Position = HealInitPos + BiasPos + MultPos * index + BoardInstance.Parent = game.Workspace + game.Debris:AddItem(BoardInstance, 1) +end + + +return HealBoard \ No newline at end of file diff --git a/src/StarterPlayerScripts/ClientMain/PerformanceClient/init.luau b/src/StarterPlayerScripts/ClientMain/PerformanceClient/init.luau index cf5c3a7..e7aedbd 100644 --- a/src/StarterPlayerScripts/ClientMain/PerformanceClient/init.luau +++ b/src/StarterPlayerScripts/ClientMain/PerformanceClient/init.luau @@ -21,6 +21,7 @@ local Signal = require(ReplicatedStorage.Tools.Signal) --> Variables local LocalPlayer = game.Players.LocalPlayer local DamageBoard = require(script.DamageBoard) +local HealBoard = require(script.HealBoard) local showAbilitySignal = Signal.new(Signal.ENUM.SHOW_ABILITY) -------------------------------------------------------------------------------- @@ -88,7 +89,11 @@ end) -- 监听伤害表现事件调用 RE_DamagePerformance.OnClientEvent:Connect(function(ServerTime: number, CastTag: string, CastPlayer: Player, DamageDetail: table) -- print("DamagePerformance", ServerTime, CastTag, CastPlayer, DamageDetail) - DamageBoard:CreateNormalDamageBoard(DamageDetail) + if CastTag == "Heal" then + HealBoard:CreateHealBoard(DamageDetail) + else + DamageBoard:CreateNormalDamageBoard(DamageDetail) + end end) -- 这里主要是初始化 diff --git a/src/StarterPlayerScripts/UI/Windows/CreateWindow/WeaponItem.luau b/src/StarterPlayerScripts/UI/Windows/CreateWindow/WeaponItem.luau index 24e0933..e9c384d 100644 --- a/src/StarterPlayerScripts/UI/Windows/CreateWindow/WeaponItem.luau +++ b/src/StarterPlayerScripts/UI/Windows/CreateWindow/WeaponItem.luau @@ -44,9 +44,22 @@ function WeaponItem:Refresh() self.Variables._tmpName.Text = Localization:GetLanguageData(itemData.nameId) self.Variables._tmpQuality.Text = Localization:GetColoredEquipmentQualityDesc(self.Data.Quality) + -- 清理旧的模型展示 + if self.Prefab then + self.Prefab:Destroy() + self.Prefab = nil + end + + -- 清理旧的相机 + if self.ViewportCamera then + self.ViewportCamera:Destroy() + self.ViewportCamera = nil + end + -- 模型展示 - local taskRotation, part = EquipmentModelDetail:ShowDetail(self.Variables["_imgView"], self.Data.OrgId, false) + local taskRotation, part, viewportCamera = EquipmentModelDetail:ShowDetail(self.Variables["_imgView"], self.Data.OrgId, false) self.Prefab = part + self.ViewportCamera = viewportCamera -- 如果图鉴没有,就设置成黑色的 if self.Data.Timestamp == 0 then @@ -69,6 +82,25 @@ function WeaponItem:OnInitFinish() end function WeaponItem:Destroy() + -- 清理模型展示 + if self.Prefab then + self.Prefab:Destroy() + self.Prefab = nil + end + + -- 清理相机 + if self.ViewportCamera then + self.ViewportCamera:Destroy() + self.ViewportCamera = nil + end + + -- 清理连接 + for _, connection in ipairs(self.Connections) do + if connection then + connection:Disconnect() + end + end + for k, v in pairs(self) do self[k] = nil end diff --git a/src/StarterPlayerScripts/UI/Windows/CreateWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/CreateWindow/init.luau index 5ec7f59..acf2572 100644 --- a/src/StarterPlayerScripts/UI/Windows/CreateWindow/init.luau +++ b/src/StarterPlayerScripts/UI/Windows/CreateWindow/init.luau @@ -99,6 +99,15 @@ end function CreateWindow:ShowDetailInfo(data: table?) if data then + if self.OldPrefab then + self.OldPrefab:Destroy() + self.OldPrefab = nil + end + if self.OldViewportCamera then + self.OldViewportCamera:Destroy() + self.OldViewportCamera = nil + end + self.Variables["_imgIcon"].Image = Localization:GetImageData(Utils:GetIdDataFromJson(JsonItemProp, data.OrgId).iconId) self.Variables["_tmpName"].Text = Localization:GetLanguageData(Utils:GetIdDataFromJson(JsonItemProp, data.OrgId).nameId) self.Variables["_tmpQuality"].Text = Localization:GetColoredEquipmentQualityDesc(data.Quality) diff --git a/src/StarterPlayerScripts/UI/Windows/RuneStateWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/RuneStateWindow/init.luau index 6674af9..d2711c5 100644 --- a/src/StarterPlayerScripts/UI/Windows/RuneStateWindow/init.luau +++ b/src/StarterPlayerScripts/UI/Windows/RuneStateWindow/init.luau @@ -486,6 +486,7 @@ function RuneStateWindow:CreateAttributeChangeDisplay(runeUI: Instance, record: table.insert(attributeChanges, { name = attributeName, + originalName = attrName, -- 保存原始属性名 change = change, isPercent = attributeData and attributeData.type == 2 }) @@ -546,14 +547,29 @@ function RuneStateWindow:CreateAttributeChangeContainer(runeUI: Instance, attrib changeText.Size = UDim2.new(1, -10, 0, 20) changeText.Position = UDim2.new(0, 5, 0, 5 + (i-1) * 30) - -- 格式化显示文本 - local displayValue = change.isCombatValue and FormatNumber(change.change, "Suffix") or tostring(change.change) - if change.isPercent then - displayValue = displayValue .. "%" + -- 特殊处理攻击速度:负值表示攻击更快(正向),正值表示攻击更慢(负向) + local isPositive, sign + if change.originalName == "atkSpeed" then + isPositive = change.change < 0 -- 负值表示正向 + sign = change.change < 0 and "+" or "-" + else + isPositive = change.change > 0 -- 其他属性正常处理 + sign = change.change > 0 and "+" or "-" end - 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) + -- 格式化显示文本 + local displayValue + if change.isCombatValue then + displayValue = FormatNumber(math.abs(change.change), "Suffix") + else + displayValue = tostring(math.abs(change.change)) + if change.isPercent then + displayValue = displayValue .. "%" + end + end + + changeText.Text = string.format("%s %s%s", change.name, sign, displayValue) + changeText.TextColor3 = isPositive and Color3.fromRGB(0, 255, 100) or Color3.fromRGB(255, 100, 100) changeText.TextScaled = true changeText.Font = Enum.Font.SourceSansBold changeText.BackgroundTransparency = 1