更新
This commit is contained in:
parent
e13d346923
commit
ed086039a1
BIN
excel/Rune.xlsx
BIN
excel/Rune.xlsx
Binary file not shown.
Binary file not shown.
Binary file not shown.
7
src/ReplicatedStorage/Data/ServerSignalEnum.luau
Normal file
7
src/ReplicatedStorage/Data/ServerSignalEnum.luau
Normal file
@ -0,0 +1,7 @@
|
||||
local ServerSignalEnum = {}
|
||||
|
||||
ServerSignalEnum = {
|
||||
SHOW_ABILITY = "SHOW_ABILITY",
|
||||
}
|
||||
|
||||
return ServerSignalEnum
|
@ -1,18 +1,18 @@
|
||||
[
|
||||
{"id":40000,"type":1,"name":40000,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"MCSword","specialType":2,"specialRequire":20001,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40001,"type":1,"name":40001,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":7,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40002,"type":1,"name":40002,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":8,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40003,"type":1,"name":40003,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":9,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40004,"type":1,"name":40004,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":10,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40005,"type":1,"name":40005,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":11,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40006,"type":1,"name":40006,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":12,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40007,"type":1,"name":40007,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":13,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40008,"type":1,"name":40008,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":6,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40009,"type":1,"name":40009,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":7,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40010,"type":1,"name":40010,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":8,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40011,"type":1,"name":40011,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":9,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40012,"type":1,"name":40012,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":10,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40013,"type":1,"name":40013,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":11,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40014,"type":1,"name":40014,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":12,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40015,"type":1,"name":40015,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":13,"specialActive":[14,25],"recycle":100}
|
||||
{"id":40000,"type":1,"subType":1,"name":40000,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"MCSword","specialType":2,"specialRequire":20001,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40001,"type":1,"subType":2,"name":40001,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":7,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40002,"type":1,"subType":3,"name":40002,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":8,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40003,"type":1,"subType":4,"name":40003,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":9,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40004,"type":1,"subType":1,"name":40004,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":10,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40005,"type":1,"subType":2,"name":40005,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":11,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40006,"type":1,"subType":3,"name":40006,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":12,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40007,"type":1,"subType":4,"name":40007,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":13,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40008,"type":1,"subType":1,"name":40008,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":6,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40009,"type":1,"subType":2,"name":40009,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":7,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40010,"type":1,"subType":3,"name":40010,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":8,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40011,"type":1,"subType":4,"name":40011,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":9,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40012,"type":1,"subType":1,"name":40012,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":10,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40013,"type":1,"subType":2,"name":40013,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":11,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40014,"type":1,"subType":3,"name":40014,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":12,"specialActive":[14,25],"recycle":100},
|
||||
{"id":40015,"type":1,"subType":4,"name":40015,"attributes":[14,100,0,15,100,0,16,100,0],"modelName":"Zeus","specialType":1,"specialRequire":13,"specialActive":[14,25],"recycle":100}
|
||||
]
|
@ -1,5 +1,56 @@
|
||||
[
|
||||
{"id":60000,"quality":1,"type":1,"icon":1,"nameId":60000,"runeName":"RuneFireDamage","behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60001,"quality":1,"type":2,"icon":1,"nameId":60001,"runeName":"RuneIceDamage","behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60002,"quality":1,"type":3,"icon":1,"nameId":60002,"runeName":"RuneLightDamage","behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60003,"quality":1,"type":4,"icon":1,"nameId":60003,"runeName":"RuneShadowDamage","behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60004,"quality":1,"type":null,"icon":1,"nameId":60004,"runeName":"RuneBookQualityPurple","behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60005,"quality":1,"type":null,"icon":1,"nameId":60005,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60006,"quality":1,"type":null,"icon":1,"nameId":60006,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60007,"quality":1,"type":null,"icon":1,"nameId":60007,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60008,"quality":1,"type":null,"icon":1,"nameId":60008,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60009,"quality":1,"type":null,"icon":1,"nameId":60009,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60010,"quality":1,"type":null,"icon":1,"nameId":60010,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60011,"quality":1,"type":null,"icon":1,"nameId":60011,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60012,"quality":1,"type":null,"icon":1,"nameId":60012,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60013,"quality":1,"type":null,"icon":1,"nameId":60013,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60014,"quality":1,"type":null,"icon":1,"nameId":60014,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60015,"quality":1,"type":null,"icon":1,"nameId":60015,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60016,"quality":1,"type":null,"icon":1,"nameId":60016,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60017,"quality":1,"type":null,"icon":1,"nameId":60017,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60018,"quality":1,"type":null,"icon":1,"nameId":60018,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60019,"quality":1,"type":null,"icon":1,"nameId":60019,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60020,"quality":1,"type":null,"icon":1,"nameId":60020,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60021,"quality":1,"type":null,"icon":1,"nameId":60021,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60022,"quality":1,"type":null,"icon":1,"nameId":60022,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60023,"quality":1,"type":null,"icon":1,"nameId":60023,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":60024,"quality":1,"type":null,"icon":1,"nameId":60024,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61000,"quality":2,"type":1,"icon":1,"nameId":61000,"runeName":"RuneIceCoffin","behaviorName":"IceCoffine","recycle":[],"isInPool":1},
|
||||
{"id":61001,"quality":2,"type":null,"icon":1,"nameId":61001,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61002,"quality":2,"type":null,"icon":1,"nameId":61002,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61003,"quality":2,"type":null,"icon":1,"nameId":61003,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61004,"quality":2,"type":null,"icon":1,"nameId":61004,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61005,"quality":2,"type":null,"icon":1,"nameId":61005,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61006,"quality":2,"type":null,"icon":1,"nameId":61006,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61007,"quality":2,"type":null,"icon":1,"nameId":61007,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61008,"quality":2,"type":null,"icon":1,"nameId":61008,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61009,"quality":2,"type":null,"icon":1,"nameId":61009,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61010,"quality":2,"type":null,"icon":1,"nameId":61010,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61011,"quality":2,"type":null,"icon":1,"nameId":61011,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61012,"quality":2,"type":null,"icon":1,"nameId":61012,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61013,"quality":2,"type":null,"icon":1,"nameId":61013,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61014,"quality":2,"type":null,"icon":1,"nameId":61014,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61015,"quality":2,"type":null,"icon":1,"nameId":61015,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61016,"quality":2,"type":null,"icon":1,"nameId":61016,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61017,"quality":2,"type":null,"icon":1,"nameId":61017,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61018,"quality":2,"type":null,"icon":1,"nameId":61018,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61019,"quality":2,"type":null,"icon":1,"nameId":61019,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61020,"quality":2,"type":null,"icon":1,"nameId":61020,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61021,"quality":2,"type":null,"icon":1,"nameId":61021,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61022,"quality":2,"type":null,"icon":1,"nameId":61022,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61023,"quality":2,"type":null,"icon":1,"nameId":61023,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61024,"quality":2,"type":null,"icon":1,"nameId":61024,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61025,"quality":2,"type":null,"icon":1,"nameId":61025,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61026,"quality":2,"type":null,"icon":1,"nameId":61026,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":61027,"quality":2,"type":null,"icon":1,"nameId":61027,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1},
|
||||
{"id":62000,"quality":3,"type":1,"icon":1,"nameId":62000,"runeName":null,"behaviorName":null,"recycle":[],"isInPool":1}
|
||||
]
|
184
src/ReplicatedStorage/Modules/EventFilter.luau
Normal file
184
src/ReplicatedStorage/Modules/EventFilter.luau
Normal file
@ -0,0 +1,184 @@
|
||||
--[[
|
||||
EventFilter System - 自动回收版本
|
||||
结合Signal和Filter实现事件数据过滤系统
|
||||
支持事件触发时的数据修改和回调处理
|
||||
自动回收机制,无需手动管理生命周期
|
||||
]]
|
||||
|
||||
local Signal = require(script.Parent.Signal)
|
||||
local Filter = require(script.Parent.Filter)
|
||||
|
||||
-- 事件Filter处理器类型
|
||||
export type EventFilterHandler = {
|
||||
handlerFunction: (eventData: any) -> any,
|
||||
priority: number,
|
||||
id: string,
|
||||
eventName: string
|
||||
}
|
||||
|
||||
-- EventFilter系统类
|
||||
local EventFilter = {}
|
||||
EventFilter.__index = EventFilter
|
||||
EventFilter.ClassName = "EventFilter"
|
||||
|
||||
export type EventFilter = typeof(EventFilter)
|
||||
|
||||
-- 全局EventFilter实例(使用弱表自动回收)
|
||||
local GlobalEventFilters = setmetatable({}, {__mode = "k"})
|
||||
|
||||
function EventFilter.new(name: string?): EventFilter
|
||||
local eventFilter = setmetatable({
|
||||
Name = name or "GlobalEventFilter",
|
||||
_signals = {}, -- 存储事件信号
|
||||
_filters = {}, -- 存储每个事件的Filter
|
||||
_nextHandlerId = 1,
|
||||
_weakRefs = setmetatable({}, {__mode = "k"}) -- 弱引用表
|
||||
}, EventFilter)
|
||||
|
||||
if name then
|
||||
GlobalEventFilters[eventFilter] = true
|
||||
end
|
||||
|
||||
return eventFilter
|
||||
end
|
||||
|
||||
-- 注册事件(创建Signal和对应的Filter)
|
||||
function EventFilter:RegisterEvent(eventName: string): Signal
|
||||
if not self._signals[eventName] then
|
||||
self._signals[eventName] = Signal.new(eventName)
|
||||
self._filters[eventName] = Filter.new(eventName .. "_Filter")
|
||||
end
|
||||
return self._signals[eventName]
|
||||
end
|
||||
|
||||
-- 订阅事件Filter(自动回收版本)
|
||||
function EventFilter:SubscribeFilter(eventName: string, filterFunction: (eventData: any) -> any, priority: number?, owner: any?): string
|
||||
-- 确保事件已注册
|
||||
self:RegisterEvent(eventName)
|
||||
|
||||
local handlerId = tostring(self._nextHandlerId)
|
||||
self._nextHandlerId = self._nextHandlerId + 1
|
||||
|
||||
-- 添加到Filter(带所有者引用)
|
||||
local filterId = self._filters[eventName]:AddHandler(filterFunction, priority, owner)
|
||||
|
||||
-- 如果提供了所有者,创建弱引用
|
||||
if owner then
|
||||
self._weakRefs[owner] = {eventName = eventName, handlerId = handlerId}
|
||||
end
|
||||
|
||||
return handlerId
|
||||
end
|
||||
|
||||
-- 取消订阅事件Filter
|
||||
function EventFilter:UnsubscribeFilter(eventName: string, handlerId: string): boolean
|
||||
if self._filters[eventName] then
|
||||
return self._filters[eventName]:RemoveHandler(handlerId)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- 清理无效的处理器(自动回收)
|
||||
function EventFilter:CleanupFilters()
|
||||
for eventName, filter in pairs(self._filters) do
|
||||
filter:CleanupHandlers()
|
||||
end
|
||||
end
|
||||
|
||||
-- 发送事件(带Filter处理,自动清理)
|
||||
function EventFilter:FireWithFilter(eventName: string, eventData: any, callback: (processedData: any) -> ())
|
||||
-- 确保事件已注册
|
||||
self:RegisterEvent(eventName)
|
||||
|
||||
-- 自动清理无效处理器
|
||||
self:CleanupFilters()
|
||||
|
||||
-- 通过Filter处理数据
|
||||
self._filters[eventName]:ProcessDataWithCallback(eventData, function(processedData)
|
||||
-- 触发Signal事件
|
||||
self._signals[eventName]:Fire(processedData)
|
||||
|
||||
-- 执行回调
|
||||
if callback then
|
||||
callback(processedData)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- 发送事件(不带Filter,直接触发)
|
||||
function EventFilter:Fire(eventName: string, eventData: any)
|
||||
-- 确保事件已注册
|
||||
self:RegisterEvent(eventName)
|
||||
|
||||
-- 自动清理无效处理器
|
||||
self:CleanupFilters()
|
||||
|
||||
-- 直接触发Signal事件
|
||||
self._signals[eventName]:Fire(eventData)
|
||||
end
|
||||
|
||||
-- 订阅事件(监听处理后的数据)
|
||||
function EventFilter:Subscribe(eventName: string, callback: (processedData: any) -> ()): any
|
||||
-- 确保事件已注册
|
||||
self:RegisterEvent(eventName)
|
||||
|
||||
-- 订阅Signal事件
|
||||
return self._signals[eventName]:Connect(callback)
|
||||
end
|
||||
|
||||
-- 获取事件Signal
|
||||
function EventFilter:GetSignal(eventName: string): Signal?
|
||||
return self._signals[eventName]
|
||||
end
|
||||
|
||||
-- 获取事件Filter
|
||||
function EventFilter:GetFilter(eventName: string): Filter?
|
||||
return self._filters[eventName]
|
||||
end
|
||||
|
||||
-- 获取所有已注册的事件名称
|
||||
function EventFilter:GetRegisteredEvents(): {string}
|
||||
local events = {}
|
||||
for eventName, _ in pairs(self._signals) do
|
||||
table.insert(events, eventName)
|
||||
end
|
||||
return events
|
||||
end
|
||||
|
||||
-- 便捷方法:获取全局EventFilter实例
|
||||
function EventFilter.GetGlobal(): EventFilter
|
||||
for eventFilter, _ in pairs(GlobalEventFilters) do
|
||||
if eventFilter.Name == "GlobalEventFilter" then
|
||||
return eventFilter
|
||||
end
|
||||
end
|
||||
|
||||
return EventFilter.new("GlobalEventFilter")
|
||||
end
|
||||
|
||||
-- 便捷方法:全局订阅Filter(带所有者)
|
||||
function EventFilter.SubscribeGlobalFilter(eventName: string, filterFunction: (eventData: any) -> any, priority: number?, owner: any?): string
|
||||
return EventFilter.GetGlobal():SubscribeFilter(eventName, filterFunction, priority, owner)
|
||||
end
|
||||
|
||||
-- 便捷方法:全局取消订阅Filter
|
||||
function EventFilter.UnsubscribeGlobalFilter(eventName: string, handlerId: string): boolean
|
||||
return EventFilter.GetGlobal():UnsubscribeFilter(eventName, handlerId)
|
||||
end
|
||||
|
||||
-- 便捷方法:全局发送事件(带Filter)
|
||||
function EventFilter.FireGlobalWithFilter(eventName: string, eventData: any, callback: (processedData: any) -> ())
|
||||
EventFilter.GetGlobal():FireWithFilter(eventName, eventData, callback)
|
||||
end
|
||||
|
||||
-- 便捷方法:全局发送事件(不带Filter)
|
||||
function EventFilter.FireGlobal(eventName: string, eventData: any)
|
||||
EventFilter.GetGlobal():Fire(eventName, eventData)
|
||||
end
|
||||
|
||||
-- 便捷方法:全局订阅事件
|
||||
function EventFilter.SubscribeGlobal(eventName: string, callback: (processedData: any) -> ()): any
|
||||
return EventFilter.GetGlobal():Subscribe(eventName, callback)
|
||||
end
|
||||
|
||||
return EventFilter
|
230
src/ReplicatedStorage/Modules/EventFilterExample.luau
Normal file
230
src/ReplicatedStorage/Modules/EventFilterExample.luau
Normal file
@ -0,0 +1,230 @@
|
||||
--[[
|
||||
EventFilter使用例子
|
||||
演示如何使用事件过滤系统
|
||||
]]
|
||||
|
||||
local EventFilter = require(script.Parent.EventFilter)
|
||||
|
||||
-- ===== 基础使用示例 =====
|
||||
|
||||
-- 1. 创建符文对象(作为所有者)
|
||||
local function createRunes()
|
||||
local fireRune = {
|
||||
name = "火焰符文",
|
||||
level = 5,
|
||||
element = "fire"
|
||||
}
|
||||
|
||||
local iceRune = {
|
||||
name = "冰霜符文",
|
||||
level = 3,
|
||||
element = "ice"
|
||||
}
|
||||
|
||||
local criticalRune = {
|
||||
name = "暴击符文",
|
||||
level = 4,
|
||||
criticalChance = 0.3
|
||||
}
|
||||
|
||||
-- 添加Destroy方法(用于自动回收)
|
||||
function fireRune:Destroy()
|
||||
print("销毁火焰符文")
|
||||
for k, v in pairs(self) do self[k] = nil end
|
||||
self = nil
|
||||
end
|
||||
|
||||
function iceRune:Destroy()
|
||||
print("销毁冰霜符文")
|
||||
for k, v in pairs(self) do self[k] = nil end
|
||||
self = nil
|
||||
end
|
||||
|
||||
function criticalRune:Destroy()
|
||||
print("销毁暴击符文")
|
||||
for k, v in pairs(self) do self[k] = nil end
|
||||
self = nil
|
||||
end
|
||||
|
||||
return fireRune, iceRune, criticalRune
|
||||
end
|
||||
|
||||
-- 2. 设置符文效果
|
||||
local function setupRuneEffects(fireRune, iceRune, criticalRune)
|
||||
-- 火焰符文:增加50%伤害
|
||||
EventFilter.SubscribeGlobalFilter("OnAttack", function(eventData)
|
||||
print("🔥 火焰符文生效:伤害 +50%")
|
||||
eventData.damage = eventData.damage * 1.5
|
||||
eventData.element = "fire"
|
||||
return eventData
|
||||
end, 10, fireRune) -- 优先级10,所有者是fireRune
|
||||
|
||||
-- 冰霜符文:增加30%伤害,有概率冰冻
|
||||
EventFilter.SubscribeGlobalFilter("OnAttack", function(eventData)
|
||||
print("❄️ 冰霜符文生效:伤害 +30%")
|
||||
eventData.damage = eventData.damage * 1.3
|
||||
eventData.element = "ice"
|
||||
|
||||
-- 20%概率冰冻
|
||||
if math.random() < 0.2 then
|
||||
eventData.freeze = true
|
||||
print(" 💎 触发冰冻效果!")
|
||||
end
|
||||
|
||||
return eventData
|
||||
end, 8, iceRune) -- 优先级8,所有者是iceRune
|
||||
|
||||
-- 暴击符文:30%概率暴击
|
||||
EventFilter.SubscribeGlobalFilter("OnAttack", function(eventData)
|
||||
if math.random() < 0.3 then
|
||||
print("⚡ 暴击符文生效:暴击!")
|
||||
eventData.damage = eventData.damage * 2
|
||||
eventData.isCritical = true
|
||||
end
|
||||
return eventData
|
||||
end, 5, criticalRune) -- 优先级5,所有者是criticalRune
|
||||
end
|
||||
|
||||
-- 3. 监听最终结果
|
||||
local function setupResultListener()
|
||||
EventFilter.SubscribeGlobal("OnAttack", function(finalData)
|
||||
print("=== 最终攻击结果 ===")
|
||||
print("伤害:", finalData.damage)
|
||||
print("元素:", finalData.element or "无")
|
||||
print("暴击:", finalData.isCritical and "是" or "否")
|
||||
print("冰冻:", finalData.freeze and "是" or "否")
|
||||
print("==================")
|
||||
end)
|
||||
end
|
||||
|
||||
-- 4. 发送攻击事件
|
||||
local function sendAttackEvent()
|
||||
local attackData = {
|
||||
damage = 100,
|
||||
attacker = "玩家",
|
||||
target = "敌人"
|
||||
}
|
||||
|
||||
print("🗡️ 发送攻击事件,基础伤害:", attackData.damage)
|
||||
|
||||
EventFilter.FireGlobalWithFilter("OnAttack", attackData, function(processedData)
|
||||
print("✅ 攻击事件处理完成!")
|
||||
-- 这里可以执行实际的攻击逻辑
|
||||
-- 比如:DealDamage(processedData.damage, processedData.target)
|
||||
end)
|
||||
end
|
||||
|
||||
-- ===== 演示自动回收 =====
|
||||
|
||||
local function demonstrateAutoCleanup()
|
||||
print("\n=== 演示自动回收 ===")
|
||||
|
||||
-- 第一次攻击:所有符文生效
|
||||
print("\n第一次攻击(所有符文生效):")
|
||||
sendAttackEvent()
|
||||
|
||||
-- 销毁火焰符文
|
||||
print("\n销毁火焰符文...")
|
||||
fireRune:Destroy()
|
||||
|
||||
-- 第二次攻击:只有冰霜和暴击符文生效
|
||||
print("\n第二次攻击(冰霜+暴击符文生效):")
|
||||
sendAttackEvent()
|
||||
|
||||
-- 销毁冰霜符文
|
||||
print("\n销毁冰霜符文...")
|
||||
iceRune:Destroy()
|
||||
|
||||
-- 第三次攻击:只有暴击符文生效
|
||||
print("\n第三次攻击(只有暴击符文生效):")
|
||||
sendAttackEvent()
|
||||
|
||||
-- 销毁暴击符文
|
||||
print("\n销毁暴击符文...")
|
||||
criticalRune:Destroy()
|
||||
|
||||
-- 第四次攻击:没有符文生效
|
||||
print("\n第四次攻击(没有符文生效):")
|
||||
sendAttackEvent()
|
||||
end
|
||||
|
||||
-- ===== 实际游戏场景示例 =====
|
||||
|
||||
local function gameSceneExample()
|
||||
print("\n=== 实际游戏场景示例 ===")
|
||||
|
||||
-- 模拟玩家攻击
|
||||
local function playerAttack()
|
||||
local attackData = {
|
||||
damage = 80,
|
||||
attackType = "melee",
|
||||
attacker = game.Players.LocalPlayer,
|
||||
target = nil, -- 目标敌人
|
||||
weaponType = "sword"
|
||||
}
|
||||
|
||||
print("玩家发起攻击...")
|
||||
|
||||
-- 发送攻击事件,让符文系统处理
|
||||
EventFilter.FireGlobalWithFilter("OnAttack", attackData, function(finalData)
|
||||
print("执行攻击:", finalData.damage, "点伤害")
|
||||
|
||||
-- 应用元素效果
|
||||
if finalData.element == "fire" then
|
||||
print("🔥 造成燃烧效果")
|
||||
elseif finalData.element == "ice" then
|
||||
print("❄️ 造成冰冻效果")
|
||||
end
|
||||
|
||||
-- 应用暴击效果
|
||||
if finalData.isCritical then
|
||||
print("⚡ 暴击!")
|
||||
end
|
||||
|
||||
-- 应用冰冻效果
|
||||
if finalData.freeze then
|
||||
print("💎 目标被冰冻!")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- 执行攻击
|
||||
playerAttack()
|
||||
end
|
||||
|
||||
-- ===== 主函数:完整演示 =====
|
||||
|
||||
local function runCompleteExample()
|
||||
print("=== EventFilter使用示例 ===")
|
||||
|
||||
-- 1. 创建符文
|
||||
local fireRune, iceRune, criticalRune = createRunes()
|
||||
print("创建了三个符文")
|
||||
|
||||
-- 2. 设置符文效果
|
||||
setupRuneEffects(fireRune, iceRune, criticalRune)
|
||||
print("设置了符文效果")
|
||||
|
||||
-- 3. 设置结果监听
|
||||
setupResultListener()
|
||||
print("设置了结果监听")
|
||||
|
||||
-- 4. 演示自动回收
|
||||
demonstrateAutoCleanup()
|
||||
|
||||
-- 5. 实际游戏场景
|
||||
gameSceneExample()
|
||||
|
||||
print("\n=== 示例完成 ===")
|
||||
end
|
||||
|
||||
-- ===== 导出函数 =====
|
||||
|
||||
return {
|
||||
runCompleteExample = runCompleteExample,
|
||||
createRunes = createRunes,
|
||||
setupRuneEffects = setupRuneEffects,
|
||||
sendAttackEvent = sendAttackEvent,
|
||||
demonstrateAutoCleanup = demonstrateAutoCleanup,
|
||||
gameSceneExample = gameSceneExample
|
||||
}
|
86
src/ReplicatedStorage/Modules/EventFilterQuickStart.luau
Normal file
86
src/ReplicatedStorage/Modules/EventFilterQuickStart.luau
Normal file
@ -0,0 +1,86 @@
|
||||
--[[
|
||||
EventFilter快速入门指南
|
||||
最简单的使用方式
|
||||
]]
|
||||
|
||||
local EventFilter = require(script.Parent.EventFilter)
|
||||
|
||||
-- ===== 最简单的使用方式 =====
|
||||
|
||||
-- 1. 创建符文对象
|
||||
local myRune = {
|
||||
name = "我的符文",
|
||||
level = 1
|
||||
}
|
||||
|
||||
-- 2. 添加Destroy方法(用于自动回收)
|
||||
function myRune:Destroy()
|
||||
print("销毁符文:", self.name)
|
||||
for k, v in pairs(self) do self[k] = nil end
|
||||
self = nil
|
||||
end
|
||||
|
||||
-- 3. 让符文订阅事件
|
||||
EventFilter.SubscribeGlobalFilter("OnAttack", function(eventData)
|
||||
print("符文生效:伤害 +50%")
|
||||
eventData.damage = eventData.damage * 1.5
|
||||
return eventData
|
||||
end, 10, myRune) -- 事件名, 处理函数, 优先级, 所有者
|
||||
|
||||
-- 4. 发送事件
|
||||
local attackData = {damage = 100}
|
||||
EventFilter.FireGlobalWithFilter("OnAttack", attackData, function(processedData)
|
||||
print("最终伤害:", processedData.damage) -- 输出:150
|
||||
end)
|
||||
|
||||
-- 5. 销毁符文(自动回收)
|
||||
myRune:Destroy() -- Filter自动失效,不需要手动取消订阅
|
||||
|
||||
-- ===== 实际游戏中的使用 =====
|
||||
|
||||
-- 在攻击脚本中:
|
||||
local function playerAttack()
|
||||
local attackData = {
|
||||
damage = 100,
|
||||
attackType = "melee",
|
||||
target = enemy
|
||||
}
|
||||
|
||||
-- 发送攻击事件,让符文系统处理
|
||||
EventFilter.FireGlobalWithFilter("OnAttack", attackData, function(finalData)
|
||||
-- 使用处理后的数据执行实际攻击
|
||||
DealDamage(finalData.damage, finalData.target)
|
||||
end)
|
||||
end
|
||||
|
||||
-- 在符文脚本中:
|
||||
local function setupRune(runeInstance)
|
||||
-- 符文订阅攻击事件
|
||||
EventFilter.SubscribeGlobalFilter("OnAttack", function(data)
|
||||
-- 符文效果:增加伤害
|
||||
data.damage = data.damage * 1.2
|
||||
return data
|
||||
end, 5, runeInstance)
|
||||
end
|
||||
|
||||
-- ===== 常用事件类型 =====
|
||||
-- "OnAttack" - 攻击事件
|
||||
-- "OnMove" - 移动事件
|
||||
-- "OnSkill" - 技能事件
|
||||
-- "OnDamage" - 受伤事件
|
||||
-- "OnHeal" - 治疗事件
|
||||
|
||||
-- ===== 优先级说明 =====
|
||||
-- 数字越大,优先级越高,越先执行
|
||||
-- 10: 最高优先级(比如基础属性修改)
|
||||
-- 5: 中等优先级(比如元素转换)
|
||||
-- 1: 最低优先级(比如暴击判定)
|
||||
|
||||
-- ===== 自动回收的好处 =====
|
||||
-- 1. 不需要手动管理:符文销毁时Filter自动失效
|
||||
-- 2. 内存安全:不会造成内存泄露
|
||||
-- 3. 代码简洁:不需要写清理代码
|
||||
|
||||
return {
|
||||
-- 这里可以添加一些辅助函数
|
||||
}
|
178
src/ReplicatedStorage/Modules/Filter.luau
Normal file
178
src/ReplicatedStorage/Modules/Filter.luau
Normal file
@ -0,0 +1,178 @@
|
||||
--[[
|
||||
Filter System - 自动回收版本
|
||||
用于实现事件数据的过滤和处理功能
|
||||
支持多个Filter的链式处理、优先级排序和数据回调
|
||||
自动回收机制,无需手动管理生命周期
|
||||
]]
|
||||
|
||||
-- Filter处理器类型
|
||||
export type FilterHandler = {
|
||||
handlerFunction: (data: any) -> any,
|
||||
priority: number,
|
||||
id: string,
|
||||
weakRef: any -- 弱引用,用于自动回收
|
||||
}
|
||||
|
||||
-- Filter系统类
|
||||
local Filter = {}
|
||||
Filter.__index = Filter
|
||||
Filter.ClassName = "Filter"
|
||||
|
||||
export type Filter = typeof(Filter)
|
||||
|
||||
-- 全局Filter实例(使用弱表自动回收)
|
||||
local GlobalFilters = setmetatable({}, {__mode = "k"})
|
||||
|
||||
function Filter.new(name: string?): Filter
|
||||
local filter = setmetatable({
|
||||
Name = name or "GlobalFilter",
|
||||
_handlers = {}, -- 存储所有Filter处理器
|
||||
_nextHandlerId = 1,
|
||||
_weakRefs = setmetatable({}, {__mode = "k"}) -- 弱引用表
|
||||
}, Filter)
|
||||
|
||||
if name then
|
||||
GlobalFilters[filter] = true
|
||||
end
|
||||
|
||||
return filter
|
||||
end
|
||||
|
||||
-- 添加Filter处理器(自动回收版本)
|
||||
function Filter:AddHandler(handlerFunction: (data: any) -> any, priority: number?, owner: any?): string
|
||||
local handlerId = tostring(self._nextHandlerId)
|
||||
self._nextHandlerId = self._nextHandlerId + 1
|
||||
|
||||
local handler: FilterHandler = {
|
||||
handlerFunction = handlerFunction,
|
||||
priority = priority or 0,
|
||||
id = handlerId,
|
||||
weakRef = owner -- 存储所有者引用
|
||||
}
|
||||
|
||||
table.insert(self._handlers, handler)
|
||||
|
||||
-- 如果提供了所有者,创建弱引用
|
||||
if owner then
|
||||
self._weakRefs[owner] = handlerId
|
||||
end
|
||||
|
||||
-- 按优先级排序(优先级高的先执行)
|
||||
table.sort(self._handlers, function(a, b)
|
||||
return a.priority > b.priority
|
||||
end)
|
||||
|
||||
return handlerId
|
||||
end
|
||||
|
||||
-- 移除Filter处理器
|
||||
function Filter:RemoveHandler(handlerId: string): boolean
|
||||
for i, handler in ipairs(self._handlers) do
|
||||
if handler.id == handlerId then
|
||||
table.remove(self._handlers, i)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- 清理无效的处理器(自动回收)
|
||||
function Filter:CleanupHandlers()
|
||||
local validHandlers = {}
|
||||
|
||||
for _, handler in ipairs(self._handlers) do
|
||||
local isValid = true
|
||||
|
||||
if handler.weakRef then
|
||||
-- 检查Instance类型
|
||||
if typeof(handler.weakRef) == "Instance" then
|
||||
-- Instance被销毁时Parent为nil
|
||||
if handler.weakRef.Parent == nil then
|
||||
isValid = false
|
||||
end
|
||||
else
|
||||
-- 对于table类型(如Rune类),检查是否有Destroy方法且是否已被销毁
|
||||
if type(handler.weakRef) == "table" then
|
||||
-- 检查是否还在弱引用表中(如果不在,说明已被垃圾回收)
|
||||
if not self._weakRefs[handler.weakRef] then
|
||||
isValid = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if isValid then
|
||||
table.insert(validHandlers, handler)
|
||||
end
|
||||
end
|
||||
|
||||
self._handlers = validHandlers
|
||||
end
|
||||
|
||||
-- 处理数据(链式Filter,自动清理)
|
||||
function Filter:ProcessData(data: any): any
|
||||
-- 自动清理无效处理器
|
||||
self:CleanupHandlers()
|
||||
|
||||
local processedData = data
|
||||
|
||||
for _, handler in ipairs(self._handlers) do
|
||||
local success, result = pcall(handler.handlerFunction, processedData)
|
||||
if success and result ~= nil then
|
||||
processedData = result
|
||||
end
|
||||
end
|
||||
|
||||
return processedData
|
||||
end
|
||||
|
||||
-- 带回调的数据处理(用于事件系统)
|
||||
function Filter:ProcessDataWithCallback(data: any, callback: (processedData: any) -> ())
|
||||
local processedData = self:ProcessData(data)
|
||||
callback(processedData)
|
||||
end
|
||||
|
||||
-- 获取处理器数量
|
||||
function Filter:GetHandlerCount(): number
|
||||
self:CleanupHandlers()
|
||||
return #self._handlers
|
||||
end
|
||||
|
||||
-- 获取所有处理器信息
|
||||
function Filter:GetHandlers(): {FilterHandler}
|
||||
self:CleanupHandlers()
|
||||
return self._handlers
|
||||
end
|
||||
|
||||
-- 便捷方法:创建全局Filter实例
|
||||
function Filter.GetGlobal(): Filter
|
||||
for filter, _ in pairs(GlobalFilters) do
|
||||
if filter.Name == "GlobalFilter" then
|
||||
return filter
|
||||
end
|
||||
end
|
||||
|
||||
return Filter.new("GlobalFilter")
|
||||
end
|
||||
|
||||
-- 便捷方法:快速添加处理器(带所有者)
|
||||
function Filter.AddGlobalHandler(handlerFunction: (data: any) -> any, priority: number?, owner: any?): string
|
||||
return Filter.GetGlobal():AddHandler(handlerFunction, priority, owner)
|
||||
end
|
||||
|
||||
-- 便捷方法:快速移除处理器
|
||||
function Filter.RemoveGlobalHandler(handlerId: string): boolean
|
||||
return Filter.GetGlobal():RemoveHandler(handlerId)
|
||||
end
|
||||
|
||||
-- 便捷方法:快速处理数据
|
||||
function Filter.ProcessGlobalData(data: any): any
|
||||
return Filter.GetGlobal():ProcessData(data)
|
||||
end
|
||||
|
||||
-- 便捷方法:快速处理数据带回调
|
||||
function Filter.ProcessGlobalDataWithCallback(data: any, callback: (processedData: any) -> ())
|
||||
Filter.GetGlobal():ProcessDataWithCallback(data, callback)
|
||||
end
|
||||
|
||||
return Filter
|
@ -154,6 +154,12 @@ function Random:GetRandomInt(min: number, max: number)
|
||||
return math.random(min, max)
|
||||
end
|
||||
|
||||
-- 百分比概率随机
|
||||
function Random:RandomPercent(percent: number)
|
||||
-- 随机1-100,如果随机值小于等于百分比,则返回true,否则返回false
|
||||
local randomValue = self:GetRandomInt(1, 100)
|
||||
return randomValue <= percent
|
||||
end
|
||||
|
||||
|
||||
-- 初始化随机种子
|
||||
|
@ -10,6 +10,7 @@ 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 Rng = require(ReplicatedStorage.Tools.Rng)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -20,11 +21,11 @@ setmetatable(Attack, {__index = Behaviour})
|
||||
local CAST_DISTANCE = 8
|
||||
local COOLDOWN = 1
|
||||
local ATTRIBUTE_LIST = {
|
||||
{Name = "attack", ElementType = DamageProxy.ElementType.NONE},
|
||||
{Name = "fireAtk", ElementType = DamageProxy.ElementType.FIRE},
|
||||
{Name = "iceAtk", ElementType = DamageProxy.ElementType.ICE},
|
||||
{Name = "lightAtk", ElementType = DamageProxy.ElementType.LIGHT},
|
||||
{Name = "shadowAtk", ElementType = DamageProxy.ElementType.SHADOW},
|
||||
{Name = "attack", ElementType = DamageProxy.ElementType.NONE, CritCheckRateName = "critRate", CritDamageRateName = "critDamageRate"},
|
||||
{Name = "fireAtk", ElementType = DamageProxy.ElementType.FIRE, CritCheckRateName = "critRateFire", CritDamageRateName = "critDamageRateFire"},
|
||||
{Name = "iceAtk", ElementType = DamageProxy.ElementType.ICE, CritCheckRateName = "critRateIce", CritDamageRateName = "critDamageRateIce"},
|
||||
{Name = "lightAtk", ElementType = DamageProxy.ElementType.LIGHT, CritCheckRateName = "critRateLight", CritDamageRateName = "critDamageRateLight"},
|
||||
{Name = "shadowAtk", ElementType = DamageProxy.ElementType.SHADOW, CritCheckRateName = "critRateShadow", CritDamageRateName = "critDamageRateShadow"},
|
||||
|
||||
}
|
||||
|
||||
@ -95,17 +96,28 @@ function Attack:Execute()
|
||||
})
|
||||
-- 攻击前摇
|
||||
task.wait(atkSpeed)
|
||||
|
||||
-- TODO: 之后这里可以提前做暴击判定
|
||||
|
||||
|
||||
-- 伤害逻辑计算部分
|
||||
local damageData = {}
|
||||
for _, attribute in ATTRIBUTE_LIST do
|
||||
local attributeValue = self:GetAttributeValue(attribute.Name)
|
||||
if attributeValue then
|
||||
|
||||
-- 暴击判定
|
||||
local DamageType = DamageProxy.DamageType.NORMAL
|
||||
local critCheckRate = self:GetAttributeValue(attribute.CritCheckRateName) or 0
|
||||
local critDamageRate = self:GetAttributeValue(attribute.CritDamageRateName) or 0
|
||||
if critCheckRate then
|
||||
if Rng:RandomPercent(critCheckRate) then
|
||||
attributeValue = attributeValue * (1 + (200 + critDamageRate) / 100)
|
||||
DamageType = DamageProxy.DamageType.CRIT
|
||||
end
|
||||
end
|
||||
|
||||
-- 记录伤害数据
|
||||
table.insert(damageData, {
|
||||
Damage = attributeValue,
|
||||
Type = DamageProxy.DamageType.NORMAL,
|
||||
Type = DamageType,
|
||||
Tag = DamageProxy.DamageTag.NORMAL,
|
||||
ElementType = attribute.ElementType,
|
||||
})
|
||||
|
51
src/ServerStorage/Modules/Runes/RuneBookQualityPurple.luau
Normal file
51
src/ServerStorage/Modules/Runes/RuneBookQualityPurple.luau
Normal file
@ -0,0 +1,51 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneBookQualityPurple = {}
|
||||
RuneBookQualityPurple.__index = RuneBookQualityPurple
|
||||
setmetatable(RuneBookQualityPurple, {__index = Rune})
|
||||
|
||||
|
||||
function RuneBookQualityPurple:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneBookQualityPurple)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneBookQualityPurple:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneBookQualityPurple:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData")
|
||||
if not pDataFolder then return nil end
|
||||
local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId)
|
||||
if not pData then return nil end
|
||||
|
||||
local bookFolder = pData:FindFirstChild("Book")
|
||||
if not bookFolder then return nil end
|
||||
local bookList = bookFolder:GetChildren()
|
||||
if #bookList == 0 then return nil end
|
||||
|
||||
local qualityNumber = 0
|
||||
for _, book in bookList do
|
||||
local bookQuality = book:GetAttribute("quality")
|
||||
if bookQuality >= 3 then
|
||||
qualityNumber = qualityNumber + 1
|
||||
end
|
||||
end
|
||||
local attackRate = math.floor(qualityNumber * 25 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneBookQualityPurple
|
34
src/ServerStorage/Modules/Runes/RuneCritDamageRateFire.luau
Normal file
34
src/ServerStorage/Modules/Runes/RuneCritDamageRateFire.luau
Normal file
@ -0,0 +1,34 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneCritDamageRateFire = {}
|
||||
RuneCritDamageRateFire.__index = RuneCritDamageRateFire
|
||||
setmetatable(RuneCritDamageRateFire, {__index = Rune})
|
||||
|
||||
|
||||
function RuneCritDamageRateFire:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneCritDamageRateFire)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneCritDamageRateFire:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneCritDamageRateFire:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local nowAttribute = AttributesData.critDamageRateFire or 200
|
||||
local addAttribute = math.floor(nowAttribute * 50 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "critDamageRateFire", addAttribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneCritDamageRateFire
|
34
src/ServerStorage/Modules/Runes/RuneCritDamageRateIce.luau
Normal file
34
src/ServerStorage/Modules/Runes/RuneCritDamageRateIce.luau
Normal file
@ -0,0 +1,34 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneCritDamageRateIce = {}
|
||||
RuneCritDamageRateIce.__index = RuneCritDamageRateIce
|
||||
setmetatable(RuneCritDamageRateIce, {__index = Rune})
|
||||
|
||||
|
||||
function RuneCritDamageRateIce:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneCritDamageRateIce)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneCritDamageRateIce:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneCritDamageRateIce:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local nowAttribute = AttributesData.critDamageRateIce or 200
|
||||
local addAttribute = math.floor(nowAttribute * 50 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "critDamageRateIce", addAttribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneCritDamageRateIce
|
34
src/ServerStorage/Modules/Runes/RuneCritDamageRateLight.luau
Normal file
34
src/ServerStorage/Modules/Runes/RuneCritDamageRateLight.luau
Normal file
@ -0,0 +1,34 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneCritDamageRateLight = {}
|
||||
RuneCritDamageRateLight.__index = RuneCritDamageRateLight
|
||||
setmetatable(RuneCritDamageRateLight, {__index = Rune})
|
||||
|
||||
|
||||
function RuneCritDamageRateLight:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneCritDamageRateLight)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneCritDamageRateLight:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneCritDamageRateLight:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local nowAttribute = AttributesData.critDamageRateLight or 200
|
||||
local addAttribute = math.floor(nowAttribute * 50 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "critDamageRateLight", addAttribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneCritDamageRateLight
|
@ -0,0 +1,34 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneCritDamageRateShadow = {}
|
||||
RuneCritDamageRateShadow.__index = RuneCritDamageRateShadow
|
||||
setmetatable(RuneCritDamageRateShadow, {__index = Rune})
|
||||
|
||||
|
||||
function RuneCritDamageRateShadow:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneCritDamageRateShadow)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneCritDamageRateShadow:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneCritDamageRateShadow:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local nowAttribute = AttributesData.critDamageRateShadow or 200
|
||||
local addAttribute = math.floor(nowAttribute * 50 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "critDamageRateShadow", addAttribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneCritDamageRateShadow
|
@ -24,8 +24,9 @@ function RuneFireDamage:Check(index: number, AttributesData: table, BehaviorName
|
||||
end
|
||||
|
||||
function RuneFireDamage:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
print("RuneFireDamage:OnExecute", index, AttributesData, BehaviorNameList)
|
||||
Utils:TableSafeAddValue(AttributesData, "fireAtk", 100)
|
||||
local baseAttribute = AttributesData.fireAtk or 100
|
||||
local addAttribute = math.floor(baseAttribute * 50 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "fireAtk", addAttribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
@ -24,7 +24,6 @@ function RuneIceCoffin:Check(index: number, AttributesData: table, BehaviorNameL
|
||||
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)
|
||||
|
34
src/ServerStorage/Modules/Runes/RuneIceDamage.luau
Normal file
34
src/ServerStorage/Modules/Runes/RuneIceDamage.luau
Normal file
@ -0,0 +1,34 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneIceDamage = {}
|
||||
RuneIceDamage.__index = RuneIceDamage
|
||||
setmetatable(RuneIceDamage, {__index = Rune})
|
||||
|
||||
|
||||
function RuneIceDamage:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneIceDamage)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneIceDamage:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneIceDamage:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local baseAttribute = AttributesData.iceAtk or 100
|
||||
local addAttribute = math.floor(baseAttribute * 50 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "iceAtk", addAttribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneIceDamage
|
34
src/ServerStorage/Modules/Runes/RuneLightDamage.luau
Normal file
34
src/ServerStorage/Modules/Runes/RuneLightDamage.luau
Normal file
@ -0,0 +1,34 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneLightDamage = {}
|
||||
RuneLightDamage.__index = RuneLightDamage
|
||||
setmetatable(RuneLightDamage, {__index = Rune})
|
||||
|
||||
|
||||
function RuneLightDamage:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneLightDamage)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneLightDamage:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneLightDamage:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local baseAttribute = AttributesData.lightAtk or 100
|
||||
local addAttribute = math.floor(baseAttribute * 50 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "lightAtk", addAttribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneLightDamage
|
34
src/ServerStorage/Modules/Runes/RuneShadowDamage.luau
Normal file
34
src/ServerStorage/Modules/Runes/RuneShadowDamage.luau
Normal file
@ -0,0 +1,34 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneShadowDamage = {}
|
||||
RuneShadowDamage.__index = RuneShadowDamage
|
||||
setmetatable(RuneShadowDamage, {__index = Rune})
|
||||
|
||||
|
||||
function RuneShadowDamage:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneShadowDamage)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneShadowDamage:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneShadowDamage:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local baseAttribute = AttributesData.shadowAtk or 100
|
||||
local addAttribute = math.floor(baseAttribute * 50 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "shadowAtk", addAttribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneShadowDamage
|
52
src/ServerStorage/Modules/Runes/RuneWearElementAttack.luau
Normal file
52
src/ServerStorage/Modules/Runes/RuneWearElementAttack.luau
Normal file
@ -0,0 +1,52 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneWearElementAttack = {}
|
||||
RuneWearElementAttack.__index = RuneWearElementAttack
|
||||
setmetatable(RuneWearElementAttack, {__index = Rune})
|
||||
|
||||
|
||||
function RuneWearElementAttack:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneWearElementAttack)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneWearElementAttack:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneWearElementAttack:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData")
|
||||
if not pDataFolder then return nil end
|
||||
local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId)
|
||||
if not pData then return nil end
|
||||
|
||||
local equipmentFolder = pData:FindFirstChild("Equipment")
|
||||
if not equipmentFolder then return nil end
|
||||
local equipmentList = equipmentFolder:GetChildren()
|
||||
if #equipmentList == 0 then return nil end
|
||||
|
||||
local elementNumber = 0
|
||||
for _, equipment in equipmentList do
|
||||
local equipmentWearing = equipment:GetAttribute("wearing")
|
||||
if equipmentWearing > 0 then
|
||||
elementNumber = elementNumber + #equipment:FindFirstChild("Element"):GetAttributes()
|
||||
end
|
||||
end
|
||||
|
||||
local attackRate = math.floor(elementNumber * 25 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneWearElementAttack
|
70
src/ServerStorage/Modules/Runes/RuneWearEmptySlot.luau
Normal file
70
src/ServerStorage/Modules/Runes/RuneWearEmptySlot.luau
Normal file
@ -0,0 +1,70 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneWearEmptySlot = {}
|
||||
RuneWearEmptySlot.__index = RuneWearEmptySlot
|
||||
setmetatable(RuneWearEmptySlot, {__index = Rune})
|
||||
|
||||
|
||||
function RuneWearEmptySlot:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneWearEmptySlot)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneWearEmptySlot:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneWearEmptySlot:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData")
|
||||
if not pDataFolder then return nil end
|
||||
local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId)
|
||||
if not pData then return nil end
|
||||
|
||||
local equipmentFolder = pData:FindFirstChild("Equipment")
|
||||
if not equipmentFolder then return nil end
|
||||
local equipmentList = equipmentFolder:GetChildren()
|
||||
if #equipmentList == 0 then return nil end
|
||||
|
||||
local runeFolder = pData:FindFirstChild("Rune")
|
||||
if not runeFolder then return nil end
|
||||
local runeList = runeFolder:GetChildren()
|
||||
if #runeList == 0 then return nil end
|
||||
|
||||
|
||||
local maxRuneNumber = 0
|
||||
local hasSlotNumber = 0
|
||||
local wearWeaponList = {}
|
||||
for _, equipment in equipmentList do
|
||||
local equipmentWearing = equipment:GetAttribute("wearing")
|
||||
if equipmentWearing > 0 then
|
||||
maxRuneNumber = maxRuneNumber + 1
|
||||
table.insert(wearWeaponList, equipment.Name)
|
||||
end
|
||||
end
|
||||
|
||||
for _, rune in runeList do
|
||||
local runeWearing = rune:GetAttribute("wearing")
|
||||
if runeWearing then
|
||||
if table.find(wearWeaponList, tostring(runeWearing)) then
|
||||
hasSlotNumber = hasSlotNumber + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local attackRate = math.floor((maxRuneNumber - hasSlotNumber) * 25 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneWearEmptySlot
|
70
src/ServerStorage/Modules/Runes/RuneWearFillSlot.luau
Normal file
70
src/ServerStorage/Modules/Runes/RuneWearFillSlot.luau
Normal file
@ -0,0 +1,70 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneWearFillSlot = {}
|
||||
RuneWearFillSlot.__index = RuneWearFillSlot
|
||||
setmetatable(RuneWearFillSlot, {__index = Rune})
|
||||
|
||||
|
||||
function RuneWearFillSlot:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneWearFillSlot)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneWearFillSlot:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneWearFillSlot:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData")
|
||||
if not pDataFolder then return nil end
|
||||
local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId)
|
||||
if not pData then return nil end
|
||||
|
||||
local equipmentFolder = pData:FindFirstChild("Equipment")
|
||||
if not equipmentFolder then return nil end
|
||||
local equipmentList = equipmentFolder:GetChildren()
|
||||
if #equipmentList == 0 then return nil end
|
||||
|
||||
local runeFolder = pData:FindFirstChild("Rune")
|
||||
if not runeFolder then return nil end
|
||||
local runeList = runeFolder:GetChildren()
|
||||
if #runeList == 0 then return nil end
|
||||
|
||||
|
||||
local maxRuneNumber = 0
|
||||
local hasSlotNumber = 0
|
||||
local wearWeaponList = {}
|
||||
for _, equipment in equipmentList do
|
||||
local equipmentWearing = equipment:GetAttribute("wearing")
|
||||
if equipmentWearing > 0 then
|
||||
maxRuneNumber = maxRuneNumber + 1
|
||||
table.insert(wearWeaponList, equipment.Name)
|
||||
end
|
||||
end
|
||||
|
||||
for _, rune in runeList do
|
||||
local runeWearing = rune:GetAttribute("wearing")
|
||||
if runeWearing then
|
||||
if table.find(wearWeaponList, tostring(runeWearing)) then
|
||||
hasSlotNumber = hasSlotNumber + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local attackRate = math.floor(hasSlotNumber * 25 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneWearFillSlot
|
60
src/ServerStorage/Modules/Runes/RuneWearHeavySword.luau
Normal file
60
src/ServerStorage/Modules/Runes/RuneWearHeavySword.luau
Normal file
@ -0,0 +1,60 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneWearHeavySword = {}
|
||||
RuneWearHeavySword.__index = RuneWearHeavySword
|
||||
setmetatable(RuneWearHeavySword, {__index = Rune})
|
||||
|
||||
|
||||
function RuneWearHeavySword:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneWearHeavySword)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneWearHeavySword:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneWearHeavySword:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData")
|
||||
if not pDataFolder then return nil end
|
||||
local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId)
|
||||
if not pData then return nil end
|
||||
|
||||
local equipmentFolder = pData:FindFirstChild("Equipment")
|
||||
if not equipmentFolder then return nil end
|
||||
local equipmentList = equipmentFolder:GetChildren()
|
||||
if #equipmentList == 0 then return nil end
|
||||
|
||||
|
||||
local CheckSubType = 4
|
||||
local subTypeNumber = 0
|
||||
for _, equipment in equipmentList do
|
||||
local equipmentSubType = equipment:GetAttribute("subType")
|
||||
local equipmentWearing = equipment:GetAttribute("wearing")
|
||||
if equipmentSubType == CheckSubType and equipmentWearing > 0 then
|
||||
subTypeNumber = subTypeNumber + 1
|
||||
end
|
||||
end
|
||||
|
||||
local CheckShareName = "RuneTagHeavySword"
|
||||
if self.PlayerAI:GetSharedData(CheckShareName) then
|
||||
subTypeNumber = subTypeNumber + self.PlayerAI:GetSharedData(CheckShareName)
|
||||
end
|
||||
|
||||
local attackRate = math.floor(subTypeNumber * 25 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneWearHeavySword
|
60
src/ServerStorage/Modules/Runes/RuneWearKnife.luau
Normal file
60
src/ServerStorage/Modules/Runes/RuneWearKnife.luau
Normal file
@ -0,0 +1,60 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneWearKnife = {}
|
||||
RuneWearKnife.__index = RuneWearKnife
|
||||
setmetatable(RuneWearKnife, {__index = Rune})
|
||||
|
||||
|
||||
function RuneWearKnife:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneWearKnife)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneWearKnife:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneWearKnife:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData")
|
||||
if not pDataFolder then return nil end
|
||||
local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId)
|
||||
if not pData then return nil end
|
||||
|
||||
local equipmentFolder = pData:FindFirstChild("Equipment")
|
||||
if not equipmentFolder then return nil end
|
||||
local equipmentList = equipmentFolder:GetChildren()
|
||||
if #equipmentList == 0 then return nil end
|
||||
|
||||
|
||||
local CheckSubType = 1
|
||||
local subTypeNumber = 0
|
||||
for _, equipment in equipmentList do
|
||||
local equipmentSubType = equipment:GetAttribute("subType")
|
||||
local equipmentWearing = equipment:GetAttribute("wearing")
|
||||
if equipmentSubType == CheckSubType and equipmentWearing > 0 then
|
||||
subTypeNumber = subTypeNumber + 1
|
||||
end
|
||||
end
|
||||
|
||||
local CheckShareName = "RuneTagKnife"
|
||||
if self.PlayerAI:GetSharedData(CheckShareName) then
|
||||
subTypeNumber = subTypeNumber + self.PlayerAI:GetSharedData(CheckShareName)
|
||||
end
|
||||
|
||||
local attackRate = math.floor(subTypeNumber * 25 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneWearKnife
|
60
src/ServerStorage/Modules/Runes/RuneWearStick.luau
Normal file
60
src/ServerStorage/Modules/Runes/RuneWearStick.luau
Normal file
@ -0,0 +1,60 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneWearStick = {}
|
||||
RuneWearStick.__index = RuneWearStick
|
||||
setmetatable(RuneWearStick, {__index = Rune})
|
||||
|
||||
|
||||
function RuneWearStick:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneWearStick)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneWearStick:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneWearStick:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData")
|
||||
if not pDataFolder then return nil end
|
||||
local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId)
|
||||
if not pData then return nil end
|
||||
|
||||
local equipmentFolder = pData:FindFirstChild("Equipment")
|
||||
if not equipmentFolder then return nil end
|
||||
local equipmentList = equipmentFolder:GetChildren()
|
||||
if #equipmentList == 0 then return nil end
|
||||
|
||||
|
||||
local CheckSubType = 3
|
||||
local subTypeNumber = 0
|
||||
for _, equipment in equipmentList do
|
||||
local equipmentSubType = equipment:GetAttribute("subType")
|
||||
local equipmentWearing = equipment:GetAttribute("wearing")
|
||||
if equipmentSubType == CheckSubType and equipmentWearing > 0 then
|
||||
subTypeNumber = subTypeNumber + 1
|
||||
end
|
||||
end
|
||||
|
||||
local CheckShareName = "RuneTagStick"
|
||||
if self.PlayerAI:GetSharedData(CheckShareName) then
|
||||
subTypeNumber = subTypeNumber + self.PlayerAI:GetSharedData(CheckShareName)
|
||||
end
|
||||
|
||||
local attackRate = math.floor(subTypeNumber * 25 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneWearStick
|
60
src/ServerStorage/Modules/Runes/RuneWearSword.luau
Normal file
60
src/ServerStorage/Modules/Runes/RuneWearSword.luau
Normal file
@ -0,0 +1,60 @@
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Rune = require(ServerStorage.Base.Rune)
|
||||
|
||||
local RuneWearSword = {}
|
||||
RuneWearSword.__index = RuneWearSword
|
||||
setmetatable(RuneWearSword, {__index = Rune})
|
||||
|
||||
|
||||
function RuneWearSword:Init(PlayerAI, Character: TypeList.Character)
|
||||
local self = Rune:Init(PlayerAI, Character, script.Name)
|
||||
setmetatable(self, RuneWearSword)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function RuneWearSword:Check(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
return true
|
||||
end
|
||||
|
||||
function RuneWearSword:OnExecute(index: number, AttributesData: table, BehaviorNameList: table)
|
||||
local pDataFolder = ReplicatedStorage:FindFirstChild("PlayerData")
|
||||
if not pDataFolder then return nil end
|
||||
local pData = pDataFolder:FindFirstChild(self.PlayerAI.Player.UserId)
|
||||
if not pData then return nil end
|
||||
|
||||
local equipmentFolder = pData:FindFirstChild("Equipment")
|
||||
if not equipmentFolder then return nil end
|
||||
local equipmentList = equipmentFolder:GetChildren()
|
||||
if #equipmentList == 0 then return nil end
|
||||
|
||||
|
||||
local CheckSubType = 2
|
||||
local subTypeNumber = 0
|
||||
for _, equipment in equipmentList do
|
||||
local equipmentSubType = equipment:GetAttribute("subType")
|
||||
local equipmentWearing = equipment:GetAttribute("wearing")
|
||||
if equipmentSubType == CheckSubType and equipmentWearing > 0 then
|
||||
subTypeNumber = subTypeNumber + 1
|
||||
end
|
||||
end
|
||||
|
||||
local CheckShareName = "RuneTagSword"
|
||||
if self.PlayerAI:GetSharedData(CheckShareName) then
|
||||
subTypeNumber = subTypeNumber + self.PlayerAI:GetSharedData(CheckShareName)
|
||||
end
|
||||
|
||||
local attackRate = math.floor(subTypeNumber * 25 / 100)
|
||||
Utils:TableSafeAddValue(AttributesData, "attackRate", attackRate)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return RuneWearSword
|
Loading…
x
Reference in New Issue
Block a user