From ac7c83a9bb8a4989fb5b4af9f747693a0a3b70da Mon Sep 17 00:00:00 2001 From: Ggafrik <906823881@qq.com> Date: Sat, 12 Jul 2025 05:06:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- default.project.json | 3 + excel/attribute.xlsx | Bin 0 -> 9816 bytes excel/cha.xlsx | Bin 10775 -> 10897 bytes excel/gem.xlsx | Bin 0 -> 18848 bytes excel/item.xlsx | Bin 87589 -> 20783 bytes .../Base/BehaviourClient.luau | 38 ++++ src/ReplicatedStorage/Json/Attributes.json | 21 ++ src/ReplicatedStorage/Json/Gem.json | 58 +++++ src/ReplicatedStorage/Json/ItemProp.json | 59 ++++- .../Modules/BehavioursClient/SwordWave.luau | 47 ++++ .../Modules/EffectDispatcher.luau | 46 ++++ src/ReplicatedStorage/Tools/Utils.luau | 39 ++++ src/ServerStorage/Base/Behaviour.luau | 52 ++++- src/ServerStorage/Base/Character.luau | 12 +- src/ServerStorage/Base/TypeList.luau | 6 + .../Modules/Behaviours/Move.luau | 16 +- .../Modules/Behaviours/SwordWave.luau | 102 +++++++++ .../Modules/Tools/Communicate.luau | 11 + src/ServerStorage/Proxy/DamageProxy.luau | 60 ++++++ src/ServerStorage/Proxy/EquipmentProxy.luau | 34 ++- src/ServerStorage/Proxy/GemProxy.luau | 204 ++++++++++++++++++ src/ServerStorage/Proxy/LevelProxy.luau | 70 +++--- src/ServerStorage/Proxy/MobsProxy/init.luau | 10 +- .../Proxy/PlayerFightProxy/LevelLoop.luau | 6 +- .../Proxy/PlayerFightProxy/PlayerAI.luau | 12 +- .../Proxy/PlayerFightProxy/init.luau | 11 + .../ClientMain/Helper.luau | 1 - .../ClientMain/PerformanceClient.luau | 88 ++++++++ 28 files changed, 931 insertions(+), 75 deletions(-) create mode 100644 excel/attribute.xlsx create mode 100644 excel/gem.xlsx create mode 100644 src/ReplicatedStorage/Base/BehaviourClient.luau create mode 100644 src/ReplicatedStorage/Json/Attributes.json create mode 100644 src/ReplicatedStorage/Json/Gem.json create mode 100644 src/ReplicatedStorage/Modules/BehavioursClient/SwordWave.luau create mode 100644 src/ReplicatedStorage/Modules/EffectDispatcher.luau create mode 100644 src/ServerStorage/Modules/Behaviours/SwordWave.luau create mode 100644 src/ServerStorage/Modules/Tools/Communicate.luau create mode 100644 src/ServerStorage/Proxy/GemProxy.luau create mode 100644 src/StarterPlayerScripts/ClientMain/PerformanceClient.luau diff --git a/default.project.json b/default.project.json index a69113d..72839bd 100644 --- a/default.project.json +++ b/default.project.json @@ -32,6 +32,9 @@ "ReplicatedStorage": { "$className": "ReplicatedStorage", + "Base": { + "$path": "src/ReplicatedStorage/Base" + }, "Data": { "$path": "src/ReplicatedStorage/Data" }, diff --git a/excel/attribute.xlsx b/excel/attribute.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b4f666ee0f3f8f8fc6b8fa3f9db626c0db8bfa48 GIT binary patch literal 9816 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 V4Feus0005J`+_CB`}J?X{ts6v7Y+ab literal 0 HcmV?d00001 diff --git a/excel/cha.xlsx b/excel/cha.xlsx index cb4048da6fa4fffb00ff6af13cf055d4d65d9eb1..521ef7fce8d8b786a3fa68d7dfa754419a51c000 100644 GIT binary patch delta 1936 zcmV;B2XFY7RFPG%&<1~NqV5`k0{{T{2mk;N0001ZY%h0ja%*C5Z)+}iZEUPnZEvGE z5dMDB{s+W&icNq9RJuw6=pwbND4T8fq)L?oPVf~lXG}x2+W)>|$m`~G%5@hdHXe^3 zKQr^#+lIRVvrDoYXQ( znWSl;U&D}Z=)nL{iKZGiEQeWZ=vj_#-tOf*6EJ|v z;~-*fPXB3`pm26TLJ$tLB=O0zo)MX8jmQIi;y=v<|C=VVeiF-en&$M8l8Tp4v`uLK zbfiIYF8KeULXxN?m=JhRu7CeI3BXbKJEhH}(BOR<-a)oMlUK++R5;xp%_$@o51z|J z`1tu--U?tnP)8VF@d}OK2 zKtayX0+-(QCuQpl7~_G5z(^9wUg?4?!Js{NHhPcIU?5eT@`L$cbD)T3+BAHm9pGsX>}uCQRUaOm^%H$7lc)?HI>~jXh+H z$F6NSVLWiIaX5*b_&`>Lzk27zH8i``l*k57ygKaN*jH`5weF3p-mtCl$tm{dq00Mq z^?x~jhUjy8p>zCjq2uJ!{o?*Y-@9n>{1_r%>O8t1hoj5=NAvmUuSN8Aw}tty3GEB6 z+D@kCPA0cM0Fwa~6te;flm!JjGR}=hlba7Ee_4;4Fc8PzEA=~Aeg|{p02H!{Hc7j0 zRnKR~48aP<)OIda{q7yev5_LR=}N#Dd*=6_u?Hqk2UU|D7%O#?)6fqnfkx;;HtU>z z`?~ZJO045e!E4<>PLE*e)Aaqj$zGd{tpFTBLSu7UIoD>4Sy6%F*4HgGxKe7PxWiYo ze`dBdz>7Xe)hr5v5mQ_?^hC(aBMe=ZQovk`t%Am#AO>pgFn?Rg)?R2zJc3i)Y__c@ zv}zHtlC^Zl9!iN4*~_}ohOcU@`w$MeAP0k2gm-+A>F4j1loUo=T{<7h?3D9;`6){o z7gy4K{SRTn0W+|Z-2uL$qPL|K4zH}}e-#$L5jMKQy6rOARu(z^m4wULJeWOuqeVLM z28+eQOVY*68xF%{mPX@IoF>2NbW%t>;jSuTpv>tk%wEDFWz$LDK;I?o?ai1tzWM?+ z2nQ$u3FD0{#KBz!5JH1stYeK1H+iAu<7fP`b&S4X{Mbo?K!g zi^jL6y<R&*^v1y=l5S$U67}W2;7Gh(s|8K=DRYs?5-~Scgj# zSjUuLb)z6dN3dv>UtgtMQ{EVOHjM`3DzJekDNDJ|(B3&sF}8dUlG(^Rloxl6k<9th zlvp$V!AiihI9_0X362To818_f9*O9L6nsSLPgC~*!7#@N(>s4fG7|gIWo?TM+E=?;}ie@7ytkO0000000000000FLldLF20fLk9C_oH1 z8~^}#Y%gA{QYjh%e3NY{CmbB6U_M0w00374000pH000000000000000 WTq2XODLnz$lkO=a2DK*u0000JU7)N0 delta 1793 zcmV+c2mbhxRhLw-&<1~YSyDa)0{{RA2LJ#M0001ZY%h0ja%*C5Z)+}iZEUPnTW^~% z6n>wy|A72X!30Q)N~heaMcSsQ>*XcV|+LpANc@0gS{ZC<(yN^I83d=%re<^Q?e7V7084&~hl22O4C@g8u^* zGH#RLVcd%)adg|nxvImhJE!MBR5gns)u^`m$= z9Q*D#im87aMiF&K(@E_5<8TsipfRGe_h8k0Yj)k3Ev#2Ox%KC`yBP(Nuz z_Dtia|Ma-Ff7SH1Up8QSfZYn%>SqDiq0`=pDwErkxYWw_@#S#a8Sg}9a#T=s8sI0p zxsM<=IWne$Gan}zH{t=V*$QWD2!Z99k{A4@JAQwc__(%t!OuG&*d3fmwCkO!6Z<4* z3Y~z$L)xCJUDi?GiFKpq8MQ$kE*Kf3#Hul%Z|aR=85}Ic6K%gR=;YA5;;V84LYeA1@tQLq9-qoF?<`e&i*&jyhj;`VY+!$IIq!f7yzhO_Bx9N9|SOC$Lo zM`t9rZ<78tvMezt<{Hy-k9XJ=tjA2FG`mcA$QPB}v-bK`7rz0MF&q@Le+rZZ1z`{d zyh)Q75G8-xj+-zLhVLu&9W392F(d>~$ST?pHFs6Fhik`}U(WawvW~SSYji7e{3{2v!bBsv%(z#6&UK;u9e= zk1%vqNiG(e@04iW31URU9Mo@X+1U$C@kelqneDFgxKxxJYAfR1}4mq{ZADk7+Vb!$};a$!|QH zmJ)WjcZH0oay+NmijFavO@{{hF2%v#jFDsO7tsjr1c*?K`u<#Nz3nHi;86fbJ51=2 zj61m(&!TB^Tu|_8e-0}B7$nG5<92+}TMmCc{n?;WRBYF{FZ%FF$W84)cmz)SR>{iO zg|HlY6r}yAhjQHj0j@|%_|{-e6gv*_AWK(6a_R?37(_H2W3(35EoG0yi0`b^>c@H3 znRTLo-avtPri2rJ@_0VX9P;C9KAreU^q*Bs&J>6jFSnGx)DORxK_B9!{=omYe=-Ct z<{tpFI}$Gt1?Xr%Y(}$hA~FGg&=xk`8eoZR z&*^v1y=l5Ss4DmZW6N4+h(-hjphYc9U1aEGyABs9u#RiVt6D>bj$qL$zrIRE!$fW1 z$ZNn0kG4DFq37{*rYL2(;-hxX#GHi|o6ngTameDDHrOvnv?R^Yhgj^hp( zHX{+8kW!4u=F?O?Kne^MDA3Mg8d3b?bzqeJ^FgmnoT_xk#_x2BJ7r5Th@<;p%hA}j zZPX@x44<|-j|v)-v?wY9E)0_)5EYa4C=~@^ z5C*(SlMg8s0*DWjArKmqKq)E#2a{_lKmxoQldUN^0RfZeDJLB0Xh3X60RRA30ssIJ j0000000000000000O28%Dk?nzUXy4lBL+Js00000C+Jau diff --git a/excel/gem.xlsx b/excel/gem.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a2035613af7213cd29c9f762be1cbe01781e0231 GIT binary patch literal 18848 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 ArT_o{ literal 87589 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 YfHx~J1v3Dbw(>Hh02AoyAW-W90GL*Y=l}o! diff --git a/src/ReplicatedStorage/Base/BehaviourClient.luau b/src/ReplicatedStorage/Base/BehaviourClient.luau new file mode 100644 index 0000000..3fabf58 --- /dev/null +++ b/src/ReplicatedStorage/Base/BehaviourClient.luau @@ -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 \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/Attributes.json b/src/ReplicatedStorage/Json/Attributes.json new file mode 100644 index 0000000..8867865 --- /dev/null +++ b/src/ReplicatedStorage/Json/Attributes.json @@ -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]} +] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/Gem.json b/src/ReplicatedStorage/Json/Gem.json new file mode 100644 index 0000000..e20b740 --- /dev/null +++ b/src/ReplicatedStorage/Json/Gem.json @@ -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} +] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/ItemProp.json b/src/ReplicatedStorage/Json/ItemProp.json index 67f4c3c..9d737c6 100644 --- a/src/ReplicatedStorage/Json/ItemProp.json +++ b/src/ReplicatedStorage/Json/ItemProp.json @@ -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} ] \ No newline at end of file diff --git a/src/ReplicatedStorage/Modules/BehavioursClient/SwordWave.luau b/src/ReplicatedStorage/Modules/BehavioursClient/SwordWave.luau new file mode 100644 index 0000000..d10be85 --- /dev/null +++ b/src/ReplicatedStorage/Modules/BehavioursClient/SwordWave.luau @@ -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 \ No newline at end of file diff --git a/src/ReplicatedStorage/Modules/EffectDispatcher.luau b/src/ReplicatedStorage/Modules/EffectDispatcher.luau new file mode 100644 index 0000000..8f9fcfd --- /dev/null +++ b/src/ReplicatedStorage/Modules/EffectDispatcher.luau @@ -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 \ No newline at end of file diff --git a/src/ReplicatedStorage/Tools/Utils.luau b/src/ReplicatedStorage/Tools/Utils.luau index 9a0ebc7..0024885 100644 --- a/src/ReplicatedStorage/Tools/Utils.luau +++ b/src/ReplicatedStorage/Tools/Utils.luau @@ -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 \ No newline at end of file diff --git a/src/ServerStorage/Base/Behaviour.luau b/src/ServerStorage/Base/Behaviour.luau index f61b055..aec57cc 100644 --- a/src/ServerStorage/Base/Behaviour.luau +++ b/src/ServerStorage/Base/Behaviour.luau @@ -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 diff --git a/src/ServerStorage/Base/Character.luau b/src/ServerStorage/Base/Character.luau index 8a10815..57cc4d2 100644 --- a/src/ServerStorage/Base/Character.luau +++ b/src/ServerStorage/Base/Character.luau @@ -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() diff --git a/src/ServerStorage/Base/TypeList.luau b/src/ServerStorage/Base/TypeList.luau index 0f7a4ff..bce9ba2 100644 --- a/src/ServerStorage/Base/TypeList.luau +++ b/src/ServerStorage/Base/TypeList.luau @@ -20,4 +20,10 @@ export type Behaviour = { Destroy: () -> (), } +export type CastInfo = { + UniqueId: number, + StartPos: Vector3, + EndPos: Vector3, +} + return {} \ No newline at end of file diff --git a/src/ServerStorage/Modules/Behaviours/Move.luau b/src/ServerStorage/Modules/Behaviours/Move.luau index e30f196..44578e7 100644 --- a/src/ServerStorage/Modules/Behaviours/Move.luau +++ b/src/ServerStorage/Modules/Behaviours/Move.luau @@ -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 \ No newline at end of file diff --git a/src/ServerStorage/Modules/Behaviours/SwordWave.luau b/src/ServerStorage/Modules/Behaviours/SwordWave.luau new file mode 100644 index 0000000..2ded39c --- /dev/null +++ b/src/ServerStorage/Modules/Behaviours/SwordWave.luau @@ -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 \ No newline at end of file diff --git a/src/ServerStorage/Modules/Tools/Communicate.luau b/src/ServerStorage/Modules/Tools/Communicate.luau new file mode 100644 index 0000000..961b41f --- /dev/null +++ b/src/ServerStorage/Modules/Tools/Communicate.luau @@ -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 \ No newline at end of file diff --git a/src/ServerStorage/Proxy/DamageProxy.luau b/src/ServerStorage/Proxy/DamageProxy.luau index 98e0c6c..2de1258 100644 --- a/src/ServerStorage/Proxy/DamageProxy.luau +++ b/src/ServerStorage/Proxy/DamageProxy.luau @@ -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 diff --git a/src/ServerStorage/Proxy/EquipmentProxy.luau b/src/ServerStorage/Proxy/EquipmentProxy.luau index 42a3b62..adbe6f1 100644 --- a/src/ServerStorage/Proxy/EquipmentProxy.luau +++ b/src/ServerStorage/Proxy/EquipmentProxy.luau @@ -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 diff --git a/src/ServerStorage/Proxy/GemProxy.luau b/src/ServerStorage/Proxy/GemProxy.luau new file mode 100644 index 0000000..062f071 --- /dev/null +++ b/src/ServerStorage/Proxy/GemProxy.luau @@ -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 \ No newline at end of file diff --git a/src/ServerStorage/Proxy/LevelProxy.luau b/src/ServerStorage/Proxy/LevelProxy.luau index c0e96e0..51aca8f 100644 --- a/src/ServerStorage/Proxy/LevelProxy.luau +++ b/src/ServerStorage/Proxy/LevelProxy.luau @@ -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 diff --git a/src/ServerStorage/Proxy/MobsProxy/init.luau b/src/ServerStorage/Proxy/MobsProxy/init.luau index c1b834a..94db091 100644 --- a/src/ServerStorage/Proxy/MobsProxy/init.luau +++ b/src/ServerStorage/Proxy/MobsProxy/init.luau @@ -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 diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau index 2d739a5..e3d170c 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau @@ -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) diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau b/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau index 1389610..54929dc 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/PlayerAI.luau @@ -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 diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau index 3be8a28..9804d7d 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/init.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/init.luau @@ -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 diff --git a/src/StarterPlayerScripts/ClientMain/Helper.luau b/src/StarterPlayerScripts/ClientMain/Helper.luau index 8302612..4a17961 100644 --- a/src/StarterPlayerScripts/ClientMain/Helper.luau +++ b/src/StarterPlayerScripts/ClientMain/Helper.luau @@ -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) diff --git a/src/StarterPlayerScripts/ClientMain/PerformanceClient.luau b/src/StarterPlayerScripts/ClientMain/PerformanceClient.luau new file mode 100644 index 0000000..078b0a5 --- /dev/null +++ b/src/StarterPlayerScripts/ClientMain/PerformanceClient.luau @@ -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 \ No newline at end of file