From 083331454f79d2b7ff9b01e5b7da9ebbe79eed2e Mon Sep 17 00:00:00 2001 From: Ggafrik <906823881@qq.com> Date: Mon, 14 Jul 2025 00:30:47 +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 --- excel/ability.xlsx | Bin 0 -> 17131 bytes excel/attribute.xlsx | Bin 9816 -> 11926 bytes excel/cha.xlsx | Bin 10897 -> 10900 bytes excel/item.xlsx | Bin 20783 -> 20948 bytes src/ReplicatedStorage/Json/Ability.json | 3 + src/ReplicatedStorage/Json/Attributes.json | 10 + src/ReplicatedStorage/Json/ExAttributes.json | 12 + src/ReplicatedStorage/Json/ItemProp.json | 4 +- src/ReplicatedStorage/Tools/Utils.luau | 40 ++++ src/ServerStorage/Proxy/AbilityProxy.luau | 238 +++++++++++++++++++ src/ServerStorage/Proxy/EquipmentProxy.luau | 95 +++++++- src/ServerStorage/Proxy/GemProxy.luau | 33 ++- src/ServerStorage/Proxy/PlayerInfoProxy.luau | 7 + 13 files changed, 439 insertions(+), 3 deletions(-) create mode 100644 excel/ability.xlsx create mode 100644 src/ReplicatedStorage/Json/Ability.json create mode 100644 src/ReplicatedStorage/Json/ExAttributes.json create mode 100644 src/ServerStorage/Proxy/AbilityProxy.luau diff --git a/excel/ability.xlsx b/excel/ability.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..38d3ee97933cbb9965c3cad6bd9a91f39a10cf38 GIT binary patch literal 17131 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 literal 0 HcmV?d00001 diff --git a/excel/attribute.xlsx b/excel/attribute.xlsx index b4f666ee0f3f8f8fc6b8fa3f9db626c0db8bfa48..1a0a58324e6f4906513dd169c590ba85c3d9e5b6 100644 GIT binary patch delta 7311 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 G>3;z{)M|qO delta 5331 zcmZWtbyO7Ew;obzV1|%RiJ`khknT=tq#Rm88ix)6i6I3ML68)1hVE`j=@5_$$dJ-7 z@VNK>-n;8}-}&d9wf5d;opsLs_SxT;VL7KsrK^F3O%A{X-~j*tW`OPfd#Du#0FaDb zL&b~EYS{5CK}!#Pt%`J+pBZr4>Nk2_Wooo}LmGs?+t^{Q2t+5h5-)#S#cggAXV4O% z`C9tsq|B@@*@e43*djQv9r8B*ME9ymi~?%SYn~??#vDF52heqiM?S0+avuxnc}h`e zsyTev#k73Qwnj$Rvr22* zF#&*1TmXRN{tf(H`Tab+Tx>l&T=@LmTq}$$J#qxdLp~tyLT|J$@y0{d%YvO#nmB(o zow4a}QgQg>jJQte8lexGqmxBOHD-y~#AYeqjI3o6zH@DWY@3 z0n8nt3naoyN?{cAzhUxW)4tPBxyx~ba=kz`o?3T?nz|BFOw4!>lr>peQVA>c3rS5A z`X;=XFFe%KEZ!JN>j(v^cn-$1RpO6kREfmu;M|dL^(b<5hIg2I?V%T00V?2E>gJH= z9q3>$ocY^0M&@(fHG4mitz?VOe%2tcn4K{ZY7_vz8;&K(V2^lzOK2&W!OZ=)uknr9L>e5JPA{;*fE>s(a z;%1h{JW`(FR)=YoV>^$!k|(yrsN>g_kt3fMn$E^WTd}gVCS`GG8w~6lg$sWLMd!VH zgYCY3azchQHqjRqR!ziE>PN(E`EF;QA-8fE=!g&prxxBQt))_!%zI6hwl68}=M#6( zz{K^!eW?P|;%6naVS`w~AzyX^BiUlhfOr?->{2tv=h!np_yO=A5ORVrnY7H`_W)?Z zL|o!SFklt>S{gk9pjN`$7y-W=UkdQN4?hdaXqNqs9FNi8qgZ&hdzB2~DmY}Ms9(F~dxXUAyvZ76 zQU`eQ$R+-`fUr@=6c)26o-|HIi#UH1cqQcQJ?>6Fq-DA?jQkmT6={H~3`f@2Gri+< z+`Ma4SUki15FWrd@tYc7?FlddFtI(&%ze?RbcT1_a^t8K@Xe*O@QP@Yu3UqmOjJ5J z+J`A-K!p*;nd-e+klk!_u;wFwJ;d3*c+4|=a^U!Lu>bq&-&cSdM4QLr008)u@F!%{ zFu^|yKrVdIy-)xYePFWSR~<}(>xD_KucTFQ=3e{RO3D$>SisS3>(lqPYhrD<@sLuX zdT3(y@v+M$|X#N=KAA?2zm@93Vi`yYobYeM2tewh-aO zc@!CB(j#j$9*|p=is67L^~hf(B|clum1w)g0OCD>kQz*$Z<+17F$T@4{tzx4+*WaiQth=8Rw)=$nH2V`=ngGAUP^%aUJ+KW1YoJpsvt(<)a$fLSQT zTp@)1swv7nIaH^B_12|<;|(L)Ke?z}P?E4vBo5b8sK6dLQ)!>{NfA{s^=nhKjQ>zw zPFkn)C_PoPYY=@&we#Dv<)_M8|J6v&<$dwLySvZ-ySuckWv@jh5G=~Nx9~v;F!csr zBW=JV90E+*bqY*ruxoU`KC_JE@g)hvH&Hu-hLISf^y<*Nn_dUn=TonPns2k0ebdVv z(N$AHI_<4I<@46xbHDMg-o47a4Gw5ODC^B^TJRX#pQt+FQ3|}euCaFAN<#a-W)SVJ zO`j&VFxRNuFstP7glP}w%#;w$sE%p77*_Ws`2JWRof)V-+hCjVigTALpTG2jwYSah z?(HeM6m)Q-OH6du7B{y@D4Ch-_xciB%P&}*nRag;+48&KdnPcdp?uA&7x#1t8^#!w zNksO2gn%f4*kdNs5^$y=ShIvn4^~zJF2lgM%Ka!P!@6djMd!pgIaSyV8(b>}v{L0}M{_8*>==Tw1|W=Y2cX-! zi7&_L*)|6v2^x)mvJbvXJ+C-&pfvp|_|`q4j~JT52-|SJDTuSk8t3}LKB0aSMN^6W zIN=4|L}Y&luCiLA0a>HKM~X%@Bx&JCWt}kN4Qdq;cS5t4Q%=s9zVEp7X#-jX=@P`E z?+8!m#v}?nVdJ(*#h>VCOlXn%EaGv-w$f>S)cyd+1eMv?Lwr3sNAv?Ab;qme>7Ieo zVq;smY1p=0f!}EVBawYdAH!r*MtK84QVf@gNb^}b~M@#e6Y-z-apT#hd-n>K&S)dbepkyX;wQ#?+ zJ4A#=Rek6qKE?IBKhK*5-m_GRkA@|vK$j@=pe5^XQ@x-plbtbRNsL%IZf;_;K9i`5-m%yLZ$k~=wV@)2TFx19_3 zbgTnDRA$M^<1d=D?+kO^BT^s8Ug=kDuX;zhJBcP-$0gW zAH*vAnmU!S$?6btX4VdJ+IDVwUKcD8N5G~PB~+Wi-iHCI<;=3uc=gC22!~?7BDJJR ziMC5_!%jR-s5f01SN%b@i%2Tog4q)6+UpJ-Q_B@=6TIk*RStc#oQ;oLTCYAk2^~Z& zYobQIvm&C0-fR;rlsSk~!DO~Rdzyqj?F-<)Fiue%XNz{u?&AIR&18|ZAZ>h{*RmmS zCa`pHhNNo+tKKt9k+8^{D&KO!E!y0O)YFU#&m6HibW3a0bs$fTrIn#5`ACBezn*ik zb(_)~c9=04o57@kmQF?V0 z3hQuD97^@jkuX=6b6Z`&PJJJ1td20po2V<(;;363sva4lo|~%M{I#ABBIXEl7vZde zE@RsWyHkrg#VDSaU6y2!7|Hnx+1~u#-=Ccw6R5XzoUk2jcz#Us3VWnw#V`5=?bKZF z?8!(3B{Vtrq5bIScUZSW!ueLc$O{*Y@&ZI)zu1rnNO0u?zbn@Dqg^bPmJ*w$HO5NO z_@jQre9qtv4=}ezoK~tE1NdG|B1dZN&`0dUXEOdn?WdVj94 zt}3@)Rq>uW&>itYLge)lN9TYPe#n^GgS-PG6?;^IO2oLD0{_#jq-X>}02s8?P08mp zc8d00Ha}jQ7Lb#KH=FHoP0z}w$lhpx_P>zs-x}oJ{7E-pSG`?MDfdj{%{^eq|AQIm zb1w&b10OFZ_ZNRb2brniF(nJ?KS;l#uaH*AHN@ol*}$cwY5^jxQs{l|;$d5U_Sjz> z*@|QKPNd8*S>AdlLY_@FA8BMJXMO0<4nyJlgjnP_%P zm`Z?luw#%&qJA8!KAz~4sp5H&z>~vo-{n3Dye*BRPf8Ve$3g_$L5I-TS){b36{YkB z>=%~_b+hm};`6JNAnl*5_FA-EnWk?Bhif^4yDU}cRoSb``RX|JiTHH_Xn-rS>Uj%e z$M&qZFWmq;G>BJ;yLF|d7PDR%xgQq$U?J9n{%NbC4oKBC14(M~Q{^XtZFrx4y<0eW za$Zcg&Q}*NhbD`(*<@PD@^($Y!l4Qwz!2CU?glW6h~uy82vOS}KIg-t9`**k(eiJT z9FcodN2P;z#@LbZ{g0(CB4kOv7tfo1P!z3sR7nGXS&>n!XNk5ZfZUzpn|7U2C5-rU z)CU-D5qcZlG-q|gIP!8|pd@|GUQe2|)<{nxj7QSql35+msf~k~o&5ROYK8uh3}mC< ztv}3efc4x{%4MyE$1@0&reGl-FeY2ChWm}Q_Vgu!p=CK;&Ht>GuCgWC)f!$M4B{AL z9C=$V2%)5z`b?P^YoLR2!;VU#ge8(y6?dck?jG|&_|Z|B>X5zMUk9|R5KpfG4#iBt zfb7RV1$~e6ouz0{JmZI(YgO>ed?e4%_r4ty!FIeRI~4;H{lTp98aaAv{&{pHe_Nz* z^C1Cc1z+4$D}&+C{4&(7@kMyhh&Y+QJ5=zCGn{e_so7>i73oZ$h^YH&%Eyp zzxuiw2nGnFLrh=^@WslV{;};gZo(HYF-7 zkC|~8Q?90_rDb0diK^;;vn2)JY`n7hg#Im8rJ4KHOJ&dRaqs)DIE+0LA=TfZu8U&M zTOmXrKK!WP+wg98epb3~OsAVipxub^2Ms(kICEWXdHIXuj2k-Jk0Q2t!=}+SNS!fI zHVp4+Fwx^k8Sbjz*Dw9CBv}(q*?f%fdywd_X-a=0u5opfTeb7(+b|Ri*)~(^n)H+GiLID zL|w?b?zAfYQlg(&&EZ0Zv?<#Y4Ss3Eb)dwNn9{mn)-uI&gTQq$;k)f~ap8xba~2$d zJ@zf!bN*=vqTI70&*5-Oem-KIXBoPU`uAdwjkzkykRce1*v3*6Nf!G0vebsVM_}#A z4#hMVEK$|>lcCHE0cWDde)$ko;ylnYLg97VRzIB>-j~Q@0ThwxfrQf`qPS?5*Sg8n z6$?Yd^I^EC8M78=Rl-}DO9I3JEztPzBP7@R8N@|QEe z#r2>Euql|AqzuERwfEz_eD;fLzl^HCXaE*KR|5l+_r6yDe{~K%&8>%#31{bFp#8Ui zbRYYl(E_*TVWItpR|5bv|7-ed{szzG;idbBbOHcW|7FJ@g3FRoz^`~H;6}VOnC)P= zCodbvzgw?=LVWJS@8zq%8!@;XFFD=6znp)3ztY0@c-iUx0{4A3n%w_O;D4<5t5*zg ke!fR^|Cg@!%^v8#9FCaa?tC=F1ONg+=zVn8qd%?x1M`8pQ~&?~ diff --git a/excel/cha.xlsx b/excel/cha.xlsx index 521ef7fce8d8b786a3fa68d7dfa754419a51c000..9a1d37ad643167d74f7585f904de5a09a81a261d 100644 GIT binary patch delta 3335 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 z0000000000000000DP0`DJL5oreHor0RRA30ssIJ00000000000000009=zSDn0?& OlWQs?2DK*u0001;`chv2 diff --git a/excel/item.xlsx b/excel/item.xlsx index 59b092f9a2e528c15147f9b88efac5f67b870ba8..d84a7a08a79c19c7e71eb5beb02d49790b1c034c 100644 GIT binary patch delta 6934 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 P4TPr6fNG@iv-AG|kexh; delta 6814 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 bzh}{}o~yy#^<==P`|uJycAQ$R>&gECH)Z41 diff --git a/src/ReplicatedStorage/Json/Ability.json b/src/ReplicatedStorage/Json/Ability.json new file mode 100644 index 0000000..0297ccb --- /dev/null +++ b/src/ReplicatedStorage/Json/Ability.json @@ -0,0 +1,3 @@ +[ +{"id":20000,"type":1,"behaviourName":"swordWave","upgradeCost":[30000,5,10],"upgradeValue":[10,200],"recycle":[30000,100]} +] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/Attributes.json b/src/ReplicatedStorage/Json/Attributes.json index 8867865..28e35a7 100644 --- a/src/ReplicatedStorage/Json/Attributes.json +++ b/src/ReplicatedStorage/Json/Attributes.json @@ -12,6 +12,16 @@ {"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":20,"type":2,"effectAttribute":"critRate","battleValue":[1,10]}, +{"id":21,"type":2,"effectAttribute":"critDamageRate","battleValue":[1,10]}, +{"id":22,"type":2,"effectAttribute":"atkSpeedRate","battleValue":[1,10]}, +{"id":23,"type":2,"effectAttribute":"cdRate","battleValue":[1,10]}, +{"id":24,"type":2,"effectAttribute":"hpRate","battleValue":[1,10]}, +{"id":25,"type":1,"effectAttribute":"mpBonus","battleValue":[1,10]}, +{"id":26,"type":2,"effectAttribute":"mpReduceRate","battleValue":[1,10]}, +{"id":27,"type":1,"effectAttribute":"mpRecoverBonus","battleValue":[1,10]}, +{"id":28,"type":2,"effectAttribute":"vampireRate","battleValue":[1,10]}, +{"id":29,"type":2,"effectAttribute":"coinBonus","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]}, diff --git a/src/ReplicatedStorage/Json/ExAttributes.json b/src/ReplicatedStorage/Json/ExAttributes.json new file mode 100644 index 0000000..9808b37 --- /dev/null +++ b/src/ReplicatedStorage/Json/ExAttributes.json @@ -0,0 +1,12 @@ +[ +{"id":20,"value":[10,20]}, +{"id":21,"value":[10,20]}, +{"id":22,"value":[10,20]}, +{"id":23,"value":[10,20]}, +{"id":24,"value":[10,20]}, +{"id":25,"value":[10,20]}, +{"id":26,"value":[10,20]}, +{"id":27,"value":[10,20]}, +{"id":28,"value":[10,20]}, +{"id":29,"value":[10,20]} +] \ No newline at end of file diff --git a/src/ReplicatedStorage/Json/ItemProp.json b/src/ReplicatedStorage/Json/ItemProp.json index 9d737c6..3ad7d02 100644 --- a/src/ReplicatedStorage/Json/ItemProp.json +++ b/src/ReplicatedStorage/Json/ItemProp.json @@ -57,5 +57,7 @@ {"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} +{"id":13106,"type":4,"typeArgs":[],"quality":7,"iconId":67,"nameId":23106,"textId":33106,"buyPrice":[11,70],"sellPrice":[11,70],"use":[],"showPackage":null}, +{"id":20000,"type":5,"typeArgs":[],"quality":1,"iconId":1,"nameId":30000,"textId":40000,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null}, +{"id":30000,"type":6,"typeArgs":[],"quality":1,"iconId":2,"nameId":40000,"textId":50000,"buyPrice":[],"sellPrice":[],"use":[],"showPackage":null} ] \ No newline at end of file diff --git a/src/ReplicatedStorage/Tools/Utils.luau b/src/ReplicatedStorage/Tools/Utils.luau index 0024885..019c897 100644 --- a/src/ReplicatedStorage/Tools/Utils.luau +++ b/src/ReplicatedStorage/Tools/Utils.luau @@ -68,6 +68,33 @@ function Utils:GetIdDataFromJson(JsonData: table, id: number) return nil -- 没有找到对应id end +-- 获取随机id,ExceptIdList为可选参数,如果传入则排除ExceptIdList中的id +function Utils:GetRandomIdFromJson(JsonData: table, ExceptIdList: table?) + local rng = Random.new() + local randomId = rng:NextInteger(1, #JsonData) + while ExceptIdList and table.find(ExceptIdList, randomId) do + randomId = rng:NextInteger(1, #JsonData) + end + return randomId +end + + +-- 获取随机id,ExceptIdList为可选参数,如果传入则排除ExceptIdList中的id +function Utils:GetRandomIdFromJsonWithType(JsonData: table, Type: number, ExceptIdList: table?) + local result = {} + for _, item in ipairs(JsonData) do + if item.type == Type then + table.insert(result, item.id) + end + end + local rng = Random.new() + local randomId = rng:NextInteger(1, #result) + while ExceptIdList and table.find(ExceptIdList, randomId) do + randomId = rng:NextInteger(1, #result) + end + return randomId +end + function Utils:GetMaxIdFromJson(JsonData: table) local maxId = 0 for _, item in ipairs(JsonData) do @@ -111,6 +138,7 @@ function Utils:CreateDataInstance(Player: Player, UniqueId: number, EquipmentDat end local Config = Instance.new("Configuration") Config.Name = UniqueId + -- TODO: 子表数据也要处理 Utils:SetAttributesList(Config, EquipmentData) Config.Parent = Folder return Config @@ -125,6 +153,18 @@ function Utils:CopyTable(t: table) return newTable end +-- 深度复制表 +function Utils:DeepCopyTable(t: table) + local newTable = {} + for k, v in pairs(t) do + if type(v) == "table" then + newTable[k] = self:DeepCopyTable(v) + else + newTable[k] = v + end + end + return newTable +end -------------------------------------------------------------------------------- return Utils \ No newline at end of file diff --git a/src/ServerStorage/Proxy/AbilityProxy.luau b/src/ServerStorage/Proxy/AbilityProxy.luau new file mode 100644 index 0000000..ff4aa45 --- /dev/null +++ b/src/ServerStorage/Proxy/AbilityProxy.luau @@ -0,0 +1,238 @@ +-- 玩家通用信息 +local AbilityProxy = {} + +--> 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 JsonAbility = require(ReplicatedStorage.Json.Ability) + +--> Events +local RE_PlayerTip = ReplicatedStorage.Events.RE_PlayerTip +local RE_UpgradeAttributes = ReplicatedStorage.Events.RE_UpgradeAttributes + +--> Constants +local STORE_NAME = "Ability" + +-------------------------------------------------------------------------------- + +-- 获取玩家信息文件夹 +local function GetPlayerAbilityFolder(Player: Player) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + local AbilityFolder = pData:FindFirstChild("Ability") + return AbilityFolder +end + +-------------------------------------------------------------------------------- + +-- 初始化玩家 +function AbilityProxy:InitPlayer(Player: Player) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + local AbilityFolder = Utils:CreateFolder("Ability", pData) + + -- 新玩家数据初始化 + if not ArchiveProxy.pData[Player.UserId][STORE_NAME] then + ArchiveProxy.pData[Player.UserId][STORE_NAME] = {} + ArchiveProxy.pData[Player.UserId][STORE_NAME].Ability = {} + end + + -- 创建玩家信息实例 + for AbilityUniqueId, AbilityData in ArchiveProxy.pData[Player.UserId][STORE_NAME].Ability do + Utils:CreateDataInstance(Player, AbilityUniqueId, AbilityData, AbilityFolder) + end +end + +-------------------------------------------------------------------------------- + +-- 添加技能 +local EXCEPT_KEYS = {"id"} +function AbilityProxy:AddAbility(Player: Player, AbilityId: number) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + + local AbilityData = Utils:GetIdDataFromJson(JsonAbility, AbilityId) + if not AbilityData then return end + + local UniqueId = Utils:GenUniqueId(ArchiveProxy.pData[Player.UserId]) + -- 配置表内容 + local ResultData = {} + for key, value in pairs(AbilityData) do + if not table.find(EXCEPT_KEYS, key) then + ResultData[key] = value + end + end + + ResultData.id = UniqueId + ResultData.orgId = AbilityId + ResultData.level = 1 + -- 记录穿戴的装备UniqueId + ResultData.wearing = 0 + + ArchiveProxy.pData[Player.UserId][UniqueId] = ResultData + local AbilityInstance = Utils:CreateDataInstance(Player, UniqueId, ResultData, GetPlayerAbilityFolder(Player)) + return Utils:DeepCopyTable(ResultData), AbilityInstance +end + +-- 升级技能 +function AbilityProxy:UpgradeAbility(Player: Player, UniqueId: number) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + + -- 获取技能实例存储数据 + local UniqueData = ArchiveProxy.pData[Player.UserId][UniqueId] + if not UniqueData then return end + + -- 获取技能数据 + local AbilityData = Utils:GetIdDataFromJson(JsonAbility, UniqueData.orgId) + if not AbilityData then warn('技能数据不存在: ' , Player.Name, UniqueId) return end + + -- 检查是否有技能实例 + local AbilityInstance = GetPlayerAbilityFolder(Player):FindFirstChild(UniqueId) + if not AbilityInstance then warn('技能实例不存在: ' , Player.Name, UniqueId) return end + + -- 检查是否有充足的技能碎片 + local shouldCost = AbilityData.upgradeCost[2] + AbilityData.upgradeCost[3] * (AbilityData.level - 1) + if not Utils:CheckPlayerHasEnoughItem(Player, AbilityData.upgradeCost[1], shouldCost) then + RE_PlayerTip:FireClient(Player, "技能不足") + return + end + + -- 扣除技能碎片 + Utils:RemoveItem(Player, AbilityData.upgradeCost[1], shouldCost) + + -- 升级 + AbilityData.level = AbilityData.level + 1 + AbilityInstance:SetAttribute("Level", AbilityData.level) +end + +-- 回收技能 +function AbilityProxy:RecycleAbility(Player: Player, UniqueId: number) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + + -- 获取技能实例存储数据 + local UniqueData = ArchiveProxy.pData[Player.UserId][UniqueId] + if not UniqueData then return end + + -- 获取技能数据 + local AbilityData = Utils:GetIdDataFromJson(JsonAbility, UniqueData.orgId) + if not AbilityData then warn('技能数据不存在: ' , Player.Name, UniqueId) return end + + -- 检查是否有技能实例 + local AbilityInstance = GetPlayerAbilityFolder(Player):FindFirstChild(UniqueId) + if not AbilityInstance then warn('技能实例不存在: ' , Player.Name, UniqueId) return end + + -- 计算升级一共消耗多少材料 + local upgradeTotalCost = AbilityData.upgradeCost[2] + AbilityData.upgradeCost[3] * (AbilityData.level - 1) + -- 回收材料 + Utils:AddItem(Player, AbilityData.upgradeCost[1], upgradeTotalCost) + + -- 销毁 + AbilityInstance:Destroy() + ArchiveProxy.pData[Player.UserId][UniqueId] = nil +end + +-- 穿戴技能 +function AbilityProxy:WearAbility(Player: Player, AbilityUniqueId: number, EquipmentUniqueId: number) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + + -- 获取技能实例存储数据 + local UniqueData = ArchiveProxy.pData[Player.UserId][AbilityUniqueId] + if not UniqueData then return end + + -- 获取装备实例存储数据 + local EquipmentData = ArchiveProxy.pData[Player.UserId][EquipmentUniqueId] + if not EquipmentData then return end + + -- 检查是否有技能实例 + local AbilityInstance = GetPlayerAbilityFolder(Player):FindFirstChild(AbilityUniqueId) + if not AbilityInstance then warn('技能实例不存在: ' , Player.Name, AbilityUniqueId) return end + + -- 获取装备数据 + local EquipmentProxy = require(ServerStorage.Proxy.EquipmentProxy) + local EquipmentData = EquipmentProxy:GetEquipmentData(Player, EquipmentUniqueId) + + -- 遍历技能查看现在穿了几个 + local wearingCount = 0 + for _, AbilityData in ArchiveProxy.pData[Player.UserId] do + if AbilityData.wearing == EquipmentUniqueId then + wearingCount = wearingCount + 1 + end + end + + -- TODO: 获取这个装备最多穿几个技能,穿戴数量>=穿戴上限就返回 + + -- 穿戴技能 + UniqueData.wearing = EquipmentUniqueId + AbilityInstance:SetAttribute("Wearing", EquipmentUniqueId) +end + +-- 获取技能等级数值(对应技能调用这个函数获取数值) +function AbilityProxy:GetAbilityLevelValue(Player: Player, UniqueId: number) + local pData = Utils:GetPlayerDataFolder(Player) + if not pData then return end + + -- 获取技能实例存储数据 + local UniqueData = ArchiveProxy.pData[Player.UserId][UniqueId] + if not UniqueData then return end + + -- 获取技能数据 + local AbilityData = Utils:GetIdDataFromJson(JsonAbility, UniqueData.orgId) + if not AbilityData then warn('技能数据不存在: ' , Player.Name, UniqueId) return end + + -- 获取技能等级数值 + local upgradeValue = AbilityData.upgradeValue[1] + AbilityData.upgradeValue[2] * (UniqueData.level - 1) + return upgradeValue +end + +-- 获取随机技能id +function AbilityProxy:GetRandomAbilityId(ExceptIdList: table) + ExceptIdList = ExceptIdList or {} + local candidateIds = {} + for _, ability in ipairs(JsonAbility) do + local id = ability.id + if not table.find(ExceptIdList, id) then + table.insert(candidateIds, id) + end + end + if #candidateIds == 0 then + return nil -- 没有可用技能 + end + local rng = Random.new() + local idx = rng:NextInteger(1, #candidateIds) + return candidateIds[idx] +end + +-------------------------------------------------------------------------------- + +-- 获取技能属性 +function AbilityProxy:GetPlayerAbilityWearingAttributes(Player: Player) + -- TODO:暂时没有,之后如果技能附带属性值时再加 +end + +-- 获取玩家属性 +function AbilityProxy:GetPlayerAttributes(Player: Player) + local attributesList = {} + attributesList.AbilityWearingAttributes = self:GetPlayerAbilityWearingAttributes(Player) + return attributesList +end + +-------------------------------------------------------------------------------- + +function AbilityProxy:OnPlayerRemoving(Player: Player) + +end + +ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(Player: Player) + AbilityProxy:OnPlayerRemoving(Player) +end) + +return AbilityProxy \ No newline at end of file diff --git a/src/ServerStorage/Proxy/EquipmentProxy.luau b/src/ServerStorage/Proxy/EquipmentProxy.luau index adbe6f1..6164bec 100644 --- a/src/ServerStorage/Proxy/EquipmentProxy.luau +++ b/src/ServerStorage/Proxy/EquipmentProxy.luau @@ -12,6 +12,8 @@ local PlayerInfoProxy = require(ServerStorage.Proxy.PlayerInfoProxy) --> Json local JsonEquipment = require(ReplicatedStorage.Json.Equipment) +local JsonAttributes = require(ReplicatedStorage.Json.Attributes) +local JsonExAttributes = require(ReplicatedStorage.Json.ExAttributes) --> Constants local STORE_NAME = "Equipment" @@ -70,7 +72,96 @@ function EquipmentProxy:AddEquipment(Player: Player, EquipmentId: number) ResultData.wearing = 0 -- TODO: 其他随机词条内容添加在下面 - -- TODO: 之后回收修改随机生成 + + -- 随机生成额外属性数量 + local rng = Random.new() + + local maxExAttributeNumber = PlayerInfoProxy:GetPlayerInfo(Player).exAttributeNumber or 0 + local exAttributeNumber = rng:NextInteger(0, maxExAttributeNumber) + ResultData.maxExAttributeNumber = exAttributeNumber + ResultData.exAttributes = {} + if exAttributeNumber > 0 then + local spawnExAttributesId = {} + for i = 1, exAttributeNumber do + local newExAttributeId = Utils:GetRandomIdFromJsonWithType(JsonExAttributes, 1, spawnExAttributesId) + table.insert(spawnExAttributesId, newExAttributeId) + + local ExAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newExAttributeId) + local randomExAttributeValue = rng:NextInteger(ExAttributeData.randomValue[1], ExAttributeData.randomValue[2]) + + local AttributeData = Utils:GetIdDataFromJson(JsonAttributes, newExAttributeId) + ResultData.exAttributes[AttributeData.name] = randomExAttributeValue + end + end + + -- 随机生成元素属性数量(暂时跟额外属性相同,之后可以改逻辑) + local maxElementNumber = PlayerInfoProxy:GetPlayerInfo(Player).elementNumber or 0 + local elementNumber = rng:NextInteger(0, maxElementNumber) + ResultData.maxElementNumber = elementNumber + ResultData.elements = {} + if elementNumber > 0 then + local spawnElementsId = {} + for i = 1, elementNumber do + local newElementAttributeId = Utils:GetRandomIdFromJsonWithType(JsonExAttributes, 1, spawnElementsId) + table.insert(spawnElementsId, newElementAttributeId) + + local ElementAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newElementAttributeId) + local randomElementAttributeValue = rng:NextInteger(ElementAttributeData.randomValue[1], ElementAttributeData.randomValue[2]) + + local AttributeData = Utils:GetIdDataFromJson(JsonAttributes, newElementAttributeId) + ResultData.elements[AttributeData.name] = randomElementAttributeValue + end + end + + -- 随机生成元素抗性数量 + local maxElementDefNumber = PlayerInfoProxy:GetPlayerInfo(Player).elementDefNumber or 0 + local elementDefNumber = rng:NextInteger(0, maxElementDefNumber) + ResultData.maxElementDefNumber = elementDefNumber + ResultData.elementDef = {} + if elementDefNumber > 0 then + local spawnElementDefId = {} + for i = 1, elementDefNumber do + local newElementDefId = Utils:GetRandomIdFromJsonWithType(JsonExAttributes, 1, spawnElementDefId) + table.insert(spawnElementDefId, newElementDefId) + + local ElementDefAttributeData = Utils:GetIdDataFromJson(JsonExAttributes, newElementDefId) + local randomElementDefAttributeValue = rng:NextInteger(ElementDefAttributeData.randomValue[1], ElementDefAttributeData.randomValue[2]) + + local AttributeData = Utils:GetIdDataFromJson(JsonAttributes, newElementDefId) + ResultData.elementDef[AttributeData.name] = randomElementDefAttributeValue + end + end + + -- 随机生成技能槽位数量 + local AbilityProxy = require(ServerStorage.Proxy.AbilityProxy) + + local maxAbilityNumber = PlayerInfoProxy:GetPlayerInfo(Player).abilityNumber or 0 + local abilityNumber = rng:NextInteger(0, maxAbilityNumber) + ResultData.maxAbilityNumber = abilityNumber + if abilityNumber > 0 then + local spawnAbilitiesId = {} + for i = 1, abilityNumber do + local newAbilityId = AbilityProxy:GetRandomAbilityId(spawnAbilitiesId) + table.insert(spawnAbilitiesId, newAbilityId) + local newAbilityData, newAbilityInstance = AbilityProxy:AddAbility(Player, newAbilityId) + AbilityProxy:WearAbility(Player, newAbilityData.id, UniqueId) + end + end + + -- 随机生成宝石数量 + local GemProxy = require(ServerStorage.Proxy.GemProxy) + local maxGemNumber = PlayerInfoProxy:GetPlayerInfo(Player).gemNumber or 0 + local gemNumber = rng:NextInteger(0, maxGemNumber) + ResultData.maxGemNumber = gemNumber + if gemNumber > 0 then + local spawnGemsId = {} + for i = 1, gemNumber do + local newGemId = GemProxy:GetRandomGemId(spawnGemsId) + table.insert(spawnGemsId, newGemId) + local newGemData, newGemInstance = GemProxy:AddGem(Player, newGemId) + GemProxy:WearGem(Player, newGemData.id, UniqueId) + end + end ------------------------------------------------------------ @@ -86,6 +177,8 @@ function EquipmentProxy:RecycleEquipment(Player: Player, EquipmentId: number) local EquipmentData = ArchiveProxy.pData[Player.UserId][STORE_NAME][EquipmentId] if not EquipmentData then return end + -- TODO:根据对应功能模块生成对应技能 + -- 回收装备返回金币 PlayerInfoProxy:ChangeItem(Player, 1, EquipmentData.recycle) diff --git a/src/ServerStorage/Proxy/GemProxy.luau b/src/ServerStorage/Proxy/GemProxy.luau index 062f071..f3753a5 100644 --- a/src/ServerStorage/Proxy/GemProxy.luau +++ b/src/ServerStorage/Proxy/GemProxy.luau @@ -55,7 +55,6 @@ 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 @@ -165,6 +164,38 @@ function GemProxy:WearGem(Player: Player, GemUniqueId: number, EquipmentUniqueId GemInstance:SetAttribute("Wearing", EquipmentUniqueId) end +-- 卸下宝石 +function GemProxy:UnwearGem(Player: Player, GemUniqueId: 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 + + -- 卸下 + GemData.wearing = 0 + GemInstance:SetAttribute("Wearing", 0) +end + +-- 获取随机技能id +function GemProxy:GetRandomGemId(ExceptIdList: table) + ExceptIdList = ExceptIdList or {} + local candidateIds = {} + for _, gem in ipairs(JsonGem) do + local id = gem.id + if not table.find(ExceptIdList, id) then + table.insert(candidateIds, id) + end + end + if #candidateIds == 0 then + return nil -- 没有可用技能 + end + local rng = Random.new() + local idx = rng:NextInteger(1, #candidateIds) + return candidateIds[idx] +end + -------------------------------------------------------------------------------- -- 获取升级加点属性 diff --git a/src/ServerStorage/Proxy/PlayerInfoProxy.luau b/src/ServerStorage/Proxy/PlayerInfoProxy.luau index 7118d54..0bd9790 100644 --- a/src/ServerStorage/Proxy/PlayerInfoProxy.luau +++ b/src/ServerStorage/Proxy/PlayerInfoProxy.luau @@ -111,6 +111,13 @@ function PlayerInfoProxy:InitPlayer(Player: Player) end end +-- 获取玩家信息 +function PlayerInfoProxy:GetPlayerInfo(Player: Player) + if not Player then warn('获取玩家信息失败: ', Player.Name) return end + local playerInfoData = Utils:DeepCopyTable(ArchiveProxy.pData[Player.UserId][STORE_NAME]) + return playerInfoData +end + -- 玩家属性升级 function PlayerInfoProxy:UpgradeAttribute(Player: Player, AttributeId: number) if not Player or not AttributeId then warn('升级属性失败: ', Player.Name, AttributeId) return end