diff --git a/excel/Rune.xlsx b/excel/Rune.xlsx index 604add4..fad7d5b 100644 Binary files a/excel/Rune.xlsx and b/excel/Rune.xlsx differ 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