From aa5baf00b5655d2eb4b2739fafd4ed900233d8bb Mon Sep 17 00:00:00 2001 From: gechangfu Date: Thu, 31 Jul 2025 19:36:32 +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/cha.xlsx | Bin 13796 -> 13755 bytes excel/enemy.xlsx | Bin 9056 -> 9057 bytes src/ReplicatedStorage/Json/Enemy.json | 2 +- src/ServerStorage/Proxy/LevelProxy.luau | 3 +- src/ServerStorage/Proxy/MobsProxy/init.luau | 13 +- .../Proxy/PlayerFightProxy/LevelLoop.luau | 27 ++++- .../ClientMain/Camera.client.luau | 2 +- .../UI/Windows/MainWindow/init.luau | 112 +++++++++++++++++- 8 files changed, 143 insertions(+), 16 deletions(-) diff --git a/excel/cha.xlsx b/excel/cha.xlsx index aa490c160311063715753aa9f76bdf7e5efbbbdb..64e1aba5dfad0f7941ef89c5de08b1f5f70112f3 100644 GIT binary patch delta 4968 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 delta 5011 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 H|0nh@l`MmI diff --git a/excel/enemy.xlsx b/excel/enemy.xlsx index acac0856dc2ff78309e9c80249b80c4065f131cc..b5f6840a6a68e8e5dbda9e25ae671f3da4296477 100644 GIT binary patch delta 2030 zcmVKIK>Ls%yt^8s{eh*5c-vyt{qBj%rP(T@p&+Z$8B9XcT8z6MT+o&j~phbEV#H$ z(eH~>cY+*kh$u)U1xwLA)9Co<>zBi=RO_XbYX<~`PEl!0lX#w{C98=(kPQ*+=@Qs|N~Q&(Q#`>|IOE>N$KsP|~d)rwP=NxG?-FujOk6)|96m%Pz~T20?0 zR};0~G%l5O0}@MKadY2^BB!Rw;#NpSmKCJk;>c+g{9^cHADUoz5`^|1RdcGOmMe1r z(q3UPEiOY-3$F7?GV9!vf;(EjR${sxVC@O46#R>u-(rt zIos-I9_-L*ued1WHbpKDAgTM;!)+J5;)N*zsHq>ql>XW`#&1h-jH8LY2;5s|DSG87 z>m8lK;o9bvBkzT!Zs!DRUGIpF_FS;~9(HKEsdj4&a3}T=YEj^>Vur(AlvLEh4P7@e z4yJfyXRy|M*QVU!9=q`;|6}{> z7*B>Tigj5MWiAwwN(KNq7%N_^m^=E@o<=>a@_nt%K-+gZ2v zEkGbhFutU12wlOL7cFS+6Wf8oFO7AY2Yi2ZE9N@~yzYavVtJZAFwLc*M?&FlVc4dT z0-mkdXfWXjaiDm>{Cz7sf1+t|3r=&l-gF~jb%%&bDj5zvloBn9<;qycD}{CMvoRNB z@9@s?xjV`9^H)k*3TM4-LV{#=%=x_*KUcG<<5difwN}_cuYu9n%5~tFr)-Q-eE`r>`XHcr7 zU!wc}_8K@u0d`h+J3gr`db4BBH8g*Gqrwln`wDW^29zBq`91DJv{6wXp1}+BFKQ=w zZ_c{}~nxm?L010I(kb(*&ch zBUrEe3IG8A{{R30|NoSg+m3=T6h(i9^aJD~h#DjrD7Vib42e(9M2Iu<_j7-0xph-g zeKBUA)i!7KRHN?Nwmq-=I*#sNKi2)iTxNCO^{u0C=M%GjUB7P5pMSjVn)cRTn6vX( z95n*{5bT9{%%Z%b^btFe{fHyG8Hi*}cq);u3121nns5UZ$=1k0C34Lsa898?V3$&Z zK*!aH*rb7!PF~5<%U%VmdUcbs4itZDWS#)U@?N!krNQ)$yTCBVVwLbsclI3YL33U1B@SfXaWxWq(^#}L_|lV;1ja_)b#)m977Eflr@+H1pjy~Xled@Feo#ptn8t6J00WB*@BPa zQ}126$g|hf>W-6*+yq2FA_Yf``gvb*sVKrQGvKU zWW4Ym68yXGFhlB*1;TSV=$QJXyv8|q_xT28QAiekxb(wCPF9rM(D>@TAA9z`&owsW zarnQ)$PusonB?J#M%Q$)oDoleY{-577qV{vlaT`yvkD$c0|i{e&rju(Ss_vZ&XcSm zEgb0L5Q5bM007Jj000;O0000000000000000SuEI3>uRUBF+U8j?^DZlj0&&0sWIV MBO?aOAOHXW0MuFEZvX%Q delta 2013 zcmV<32O{|4M&L%U$_539vA$8{lg|bmf6;E6FcgOGC+!`O?H9E0CD8g6VA|imWmXr%Ns*nHP|Djr&$D;TOOkyU=*ulOS~RsFI~pD6!CI zAnmlKPx8mEgYnT4)Te9kJ|*9gfAoo&8tz@m;DfG$y;g7#!|tcmFrd}262jtrP_4iB z=AqHWf)(_>Mb{!#^^=sQQU$UKqI8lmO|uA{!%%GK;R0kO*VTB<3W$1xz84^8w8!~I zT0lQ-weE7JW;@Q!Bw*sI&{T4w>9yb*5ZtBoS=<`!>s$cb)-C5urGIkn?()6?8^PCHMoaQ(8Q{LXw>F{|``-)THY`zOASB{B7=FO@}a^2-(a9(Dh+Td+i%#%N!iz{=i%W?v1ku9XX0y zM-w<~(;PW+URi2(PO#SW7H?=zI4!rZLz_*tSz~}ZG>?$e3^z6GVeU#vks7$6YbFNX z5ckXsTI=shH$A|`z#aD8t8;hg+iue9LwSatJ@9*;eeK6y(mzk)WZXC9F&lsQKeoSy z@v!@%7?(Mb`c9H`1>d1tx)>7$JhcgdU%;_*?R0mI{sNPc0~E8|2{Qr(@3OuX){_(r zC4XIS+aMH%?1>kAJUr#awTJ*D**dmZ#|h(_D7+Kq%}j4AV4H zz_Ss9hRz=#78LiGziVahPBblU!D(*SLq8Hm_lT&Zl71hdlxR^bSDmrEQdsvc8*@Q+ z7VjLNyOT_uzf#gtSmR9N6C|@k&e!En*_3f{CSBKm6DAuo3mX{@@Pf)emQr?qW`E@u z*xd(V4`*1|E?W$;F6rO&c#W{nLX%#a)3<+gK8rs2ZV8$ZzHyCb@EYuvQ8u5|5>G!= zOe{1d{gM^SNtll@za(tkyD{;+dIbf-1L|j#1nXADti!@3PNhLDE(k;}yxhQ7P^zRa z!To=t1`bhxofY1XPil*3cFehkhJO#r|1jGZkgL|C>^RBqaTkJ(ihBPHPN08LJIMoA z7=;jQiI(^uPSAdQ7yGTOeT(sF@;E_21Ao zgsu-`&GDE--L-8WynfVibpQIX?ic1VtNX5R9X*{-%=&eMx;cOT@wRK)+vCEVoyX#+ z5$K0tFU(^WD#4e8yH}BHiG(VVYl^@=g$98tr3QhH zs{ye|11TN7lBLaF1*>{>!IQNP6Msu&ngGSJuUfv+V0y>h-Z01FE#aHa>^0bl4Cr?p zY#+uJU*Q;J7~~if7?eXWZR^5ysb=pejR)JuD-o=?=s2RJY4eEgU)LSSQk$mQl*{x8 zVlx>B4&1A}$JJvfw53aGWIQ+*HmK%{hq0U@Gkilt_!0rfl*knHq*|8C)J2Devmr(i zGCzU{?S>^avMyr2IF(aG9NrLdkQ3qH$t7|Dzx!)A@9_YA^!cKGE*J1?-q%+(mDJF> zkon>XCc~coDgObpiVyz_1<9k9u}ZU!8!`cZ&@#r<23VqIzPQ9hjK;U7y)Yt_rmeF5 zdkbvHqVe(GbNbzLZQ+LE4q(ta zySzxaqP*4cq+12rR$x3wl7@1XqMfyhVr=*h8fF6LkWMUG-7xD)U1G)f2P*+D2wCBO z1}qcIGTZ}wH4)JfDfom`pSm6Zf@7$m0ci~mgAo6CE$GJl`Cw3H&Ze>l<#sy8owEfW z#mT)l)nx3tF6g2mhRYw~x9#Keu&Q6l{#G1NmIzL{24-8GmApvstnP1DGh?^z%tZy_ z_K@+ydr0u_zQYWuM-~Xr<)CBglkyrj-QDLKlr2aY`()*lI1jIBctfM*dq4KPK00000jJnxA diff --git a/src/ReplicatedStorage/Json/Enemy.json b/src/ReplicatedStorage/Json/Enemy.json index 3a16439..32312dd 100644 --- a/src/ReplicatedStorage/Json/Enemy.json +++ b/src/ReplicatedStorage/Json/Enemy.json @@ -1,5 +1,5 @@ [ {"id":1,"type":1,"name":1,"attack":83,"hp":400,"walkSpeed":8,"attackSpeed":1,"model":"Thief"}, {"id":2,"type":1,"name":2,"attack":30,"hp":300,"walkSpeed":8,"attackSpeed":1,"model":"Thief"}, -{"id":1000,"type":2,"name":1000,"attack":240,"hp":2000,"walkSpeed":4,"attackSpeed":1,"model":"Thief"} +{"id":1000,"type":2,"name":1000,"attack":120,"hp":1000,"walkSpeed":4,"attackSpeed":1,"model":"Thief"} ] \ No newline at end of file diff --git a/src/ServerStorage/Proxy/LevelProxy.luau b/src/ServerStorage/Proxy/LevelProxy.luau index 3ea53c8..c15576d 100644 --- a/src/ServerStorage/Proxy/LevelProxy.luau +++ b/src/ServerStorage/Proxy/LevelProxy.luau @@ -183,6 +183,7 @@ end -- 挑战关卡(挑战副本用另一个函数) function LevelProxy:ChallengeLevel(Player: Player, LevelId: number) + print("挑战关卡", LevelId) local LevelData = Utils:GetIdDataFromJson(JsonLevel, LevelId) if not LevelData then warn("Level Data not found", LevelId) return end -- 给前端传数据,做表现 @@ -259,7 +260,7 @@ function LevelProxy:ChallengeEnd(Player: Player, result: boolean) end -- 清除剩余怪物 - for _, mob in LevelProxy.pData[Player.UserId].Mobs do mob:Died(true) end + for _, mob in pairs(LevelProxy.pData[Player.UserId].Mobs) do mob:Died(true) end LevelProxy.pData[Player.UserId].Mobs = {} -- 清除玩家表现 diff --git a/src/ServerStorage/Proxy/MobsProxy/init.luau b/src/ServerStorage/Proxy/MobsProxy/init.luau index 0f3f4be..458ff6b 100644 --- a/src/ServerStorage/Proxy/MobsProxy/init.luau +++ b/src/ServerStorage/Proxy/MobsProxy/init.luau @@ -81,13 +81,12 @@ function Mob.new(Player: Player, MobId: number, OnMobDied: ((Player: Player, Mob return self end --- IsSkinOnDied:暂时意义不明,忘了之前为啥写了 -function Mob:Died(IsSkinOnDied: boolean?) +-- isChallengeFailed 挑战失败清除怪物传参 +function Mob:Died(isChallengeFailed: boolean?) MobsProxy:RemoveMob(self.Player, self.Instance) - -- 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 + if not isChallengeFailed then + if self.OnDied then self.OnDied(self.Player, self) end + end Character.Died(self) end @@ -110,7 +109,7 @@ end -- 清除玩家单个怪物 function MobsProxy:RemoveMob(Player: Player, MobInstance: Instance) local playerMobsFolder = GetPlayerMobsFolder(Player) - if not playerMobsFolder then return end + if not playerMobsFolder then warn("playerMobsFolder not found", Player.Name) return end if not MobsProxy.pData[Player.UserId][MobInstance] then warn("Mob not found", MobInstance) return end MobsProxy.pData[Player.UserId][MobInstance] = nil diff --git a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau index 6452865..4756f64 100644 --- a/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau +++ b/src/ServerStorage/Proxy/PlayerFightProxy/LevelLoop.luau @@ -6,6 +6,7 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage") --> Events local BD_ChallengeEnd = ReplicatedStorage.Events.BD_ChallengeEnd +local RE_ChallengeBoss = ReplicatedStorage.Events.RE_ChallengeBoss --> Dependencies local LevelProxy = require(ServerStorage.Proxy.LevelProxy) @@ -31,12 +32,16 @@ function LevelLoop.new(Player: Player, PlayerRole: TypeList.Character) if Player ~= self.Player then return end self:OnChallengeEnd(Player, LevelId) end) + self.ConChallengeBoss = RE_ChallengeBoss.OnServerEvent:Connect(function(Player: Player) + if Player ~= self.Player then return end + self:OnChallengeBoss(Player) + end) self:AutoChallenge() return self end -function LevelLoop:AutoChallenge() +function LevelLoop:AutoChallenge(ignoreBoss: boolean?) print("AutoChallenge") -- TODO: 回退有bug,不能一关一关回退 @@ -47,7 +52,9 @@ function LevelLoop:AutoChallenge() local LevelId = ProgressFolder:FindFirstChild("Main").Value local FailBossId = ProgressFolder:FindFirstChild("BossFail").Value -- Boss失败了就去挑战上一个关卡 - if FailBossId == LevelId then + if ignoreBoss then + LevelId = LevelId + elseif FailBossId == LevelId then LevelId = LevelId - 1 end @@ -55,6 +62,7 @@ function LevelLoop:AutoChallenge() end function LevelLoop:OnChallengeEnd(Player: Player, LevelId: number, result: boolean) + if self.ChallengeBoss then self.ChallengeBoss = nil return end self.TaskAutoChallenge = task.spawn(function() task.wait(3) -- 重置玩家状态(先临时调用角色复活,之后复杂的内容再说) @@ -63,11 +71,26 @@ function LevelLoop:OnChallengeEnd(Player: Player, LevelId: number, result: boole end) end +function LevelLoop:OnChallengeBoss(Player: Player) + self.TaskAutoChallenge = task.spawn(function() + self.ChallengeBoss = true + LevelProxy:ChallengeEnd(self.Player, false) + -- 重置玩家状态(先临时调用角色复活,之后复杂的内容再说) + task.wait(1) + self.PlayerRole:Respawn() + self:AutoChallenge(true) + end) +end + function LevelLoop:Destroy() if self.TaskAutoChallenge then task.cancel(self.TaskAutoChallenge) self.TaskAutoChallenge = nil end + if self.ConChallengeBoss then + self.ConChallengeBoss:Disconnect() + self.ConChallengeBoss = nil + end if self.ConChallengeEnd then self.ConChallengeEnd:Disconnect() self.ConChallengeEnd = nil diff --git a/src/StarterPlayerScripts/ClientMain/Camera.client.luau b/src/StarterPlayerScripts/ClientMain/Camera.client.luau index fb9d04d..633aa9b 100644 --- a/src/StarterPlayerScripts/ClientMain/Camera.client.luau +++ b/src/StarterPlayerScripts/ClientMain/Camera.client.luau @@ -6,7 +6,7 @@ local player = Players.LocalPlayer local camera = workspace.CurrentCamera local CAMERA_DISTANCE = 30 -local CAMERA_HEIGHT = 40 +local CAMERA_HEIGHT = 35 local CAMERA_ANGLE = math.rad(-45) local SCREEN_OFFSET = 5 diff --git a/src/StarterPlayerScripts/UI/Windows/MainWindow/init.luau b/src/StarterPlayerScripts/UI/Windows/MainWindow/init.luau index ddbb2fe..bb6df74 100644 --- a/src/StarterPlayerScripts/UI/Windows/MainWindow/init.luau +++ b/src/StarterPlayerScripts/UI/Windows/MainWindow/init.luau @@ -7,9 +7,13 @@ local UIEnums = require(ReplicatedStorage.Base.UIEnums) --> Json local JsonLevel = require(ReplicatedStorage.Json.Level) +local JsonForge = require(ReplicatedStorage.Json.Forge) local Utils = require(ReplicatedStorage.Tools.Utils) +--> Events +local RE_ChallengeBoss = ReplicatedStorage.Events.RE_ChallengeBoss + local LocalPlayer = game:GetService("Players").LocalPlayer -------------------------------------------------------------------------------- @@ -26,8 +30,16 @@ function MainWindow:Init(UIManager: table, Data: table?) ["_btnMainCha"] = 0, ["_btnMainAttributeUpgrade"] = 0, + -- 关卡 ["_tmpNowLevel"] = 0, ["_imgBoss"] = 0, + ["_btnChallengeBoss"] = 0, + + -- 锻造条 + ["_goForgeBar"] = 0, + ["_goForgeFill"] = 0, + ["_tmpForgeMoney"] = 0, + ["_tmpForgeTime"] = 0, } self.UIRootName = "ui_w_main" self.UIParentName = UIEnums.UIParent.UIRoot @@ -35,6 +47,7 @@ function MainWindow:Init(UIManager: table, Data: table?) return self end +-- 设置关卡显示 function MainWindow:SetShowLevel(level: number) self.Variables["_tmpNowLevel"].Text = string.format("第%d关", level) local levelData = Utils:GetIdDataFromJson(JsonLevel, level) @@ -45,6 +58,46 @@ function MainWindow:SetShowLevel(level: number) end end +-- 设置boss挑战按钮显示 +function MainWindow:SetShowBossChallenge(newValue: number) + local playerDataFolder = game.Workspace:WaitForChild("Level"):WaitForChild(LocalPlayer.UserId) + local ProgressFolder = playerDataFolder:WaitForChild("Progress") + local mainValue = ProgressFolder:FindFirstChild("Main").Value + local levelIdValue = playerDataFolder:WaitForChild("Challenge"):WaitForChild("LevelId").Value + + if levelIdValue == mainValue then + self.Variables["_btnChallengeBoss"].Visible = false + else + self.Variables["_btnChallengeBoss"].Visible = (newValue == mainValue) + end +end + +-- 手动点击按钮,挑战boss +function MainWindow:OnClickChallengeBoss() + RE_ChallengeBoss:FireServer() + + self.Variables["_btnChallengeBoss"].Visible = false +end + +function MainWindow:SetShowForgeBar(nowForgeTime : number, moneyValue: number) + local maxForgeId = Utils:GetMaxIdFromJson(JsonForge) + local forgeTime = nowForgeTime > maxForgeId and maxForgeId or nowForgeTime + local forgeData = Utils:GetIdDataFromJson(JsonForge, forgeTime) + + -- 进度条 + self.Variables["_goForgeFill"].Size = UDim2.new(math.min(moneyValue / forgeData.cost[2], 1), 0, 1, 0) + self.Variables["_tmpForgeMoney"].Text = string.format("%d/%d", moneyValue, forgeData.cost[2]) + + -- 右上角红点 + local timeRecorder = math.ceil(moneyValue / forgeData.cost[2]) + if timeRecorder > 0 then + self.Variables["_tmpForgeTime"].Visible = true + self.Variables["_tmpForgeTime"].Text = timeRecorder + else + self.Variables["_tmpForgeTime"].Visible = false + end +end + function MainWindow:OnOpenWindow() UIWindow.OnOpenWindow(self) @@ -57,22 +110,73 @@ function MainWindow:OnOpenWindow() local attributeUpgradeCon = self.Variables["_btnMainAttributeUpgrade"].Activated:Connect(function() self.UIManager:OpenWindow("AttributeLvupWindow") end) - + local challengeBossCon = self.Variables["_btnChallengeBoss"].Activated:Connect(function() + self:OnClickChallengeBoss() + end) + table.insert(self.Connections, createCon) table.insert(self.Connections, chaCon) table.insert(self.Connections, attributeUpgradeCon) + table.insert(self.Connections, challengeBossCon) -- TODO: 暂时用主关卡数显示,我记得之前这里主要是记录的,Challenge中才是正在挑战的内容 -- TODO: 之后LevelProxy也应该挪到ReplicatedStorage下,之前可能是因为觉得Challenge是临时的内容所以放在workspace下,但是逻辑做的不统一 local playerDataFolder = game.Workspace:WaitForChild("Level"):WaitForChild(LocalPlayer.UserId) - local StatsFolder = playerDataFolder:WaitForChild("Progress") - local levelCon = StatsFolder.Main.Changed:Connect(function(newValue) + local StatsFolder = playerDataFolder:WaitForChild("Challenge") + local ProgressFolder = playerDataFolder:WaitForChild("Progress") + + local levelCon = StatsFolder.LevelId.Changed:Connect(function(newValue) self:SetShowLevel(newValue) + self:SetShowBossChallenge(ProgressFolder.BossFail.Value) + end) + local bossChallengeCon = ProgressFolder.BossFail.Changed:Connect(function(newValue) + self:SetShowBossChallenge(newValue) end) -- 初始值设置 - self:SetShowLevel(StatsFolder.Main.Value) + self:SetShowLevel(StatsFolder.LevelId.Value) + self:SetShowBossChallenge(ProgressFolder.BossFail.Value) + table.insert(self.Connections, levelCon) + table.insert(self.Connections, bossChallengeCon) + + + -- 货币进度条显示 + local rePlayerDataFolder = Utils:GetPlayerDataFolder(LocalPlayer) + local playerInfoFolder = rePlayerDataFolder:WaitForChild("PlayerInfo") + local forgeInstance = playerInfoFolder:WaitForChild("Stats"):WaitForChild("forge") + + local itemFolder = playerInfoFolder:WaitForChild("Items") + local hasItem = playerInfoFolder:FindFirstChild("2") + + -- 设置锻造货币变动链接 + local function SetForgeCostChange() + local costChangeCon = hasItem.Changed:Connect(function(newValue) + self:SetShowForgeBar(forgeInstance.Value, newValue) + end) + table.insert(self.Connections, costChangeCon) + end + + if hasItem then + -- 后续变动设置 + SetForgeCostChange() + -- 初始化设置 + self:SetShowForgeBar(forgeInstance.Value, hasItem.Value) + else + -- 没有货币时监听设置 + local addCon + addCon = itemFolder.ChildAdded:Connect(function(child) + if child.Name == "2" then + self:SetShowForgeBar(forgeInstance.Value, child.Value) + addCon:Disconnect() + addCon = nil + + SetForgeCostChange() + end + end) + table.insert(self.Connections, addCon) + end + end