更新
This commit is contained in:
parent
c1c22aa963
commit
ac7c83a9bb
@ -32,6 +32,9 @@
|
||||
|
||||
"ReplicatedStorage": {
|
||||
"$className": "ReplicatedStorage",
|
||||
"Base": {
|
||||
"$path": "src/ReplicatedStorage/Base"
|
||||
},
|
||||
"Data": {
|
||||
"$path": "src/ReplicatedStorage/Data"
|
||||
},
|
||||
|
BIN
excel/attribute.xlsx
Normal file
BIN
excel/attribute.xlsx
Normal file
Binary file not shown.
BIN
excel/cha.xlsx
BIN
excel/cha.xlsx
Binary file not shown.
BIN
excel/gem.xlsx
Normal file
BIN
excel/gem.xlsx
Normal file
Binary file not shown.
BIN
excel/item.xlsx
BIN
excel/item.xlsx
Binary file not shown.
38
src/ReplicatedStorage/Base/BehaviourClient.luau
Normal file
38
src/ReplicatedStorage/Base/BehaviourClient.luau
Normal file
@ -0,0 +1,38 @@
|
||||
local BehaviourClient = {}
|
||||
BehaviourClient.__index = BehaviourClient
|
||||
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
--> Dependencies
|
||||
local EffectDispatcher = require(ReplicatedStorage.Modules.EffectDispatcher)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 刷新时,重新载入,暂时不考虑性能
|
||||
|
||||
-- 初始化内容
|
||||
function BehaviourClient:Init(CasterPlayer: Player, CastInfo: table, DelayTime: number, CastState: boolean)
|
||||
local self = {}
|
||||
self.Player = CasterPlayer
|
||||
self.Character = CasterPlayer.Character
|
||||
self.ShowTask = nil
|
||||
self.EffectDispatcher = EffectDispatcher
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function BehaviourClient:Show(CasterPlayer: Player, CastInfo: table, DelayTime: number, CastState: boolean)
|
||||
|
||||
end
|
||||
|
||||
-- 销毁
|
||||
function BehaviourClient:Destroy()
|
||||
if self.ShowTask then
|
||||
task.cancel(self.ShowTask)
|
||||
self.ShowTask = nil
|
||||
end
|
||||
self = nil
|
||||
end
|
||||
|
||||
return BehaviourClient
|
21
src/ReplicatedStorage/Json/Attributes.json
Normal file
21
src/ReplicatedStorage/Json/Attributes.json
Normal file
@ -0,0 +1,21 @@
|
||||
[
|
||||
{"id":1,"type":1,"effectAttribute":"attack","battleValue":[1,10]},
|
||||
{"id":2,"type":1,"effectAttribute":"hp","battleValue":[1,10]},
|
||||
{"id":3,"type":1,"effectAttribute":"swordAtk","battleValue":[1,10]},
|
||||
{"id":4,"type":2,"effectAttribute":"swordWearBase","battleValue":[1,10]},
|
||||
{"id":5,"type":2,"effectAttribute":"swordWearSpe","battleValue":[1,10]},
|
||||
{"id":6,"type":1,"effectAttribute":"fireAtk","battleValue":[1,10]},
|
||||
{"id":7,"type":1,"effectAttribute":"iceAtk","battleValue":[1,10]},
|
||||
{"id":8,"type":1,"effectAttribute":"lightAtk","battleValue":[1,10]},
|
||||
{"id":9,"type":1,"effectAttribute":"shadowAtk","battleValue":[1,10]},
|
||||
{"id":10,"type":1,"effectAttribute":"fireDef","battleValue":[1,10]},
|
||||
{"id":11,"type":1,"effectAttribute":"iceDef","battleValue":[1,10]},
|
||||
{"id":12,"type":1,"effectAttribute":"lightDef","battleValue":[1,10]},
|
||||
{"id":13,"type":1,"effectAttribute":"shadowDef","battleValue":[1,10]},
|
||||
{"id":50,"type":1,"effectAttribute":"wearNumber","battleValue":[1,10]},
|
||||
{"id":51,"type":1,"effectAttribute":"skillNumber","battleValue":[1,10]},
|
||||
{"id":52,"type":1,"effectAttribute":"extraAttributeNumber","battleValue":[1,10]},
|
||||
{"id":53,"type":1,"effectAttribute":"elementNumber","battleValue":[1,10]},
|
||||
{"id":54,"type":1,"effectAttribute":"elementDefNumber","battleValue":[1,10]},
|
||||
{"id":55,"type":1,"effectAttribute":"gemNumber","battleValue":[1,10]}
|
||||
]
|
58
src/ReplicatedStorage/Json/Gem.json
Normal file
58
src/ReplicatedStorage/Json/Gem.json
Normal file
@ -0,0 +1,58 @@
|
||||
[
|
||||
{"id":10000,"type":1,"quality":1,"iconId":1,"effectAttribute":"fireAtk","attributeValue":10},
|
||||
{"id":10001,"type":1,"quality":2,"iconId":2,"effectAttribute":"fireAtk","attributeValue":20},
|
||||
{"id":10002,"type":1,"quality":3,"iconId":3,"effectAttribute":"fireAtk","attributeValue":30},
|
||||
{"id":10003,"type":1,"quality":4,"iconId":4,"effectAttribute":"fireAtk","attributeValue":40},
|
||||
{"id":10004,"type":1,"quality":5,"iconId":5,"effectAttribute":"fireAtk","attributeValue":50},
|
||||
{"id":10005,"type":1,"quality":6,"iconId":6,"effectAttribute":"fireAtk","attributeValue":60},
|
||||
{"id":10006,"type":1,"quality":7,"iconId":7,"effectAttribute":"fireAtk","attributeValue":70},
|
||||
{"id":10100,"type":1,"quality":1,"iconId":1,"effectAttribute":"fireDef","attributeValue":10},
|
||||
{"id":10101,"type":1,"quality":2,"iconId":2,"effectAttribute":"fireDef","attributeValue":20},
|
||||
{"id":10102,"type":1,"quality":3,"iconId":3,"effectAttribute":"fireDef","attributeValue":30},
|
||||
{"id":10103,"type":1,"quality":4,"iconId":4,"effectAttribute":"fireDef","attributeValue":40},
|
||||
{"id":10104,"type":1,"quality":5,"iconId":5,"effectAttribute":"fireDef","attributeValue":50},
|
||||
{"id":10105,"type":1,"quality":6,"iconId":6,"effectAttribute":"fireDef","attributeValue":60},
|
||||
{"id":10106,"type":1,"quality":7,"iconId":7,"effectAttribute":"fireDef","attributeValue":70},
|
||||
{"id":11000,"type":2,"quality":1,"iconId":1,"effectAttribute":"iceAtk","attributeValue":10},
|
||||
{"id":11001,"type":2,"quality":2,"iconId":2,"effectAttribute":"iceAtk","attributeValue":20},
|
||||
{"id":11002,"type":2,"quality":3,"iconId":3,"effectAttribute":"iceAtk","attributeValue":30},
|
||||
{"id":11003,"type":2,"quality":4,"iconId":4,"effectAttribute":"iceAtk","attributeValue":40},
|
||||
{"id":11004,"type":2,"quality":5,"iconId":5,"effectAttribute":"iceAtk","attributeValue":50},
|
||||
{"id":11005,"type":2,"quality":6,"iconId":6,"effectAttribute":"iceAtk","attributeValue":60},
|
||||
{"id":11006,"type":2,"quality":7,"iconId":7,"effectAttribute":"iceAtk","attributeValue":70},
|
||||
{"id":11100,"type":2,"quality":1,"iconId":1,"effectAttribute":"iceDef","attributeValue":10},
|
||||
{"id":11101,"type":2,"quality":2,"iconId":2,"effectAttribute":"iceDef","attributeValue":20},
|
||||
{"id":11102,"type":2,"quality":3,"iconId":3,"effectAttribute":"iceDef","attributeValue":30},
|
||||
{"id":11103,"type":2,"quality":4,"iconId":4,"effectAttribute":"iceDef","attributeValue":40},
|
||||
{"id":11104,"type":2,"quality":5,"iconId":5,"effectAttribute":"iceDef","attributeValue":50},
|
||||
{"id":11105,"type":2,"quality":6,"iconId":6,"effectAttribute":"iceDef","attributeValue":60},
|
||||
{"id":11106,"type":2,"quality":7,"iconId":7,"effectAttribute":"iceDef","attributeValue":70},
|
||||
{"id":12000,"type":2,"quality":1,"iconId":1,"effectAttribute":"lightAtk","attributeValue":10},
|
||||
{"id":12001,"type":2,"quality":2,"iconId":2,"effectAttribute":"lightAtk","attributeValue":20},
|
||||
{"id":12002,"type":2,"quality":3,"iconId":3,"effectAttribute":"lightAtk","attributeValue":30},
|
||||
{"id":12003,"type":2,"quality":4,"iconId":4,"effectAttribute":"lightAtk","attributeValue":40},
|
||||
{"id":12004,"type":2,"quality":5,"iconId":5,"effectAttribute":"lightAtk","attributeValue":50},
|
||||
{"id":12005,"type":2,"quality":6,"iconId":6,"effectAttribute":"lightAtk","attributeValue":60},
|
||||
{"id":12006,"type":2,"quality":7,"iconId":7,"effectAttribute":"lightAtk","attributeValue":70},
|
||||
{"id":12100,"type":2,"quality":1,"iconId":1,"effectAttribute":"lightDef","attributeValue":10},
|
||||
{"id":12101,"type":2,"quality":2,"iconId":2,"effectAttribute":"lightDef","attributeValue":20},
|
||||
{"id":12102,"type":2,"quality":3,"iconId":3,"effectAttribute":"lightDef","attributeValue":30},
|
||||
{"id":12103,"type":2,"quality":4,"iconId":4,"effectAttribute":"lightDef","attributeValue":40},
|
||||
{"id":12104,"type":2,"quality":5,"iconId":5,"effectAttribute":"lightDef","attributeValue":50},
|
||||
{"id":12105,"type":2,"quality":6,"iconId":6,"effectAttribute":"lightDef","attributeValue":60},
|
||||
{"id":12106,"type":2,"quality":7,"iconId":7,"effectAttribute":"lightDef","attributeValue":70},
|
||||
{"id":13000,"type":2,"quality":1,"iconId":1,"effectAttribute":"shadowAtk","attributeValue":10},
|
||||
{"id":13001,"type":2,"quality":2,"iconId":2,"effectAttribute":"shadowAtk","attributeValue":20},
|
||||
{"id":13002,"type":2,"quality":3,"iconId":3,"effectAttribute":"shadowAtk","attributeValue":30},
|
||||
{"id":13003,"type":2,"quality":4,"iconId":4,"effectAttribute":"shadowAtk","attributeValue":40},
|
||||
{"id":13004,"type":2,"quality":5,"iconId":5,"effectAttribute":"shadowAtk","attributeValue":50},
|
||||
{"id":13005,"type":2,"quality":6,"iconId":6,"effectAttribute":"shadowAtk","attributeValue":60},
|
||||
{"id":13006,"type":2,"quality":7,"iconId":7,"effectAttribute":"shadowAtk","attributeValue":70},
|
||||
{"id":13100,"type":2,"quality":1,"iconId":1,"effectAttribute":"shadowDef","attributeValue":10},
|
||||
{"id":13101,"type":2,"quality":2,"iconId":2,"effectAttribute":"shadowDef","attributeValue":20},
|
||||
{"id":13102,"type":2,"quality":3,"iconId":3,"effectAttribute":"shadowDef","attributeValue":30},
|
||||
{"id":13103,"type":2,"quality":4,"iconId":4,"effectAttribute":"shadowDef","attributeValue":40},
|
||||
{"id":13104,"type":2,"quality":5,"iconId":5,"effectAttribute":"shadowDef","attributeValue":50},
|
||||
{"id":13105,"type":2,"quality":6,"iconId":6,"effectAttribute":"shadowDef","attributeValue":60},
|
||||
{"id":13106,"type":2,"quality":7,"iconId":7,"effectAttribute":"shadowDef","attributeValue":70}
|
||||
]
|
@ -1,4 +1,61 @@
|
||||
[
|
||||
{"id":1,"type":1,"typeArgs":[],"quality":4,"iconId":1,"nameId":10001,"textId":20001,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null},
|
||||
{"id":2,"type":1,"typeArgs":[],"quality":4,"iconId":2,"nameId":10002,"textId":20002,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null}
|
||||
{"id":2,"type":1,"typeArgs":[],"quality":4,"iconId":2,"nameId":10002,"textId":20002,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null},
|
||||
{"id":11,"type":1,"typeArgs":[],"quality":1,"iconId":11,"nameId":10011,"textId":20011,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null},
|
||||
{"id":10000,"type":4,"typeArgs":[],"quality":1,"iconId":12,"nameId":20000,"textId":30000,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null},
|
||||
{"id":10001,"type":4,"typeArgs":[],"quality":2,"iconId":13,"nameId":20001,"textId":30001,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null},
|
||||
{"id":10002,"type":4,"typeArgs":[],"quality":3,"iconId":14,"nameId":20002,"textId":30002,"buyPrice":[11,30],"sellPrice":[11,30],"use":[],"showPackage":null},
|
||||
{"id":10003,"type":4,"typeArgs":[],"quality":4,"iconId":15,"nameId":20003,"textId":30003,"buyPrice":[11,40],"sellPrice":[11,40],"use":[],"showPackage":null},
|
||||
{"id":10004,"type":4,"typeArgs":[],"quality":5,"iconId":16,"nameId":20004,"textId":30004,"buyPrice":[11,50],"sellPrice":[11,50],"use":[],"showPackage":null},
|
||||
{"id":10005,"type":4,"typeArgs":[],"quality":6,"iconId":17,"nameId":20005,"textId":30005,"buyPrice":[11,60],"sellPrice":[11,60],"use":[],"showPackage":null},
|
||||
{"id":10006,"type":4,"typeArgs":[],"quality":7,"iconId":18,"nameId":20006,"textId":30006,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null},
|
||||
{"id":10100,"type":4,"typeArgs":[],"quality":1,"iconId":19,"nameId":20100,"textId":30100,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null},
|
||||
{"id":10101,"type":4,"typeArgs":[],"quality":2,"iconId":20,"nameId":20101,"textId":30101,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null},
|
||||
{"id":10102,"type":4,"typeArgs":[],"quality":3,"iconId":21,"nameId":20102,"textId":30102,"buyPrice":[11,30],"sellPrice":[11,30],"use":[],"showPackage":null},
|
||||
{"id":10103,"type":4,"typeArgs":[],"quality":4,"iconId":22,"nameId":20103,"textId":30103,"buyPrice":[11,40],"sellPrice":[11,40],"use":[],"showPackage":null},
|
||||
{"id":10104,"type":4,"typeArgs":[],"quality":5,"iconId":23,"nameId":20104,"textId":30104,"buyPrice":[11,50],"sellPrice":[11,50],"use":[],"showPackage":null},
|
||||
{"id":10105,"type":4,"typeArgs":[],"quality":6,"iconId":24,"nameId":20105,"textId":30105,"buyPrice":[11,60],"sellPrice":[11,60],"use":[],"showPackage":null},
|
||||
{"id":10106,"type":4,"typeArgs":[],"quality":7,"iconId":25,"nameId":20106,"textId":30106,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null},
|
||||
{"id":11000,"type":4,"typeArgs":[],"quality":1,"iconId":26,"nameId":21000,"textId":31000,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null},
|
||||
{"id":11001,"type":4,"typeArgs":[],"quality":2,"iconId":27,"nameId":21001,"textId":31001,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null},
|
||||
{"id":11002,"type":4,"typeArgs":[],"quality":3,"iconId":28,"nameId":21002,"textId":31002,"buyPrice":[11,30],"sellPrice":[11,30],"use":[],"showPackage":null},
|
||||
{"id":11003,"type":4,"typeArgs":[],"quality":4,"iconId":29,"nameId":21003,"textId":31003,"buyPrice":[11,40],"sellPrice":[11,40],"use":[],"showPackage":null},
|
||||
{"id":11004,"type":4,"typeArgs":[],"quality":5,"iconId":30,"nameId":21004,"textId":31004,"buyPrice":[11,50],"sellPrice":[11,50],"use":[],"showPackage":null},
|
||||
{"id":11005,"type":4,"typeArgs":[],"quality":6,"iconId":31,"nameId":21005,"textId":31005,"buyPrice":[11,60],"sellPrice":[11,60],"use":[],"showPackage":null},
|
||||
{"id":11006,"type":4,"typeArgs":[],"quality":7,"iconId":32,"nameId":21006,"textId":31006,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null},
|
||||
{"id":11100,"type":4,"typeArgs":[],"quality":1,"iconId":33,"nameId":21100,"textId":31100,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null},
|
||||
{"id":11101,"type":4,"typeArgs":[],"quality":2,"iconId":34,"nameId":21101,"textId":31101,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null},
|
||||
{"id":11102,"type":4,"typeArgs":[],"quality":3,"iconId":35,"nameId":21102,"textId":31102,"buyPrice":[11,30],"sellPrice":[11,30],"use":[],"showPackage":null},
|
||||
{"id":11103,"type":4,"typeArgs":[],"quality":4,"iconId":36,"nameId":21103,"textId":31103,"buyPrice":[11,40],"sellPrice":[11,40],"use":[],"showPackage":null},
|
||||
{"id":11104,"type":4,"typeArgs":[],"quality":5,"iconId":37,"nameId":21104,"textId":31104,"buyPrice":[11,50],"sellPrice":[11,50],"use":[],"showPackage":null},
|
||||
{"id":11105,"type":4,"typeArgs":[],"quality":6,"iconId":38,"nameId":21105,"textId":31105,"buyPrice":[11,60],"sellPrice":[11,60],"use":[],"showPackage":null},
|
||||
{"id":11106,"type":4,"typeArgs":[],"quality":7,"iconId":39,"nameId":21106,"textId":31106,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null},
|
||||
{"id":12000,"type":4,"typeArgs":[],"quality":1,"iconId":40,"nameId":22000,"textId":32000,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null},
|
||||
{"id":12001,"type":4,"typeArgs":[],"quality":2,"iconId":41,"nameId":22001,"textId":32001,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null},
|
||||
{"id":12002,"type":4,"typeArgs":[],"quality":3,"iconId":42,"nameId":22002,"textId":32002,"buyPrice":[11,30],"sellPrice":[11,30],"use":[],"showPackage":null},
|
||||
{"id":12003,"type":4,"typeArgs":[],"quality":4,"iconId":43,"nameId":22003,"textId":32003,"buyPrice":[11,40],"sellPrice":[11,40],"use":[],"showPackage":null},
|
||||
{"id":12004,"type":4,"typeArgs":[],"quality":5,"iconId":44,"nameId":22004,"textId":32004,"buyPrice":[11,50],"sellPrice":[11,50],"use":[],"showPackage":null},
|
||||
{"id":12005,"type":4,"typeArgs":[],"quality":6,"iconId":45,"nameId":22005,"textId":32005,"buyPrice":[11,60],"sellPrice":[11,60],"use":[],"showPackage":null},
|
||||
{"id":12006,"type":4,"typeArgs":[],"quality":7,"iconId":46,"nameId":22006,"textId":32006,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null},
|
||||
{"id":12100,"type":4,"typeArgs":[],"quality":1,"iconId":47,"nameId":22100,"textId":32100,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null},
|
||||
{"id":12101,"type":4,"typeArgs":[],"quality":2,"iconId":48,"nameId":22101,"textId":32101,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null},
|
||||
{"id":12102,"type":4,"typeArgs":[],"quality":3,"iconId":49,"nameId":22102,"textId":32102,"buyPrice":[11,30],"sellPrice":[11,30],"use":[],"showPackage":null},
|
||||
{"id":12103,"type":4,"typeArgs":[],"quality":4,"iconId":50,"nameId":22103,"textId":32103,"buyPrice":[11,40],"sellPrice":[11,40],"use":[],"showPackage":null},
|
||||
{"id":12104,"type":4,"typeArgs":[],"quality":5,"iconId":51,"nameId":22104,"textId":32104,"buyPrice":[11,50],"sellPrice":[11,50],"use":[],"showPackage":null},
|
||||
{"id":12105,"type":4,"typeArgs":[],"quality":6,"iconId":52,"nameId":22105,"textId":32105,"buyPrice":[11,60],"sellPrice":[11,60],"use":[],"showPackage":null},
|
||||
{"id":12106,"type":4,"typeArgs":[],"quality":7,"iconId":53,"nameId":22106,"textId":32106,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null},
|
||||
{"id":13000,"type":4,"typeArgs":[],"quality":1,"iconId":54,"nameId":23000,"textId":33000,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null},
|
||||
{"id":13001,"type":4,"typeArgs":[],"quality":2,"iconId":55,"nameId":23001,"textId":33001,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null},
|
||||
{"id":13002,"type":4,"typeArgs":[],"quality":3,"iconId":56,"nameId":23002,"textId":33002,"buyPrice":[11,30],"sellPrice":[11,30],"use":[],"showPackage":null},
|
||||
{"id":13003,"type":4,"typeArgs":[],"quality":4,"iconId":57,"nameId":23003,"textId":33003,"buyPrice":[11,40],"sellPrice":[11,40],"use":[],"showPackage":null},
|
||||
{"id":13004,"type":4,"typeArgs":[],"quality":5,"iconId":58,"nameId":23004,"textId":33004,"buyPrice":[11,50],"sellPrice":[11,50],"use":[],"showPackage":null},
|
||||
{"id":13005,"type":4,"typeArgs":[],"quality":6,"iconId":59,"nameId":23005,"textId":33005,"buyPrice":[11,60],"sellPrice":[11,60],"use":[],"showPackage":null},
|
||||
{"id":13006,"type":4,"typeArgs":[],"quality":7,"iconId":60,"nameId":23006,"textId":33006,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null},
|
||||
{"id":13100,"type":4,"typeArgs":[],"quality":1,"iconId":61,"nameId":23100,"textId":33100,"buyPrice":[11,10],"sellPrice":[11,10],"use":[],"showPackage":null},
|
||||
{"id":13101,"type":4,"typeArgs":[],"quality":2,"iconId":62,"nameId":23101,"textId":33101,"buyPrice":[11,20],"sellPrice":[11,20],"use":[],"showPackage":null},
|
||||
{"id":13102,"type":4,"typeArgs":[],"quality":3,"iconId":63,"nameId":23102,"textId":33102,"buyPrice":[11,30],"sellPrice":[11,30],"use":[],"showPackage":null},
|
||||
{"id":13103,"type":4,"typeArgs":[],"quality":4,"iconId":64,"nameId":23103,"textId":33103,"buyPrice":[11,40],"sellPrice":[11,40],"use":[],"showPackage":null},
|
||||
{"id":13104,"type":4,"typeArgs":[],"quality":5,"iconId":65,"nameId":23104,"textId":33104,"buyPrice":[11,50],"sellPrice":[11,50],"use":[],"showPackage":null},
|
||||
{"id":13105,"type":4,"typeArgs":[],"quality":6,"iconId":66,"nameId":23105,"textId":33105,"buyPrice":[11,60],"sellPrice":[11,60],"use":[],"showPackage":null},
|
||||
{"id":13106,"type":4,"typeArgs":[],"quality":7,"iconId":67,"nameId":23106,"textId":33106,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null}
|
||||
]
|
@ -0,0 +1,47 @@
|
||||
-- 剑气
|
||||
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
--> Dependencies
|
||||
local BehaviourClient = require(ReplicatedStorage.Base.BehaviourClient)
|
||||
|
||||
--> Variables
|
||||
local PrefabFolder = ReplicatedStorage:WaitForChild("Prefabs")
|
||||
local Prefab_SwordWave = PrefabFolder:WaitForChild("Projectiles"):WaitForChild("SwordWave")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local SwordWave = {}
|
||||
SwordWave.__index = SwordWave
|
||||
setmetatable(SwordWave, {__index = BehaviourClient})
|
||||
|
||||
function SwordWave:Init(CasterPlayer: Player, CastInfo: table, DelayTime: number, CastState: boolean)
|
||||
local self = BehaviourClient:Init(CasterPlayer, CastInfo, DelayTime, CastState)
|
||||
setmetatable(self, SwordWave)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function SwordWave:Show(CasterPlayer: Player, CastInfo: table, DelayTime: number, CastState: boolean)
|
||||
self.ShowTask, self.Projectile, self.Tween = self.EffectDispatcher:ShowProjectile(self.Player, DelayTime,
|
||||
0, CastInfo.StartPos, CastInfo.EndPos, CastInfo.Duration, Prefab_SwordWave, Enum.EasingStyle.Linear)
|
||||
end
|
||||
|
||||
function SwordWave:Destroy()
|
||||
if self.ShowTask then
|
||||
task.cancel(self.ShowTask)
|
||||
self.ShowTask = nil
|
||||
end
|
||||
if self.Tween then
|
||||
self.Tween:Cancel()
|
||||
self.Tween = nil
|
||||
end
|
||||
if self.Projectile then
|
||||
self.Projectile:Destroy()
|
||||
self.Projectile = nil
|
||||
end
|
||||
BehaviourClient.Destroy(self)
|
||||
end
|
||||
|
||||
return SwordWave
|
46
src/ReplicatedStorage/Modules/EffectDispatcher.luau
Normal file
46
src/ReplicatedStorage/Modules/EffectDispatcher.luau
Normal file
@ -0,0 +1,46 @@
|
||||
-- 效果调度器
|
||||
|
||||
-- 客户端调用表现全部通过这里,预想效果
|
||||
-- 1. 方便做功能拓展
|
||||
-- 2. 便于统一表现逻辑(如:AOE,弹道。。。)
|
||||
|
||||
local EffectDispatcher = {}
|
||||
|
||||
--> Services
|
||||
local TweenService = game:GetService("TweenService")
|
||||
|
||||
local function GetPerformanceFolder()
|
||||
return game.Workspace:FindFirstChild("Performance")
|
||||
end
|
||||
|
||||
function EffectDispatcher:ShowProjectile(Caster: Player, DelayTime: number, PreTime: number, StartPos: Vector3, EndPos: Vector3,
|
||||
Duration: number, ProjectilePrefab: Part, EasingStyle: Enum.EasingStyle?)
|
||||
local projectileTask, Projectile, tween
|
||||
projectileTask = task.spawn(function ()
|
||||
local PerformanceFolder = GetPerformanceFolder()
|
||||
if not PerformanceFolder then warn("PerformanceFolder not found") return end
|
||||
|
||||
Projectile = ProjectilePrefab:Clone()
|
||||
Projectile.Parent = PerformanceFolder
|
||||
Projectile.CFrame = CFrame.new(StartPos, EndPos)
|
||||
Projectile.CanCollide = false
|
||||
Projectile.Anchored = true
|
||||
|
||||
|
||||
-- Tween动画
|
||||
local tweenInfo = TweenInfo.new(Duration, EasingStyle or Enum.EasingStyle.Linear)
|
||||
local direction = (EndPos - StartPos).Unit
|
||||
local lookAt = EndPos + direction
|
||||
local goal = {CFrame = CFrame.new(EndPos, lookAt)}
|
||||
tween = TweenService:Create(Projectile, tweenInfo, goal)
|
||||
|
||||
task.wait(PreTime)
|
||||
tween:Play()
|
||||
|
||||
-- 动画结束后自动销毁
|
||||
game.Debris:AddItem(Projectile, Duration + PreTime)
|
||||
end)
|
||||
return projectileTask, Projectile, tween
|
||||
end
|
||||
|
||||
return EffectDispatcher
|
@ -38,6 +38,16 @@ function Utils:GenUniqueId(t: table)
|
||||
return min_id
|
||||
end
|
||||
|
||||
function Utils:GenUniqueIdPlayerAI(LastTime: number, Counter: number)
|
||||
local now = os.time() -- 或 tick(),精度更高
|
||||
if now ~= LastTime then
|
||||
Counter = 0
|
||||
LastTime = now
|
||||
end
|
||||
Counter = Counter + 1
|
||||
return tostring(now) .. "_" .. tostring(Counter)
|
||||
end
|
||||
|
||||
-- function Utils:GetJsonIdData(JsonName: string, id: number)
|
||||
-- local JsonData = require(ReplicatedStorage.Json[JsonName])
|
||||
-- for _, item in ipairs(JsonData) do
|
||||
@ -86,6 +96,35 @@ function Utils:StringArrayToTable(StringArray: string)
|
||||
return result
|
||||
end
|
||||
|
||||
function Utils:GetFlatDirectionAndEndPos(startPos: Vector3, targetPos: Vector3, length: number)
|
||||
local flatStartPos = Vector3.new(startPos.X, 0, startPos.Z)
|
||||
local flatTarget = Vector3.new(targetPos.X, 0, targetPos.Z)
|
||||
local direction = (flatTarget - flatStartPos).Unit
|
||||
local endPos = flatStartPos + direction * length
|
||||
return flatStartPos, endPos, direction
|
||||
end
|
||||
|
||||
function Utils:CreateDataInstance(Player: Player, UniqueId: number, EquipmentData: table, Folder: Instance)
|
||||
if Player or UniqueId or EquipmentData or Folder then
|
||||
warn('创建实例失败: ' , Player.Name, UniqueId, EquipmentData, Folder)
|
||||
return
|
||||
end
|
||||
local Config = Instance.new("Configuration")
|
||||
Config.Name = UniqueId
|
||||
Utils:SetAttributesList(Config, EquipmentData)
|
||||
Config.Parent = Folder
|
||||
return Config
|
||||
end
|
||||
|
||||
-- 复制表
|
||||
function Utils:CopyTable(t: table)
|
||||
local newTable = {}
|
||||
for k, v in pairs(t) do
|
||||
newTable[k] = v
|
||||
end
|
||||
return newTable
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
return Utils
|
@ -1,20 +1,34 @@
|
||||
local Behaviour = {}
|
||||
Behaviour.__index = Behaviour
|
||||
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Events
|
||||
local RE_PerformanceEvent = ReplicatedStorage:FindFirstChild("Events"):FindFirstChild("RE_PerformanceEvent")
|
||||
local RE_CleanPlayerPerformance = ReplicatedStorage:FindFirstChild("Events"):FindFirstChild("RE_CleanPlayerPerformance")
|
||||
|
||||
--> Dependencies
|
||||
local TypeList = require(script.Parent.TypeList)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Communicate = require(ServerStorage.Modules.Tools.Communicate)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 刷新时,重新载入,暂时不考虑性能
|
||||
|
||||
-- 初始化内容
|
||||
function Behaviour:Init(PlayerAI, Character: TypeList.Character)
|
||||
function Behaviour:Init(PlayerAI, Character: TypeList.Character, ScriptName: string)
|
||||
local self = {}
|
||||
self.PlayerAI = PlayerAI
|
||||
self.Character = Character
|
||||
self.CheckData = nil
|
||||
self.ExeTask = nil
|
||||
self.UniqueIdList = {}
|
||||
self.ScriptName = ScriptName
|
||||
self.Cooldown = 0
|
||||
self.OrgCooldown = 0
|
||||
self.CooldownTask = nil
|
||||
|
||||
local Humanoid = self.Character.Humanoid
|
||||
-- 监听属性变化
|
||||
@ -38,12 +52,28 @@ function Behaviour:Execute()
|
||||
|
||||
end
|
||||
|
||||
-- 启动冷却时间清除计时
|
||||
function Behaviour:StartCooldownTask()
|
||||
self.Cooldown = self.OrgCooldown
|
||||
self.CooldownTask = task.spawn(function()
|
||||
task.wait(self.OrgCooldown)
|
||||
self.Cooldown = 0
|
||||
end)
|
||||
end
|
||||
|
||||
function Behaviour:SendPerformanceEvent(...)
|
||||
Communicate:SendToClient(RE_PerformanceEvent, ...)
|
||||
end
|
||||
|
||||
-- 检查当前状态是否可执行
|
||||
function Behaviour:CheckStat()
|
||||
if not self.Character then return true end
|
||||
-- 死亡检查
|
||||
if self.Character:GetState("Died") then return true end
|
||||
|
||||
-- 冷却中检查
|
||||
if self.Cooldown > 0 then return true end
|
||||
|
||||
-- 执行状态中检查
|
||||
local ExecutingState = self.PlayerAI.ExecutingState
|
||||
-- 其他内容执行中,就false
|
||||
@ -59,6 +89,20 @@ end
|
||||
|
||||
-- 销毁
|
||||
function Behaviour:Destroy()
|
||||
-- 清除客户端对应行为表现
|
||||
for _, UniqueId in self.UniqueIdList do
|
||||
self:SendPerformanceEvent("Destroy", self.Player, self.ScriptName, true, {UniqueId = UniqueId})
|
||||
end
|
||||
if self.CooldownTask then
|
||||
task.cancel(self.CooldownTask)
|
||||
self.CooldownTask = nil
|
||||
end
|
||||
if self.ExeTask then
|
||||
task.cancel(self.ExeTask)
|
||||
self.ExeTask = nil
|
||||
end
|
||||
-- 清除数据
|
||||
self.UniqueIdList = {}
|
||||
if self.ConAttribtueChanged then
|
||||
self.ConAttribtueChanged:Disconnect()
|
||||
self.ConAttribtueChanged = nil
|
||||
@ -67,6 +111,10 @@ function Behaviour:Destroy()
|
||||
task.cancel(self.LoopTask)
|
||||
self.LoopTask = nil
|
||||
end
|
||||
for _, UniqueId in self.UniqueIdList do
|
||||
self.PlayerAI:RemoveBehaviourUniqueId(UniqueId)
|
||||
end
|
||||
self.UniqueIdList = {}
|
||||
self = nil
|
||||
end
|
||||
|
||||
|
@ -2,8 +2,12 @@
|
||||
local Character = {}
|
||||
Character.__index = Character
|
||||
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local TypeList = require(script.Parent.TypeList)
|
||||
|
||||
|
||||
local LIMIT_ATTRIBUTE = {
|
||||
"hp"
|
||||
}
|
||||
@ -16,7 +20,7 @@ function Character.new(Player: Player, CharacterModel: Model, CharacterData: tab
|
||||
-- 生成表格数据
|
||||
local self = {}
|
||||
self.Instance = newMobModel
|
||||
self.Config = CharacterData
|
||||
self.Config = Utils:CopyTable(CharacterData)
|
||||
self.Root = HumanoidRootPart
|
||||
self.Humanoid = mobHumanoid
|
||||
self.Origin = HumanoidRootPart:GetPivot()
|
||||
@ -90,9 +94,8 @@ function Character:ChangeAttributeValue(attributeKey: string, value: any)
|
||||
|
||||
-- 死亡判断
|
||||
if attributeKey == "hp" and self.Stats.Died == false then
|
||||
if self.Config[attributeKey] <= 0 then
|
||||
self:Died()
|
||||
end
|
||||
|
||||
if self.Config[attributeKey] <= 0 then self:Died() end
|
||||
end
|
||||
end
|
||||
|
||||
@ -106,6 +109,7 @@ function Character:ChangeState(state: string, value: any)
|
||||
end
|
||||
|
||||
function Character:Died()
|
||||
print(debug.traceback("Stack trace:"))
|
||||
self:ChangeState("Died", true)
|
||||
for _, connection in self.Connections do
|
||||
connection:Disconnect()
|
||||
|
@ -20,4 +20,10 @@ export type Behaviour = {
|
||||
Destroy: () -> (),
|
||||
}
|
||||
|
||||
export type CastInfo = {
|
||||
UniqueId: number,
|
||||
StartPos: Vector3,
|
||||
EndPos: Vector3,
|
||||
}
|
||||
|
||||
return {}
|
@ -4,9 +4,9 @@
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Behaviour = require(ServerStorage.Base.Behaviour)
|
||||
local MobsProxy = require(ServerStorage.Proxy.MobsProxy)
|
||||
local TypeList = require(ServerStorage:WaitForChild("Base").TypeList)
|
||||
local Behaviour = require(ServerStorage:WaitForChild("Base").Behaviour)
|
||||
local MobsProxy = require(ServerStorage:WaitForChild("Proxy").MobsProxy)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -15,7 +15,7 @@ Move.__index = Move
|
||||
setmetatable(Move, {__index = Behaviour})
|
||||
|
||||
function Move:Init(PlayerAI, Character: TypeList.Character, Player: Player)
|
||||
local self = Behaviour:Init(PlayerAI, Character)
|
||||
local self = Behaviour:Init(PlayerAI, Character, script.Name)
|
||||
self.Player = Player
|
||||
setmetatable(self, Move)
|
||||
return self
|
||||
@ -57,12 +57,4 @@ function Move:Execute()
|
||||
end)
|
||||
end
|
||||
|
||||
function Move:Destroy()
|
||||
if self.ExeTask then
|
||||
task.cancel(self.ExeTask)
|
||||
self.ExeTask = nil
|
||||
end
|
||||
Behaviour.Destroy(self)
|
||||
end
|
||||
|
||||
return Move
|
102
src/ServerStorage/Modules/Behaviours/SwordWave.luau
Normal file
102
src/ServerStorage/Modules/Behaviours/SwordWave.luau
Normal file
@ -0,0 +1,102 @@
|
||||
-- 移动行为
|
||||
|
||||
--> 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 SwordWave = {}
|
||||
SwordWave.__index = SwordWave
|
||||
setmetatable(SwordWave, {__index = Behaviour})
|
||||
|
||||
local CAST_DISTANCE = 50
|
||||
local PROJECTILE_LENGTH = 50
|
||||
local PROJECTILE_DURATION = 3
|
||||
local COOLDOWN = 1
|
||||
|
||||
function SwordWave:Init(PlayerAI, Character: TypeList.Character, Player: Player)
|
||||
local self = Behaviour:Init(PlayerAI, Character, script.Name)
|
||||
self.Player = Player
|
||||
setmetatable(self, SwordWave)
|
||||
self.OrgCooldown = COOLDOWN
|
||||
|
||||
-- 客户端表现
|
||||
self:SendPerformanceEvent("Init", self.Player, script.Name, true, {})
|
||||
return self
|
||||
end
|
||||
|
||||
function SwordWave:Check(CheckInfo: table)
|
||||
if Behaviour.CheckStat(self) then return -1, self.CheckData end
|
||||
|
||||
local PlayerMobs = MobsProxy:GetPlayerMobs(self.Player)
|
||||
if not PlayerMobs then return end
|
||||
|
||||
local closestMob, minDistance = nil, CAST_DISTANCE
|
||||
for _, Mob in PlayerMobs do
|
||||
if Mob.Instance and Mob.Instance.PrimaryPart then
|
||||
local dist = (Mob.Instance.PrimaryPart.Position - self.Character.Instance.PrimaryPart.Position).Magnitude
|
||||
if dist < minDistance then
|
||||
minDistance = dist
|
||||
closestMob = Mob
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.CheckData = {}
|
||||
if closestMob then
|
||||
self.CheckData["ClosestCharacter"] = closestMob
|
||||
return 200, self.CheckData
|
||||
end
|
||||
|
||||
-- 返回优先级,执行数据
|
||||
return -1, self.CheckData
|
||||
end
|
||||
|
||||
function SwordWave:Execute()
|
||||
self.ExeTask = task.spawn(function ()
|
||||
self:ChangeExecutingState(true)
|
||||
task.wait(0.5)
|
||||
-- 伤害逻辑部分
|
||||
local StartPos = self.Character.Instance:GetPivot().Position
|
||||
local EndPos = StartPos + (self.CheckData["ClosestCharacter"].Instance:GetPivot().Position - StartPos).Unit * PROJECTILE_LENGTH
|
||||
|
||||
StartPos, EndPos = Utils:GetFlatDirectionAndEndPos(StartPos, self.CheckData["ClosestCharacter"].Instance:GetPivot().Position, PROJECTILE_LENGTH)
|
||||
DamageProxy:CastFreeProjectile(self.Character, StartPos, EndPos, PROJECTILE_DURATION, 4,
|
||||
function (Victim: TypeList.Character)
|
||||
self:OnHit(Victim)
|
||||
end)
|
||||
|
||||
-- 表现部分
|
||||
self:SendPerformanceEvent("Show", self.Player, self.ScriptName, true, {
|
||||
{ UniqueId = self.PlayerAI:GetBehaviourUniqueId(),
|
||||
StartPos = StartPos,
|
||||
EndPos = EndPos,
|
||||
Duration = PROJECTILE_DURATION,
|
||||
Cooldown = self.OrgCooldown,
|
||||
}
|
||||
})
|
||||
self:StartCooldownTask()
|
||||
self:ChangeExecutingState(false)
|
||||
end)
|
||||
end
|
||||
|
||||
function SwordWave:OnHit(Victim: TypeList.Character)
|
||||
DamageProxy:TakeDamage(self.Character, Victim, {
|
||||
{
|
||||
Damage = 30,
|
||||
Type = DamageProxy.DamageType.SKILL,
|
||||
Tag = DamageProxy.DamageTag.NORMAL,
|
||||
}
|
||||
})
|
||||
return false
|
||||
end
|
||||
|
||||
return SwordWave
|
11
src/ServerStorage/Modules/Tools/Communicate.luau
Normal file
11
src/ServerStorage/Modules/Tools/Communicate.luau
Normal file
@ -0,0 +1,11 @@
|
||||
local Communicate = {}
|
||||
|
||||
function Communicate:SendToClient(Event: RemoteEvent, CastTag: string, CastPlayer: Player, ...)
|
||||
Event:FireAllClients(tick(), CastTag, CastPlayer, ...)
|
||||
end
|
||||
|
||||
function Communicate:SendToClientFree(Event: RemoteEvent, ...)
|
||||
Event:FireAllClients(...)
|
||||
end
|
||||
|
||||
return Communicate
|
@ -4,6 +4,7 @@ local DamageProxy = {}
|
||||
--> Services
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Modules
|
||||
--> Variables
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
|
||||
@ -48,6 +49,65 @@ function DamageProxy:IsDied(Target: Model)
|
||||
return Humanoid:GetAttribute("hp") <= 0
|
||||
end
|
||||
|
||||
-- 获取范围内敌人
|
||||
function DamageProxy:GetAoeEnemies(Caster: TypeList.Character, Position: Vector3, Radius: number)
|
||||
local Enemies = {}
|
||||
local MobsProxy = require(ServerStorage.Proxy.MobsProxy)
|
||||
for _, enemy in pairs(MobsProxy:GetPlayerMobs(Caster.Player)) do
|
||||
if enemy ~= Caster and enemy.Instance then
|
||||
local enemy_pos = enemy.Instance:GetPivot().Position
|
||||
if (enemy_pos - Position).Magnitude <= Radius then
|
||||
table.insert(Enemies, enemy)
|
||||
end
|
||||
end
|
||||
end
|
||||
return Enemies
|
||||
end
|
||||
|
||||
-- 弹道伤害
|
||||
function DamageProxy:CastFreeProjectile(Caster: TypeList.Character, StartPos: Vector3, EndPos: Vector3, Duration: number, Range: number, OnHit: (Target: TypeList.Character) -> (boolean?))
|
||||
local projectileTask = nil
|
||||
local step_time = 0.05 -- 每帧检测间隔
|
||||
local elapsed = 0
|
||||
local hit_targets = {}
|
||||
local direction = (EndPos - StartPos).Unit
|
||||
local distance = (EndPos - StartPos).Magnitude
|
||||
local speed = distance / Duration
|
||||
local current_pos = StartPos
|
||||
local cancelled = false
|
||||
|
||||
local function cancelTask()
|
||||
cancelled = true
|
||||
if projectileTask then
|
||||
task.cancel(projectileTask)
|
||||
end
|
||||
end
|
||||
|
||||
projectileTask = task.spawn(function()
|
||||
while elapsed < Duration and not cancelled do
|
||||
-- 计算当前位置
|
||||
current_pos = StartPos + direction * speed * elapsed
|
||||
-- 检测范围内敌人
|
||||
local MobsProxy = require(ServerStorage.Proxy.MobsProxy)
|
||||
for _, enemy in pairs(MobsProxy:GetPlayerMobs(Caster.Player)) do
|
||||
if enemy ~= Caster and enemy.Instance then
|
||||
local enemy_pos = enemy.Instance:GetPivot().Position
|
||||
if (enemy_pos - current_pos).Magnitude <= Range then
|
||||
if not hit_targets[enemy] then
|
||||
hit_targets[enemy] = true
|
||||
local stop = OnHit(enemy)
|
||||
if stop then cancelTask() break end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
task.wait(step_time)
|
||||
elapsed = elapsed + step_time
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
function DamageProxy:TakeDamage(Caster: TypeList.Character, Victim: TypeList.Character, DamageInfos: {DamageInfo})
|
||||
for _, DamageInfo in DamageInfos do
|
||||
local Damage = DamageInfo.Damage
|
||||
|
@ -26,22 +26,6 @@ local function GetPlayerEquipmentFolder(Player: Player)
|
||||
return EquipmentFolder
|
||||
end
|
||||
|
||||
-- 创建装备实例
|
||||
local function CreateEquipmentInstance(Player: Player, UniqueId: number, EquipmentData: table)
|
||||
if Player or UniqueId or EquipmentData then
|
||||
warn('创建装备实例失败: ' , Player.Name, UniqueId, EquipmentData)
|
||||
return
|
||||
end
|
||||
local PlayerEquipmentFolder = GetPlayerEquipmentFolder(Player)
|
||||
if not PlayerEquipmentFolder then return end
|
||||
|
||||
local Config = Instance.new("Configuration")
|
||||
Config.Name = UniqueId
|
||||
Utils:SetAttributesList(Config, PlayerEquipmentFolder)
|
||||
Config.Parent = PlayerEquipmentFolder
|
||||
return Config
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 初始化玩家
|
||||
@ -57,10 +41,11 @@ function EquipmentProxy:InitPlayer(Player: Player)
|
||||
|
||||
-- 初始化装备
|
||||
for uniqueId, EquipmentData in ArchiveProxy.pData[Player.UserId][STORE_NAME] do
|
||||
CreateEquipmentInstance(Player, uniqueId, EquipmentData)
|
||||
Utils:CreateDataInstance(Player, uniqueId, EquipmentData, GetPlayerEquipmentFolder(Player))
|
||||
end
|
||||
end
|
||||
|
||||
-- 一些特殊记录或者不用记录的Key
|
||||
local EXCEPT_KEYS = { "id", "orgId", "name", "attributes"}
|
||||
-- 添加装备到背包
|
||||
function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number)
|
||||
@ -81,15 +66,16 @@ function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number)
|
||||
|
||||
ResultData.id = UniqueId
|
||||
ResultData.orgId = EquipmentId
|
||||
ResultData.wearing = false
|
||||
-- 到时候记录穿戴槽位
|
||||
ResultData.wearing = 0
|
||||
|
||||
-- 其他随机词条内容添加在下面
|
||||
-- 之后回收修改随机生成
|
||||
-- TODO: 其他随机词条内容添加在下面
|
||||
-- TODO: 之后回收修改随机生成
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
ArchiveProxy.pData[Player.UserId][UniqueId] = ResultData
|
||||
CreateEquipmentInstance(Player, UniqueId, ResultData)
|
||||
Utils:CreateDataInstance(Player, UniqueId, ResultData, GetPlayerEquipmentFolder(Player))
|
||||
end
|
||||
|
||||
-- 回收装备
|
||||
@ -119,6 +105,12 @@ function EquipmentProxy:WearEquipment(Player: Player, EquipmentId: number)
|
||||
|
||||
end
|
||||
|
||||
-- 获取装备数据
|
||||
function EquipmentProxy:GetEquipmentData(Player: Player, EquipmentUniqueId: number)
|
||||
local EquipmentData = ArchiveProxy.pData[Player.UserId][STORE_NAME][EquipmentUniqueId]
|
||||
return EquipmentData
|
||||
end
|
||||
|
||||
function EquipmentProxy:OnPlayerRemoving(Player: Player)
|
||||
|
||||
end
|
||||
|
204
src/ServerStorage/Proxy/GemProxy.luau
Normal file
204
src/ServerStorage/Proxy/GemProxy.luau
Normal file
@ -0,0 +1,204 @@
|
||||
-- 玩家通用信息
|
||||
local GemProxy = {}
|
||||
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Variables
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy)
|
||||
|
||||
--> Json
|
||||
local JsonItem = require(ReplicatedStorage.Json.ItemProp)
|
||||
local JsonGem = require(ReplicatedStorage.Json.Gem)
|
||||
|
||||
--> Events
|
||||
local RE_PlayerTip = ReplicatedStorage.Events.RE_PlayerTip
|
||||
local RE_UpgradeAttributes = ReplicatedStorage.Events.RE_UpgradeAttributes
|
||||
|
||||
--> Constants
|
||||
local STORE_NAME = "Gem"
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 获取玩家信息文件夹
|
||||
local function GetPlayerGemFolder(Player: Player)
|
||||
local pData = Utils:GetPlayerDataFolder(Player)
|
||||
if not pData then return end
|
||||
local GemFolder = pData:FindFirstChild("Gem")
|
||||
return GemFolder
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 初始化玩家
|
||||
function GemProxy:InitPlayer(Player: Player)
|
||||
local pData = Utils:GetPlayerDataFolder(Player)
|
||||
if not pData then return end
|
||||
local GemFolder = Utils:CreateFolder("Gem", pData)
|
||||
|
||||
-- 新玩家数据初始化
|
||||
if not ArchiveProxy.pData[Player.UserId][STORE_NAME] then
|
||||
ArchiveProxy.pData[Player.UserId][STORE_NAME] = {}
|
||||
ArchiveProxy.pData[Player.UserId][STORE_NAME].Gems = {}
|
||||
end
|
||||
|
||||
-- 创建玩家信息实例
|
||||
for GemUniqueId, GemData in ArchiveProxy.pData[Player.UserId][STORE_NAME].Gems do
|
||||
Utils:CreateDataInstance(Player, GemUniqueId, GemData, GemFolder)
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 添加宝石
|
||||
local EXCEPT_KEYS = {"id", "orgId", "iconId"}
|
||||
function GemProxy:AddGem(Player: Player, GemId: number)
|
||||
|
||||
local pData = Utils:GetPlayerDataFolder(Player)
|
||||
if not pData then return end
|
||||
|
||||
local GemData = Utils:GetIdDataFromJson(JsonGem, GemId)
|
||||
if not GemData then return end
|
||||
|
||||
local UniqueId = Utils:GenUniqueId(ArchiveProxy.pData[Player.UserId])
|
||||
-- 配置表内容
|
||||
local ResultData = {}
|
||||
for key, value in pairs(GemData) do
|
||||
if not table.find(EXCEPT_KEYS, key) then
|
||||
ResultData[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
ResultData.id = UniqueId
|
||||
ResultData.orgId = GemId
|
||||
-- 记录穿戴的装备UniqueId
|
||||
ResultData.wearing = 0
|
||||
|
||||
|
||||
ArchiveProxy.pData[Player.UserId][UniqueId] = ResultData
|
||||
Utils:CreateDataInstance(Player, UniqueId, ResultData, GetPlayerGemFolder(Player))
|
||||
end
|
||||
|
||||
-- 购买宝石
|
||||
function GemProxy:BuyGem(Player: Player, GemId: number)
|
||||
local pData = Utils:GetPlayerDataFolder(Player)
|
||||
if not pData then return end
|
||||
|
||||
local ItemData = Utils:GetIdDataFromJson(JsonItem, GemId)
|
||||
if not ItemData then warn('无法获取宝石Item数据: ' , Player.Name, GemId) return end
|
||||
|
||||
local GemData = Utils:GetIdDataFromJson(JsonGem, GemId)
|
||||
if not GemData then warn('无法获取宝石配置数据: ' , Player.Name, GemId) return end
|
||||
|
||||
local PlayerInfoProxy = require(ServerStorage.Proxy.PlayerInfoProxy)
|
||||
|
||||
-- 判断是否花钱
|
||||
local buyPrice = ItemData.buyPrice
|
||||
if buyPrice then
|
||||
if PlayerInfoProxy:HasEnoughItem(Player, buyPrice[1], buyPrice[2]) then
|
||||
PlayerInfoProxy:ChangeItemCount(Player, buyPrice[1], -buyPrice[2])
|
||||
else
|
||||
RE_PlayerTip:FireClient(Player, "钱不够")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- 添加宝石
|
||||
GemProxy:AddGem(Player, GemId)
|
||||
end
|
||||
|
||||
-- 回收宝石
|
||||
function GemProxy:RecycleGem(Player: Player, UniqueId: number)
|
||||
local GemFolder = GetPlayerGemFolder(Player)
|
||||
|
||||
local GemData = ArchiveProxy.pData[Player.UserId][UniqueId]
|
||||
if not GemData then warn('无法获取宝石数据: ' , Player.Name, UniqueId) return end
|
||||
|
||||
local GemInstance = GemFolder:FindFirstChild(UniqueId)
|
||||
if not GemInstance then warn('宝石实例不存在: ' , Player.Name, UniqueId) return end
|
||||
|
||||
local ItemData = Utils:GetIdDataFromJson(JsonItem, GemData.orgId)
|
||||
if not ItemData then warn('无法获取宝石Item数据: ' , Player.Name, GemData.orgId) return end
|
||||
|
||||
-- 判断是否穿戴
|
||||
if GemData.wearing ~= 0 then
|
||||
RE_PlayerTip:FireClient(Player, "宝石穿戴中")
|
||||
return
|
||||
end
|
||||
|
||||
-- 增加货币
|
||||
local PlayerInfoProxy = require(ServerStorage.Proxy.PlayerInfoProxy)
|
||||
PlayerInfoProxy:ChangeItemCount(Player, ItemData.sellPrice[1], ItemData.sellPrice[2])
|
||||
|
||||
-- 移除内容
|
||||
ArchiveProxy.pData[Player.UserId][UniqueId] = nil
|
||||
GemInstance:Destroy()
|
||||
end
|
||||
|
||||
-- 穿戴宝石
|
||||
function GemProxy:WearGem(Player: Player, GemUniqueId: number, EquipmentUniqueId: number)
|
||||
-- 检查是否有这个宝石
|
||||
local GemData = ArchiveProxy.pData[Player.UserId][GemUniqueId]
|
||||
if not GemData then warn('无法获取宝石数据: ' , Player.Name, GemUniqueId) return end
|
||||
|
||||
-- 检查是否有宝石实例
|
||||
local GemInstance = GetPlayerGemFolder(Player):FindFirstChild(GemUniqueId)
|
||||
if not GemInstance then warn('宝石实例不存在: ' , Player.Name, GemUniqueId) return end
|
||||
|
||||
-- 检查是否有这个装备
|
||||
local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy)
|
||||
local EquipmentData = EquipmentProxy:GetEquipmentData(Player, EquipmentUniqueId)
|
||||
if not EquipmentData then warn('无法获取装备数据: ' , Player.Name, EquipmentUniqueId) return end
|
||||
|
||||
-- 检查是否正在穿戴中
|
||||
if GemData.wearing ~= 0 then
|
||||
RE_PlayerTip:FireClient(Player, "宝石穿戴中, 请先卸下")
|
||||
return
|
||||
end
|
||||
|
||||
-- TODO: 检查对应装备是否有充足的宝石槽位
|
||||
|
||||
-- 穿戴
|
||||
GemData.wearing = EquipmentUniqueId
|
||||
GemInstance:SetAttribute("Wearing", EquipmentUniqueId)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 获取升级加点属性
|
||||
function GemProxy:GetPlayerGemWearingAttributes(Player: Player)
|
||||
if not Player then warn('获取玩家属性失败: ', Player.Name) return end
|
||||
local playerGems = ArchiveProxy.pData[Player.UserId][STORE_NAME].Gems
|
||||
local attributes = {}
|
||||
for _, gemData in playerGems do
|
||||
if gemData.wearing ~= 0 then
|
||||
if attributes[gemData.effectAttribute] then
|
||||
attributes[gemData.effectAttribute] = attributes[gemData.effectAttribute] + gemData.attributeValue
|
||||
else
|
||||
attributes[gemData.effectAttribute] = gemData.attributeValue
|
||||
end
|
||||
end
|
||||
end
|
||||
return attributes
|
||||
end
|
||||
|
||||
-- 获取玩家属性
|
||||
function GemProxy:GetPlayerAttributes(Player: Player)
|
||||
local attributesList = {}
|
||||
attributesList.GemWearingAttributes = self:GetPlayerGemWearingAttributes(Player)
|
||||
return attributesList
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function GemProxy:OnPlayerRemoving(Player: Player)
|
||||
|
||||
end
|
||||
|
||||
ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(Player: Player)
|
||||
GemProxy:OnPlayerRemoving(Player)
|
||||
end)
|
||||
|
||||
return GemProxy
|
@ -12,11 +12,16 @@ local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy)
|
||||
local MobsProxy = require(ServerStorage.Proxy.MobsProxy)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
|
||||
--> Dependencies
|
||||
local Communicate = require(ServerStorage.Modules.Tools.Communicate)
|
||||
|
||||
--> Json
|
||||
local JsonLevel = require(ReplicatedStorage.Json.Level)
|
||||
|
||||
--> Events
|
||||
local BD_ChallengeEnd = ReplicatedStorage.Events.BD_ChallengeEnd
|
||||
local RE_CleanPlayerPerformance = ReplicatedStorage.Events.RE_CleanPlayerPerformance
|
||||
|
||||
|
||||
--> Constants
|
||||
local STORE_NAME = "Level"
|
||||
@ -33,11 +38,15 @@ local LevelFolder = Utils:CreateFolder(STORE_NAME, game.Workspace)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 获取玩家关卡文件夹
|
||||
local function GetPlayerLevelFolder(Player: Player)
|
||||
local pData = Utils:GetPlayerDataFolder(Player)
|
||||
if not pData then return end
|
||||
local LevelFolder = pData:FindFirstChild("Level")
|
||||
return LevelFolder
|
||||
local function GetPlayerLevelFolder(Player: Player, ChildFolderName: string?)
|
||||
local PlayerFolder = LevelFolder:FindFirstChild(Player.UserId)
|
||||
if not PlayerFolder then warn("PlayerFolder not found", Player.UserId) return end
|
||||
if ChildFolderName then
|
||||
local ChildFolder = PlayerFolder:FindFirstChild(ChildFolderName)
|
||||
if not ChildFolder then warn("ChildFolder not found", ChildFolderName) return end
|
||||
return ChildFolder
|
||||
end
|
||||
return PlayerFolder
|
||||
end
|
||||
|
||||
-- 获取玩家关卡Workspace目录
|
||||
@ -46,9 +55,19 @@ local function GetPlayerLevelWorkspaceFolder(PlayerUserId: string)
|
||||
end
|
||||
|
||||
-- 创建关卡信息实例
|
||||
local function CreateLevelInstance(Player: Player, Folder: Instance, LevelKey: string, LevelValue: number)
|
||||
if not Player or not Folder or not LevelKey or not LevelValue then return end
|
||||
local LevelInstance = Instance.new("NumberValue")
|
||||
local function CreateLevelInstance(Player: Player, Folder: Instance, LevelKey: string, LevelValue: any)
|
||||
if not Player or not Folder or not LevelKey then return end
|
||||
local InstanceType
|
||||
if type(LevelValue) == "number" then
|
||||
InstanceType = "NumberValue"
|
||||
elseif type(LevelValue) == "boolean" then
|
||||
InstanceType = "BoolValue"
|
||||
elseif type(LevelValue) == "string" then
|
||||
InstanceType = "StringValue"
|
||||
else
|
||||
InstanceType = "NumberValue"
|
||||
end
|
||||
local LevelInstance = Instance.new(InstanceType)
|
||||
LevelInstance.Name = LevelKey
|
||||
LevelInstance.Parent = Folder
|
||||
LevelInstance.Value = LevelValue
|
||||
@ -68,9 +87,9 @@ end
|
||||
|
||||
local EXCEPT_KEY = { "Task", "Mobs"}
|
||||
local function ChangeValue(Player: Player, Folder: Instance, LevelKey: string, LevelValue: any)
|
||||
if not Player or not Folder or not LevelKey or not LevelValue then return end
|
||||
if not Player or not Folder or not LevelKey then warn("LevelProxy ChangeValue", Player.UserId, Folder.Name, LevelKey, LevelValue) return end
|
||||
local ValueInstance = Folder:FindFirstChild(LevelKey)
|
||||
if not ValueInstance then return end
|
||||
if not ValueInstance then warn("ValueInstance not found", LevelKey) return end
|
||||
|
||||
local storeTable
|
||||
if Folder.Name == "Challenge" then
|
||||
@ -86,17 +105,17 @@ end
|
||||
-- 怪物死亡,由初始化时传入
|
||||
local function OnMobDied(Player: Player, Mob: TypeList.Character)
|
||||
for _, mob in LevelProxy.pData[Player.UserId].Mobs do
|
||||
if mob ~= Mob then continue end
|
||||
if mob.Instance ~= Mob.Instance then continue end
|
||||
table.remove(LevelProxy.pData[Player.UserId].Mobs, table.find(LevelProxy.pData[Player.UserId].Mobs, mob))
|
||||
|
||||
-- 怪物清除判断
|
||||
local LevelData = Utils:GetJsonData(JsonLevel, LevelProxy.pData[Player.UserId].LevelId)
|
||||
-- 怪物被击杀时做关卡数据处理
|
||||
local LevelData = Utils:GetIdDataFromJson(JsonLevel, LevelProxy.pData[Player.UserId].LevelId)
|
||||
if LevelProxy.pData[Player.UserId].SpawnWaveFinish and #LevelProxy.pData[Player.UserId].Mobs == 0 then
|
||||
if LevelProxy.pData[Player.UserId].NowWave < #LevelData["wave"] then
|
||||
-- 波数增长
|
||||
LevelProxy.pData[Player.UserId].NowWave = LevelProxy.pData[Player.UserId].NowWave + 1
|
||||
-- -- 波数增长
|
||||
LevelProxy.pData[Player.UserId].ShouldWave = LevelProxy.pData[Player.UserId].ShouldWave + 1
|
||||
-- 新波次重置怪物生成状态标记
|
||||
local ChallengeFolder = LevelFolder:FindFirstChild("Challenge")
|
||||
local ChallengeFolder = GetPlayerLevelFolder(Player, "Challenge")
|
||||
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", false)
|
||||
elseif LevelProxy.pData[Player.UserId].NowWave >= #LevelData["wave"] then
|
||||
-- 结束判断
|
||||
@ -110,8 +129,6 @@ end
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function LevelProxy:InitPlayer(Player: Player)
|
||||
local pData = Utils:GetPlayerDataFolder(Player)
|
||||
if not pData then warn("Level pData not found", Player.UserId) return end
|
||||
local PlayerLevelFolder = Utils:CreateFolder(Player.UserId, LevelFolder)
|
||||
local ProgressFolder = Utils:CreateFolder("Progress", PlayerLevelFolder)
|
||||
local DungeonFolder = Utils:CreateFolder("Dungeon", PlayerLevelFolder)
|
||||
@ -163,8 +180,7 @@ function LevelProxy:ChallengeLevel(Player: Player, LevelId: number)
|
||||
-- 场景后端生成
|
||||
|
||||
-- 后端生成当前关卡状态数据
|
||||
local LevelFolder = GetPlayerLevelWorkspaceFolder(Player.UserId)
|
||||
local ChallengeFolder = LevelFolder:FindFirstChild("Challenge")
|
||||
local ChallengeFolder = GetPlayerLevelFolder(Player,"Challenge")
|
||||
if not ChallengeFolder then warn("ChallengeFolder not found") return end
|
||||
local levelTask = task.spawn(function()
|
||||
ChangeValue(Player, ChallengeFolder, "IsBoss", LevelData.type == 2 and true or false)
|
||||
@ -184,13 +200,13 @@ function LevelProxy:ChallengeLevel(Player: Player, LevelId: number)
|
||||
LevelProxy.pData[Player.UserId].NowWave < LevelProxy.pData[Player.UserId].ShouldWave and
|
||||
LevelProxy.pData[Player.UserId].SpawnWaveFinish == false then
|
||||
ChangeValue(Player, ChallengeFolder, "NowWave", LevelProxy.pData[Player.UserId].NowWave + 1)
|
||||
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", true)
|
||||
|
||||
local waveData = LevelData.wave[LevelProxy.pData[Player.UserId].NowWave]
|
||||
for i = 1, #waveData, 3 do
|
||||
local mobId = waveData[i + 1]
|
||||
local mobCount = waveData[i + 2]
|
||||
for _ = 1, mobCount do
|
||||
print("怪物增益", LevelData.atkBonus, LevelData.hpBonus)
|
||||
local mob = MobsProxy:CreateMob(Player, mobId, LevelData.atkBonus, LevelData.hpBonus, OnMobDied)
|
||||
table.insert(LevelProxy.pData[Player.UserId].Mobs, mob)
|
||||
end
|
||||
@ -204,7 +220,7 @@ function LevelProxy:ChallengeLevel(Player: Player, LevelId: number)
|
||||
local maxWave = #LevelData.wave
|
||||
if LevelProxy.pData[Player.UserId].NowWave < maxWave then
|
||||
-- 下一波
|
||||
ChangeValue(Player, ChallengeFolder, "ShouldWave", LevelProxy.pData[Player.UserId].ShouldWave + 1)
|
||||
ChangeValue(Player, ChallengeFolder, "ShouldWave", LevelProxy.pData[Player.UserId].ShouldWave)
|
||||
else
|
||||
-- 挑战胜利
|
||||
self:ChallengeEnd(Player, true)
|
||||
@ -224,9 +240,7 @@ end
|
||||
|
||||
-- 挑战结束
|
||||
function LevelProxy:ChallengeEnd(Player: Player, result: boolean)
|
||||
local pData = Utils:GetPlayerDataFolder(Player)
|
||||
local LevelFolder = Utils:CreateFolder(STORE_NAME, pData)
|
||||
local ProgressFolder = Utils:CreateFolder("Progress", LevelFolder)
|
||||
local ProgressFolder = GetPlayerLevelFolder(Player, "Progress")
|
||||
|
||||
-- 停止关卡循环
|
||||
if LevelProxy.pData[Player.UserId].Task then
|
||||
@ -235,12 +249,16 @@ function LevelProxy:ChallengeEnd(Player: Player, result: boolean)
|
||||
end
|
||||
|
||||
-- 清除剩余怪物
|
||||
print("清除剩余怪物", LevelProxy.pData[Player.UserId].Mobs)
|
||||
for _, mob in LevelProxy.pData[Player.UserId].Mobs do mob:Died(true) end
|
||||
LevelProxy.pData[Player.UserId].Mobs = {}
|
||||
|
||||
-- 清除玩家表现
|
||||
Communicate:SendToClientFree(RE_CleanPlayerPerformance, Player)
|
||||
|
||||
-- 判断玩家是否通关
|
||||
if result then
|
||||
ChangeValue(Player, ProgressFolder, "LevelId", LevelProxy.pData[Player.UserId].LevelId + 1)
|
||||
ChangeValue(Player, ProgressFolder, "Main", LevelProxy.pData[Player.UserId].LevelId + 1)
|
||||
else
|
||||
local IsBoss = LevelProxy.pData[Player.UserId].IsBoss
|
||||
if IsBoss then
|
||||
|
@ -68,7 +68,7 @@ function Mob.new(Player: Player, MobId: number, OnMobDied: ((Player: Player, Mob
|
||||
newMobModel.Parent = playerMobsFolder
|
||||
|
||||
-- 死亡函数
|
||||
if OnMobDied then Mob.OnDied = OnMobDied end
|
||||
if OnMobDied then self.OnDied = OnMobDied end
|
||||
|
||||
-- -- 接入统一AI
|
||||
-- self.Humanoid.MoveToFinished:Connect(function()
|
||||
@ -81,11 +81,13 @@ function Mob.new(Player: Player, MobId: number, OnMobDied: ((Player: Player, Mob
|
||||
return self
|
||||
end
|
||||
|
||||
-- IsSkinOnDied:暂时意义不明,忘了之前为啥写了
|
||||
function Mob:Died(IsSkinOnDied: boolean?)
|
||||
MobsProxy:RemoveMob(self.Player, self.Instance)
|
||||
if not IsSkinOnDied then
|
||||
if self.OnDied then self.OnDied(self.Player, self) end
|
||||
end
|
||||
-- if not IsSkinOnDied then
|
||||
-- if self.OnDied then self.OnDied(self.Player, self) end
|
||||
-- end
|
||||
if self.OnDied then self.OnDied(self.Player, self) end
|
||||
Character.Died(self)
|
||||
end
|
||||
|
||||
|
@ -38,6 +38,9 @@ function LevelLoop.new(Player: Player, PlayerRole: TypeList.Character)
|
||||
end
|
||||
|
||||
function LevelLoop:AutoChallenge()
|
||||
print("AutoChallenge")
|
||||
|
||||
-- TODO: 回退有bug,不能一关一关回退
|
||||
-- 重置玩家状态(先临时调用角色复活,之后复杂的内容再说)
|
||||
self.PlayerRole:Respawn()
|
||||
|
||||
@ -50,11 +53,12 @@ function LevelLoop:AutoChallenge()
|
||||
if FailBossId == LevelId then
|
||||
LevelId = LevelId - 1
|
||||
end
|
||||
|
||||
LevelProxy:ChallengeLevel(self.Player, LevelId)
|
||||
end
|
||||
|
||||
function LevelLoop:OnChallengeEnd(Player: Player, LevelId: number, result: boolean)
|
||||
self.TaskAutoChallenge = task.defer(function()
|
||||
self.TaskAutoChallenge = task.spawn(function()
|
||||
task.wait(3)
|
||||
self:AutoChallenge()
|
||||
end)
|
||||
|
@ -9,6 +9,7 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
--> Dependencies
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
|
||||
--> Events
|
||||
local RE_PlayerAI = ReplicatedStorage.Events.RE_PlayerAI
|
||||
@ -17,8 +18,6 @@ local RE_PlayerAI = ReplicatedStorage.Events.RE_PlayerAI
|
||||
local DamageProxy = require(ServerStorage.Proxy.DamageProxy)
|
||||
local ActivePlayers = {}
|
||||
|
||||
local BehavioursFolder = ServerStorage:FindFirstChild("Modules"):FindFirstChild("Behaviours")
|
||||
|
||||
local Behaviours = {}
|
||||
local BehaviourFolder = ServerStorage:FindFirstChild("Modules"):FindFirstChild("Behaviours")
|
||||
if BehaviourFolder then
|
||||
@ -36,7 +35,6 @@ if BehaviourFolder then
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 新建玩家AI
|
||||
@ -48,6 +46,9 @@ function PlayerAI.new(Player: Player, PlayerRole: TypeList.Character)
|
||||
self.ExecutingState = false
|
||||
self.PlayerControling = false
|
||||
|
||||
self.LastTime = 0
|
||||
self.Counter = 0
|
||||
|
||||
self.BehaviourList = {}
|
||||
self.LoopTask = task.spawn(function()
|
||||
while task.wait(0.25) do
|
||||
@ -91,6 +92,11 @@ function PlayerAI:AddBehaviour(BehaviourName: string)
|
||||
self.BehaviourList[BehaviourName] = newBehaviour
|
||||
end
|
||||
|
||||
-- 获取并记录行为UniqueId
|
||||
function PlayerAI:GetBehaviourUniqueId()
|
||||
return Utils:GenUniqueIdPlayerAI(self.LastTime, self.Counter)
|
||||
end
|
||||
|
||||
-- 动态删除行为
|
||||
function PlayerAI:RemoveBehaviour(BehaviourName: string)
|
||||
if self.BehaviourList[BehaviourName] then
|
||||
|
@ -17,6 +17,10 @@ local JsonCharacter = require(ReplicatedStorage.Json.Character)
|
||||
--> Dependencies
|
||||
local LevelLoop = require(script.LevelLoop)
|
||||
local PlayerAI = require(script.PlayerAI)
|
||||
local Communicate = require(ServerStorage.Modules.Tools.Communicate)
|
||||
|
||||
--> Events
|
||||
local RE_CleanPlayerPerformance = ReplicatedStorage.Events.RE_CleanPlayerPerformance
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -43,6 +47,9 @@ function PlayerRole.new(Player: Player, CharacterId: number)
|
||||
-- 调用父类Character的new方法,初始化通用属性
|
||||
local self = Character.new(Player, playerCharacter, CharacterData)
|
||||
setmetatable(self, PlayerRole)
|
||||
|
||||
-- 玩家放到Character目录下
|
||||
playerCharacter.Parent = game.Workspace.Characters
|
||||
return self
|
||||
end
|
||||
|
||||
@ -80,6 +87,7 @@ function PlayerFightProxy:InitPlayer(Player: Player)
|
||||
local PlayerAI = PlayerAI.new(Player, PlayerRole)
|
||||
PlayerFightProxy.pData[Player.UserId].PlayerAI = PlayerAI
|
||||
PlayerAI:AddBehaviour("Move")
|
||||
PlayerAI:AddBehaviour("SwordWave")
|
||||
end
|
||||
|
||||
function PlayerFightProxy:GetPlayerRole(Player: Player)
|
||||
@ -103,6 +111,9 @@ function PlayerFightProxy:CleanPlayer(Player: Player)
|
||||
end
|
||||
|
||||
function PlayerFightProxy:OnPlayerRemoving(Player: Player)
|
||||
-- 玩家离开时,通知其他客户端销毁玩家表现内容
|
||||
Communicate:SendToClientFree(RE_CleanPlayerPerformance, Player)
|
||||
-- 正常清除玩家该模块下数据
|
||||
if not PlayerFightProxy.pData[Player.UserId] then warn("PlayerFight Remove Data not found", Player.Name) return end
|
||||
PlayerFightProxy.pData[Player.UserId] = nil
|
||||
end
|
||||
|
@ -15,7 +15,6 @@ UserInputService.InputBegan:Connect(function(input, gameProcessed)
|
||||
if input.KeyCode == Enum.KeyCode.H then
|
||||
RE_PlayerHelper:FireServer("CleanPlayerData")
|
||||
elseif input.KeyCode == Enum.KeyCode.J then
|
||||
print("添加物品")
|
||||
RE_PlayerHelper:FireServer("AddItem", {1, 100})
|
||||
elseif input.KeyCode == Enum.KeyCode.K then
|
||||
RE_UpgradeAttributes:FireServer(1)
|
||||
|
88
src/StarterPlayerScripts/ClientMain/PerformanceClient.luau
Normal file
88
src/StarterPlayerScripts/ClientMain/PerformanceClient.luau
Normal file
@ -0,0 +1,88 @@
|
||||
-- 控制客户端表现管理
|
||||
|
||||
local PerformanceClient = {}
|
||||
PerformanceClient.pData = {}
|
||||
|
||||
--> Services
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
|
||||
--> Events
|
||||
local EventsFolder = ReplicatedStorage:FindFirstChild("Events")
|
||||
local RE_PerformanceEvent = EventsFolder:FindFirstChild("RE_PerformanceEvent")
|
||||
local RE_CleanPlayerPerformance = EventsFolder:FindFirstChild("RE_CleanPlayerPerformance")
|
||||
|
||||
--> Variables
|
||||
local LocalPlayer = game.Players.LocalPlayer
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- 生成本地化表现目录
|
||||
local PerformanceFolder = Instance.new("Folder")
|
||||
PerformanceFolder.Name = "Performance"
|
||||
PerformanceFolder.Parent = game.Workspace
|
||||
|
||||
-- 加载所有客户端行为
|
||||
local Behaviours = {}
|
||||
local BehaviourFolder = ReplicatedStorage:FindFirstChild("Modules"):FindFirstChild("BehavioursClient")
|
||||
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
|
||||
|
||||
|
||||
-- 监听表现事件调用
|
||||
RE_PerformanceEvent.OnClientEvent:Connect(function(ServerTime: number, CastTag: string, CasterPlayer: Player, BehaviourName: string, CastState: boolean, Infos: table)
|
||||
-- 初始化玩家存储
|
||||
local UserId = CasterPlayer.UserId
|
||||
if not PerformanceClient.pData[UserId] then PerformanceClient.pData[UserId] = {} end
|
||||
|
||||
local delayTime = ServerTime - tick()
|
||||
if CastTag == "Init" then
|
||||
print("Init", BehaviourName)
|
||||
-- 暂时就新增一个表,不调用初始化,因为服务端不是多个new做的,而是多次调用
|
||||
if not PerformanceClient.pData[UserId][BehaviourName] then
|
||||
PerformanceClient.pData[UserId][BehaviourName] = {}
|
||||
end
|
||||
elseif CastTag == "Show" then
|
||||
print("Show", BehaviourName, Behaviours)
|
||||
-- 直接调用init和对应的show(因为服务端只new一次,客户端多次调用)
|
||||
if not PerformanceClient.pData[UserId][BehaviourName] then return end
|
||||
for _, CastInfo in pairs(Infos) do
|
||||
local BehaviourTable = PerformanceClient.pData[UserId][BehaviourName]
|
||||
BehaviourTable[CastInfo.UniqueId] = Behaviours[BehaviourName]:Init(CasterPlayer, CastInfo, delayTime, CastState)
|
||||
BehaviourTable[CastInfo.UniqueId]:Show(CasterPlayer, CastInfo, delayTime, CastState)
|
||||
end
|
||||
elseif CastTag == "Destroy" then
|
||||
if not PerformanceClient.pData[UserId][BehaviourName] then return end
|
||||
for _, CastInfo in pairs(Infos) do
|
||||
local Behaviour = PerformanceClient.pData[UserId][BehaviourName][CastInfo.UniqueId]
|
||||
if Behaviour and Behaviour.Destroy then
|
||||
Behaviour:Destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- 清理玩家所有表现数据
|
||||
RE_CleanPlayerPerformance.OnClientEvent:Connect(function(CleanedPlayer: Player)
|
||||
-- print("CleanPlayerPerformance", CleanedPlayer)
|
||||
local UserId = CleanedPlayer.UserId
|
||||
if not PerformanceClient.pData[UserId] then return end
|
||||
for _, BehaviourList in pairs(PerformanceClient.pData[UserId]) do
|
||||
for _, Behaviour in pairs(BehaviourList) do
|
||||
Behaviour:Destroy()
|
||||
end
|
||||
end
|
||||
PerformanceClient.pData[UserId] = nil
|
||||
end)
|
||||
|
||||
return PerformanceClient
|
Loading…
x
Reference in New Issue
Block a user