更新-主要符文后端内容
This commit is contained in:
parent
4ccf2a6709
commit
924b1dccad
BIN
excel/Rune.xlsx
BIN
excel/Rune.xlsx
Binary file not shown.
Binary file not shown.
31
src/ReplicatedStorage/Tools/ScriptModule.luau
Normal file
31
src/ReplicatedStorage/Tools/ScriptModule.luau
Normal file
@ -0,0 +1,31 @@
|
||||
local ScriptModule = {}
|
||||
|
||||
-- 将目标类的所有函数全部注入到指定表中
|
||||
function ScriptModule:InjectScriptFunctions(ParentTable: table, ScriptModule: table)
|
||||
for key, value in ScriptModule do
|
||||
if typeof(value) == "function" then
|
||||
ParentTable[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 注入文件夹下所有模块,到指定表中
|
||||
function ScriptModule:InjectFolderModules(ParentTable: table, Folder: Instance)
|
||||
if Folder then
|
||||
for _, module in ipairs(Folder:GetChildren()) do
|
||||
if module:IsA("ModuleScript") then
|
||||
local success, result = pcall(require, module)
|
||||
if success then
|
||||
-- 去掉文件名后缀
|
||||
local name = module.Name
|
||||
ParentTable[name] = result
|
||||
else
|
||||
warn("加载代理模块失败: " .. module.Name, result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return ScriptModule
|
108
src/ServerStorage/Base/Rune.luau
Normal file
108
src/ServerStorage/Base/Rune.luau
Normal file
@ -0,0 +1,108 @@
|
||||
local Rune = {}
|
||||
Rune.__index = Rune
|
||||
|
||||
--> 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
|
71
src/ServerStorage/Modules/Behaviours/IceCoffine.luau
Normal file
71
src/ServerStorage/Modules/Behaviours/IceCoffine.luau
Normal file
@ -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
|
31
src/ServerStorage/Modules/Runes/RuneFireDamage.luau
Normal file
31
src/ServerStorage/Modules/Runes/RuneFireDamage.luau
Normal file
@ -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
|
36
src/ServerStorage/Modules/Runes/RuneIceCoffin.luau
Normal file
36
src/ServerStorage/Modules/Runes/RuneIceCoffin.luau
Normal file
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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")
|
||||
|
79
src/ServerStorage/Proxy/RuneProxy/RuneCalculation.luau
Normal file
79
src/ServerStorage/Proxy/RuneProxy/RuneCalculation.luau
Normal file
@ -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
|
@ -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
|
||||
|
||||
-- 获取对应装备槽位上的技能
|
Loading…
x
Reference in New Issue
Block a user