From 924b1dccad8eccc3d4ee72566e760a322f5094c8 Mon Sep 17 00:00:00 2001 From: gechangfu Date: Thu, 14 Aug 2025 17:01:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0-=E4=B8=BB=E8=A6=81=E7=AC=A6?= =?UTF-8?q?=E6=96=87=E5=90=8E=E7=AB=AF=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- excel/Rune.xlsx | Bin 10598 -> 10670 bytes excel/attribute.xlsx | Bin 13405 -> 13405 bytes src/ReplicatedStorage/Tools/ScriptModule.luau | 31 ++++ src/ServerStorage/Base/Rune.luau | 108 +++++++++++++ .../Modules/Behaviours/IceCoffine.luau | 71 +++++++++ .../Modules/Runes/RuneFireDamage.luau | 31 ++++ .../Modules/Runes/RuneIceCoffin.luau | 36 +++++ src/ServerStorage/Proxy/DamageProxy.luau | 60 +++++++ .../Proxy/PlayerFightProxy/PlayerAI.luau | 147 ++++++++++++++++-- .../Proxy/PlayerFightProxy/init.luau | 10 +- .../Proxy/RuneProxy/RuneCalculation.luau | 79 ++++++++++ .../{RuneProxy.luau => RuneProxy/init.luau} | 17 +- 12 files changed, 569 insertions(+), 21 deletions(-) create mode 100644 src/ReplicatedStorage/Tools/ScriptModule.luau create mode 100644 src/ServerStorage/Base/Rune.luau create mode 100644 src/ServerStorage/Modules/Behaviours/IceCoffine.luau create mode 100644 src/ServerStorage/Modules/Runes/RuneFireDamage.luau create mode 100644 src/ServerStorage/Modules/Runes/RuneIceCoffin.luau create mode 100644 src/ServerStorage/Proxy/RuneProxy/RuneCalculation.luau rename src/ServerStorage/Proxy/{RuneProxy.luau => RuneProxy/init.luau} (94%) diff --git a/excel/Rune.xlsx b/excel/Rune.xlsx index d48bb19421f7438044f93ee2f1454c71d73caedb..73fe2004fc5cc4821d3cb0b186b322a4341251dc 100644 GIT binary patch delta 5026 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 diff --git a/excel/attribute.xlsx b/excel/attribute.xlsx index 16f4933252c2b4922e99d3991cc530c47d77ae0e..1c5e8f95a9e91b7ca5d311923647109a81ecf83d 100644 GIT binary patch delta 1829 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 Services +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local ServerStorage = game:GetService("ServerStorage") + +--> Dependencies +local TypeList = require(ServerStorage.Base.TypeList) +local Communicate = require(ServerStorage.Modules.Tools.Communicate) +local Utils = require(ReplicatedStorage.Tools.Utils) + + + +function Rune:Init(PlayerAI: Player, Character: TypeList.Character, ScriptName: string) + local self = {} + setmetatable(self, Rune) + self.PlayerAI = PlayerAI + self.Character = Character + self.ScriptName = ScriptName + self.TriggerSlot = 0 + self.WearingSlot = 0 + self.TriggerTime = 0 +end + +-- 触发最开始事件 +function Rune:OnStartEvent(runeName: string, triggerSlot: number, AttributesData: table?, BehaviorNameList: table?) + -- runeName: 符文名称 + -- triggerSlot: 触发槽位 + -- AttributesData: 属性数据,符文可以修改 + -- BehaviorNameList: 行为名称列表,符文可以修改 + -- 返回值: 可以返回下一个index来控制流程,或者nil表示不干预 +end + +-- 卡牌触发前事件 +function Rune:OnTriggerBeginEvent(index: number, AttributesData: table?, BehaviorNameList: table?) + -- index: 当前符文在列表中的位置 + -- AttributesData: 属性数据,符文可以修改 + -- BehaviorNameList: 行为名称列表,符文可以修改 + -- 返回值: 可以返回下一个index来控制流程,或者nil表示不干预 +end + +-- 卡牌触发后事件 +function Rune:OnTriggerEndEvent(index: number, AttributesData: table?, BehaviorNameList: table?) + -- index: 当前符文在列表中的位置 + -- AttributesData: 属性数据,符文可以修改 + -- BehaviorNameList: 行为名称列表,符文可以修改 + -- 返回值: 可以返回下一个index来控制流程,或者nil表示不干预 +end + +-- 触发结束事件 +function Rune:OnEndEvent(runeName: string, triggerSlot: number, AttributesData: table?, BehaviorNameList: table?) + -- runeName: 符文名称 + -- triggerSlot: 触发槽位 + -- AttributesData: 属性数据,符文可以修改 + -- BehaviorNameList: 行为名称列表,符文可以修改 + -- 返回值: 可以返回下一个index来控制流程,或者nil表示不干预 +end + +-- 检查事件 +function Rune:Check(index: number, AttributesData: table?, BehaviorNameList: table?) + -- index: 当前符文在列表中的位置 + -- AttributesData: 属性数据,符文可以修改 + -- BehaviorNameList: 行为名称列表,符文可以修改 + return false -- 默认返回false,表示不可以执行 +end + +-- 执行事件 +function Rune:Execute(index: number, AttributesData: table?, BehaviorNameList: table?) + -- 使用PlayerAI的专用方法,性能更好 + local beginNextIndex = self.PlayerAI:TriggerAllRunesExcept(self, "OnTriggerBeginEvent", index, AttributesData, BehaviorNameList) + if type(beginNextIndex) == "number" then + return beginNextIndex + end + + -- 执行自己的逻辑 + local nextIndex = self:OnExecute(index, AttributesData, BehaviorNameList) + if type(nextIndex) == "number" then + self.PlayerAI:TriggerAllRunesExcept(self, "OnTriggerEndEvent", index, AttributesData, BehaviorNameList) + return nextIndex + end + + local endNextIndex = self.PlayerAI:TriggerAllRunesExcept(self, "OnTriggerEndEvent", index, AttributesData, BehaviorNameList) + if type(endNextIndex) == "number" then + return endNextIndex + end + self.TriggerTime = self.TriggerTime + 1 + return nextIndex -- 返回下一个要执行的index +end + +-- 子类可以重写这个方法 +function Rune:OnExecute(index: number, AttributesData: table?, BehaviorNameList: table?) + -- 默认实现,子类可以重写 + -- index: 当前符文在列表中的位置 + -- AttributesData: 属性数据,符文可以修改 + -- BehaviorNameList: 行为名称列表,符文可以修改 + -- 返回值: 下一个要执行的index,或者nil表示继续下一个 + return nil -- 默认继续下一个符文 +end + +-- 销毁 +function Rune:OnDestroy() + self = nil +end + + + +return Rune \ No newline at end of file diff --git a/src/ServerStorage/Modules/Behaviours/IceCoffine.luau b/src/ServerStorage/Modules/Behaviours/IceCoffine.luau new file mode 100644 index 0000000..d3911c3 --- /dev/null +++ b/src/ServerStorage/Modules/Behaviours/IceCoffine.luau @@ -0,0 +1,71 @@ +-- 冰棺技能:残血后立即回血 + +--> Services +local ServerStorage = game:GetService("ServerStorage") +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +--> Dependencies +local TypeList = require(ServerStorage.Base.TypeList) +local Behaviour = require(ServerStorage.Base.Behaviour) +local MobsProxy = require(ServerStorage.Proxy.MobsProxy) +local DamageProxy = require(ServerStorage.Proxy.DamageProxy) +local Utils = require(ReplicatedStorage.Tools.Utils) + +-------------------------------------------------------------------------------- + +local IceCoffine = {} +IceCoffine.__index = IceCoffine +setmetatable(IceCoffine, {__index = Behaviour}) + +local CAST_DISTANCE = 50 +local PROJECTILE_LENGTH = 50 +local PROJECTILE_DURATION = 3 +local COOLDOWN = 1000 + +function IceCoffine:Init(PlayerAI, Character: TypeList.Character, Player: Player) + local self = Behaviour:Init(PlayerAI, Character, script.Name) + self.Player = Player + self.Mobs = nil + setmetatable(self, IceCoffine) + self.OrgCooldown = COOLDOWN + self:StartCooldownTask() + + -- 客户端表现 + self:SendPerformanceEvent("Init", self.Player, script.Name, true, {}) + return self +end + +function IceCoffine:Check(CheckInfo: table) + if Behaviour.CheckStat(self) then return -1, self.CheckData end + self:CheckClean() + + -- 当前血量<=20%时触发技能 + local maxHp = self.Character.Stats.MaxHp + local currentHp = self.Character.Stats.Hp + local recoverHp = maxHp * 0.2 + if currentHp <= recoverHp then + self.CheckData = {} + return 300, self.CheckData + end + + -- 返回优先级,执行数据 + return -1, self.CheckData +end + +function IceCoffine:Execute() + self.ExeTask = task.spawn(function () + self:ChangeExecutingState(true) + -- cd放前面之后发送事件才能正常记录cd + self:StartCooldownTask() + + local maxHp = self.Character.Stats.MaxHp + local recoverHp = math.floor(maxHp * (self.PlayerAI:GetSharedData("IceCoffin_MaxRecover") / 100)) + DamageProxy:Heal(self.Character, self.Character, recoverHp) + task.wait(0.5) + + self:ChangeExecutingState(false) + end) +end + + +return IceCoffine \ No newline at end of file diff --git a/src/ServerStorage/Modules/Runes/RuneFireDamage.luau b/src/ServerStorage/Modules/Runes/RuneFireDamage.luau new file mode 100644 index 0000000..3e5d225 --- /dev/null +++ b/src/ServerStorage/Modules/Runes/RuneFireDamage.luau @@ -0,0 +1,31 @@ +--> Services +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +--> Dependencies +local Utils = require(ReplicatedStorage.Tools.Utils) + +local RuneFireDamage = {} +RuneFireDamage.__index = RuneFireDamage +setmetatable(RuneFireDamage, {__index = Rune}) + + +function RuneFireDamage:Init(PlayerAI, Character: TypeList.Character, Player: Player) + local self = Rune:Init(PlayerAI, Character, script.Name) + self.Player = Player + setmetatable(self, RuneFireDamage) + + return self +end + +function RuneFireDamage:Check(index: number, AttributesData: table, BehaviorNameList: table) + return true +end + +function RuneFireDamage:OnExecute(index: number, AttributesData: table, BehaviorNameList: table) + print("RuneFireDamage:OnExecute", index, AttributesData, BehaviorNameList) + Utils:TableSafeAddValue(AttributesData, "fireAtk", 100) + return nil +end + + +return RuneFireDamage \ No newline at end of file diff --git a/src/ServerStorage/Modules/Runes/RuneIceCoffin.luau b/src/ServerStorage/Modules/Runes/RuneIceCoffin.luau new file mode 100644 index 0000000..040e688 --- /dev/null +++ b/src/ServerStorage/Modules/Runes/RuneIceCoffin.luau @@ -0,0 +1,36 @@ +--> Services +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +--> Dependencies +local Utils = require(ReplicatedStorage.Tools.Utils) + +local RuneIceCoffin = {} +RuneIceCoffin.__index = RuneIceCoffin +setmetatable(RuneIceCoffin, {__index = Rune}) + + +function RuneIceCoffin:Init(PlayerAI, Character: TypeList.Character, Player: Player) + local self = Rune:Init(PlayerAI, Character, script.Name) + self.Player = Player + setmetatable(self, RuneIceCoffin) + + return self +end + +function RuneIceCoffin:Check(index: number, AttributesData: table, BehaviorNameList: table) + return true +end + +function RuneIceCoffin:OnExecute(index: number, AttributesData: table, BehaviorNameList: table) + print("RuneIceCoffin:OnExecute", index, AttributesData, BehaviorNameList) + local maxRecover = self.PlayerAI:GetSharedData("IceCoffin_MaxRecover") + if maxRecover then + self.PlayerAI:SetSharedData("IceCoffin_MaxRecover", maxRecover + 60) + else + self.PlayerAI:SetSharedData("IceCoffin_MaxRecover", 60) + end + return nil +end + + +return RuneIceCoffin \ No newline at end of file diff --git a/src/ServerStorage/Proxy/DamageProxy.luau b/src/ServerStorage/Proxy/DamageProxy.luau index 069887a..318ad07 100644 --- a/src/ServerStorage/Proxy/DamageProxy.luau +++ b/src/ServerStorage/Proxy/DamageProxy.luau @@ -42,6 +42,12 @@ export type DamageInfo = { ElementType: ElementType, } +export type HealInfo = { + Caster: TypeList.Character, + Victim: TypeList.Character, + Amount: number, +} + DamageProxy.DamageType = DamageType DamageProxy.DamageTag = DamageTag DamageProxy.ElementType = ElementType @@ -275,4 +281,58 @@ function DamageProxy:TakeDamage(Caster: TypeList.Character, Victim: TypeList.Cha end end +-- 治疗处理(简化版本) +function DamageProxy:Heal(Caster: TypeList.Character, Victim: TypeList.Character, Amount: number) + -- 基础参数验证 + if not Caster or not Victim or not Amount or Amount <= 0 then + warn("Heal: 基础参数无效") + return + end + + -- 注册对象到生命周期管理器 + globalLifecycleManager:RegisterObject(Caster) + globalLifecycleManager:RegisterObject(Victim) + + -- 检查对象是否仍然有效 + if not globalLifecycleManager:IsObjectValid(Caster) or not globalLifecycleManager:IsObjectValid(Victim) then + warn("Heal: 施法者或目标已被销毁") + return + end + + -- 治疗计算 + local VictimHealth = Victim:GetAttributeValue("hp") or 0 + local MaxHealth = Victim:GetAttributeValue("maxHp") or 0 + + -- 计算实际治疗量(不超过最大生命值) + local actualHeal = math.min(Amount, MaxHealth - VictimHealth) + local overheal = math.max(0, Amount - actualHeal) + + if actualHeal > 0 then + Victim:ChangeAttributeValue("hp", VictimHealth + actualHeal) + end + + -- 给前端发送治疗信息 + local clientHealInfo = { + Caster = Caster.Instance, + Victim = Victim.Instance, + ServerTime = os.time(), + HealPosition = Victim.Instance.PrimaryPart.Position, + HealAmount = actualHeal, + Overheal = overheal, + OriginalHealth = VictimHealth, + NewHealth = VictimHealth + actualHeal + } + + -- 发送数据到客户端 + local success, error = pcall(function() + Communicate:SendToClient(RE_DamagePerformance, "Heal", Caster.Player, clientHealInfo) + end) + + if not success then + warn("Heal: 发送治疗数据失败:", error) + end + + return actualHeal, overheal +end + return DamageProxy \ No newline at end of file diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau b/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau index 4544910..685b939 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau @@ -10,6 +10,7 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage") --> Dependencies local TypeList = require(ServerStorage.Base.TypeList) local Utils = require(ReplicatedStorage.Tools.Utils) +local ScriptModule = require(ReplicatedStorage.Tools.ScriptModule) local Communicate = require(ServerStorage.Modules.Tools.Communicate) --> Events @@ -21,21 +22,10 @@ local DamageProxy = require(ServerStorage.Proxy.DamageProxy) local ActivePlayers = {} local Behaviours = {} -local BehaviourFolder = ServerStorage:FindFirstChild("Modules"):FindFirstChild("Behaviours") -if BehaviourFolder then - for _, behaviourModule in ipairs(BehaviourFolder:GetChildren()) do - if behaviourModule:IsA("ModuleScript") then - local success, result = pcall(require, behaviourModule) - if success then - -- 去掉文件名后缀 - local name = behaviourModule.Name - Behaviours[name] = result - else - warn("加载代理模块失败: " .. behaviourModule.Name, result) - end - end - end -end +ScriptModule:InjectFolderModules(Behaviours, ServerStorage:FindFirstChild("Modules"):FindFirstChild("Behaviours")) + +local Runes = {} +ScriptModule:InjectFolderModules(Runes, ServerStorage:FindFirstChild("Modules"):FindFirstChild("Runes")) -------------------------------------------------------------------------------- @@ -53,6 +43,8 @@ function PlayerAI.new(Player: Player, PlayerRole: TypeList.Character) self.Counter = 0 self.BehaviourList = {} + self.RuneList = {} + self.SharedData = {} -- 符文和行为之间的共享数据 self.LoopTask = task.spawn(function() while task.wait(0.25) do if self.Character.Stats.Died then continue end @@ -109,11 +101,118 @@ function PlayerAI:AddBehaviour(BehaviourName: string, WearingSlot: number?) self.BehaviourList[BehaviourName] = newBehaviour end +-- 动态添加符文 +function PlayerAI:AddRune(RuneName: string, WearingSlot: number?) + if not Runes[RuneName] then warn("Rune not found") return end + local newRune = Runes[RuneName]:Init(self, self.Character, self.Player) + newRune.WearingSlot = WearingSlot or 4 + + self.RuneList[RuneName] = newRune + + -- 更新所有符文的TriggerSlot + self:UpdateRuneTriggerSlots() +end + +-- 更新所有符文的TriggerSlot +function PlayerAI:UpdateRuneTriggerSlots() + -- 收集所有符文并按WearingSlot排序 + local runeArray = {} + for runeName, rune in pairs(self.RuneList) do + table.insert(runeArray, { + name = runeName, + rune = rune, + slot = rune.WearingSlot + }) + end + + -- 按WearingSlot排序 + table.sort(runeArray, function(a, b) + return a.slot < b.slot + end) + + -- 分配TriggerSlot(从1开始,排除空槽位) + local currentTriggerSlot = 1 + for _, runeData in ipairs(runeArray) do + runeData.rune.TriggerSlot = currentTriggerSlot + currentTriggerSlot = currentTriggerSlot + 1 + end +end + -- 获取并记录行为UniqueId function PlayerAI:GetBehaviourUniqueId() return Utils:GenUniqueIdPlayerAI(self.LastTime, self.Counter) end +-- 获取当前符文列表 +function PlayerAI:GetRuneList() + local runeArray = {} + for runeName, rune in self.RuneList do + runeArray[rune.TriggerSlot] = runeName + end + return runeArray +end + + +-- 遍历符文并执行回调 +function PlayerAI:ForEachRune(callback: (runeName: string, triggerSlot: number, rune: table) -> ()) + for runeName, rune in pairs(self.RuneList) do + local result = callback(runeName, rune.TriggerSlot, rune) + -- 如果回调返回了数字,表示要控制流程 + if type(result) == "number" then + return result + end + end + return nil -- 没有符文要控制流程 +end + +-- 触发所有符文的指定事件(除了指定符文) +function PlayerAI:TriggerAllRunesExcept(excludeRune: table, eventName: string, ...) + for runeName, rune in pairs(self.RuneList) do + if rune ~= excludeRune and rune[eventName] and typeof(rune[eventName]) == "function" then + local result = rune[eventName](rune, ...) + if type(result) == "number" then + return result + end + end + end + return nil +end + +-- 触发所有符文的指定事件 +function PlayerAI:TriggerAllRunes(eventName: string, ...) + for runeName, rune in pairs(self.RuneList) do + if rune[eventName] and typeof(rune[eventName]) == "function" then + rune[eventName](rune, ...) + end + end +end + +-- 触发指定符文的指定事件 +function PlayerAI:TriggerRune(runeName: string, eventName: string, ...) + if self.RuneList[runeName] and self.RuneList[runeName][eventName] and typeof(self.RuneList[runeName][eventName]) == "function" then + return self.RuneList[runeName][eventName](self.RuneList[runeName], ...) + end +end + +-- 设置共享数据 +function PlayerAI:SetSharedData(key: string, value: any) + self.SharedData[key] = value +end + +-- 获取共享数据 +function PlayerAI:GetSharedData(key: string) + return self.SharedData[key] +end + +-- 清除共享数据 +function PlayerAI:ClearSharedData(key: string?) + if key then + self.SharedData[key] = nil + else + self.SharedData = {} + end +end + -- 获取客户端行为列表 function PlayerAI:GetClientBehaviourList() local clientBehaviourList = { @@ -144,6 +243,24 @@ function PlayerAI:RemoveBehaviour(BehaviourName: string) end end +-- 动态删除符文 +function PlayerAI:RemoveRune(RuneName: string) + if self.RuneList[RuneName] then + self.RuneList[RuneName]:Destroy() + self.RuneList[RuneName] = nil + + -- 更新所有符文的TriggerSlot + self:UpdateRuneTriggerSlots() + end +end + +-- 清除所有符文 +function PlayerAI:ClearAllRune() + for _, rune in self.RuneList do rune:Destroy() end + self.RuneList = {} + -- 清除后不需要更新TriggerSlot,因为已经没有符文了 +end + -- 清除所有行为 function PlayerAI:ClearAllBehaviour() for _, behaviour in self.BehaviourList do behaviour:Destroy() end diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau index 95a1801..305a5a4 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau @@ -192,13 +192,17 @@ function PlayerFightProxy:UpdatePlayerFightData(Player: Player) end -- 根据技能添加玩家AI行为 - local abilityIdList, behaviourNameList = AbilityProxy:GetPlayerWearingAbilityData(Player) + local abilityIdList, behaviorNameList = AbilityProxy:GetPlayerWearingAbilityData(Player) local playerAI = PlayerFightProxy:GetPlayerAI(Player) + -- 玩家符文影响 + local RuneProxy = require(ServerStorage.Proxy.RuneProxy) + RuneProxy:GetRuneAttributes(Player, playerAI, AttributesData, behaviorNameList) + -- TODO:设置AI行为(临时清除所有行为,添加新的玩家行为) playerAI:ClearAllBehaviour() - for _, behaviourName in behaviourNameList do - playerAI:AddBehaviour(behaviourName) + for _, behaviorName in behaviorNameList do + playerAI:AddBehaviour(behaviorName) end playerAI:AddBehaviour("Move") -- playerAI:AddBehaviour("SwordWave") diff --git a/src/ServerStorage/Proxy/RuneProxy/RuneCalculation.luau b/src/ServerStorage/Proxy/RuneProxy/RuneCalculation.luau new file mode 100644 index 0000000..8ad3573 --- /dev/null +++ b/src/ServerStorage/Proxy/RuneProxy/RuneCalculation.luau @@ -0,0 +1,79 @@ +local RuneCalculation = {} + +-- 处理符文机制主函数 +function RuneCalculation:GetRuneAttributes(Player: Player, PlayerAI: table, AttributesData: table, BehaviorNameList: table) + if not Player and not PlayerAI then warn("Player or PlayerAI not found") return end + + -- 没穿戴符文,直接返回 + local wearingRuneUniqueId, wearingRuneName, wearingRuneBehaviorName = self:GetPlayerWearingRuneData(Player) + if #wearingRuneUniqueId == 0 then return AttributesData, BehaviorNameList end + + -- 行为名称列表处理 + for _, behaviorName in wearingRuneBehaviorName do + if not table.find(BehaviorNameList, behaviorName) then + table.insert(BehaviorNameList, behaviorName) + end + end + + -- 符文初始化 + PlayerAI:ClearSharedData() + PlayerAI:ClearAllRune() + for wearingSlot, runeName in wearingRuneName do PlayerAI:AddRune(runeName, wearingSlot) end + + -- 触发开始事件,并检查是否有符文要控制流程 + local startNextIndex = PlayerAI:ForEachRune(function(runeName, triggerSlot, rune) + local result = rune:OnStartEvent(runeName, triggerSlot, AttributesData, BehaviorNameList) + if type(result) == "number" then + return result -- 返回要跳转的index + end + end) + + local index = 1 + local maxSteps = 1000 -- 防止无限循环 + + -- 如果开始事件指定了起始位置,使用它 + if type(startNextIndex) == "number" then + index = startNextIndex + end + + -- 执行符文循环 + self:ExecuteRuneLoop(PlayerAI, wearingRuneName, wearingRuneUniqueId, index, maxSteps) +end + +-- 执行符文循环的辅助函数 +function RuneCalculation:ExecuteRuneLoop(PlayerAI: table, wearingRuneName: table, wearingRuneUniqueId: table, startIndex: number, maxSteps: number, AttributesData: table, BehaviorNameList: table) + local index = startIndex + + while index <= #wearingRuneUniqueId and maxSteps > 0 do + local result = PlayerAI:TriggerRune(wearingRuneName[index], "Check", index, AttributesData, BehaviorNameList) + if result then + local nextIndex = PlayerAI:TriggerRune(wearingRuneName[index], "Execute", index, AttributesData, BehaviorNameList) + + -- 根据返回值决定下一个index + if type(nextIndex) == "number" then + index = nextIndex -- 符文指定了下一个位置 + else + index += 1 -- 默认继续下一个 + end + else + index += 1 + end + maxSteps -= 1 -- 防止无限循环 + end + + -- 触发结束事件,并检查是否有符文要控制流程 + local endNextIndex = PlayerAI:ForEachRune(function(runeName, triggerSlot, rune) + local result = rune:OnEndEvent(runeName, triggerSlot, AttributesData, BehaviorNameList) + if type(result) == "number" then + return result -- 返回要跳转的index + end + end) + + -- 如果结束事件指定了要跳转的位置,重新开始循环 + if type(endNextIndex) == "number" and endNextIndex <= #wearingRuneUniqueId and maxSteps > 0 then + self:ExecuteRuneLoop(PlayerAI, wearingRuneName, wearingRuneUniqueId, endNextIndex, maxSteps, AttributesData, BehaviorNameList) + end +end + + +return RuneCalculation \ No newline at end of file diff --git a/src/ServerStorage/Proxy/RuneProxy.luau b/src/ServerStorage/Proxy/RuneProxy/init.luau similarity index 94% rename from src/ServerStorage/Proxy/RuneProxy.luau rename to src/ServerStorage/Proxy/RuneProxy/init.luau index 3d4096e..003ede8 100644 --- a/src/ServerStorage/Proxy/RuneProxy.luau +++ b/src/ServerStorage/Proxy/RuneProxy/init.luau @@ -9,6 +9,7 @@ local ServerStorage = game:GetService("ServerStorage") local Utils = require(ReplicatedStorage.Tools.Utils) local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy) local Rng = require(ReplicatedStorage.Tools.Rng) +local ScriptModule = require(ReplicatedStorage.Tools.ScriptModule) --> Json local JsonRune = require(ReplicatedStorage.Json.Rune) @@ -16,6 +17,10 @@ local JsonRune = require(ReplicatedStorage.Json.Rune) --> Events local RE_PlayerTip = ReplicatedStorage.Events.RE_PlayerTip +--> SubFunctions +local RuneCalculation = require(script.RuneCalculation) +ScriptModule:InjectScriptFunctions(RuneProxy, RuneCalculation) + --> Constants local STORE_NAME = "Rune" @@ -225,7 +230,8 @@ end -- 获取穿戴中的符文 function RuneProxy:GetPlayerWearingRuneData(Player: Player) local wearingRuneUniqueId = {} - local behaviourNames = {} + local wearingRuneName = {} + local wearingRuneBehaviorName = {} -- 穿戴中的填入 local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy) local wearingEquipments = EquipmentProxy:GetPlayerWearingEquipmentUniqueId(Player) @@ -233,10 +239,15 @@ function RuneProxy:GetPlayerWearingRuneData(Player: Player) if RuneData.wearing > 0 and table.find(wearingEquipments, RuneData.wearing) then table.insert(wearingRuneUniqueId, RuneData.id) local RuneData = Utils:GetIdDataFromJson(JsonRune, RuneData.orgId) - table.insert(behaviourNames, RuneData.behaviourName) + if RuneData.runeName then + wearingRuneName[RuneData.wearingSlot] = RuneData.runeName + end + if RuneData.behaviorName then + table.insert(wearingRuneBehaviorName, RuneData.behaviorName) + end end end - return wearingRuneUniqueId, behaviourNames + return wearingRuneUniqueId, wearingRuneName end -- 获取对应装备槽位上的技能