diff --git a/Ananta.Proxy/proxy/public/fastpatch_4229938.zip b/Ananta.Proxy/proxy/public/fastpatch_4229938.zip index 0bfce94..c103181 100644 Binary files a/Ananta.Proxy/proxy/public/fastpatch_4229938.zip and b/Ananta.Proxy/proxy/public/fastpatch_4229938.zip differ diff --git a/Ananta.Proxy/proxy/tools/generate_client_config_patch.js b/Ananta.Proxy/proxy/tools/generate_client_config_patch.js index 439d5a9..413d06d 100644 --- a/Ananta.Proxy/proxy/tools/generate_client_config_patch.js +++ b/Ananta.Proxy/proxy/tools/generate_client_config_patch.js @@ -122,82 +122,7 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + `\n` + `gGameSwitch = M\n\n` + `local ProcessDebugCommand\n` + -`local _lastHotkeyFrame = -1\n` + `local function CheckCustomHotkeys()\n` + -` pcall(function()\n` + -` if not UnityEngine or not UnityEngine.Input then return end\n` + -` local curFrame = UnityEngine.Time and UnityEngine.Time.frameCount or -1\n` + -` if curFrame == _lastHotkeyFrame then return end\n` + -` _lastHotkeyFrame = curFrame\n\n` + -` local UnityInput = (CS and CS.UnityEngine and CS.UnityEngine.Input) or (UnityEngine and UnityEngine.Input)\n` + -` local UnityKeyCode = (CS and CS.UnityEngine and CS.UnityEngine.KeyCode) or (UnityEngine and UnityEngine.KeyCode) or KeyCode\n` + -` local f8 = false\n` + -` local f7 = false\n` + -` local isShift = false\n` + -` if UnityInput then\n` + -` if UnityKeyCode and UnityKeyCode.F8 then\n` + -` pcall(function() f8 = UnityInput.GetKeyDown(UnityKeyCode.F8) end)\n` + -` end\n` + -` if UnityKeyCode and UnityKeyCode.F7 then\n` + -` pcall(function() f7 = UnityInput.GetKeyDown(UnityKeyCode.F7) end)\n` + -` end\n` + -` if not f8 then\n` + -` pcall(function() f8 = UnityInput.GetKeyDown(289) end)\n` + -` end\n` + -` if not f7 then\n` + -` pcall(function() f7 = UnityInput.GetKeyDown(288) end)\n` + -` end\n` + -` if not f8 then\n` + -` pcall(function() f8 = UnityInput.GetKeyDown("f8") end)\n` + -` end\n` + -` if not f7 then\n` + -` pcall(function() f7 = UnityInput.GetKeyDown("f7") end)\n` + -` end\n` + -` if UnityKeyCode and UnityKeyCode.LeftShift then\n` + -` pcall(function() isShift = UnityInput.GetKey(UnityKeyCode.LeftShift) or UnityInput.GetKey(UnityKeyCode.RightShift) end)\n` + -` end\n` + -` if not isShift then\n` + -` pcall(function() isShift = UnityInput.GetKey(304) or UnityInput.GetKey(303) end)\n` + -` end\n` + -` if not isShift then\n` + -` pcall(function() isShift = UnityInput.GetKey("left shift") or UnityInput.GetKey("right shift") end)\n` + -` end\n` + -` end\n\n` + -` if f8 then\n` + -` if ProcessDebugCommand then ProcessDebugCommand("TOGGLE_CLOTHES") end\n` + -` end\n` + -` if f7 then\n` + -` if isShift then\n` + -` if ProcessDebugCommand then ProcessDebugCommand("OPEN_MONSTER_PANEL") end\n` + -` else\n` + -` if ProcessDebugCommand then ProcessDebugCommand("SPAWN_ENEMY") end\n` + -` end\n` + -` end\n` + -` pcall(function()\n` + -` local myUnit = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit\n` + -` if myUnit then\n` + -` local hasMove = UnityEngine.Input.GetKey(119) or UnityEngine.Input.GetKey(97) or UnityEngine.Input.GetKey(115) or UnityEngine.Input.GetKey(100)\n` + -` if hasMove then\n` + -` if CS and CS.LX6 and CS.LX6.Units and CS.LX6.Units.Module and CS.LX6.Units.Module.LockMoveDirModule then\n` + -` CS.LX6.Units.Module.LockMoveDirModule.ClearLockMoveDir(myUnit)\n` + -` end\n` + -` end\n` + -` if gCS and gCS.PaoKuManager and gCS.PaoKuManager.ParkourStateLua == 25 then\n` + -` gCS.PaoKuManager.enableAccSpeed = true\n` + -` if CS and CS.LX6 and CS.LX6.Units and CS.LX6.Units.Module and CS.LX6.Units.Module.MotoModule then\n` + -` local motoMod = myUnit:GetModule(typeof(CS.LX6.Units.Module.MotoModule))\n` + -` if motoMod then\n` + -` motoMod.acceleratorValue = 1.0\n` + -` local isShiftKey = UnityEngine.Input.GetKey(304) or UnityEngine.Input.GetKey(303)\n` + -` if isShiftKey then\n` + -` motoMod.isMotoRush = true\n` + -` end\n` + -` end\n` + -` end\n` + -` end\n` + -` end\n` + -` end)\n` + -` end)\n` + `end\n\n` + `-- Bypass CBT date expiration for Gacha pools and unlock all map/systems\n` + `local function ApplyAllGlobalHooks()\n` + @@ -280,9 +205,6 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` C_MapView_Fog.InFog = function(self, instanceId) return false end\n` + ` C_MapView_Fog.SetFogEnable = function(self, enable) end\n` + ` end\n` + -` if L50 and L50.Gm and L50.Gm.AutoQaFunctions then\n` + -` L50.Gm.AutoQaFunctions.GetMapClickToTeleport = function() return true end\n` + -` end\n` + ` if gCS and gCS.LuaUtils then\n` + ` gCS.LuaUtils.IsNotUseGM = false\n` + ` end\n` + @@ -302,29 +224,66 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` local isAlt = false\n` + ` pcall(function()\n` + ` if UnityEngine and UnityEngine.Input and UnityEngine.KeyCode then\n` + -` isAlt = UnityEngine.Input.GetKey(UnityEngine.KeyCode.LeftAlt) or UnityEngine.Input.GetKey(UnityEngine.KeyCode.RightAlt)\n` + +` isAlt = UnityEngine.Input.GetKey(UnityEngine.KeyCode.LeftAlt) or UnityEngine.Input.GetKey(UnityEngine.KeyCode.RightAlt) or UnityEngine.Input.GetKey(308) or UnityEngine.Input.GetKey(307)\n` + ` end\n` + ` end)\n` + -` if isAlt or (evtData and evtData.button == 1) or (L50 and L50.Gm and L50.Gm.AutoQaFunctions and L50.Gm.AutoQaFunctions.GetMapClickToTeleport()) then\n` + -` local uiPos = self:GetPointerUIPos()\n` + -` local texPos = self:TransformUIToTex(uiPos)\n` + -` local areaId, worldPos = self:TryTransformTexToWorld(texPos)\n` + -` if worldPos then\n` + +` if isAlt or (evtData and evtData.button == 1) then\n` + +` local worldX, worldZ = nil, nil\n` + +` pcall(function()\n` + +` local uiPos = self.GetPointerUIPos and self:GetPointerUIPos()\n` + +` local mousePos = (evtData and evtData.position) or (UnityEngine and UnityEngine.Input and UnityEngine.Input.mousePosition)\n` + +` if not uiPos and mousePos and gCS and gCS.LuaUtils and self.bindData and self.bindData.rootRT then\n` + +` uiPos = gCS.LuaUtils.TransformScreenPointToUI(self.bindData.rootRT, mousePos)\n` + +` end\n` + +` if uiPos and self.TransformUIToTex then\n` + +` local texPos = self:TransformUIToTex(uiPos)\n` + +` if texPos then\n` + +` if self.bindData and self.bindData.bigWorldBg and self.bindData.bigWorldBg.LuaTryGetWorldPos then\n` + +` local suc, areaId, wx, wz = self.bindData.bigWorldBg:LuaTryGetWorldPos(texPos.x, texPos.y)\n` + +` if suc and wx and wz and (math.abs(wx) > 0.1 or math.abs(wz) > 0.1) then\n` + +` worldX, worldZ = wx, wz\n` + +` end\n` + +` end\n` + +` if not worldX and self.TryTransformTexToWorld then\n` + +` local areaId, wPos = self:TryTransformTexToWorld(texPos)\n` + +` if wPos and (math.abs(wPos.x) > 0.1 or math.abs(wPos.z) > 0.1) then\n` + +` worldX, worldZ = wPos.x, wPos.z\n` + +` end\n` + +` end\n` + +` end\n` + +` end\n` + +` end)\n` + +` if worldX and worldZ and (math.abs(worldX) > 0.1 or math.abs(worldZ) > 0.1) then\n` + ` local playerY = 274.6\n` + ` pcall(function()\n` + -` if gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit then\n` + -` local p = gCS.MyPlayerManager.PlayerUnit.Pos\n` + -` if p and p.y > 10 then playerY = p.y end\n` + +` local p = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit and gCS.MyPlayerManager.PlayerUnit.Pos\n` + +` if p and p.y > 10 then playerY = p.y end\n` + +` end)\n` + +` pcall(function()\n` + +` if gClientToGameSceneGMDelegate and gClientToGameSceneGMDelegate.GmTeleportXYZ then\n` + +` gClientToGameSceneGMDelegate:GmTeleportXYZ(worldX, playerY, worldZ, 0)\n` + +` end\n` + +` end)\n` + +` pcall(function()\n` + +` if gCS and gCS.GmUtils and gCS.GmUtils.TeleportXYZ then\n` + +` gCS.GmUtils.TeleportXYZ(worldX, playerY, worldZ, 0)\n` + +` end\n` + +` end)\n` + +` pcall(function()\n` + +` if gDisplayMessageMgr and gDisplayMessageMgr.ShowMessageContent then\n` + +` gDisplayMessageMgr:ShowMessageContent(string.format("Map Teleport: X=%.1f, Z=%.1f", worldX, worldZ))\n` + ` end\n` + ` end)\n` + -` if L50 and L50.Gm and L50.Gm.AutoQaFunctions and L50.Gm.AutoQaFunctions.TeleportXYZ then\n` + -` L50.Gm.AutoQaFunctions.TeleportXYZ(worldPos.x, playerY, worldPos.z)\n` + -` elseif L50 and L50.Gm and L50.Gm.AutoQaFunctions and L50.Gm.AutoQaFunctions.TeleportToPos then\n` + -` L50.Gm.AutoQaFunctions.TeleportToPos(worldPos.x, worldPos.z)\n` + -` end\n` + ` pcall(function() gMainPhoneUtils.CloseMainPhonePanel(true) end)\n` + ` pcall(function() self:OnBtnClose() end)\n` + ` return\n` + +` else\n` + +` pcall(function()\n` + +` if gDisplayMessageMgr and gDisplayMessageMgr.ShowMessageContent then\n` + +` gDisplayMessageMgr:ShowMessageContent("Map Click: Target outside world bounds")\n` + +` end\n` + +` end)\n` + +` return\n` + ` end\n` + ` end\n` + ` if origOnMainClick then return origOnMainClick(self, evtData) end\n` + @@ -333,7 +292,8 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` if C_InteractionManager then\n` + ` local origCheck = C_InteractionManager.CheckUnitPcBtnShow\n` + ` C_InteractionManager.CheckUnitPcBtnShow = function(self, pid)\n` + -` if gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit and gCS.MyPlayerManager.PlayerUnit.Pid == pid then\n` + +` local myUnit = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit\n` + +` if myUnit and myUnit.Pid == pid then\n` + ` return false\n` + ` end\n` + ` if origCheck then return origCheck(self, pid) end\n` + @@ -343,7 +303,8 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` if gInteractionManager then\n` + ` local origCheckG = gInteractionManager.CheckUnitPcBtnShow\n` + ` gInteractionManager.CheckUnitPcBtnShow = function(self, pid)\n` + -` if gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit and gCS.MyPlayerManager.PlayerUnit.Pid == pid then\n` + +` local myUnit = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit\n` + +` if myUnit and myUnit.Pid == pid then\n` + ` return false\n` + ` end\n` + ` if origCheckG then return origCheckG(self, pid) end\n` + @@ -355,12 +316,23 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` hudCtrl._hideFHooked = true\n` + ` local oldHudUpdate = hudCtrl.Update\n` + ` hudCtrl.Update = function(self)\n` + -` if self.unit and self.unit.IsMe then\n` + +` local isCurrentControlled = false\n` + +` local myUnit = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit\n` + +` if self.unit then\n` + +` if myUnit and self.unit.Pid == myUnit.Pid then\n` + +` isCurrentControlled = true\n` + +` elseif self.unit.IsMe and (not myUnit or self.unit.Pid == myUnit.Pid) then\n` + +` isCurrentControlled = true\n` + +` end\n` + +` end\n` + +` if isCurrentControlled then\n` + +` self.isBtnShowNew = false\n` + ` pcall(function()\n` + -` if self.interactBtn then\n` + -` self.interactBtn:SetActive(false)\n` + -` end\n` + +` if self.SetPlayerHeadInfoVisible then self:SetPlayerHeadInfoVisible(true) end\n` + +` if self.interactBtn then self.interactBtn:SetActive(false) end\n` + +` if self.bindData then self.bindData.isBtnShow = false end\n` + ` end)\n` + +` return\n` + ` end\n` + ` if oldHudUpdate then return oldHudUpdate(self) end\n` + ` end\n` + @@ -395,31 +367,54 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` local origBeforeSet = switchMgr.BeforeSetChangeUnit\n` + ` switchMgr.BeforeSetChangeUnit = function(self, spiritUnitPid, noClearold)\n` + ` local oldUnit = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit\n` + +` local newUnit = gCS and gCS.SceneDataMgr and gCS.SceneDataMgr.GetUnit(spiritUnitPid)\n` + +` if oldUnit and newUnit and CS and CS.LX6 and CS.LX6.Manager and CS.LX6.Manager.SwitchSpiritManager and CS.LX6.Manager.SwitchSpiritManager.CopyNewCCMove then\n` + +` pcall(function() CS.LX6.Manager.SwitchSpiritManager.CopyNewCCMove(oldUnit, newUnit) end)\n` + +` end\n` + ` local res = origBeforeSet and origBeforeSet(self, spiritUnitPid, noClearold)\n` + ` pcall(function()\n` + -` local newUnit = gCS and gCS.SceneDataMgr and gCS.SceneDataMgr.GetUnit(spiritUnitPid)\n` + -` if newUnit then\n` + +` local curUnit = (gCS and gCS.SceneDataMgr and gCS.SceneDataMgr.GetUnit(spiritUnitPid)) or (gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit)\n` + +` if curUnit then\n` + +` pcall(function() curUnit.IsMe = true end)\n` + +` if curUnit.CharacterController then\n` + +` pcall(function() curUnit.CharacterController.enabled = true end)\n` + +` end\n` + ` if CS and CS.LX6 and CS.LX6.Units and CS.LX6.Units.Module and CS.LX6.Units.Module.LockMoveDirModule then\n` + -` CS.LX6.Units.Module.LockMoveDirModule.ClearLockMoveDir(newUnit)\n` + +` pcall(function() CS.LX6.Units.Module.LockMoveDirModule.ClearLockMoveDir(curUnit) end)\n` + ` end\n` + -` if newUnit.RootMotionLockMoveAndRotate then\n` + -` pcall(function() newUnit.RootMotionLockMoveAndRotate:ClearAll() end)\n` + -` pcall(function() newUnit.RootMotionLockMoveAndRotate:ClearLockExtraRotation() end)\n` + +` if curUnit.RootMotionLockMoveAndRotate then\n` + +` pcall(function() curUnit.RootMotionLockMoveAndRotate:ClearAll() end)\n` + +` pcall(function() curUnit.RootMotionLockMoveAndRotate:ClearLockExtraRotation() end)\n` + ` end\n` + -` if newUnit.State then\n` + -` newUnit.State.nowInteractiveAction = 0\n` + -` newUnit.State.isFree = true\n` + +` if curUnit.State then\n` + +` curUnit.State.nowInteractiveAction = 0\n` + +` curUnit.State.isFree = true\n` + +` curUnit.State.isPause = false\n` + +` curUnit.State.isLockMove = false\n` + +` curUnit.State.isLockRotate = false\n` + +` end\n` + +` if curUnit.CCMove then\n` + +` pcall(function() curUnit.CCMove:SetEnable(true) end)\n` + +` pcall(function() curUnit.CCMove:ResetMoveSpeed() end)\n` + +` end\n` + +` if curUnit.UnitFightAction then\n` + +` pcall(function() curUnit.UnitFightAction:ClearAllAction() end)\n` + +` pcall(function() curUnit.UnitFightAction:StopAllAction() end)\n` + +` end\n` + +` if curUnit.Animator then\n` + +` pcall(function() curUnit.Animator.speed = 1.0 end)\n` + ` end\n` + ` if gCS and gCS.BattleManager and gCS.BattleManager.RefreshAllSkills then\n` + -` gCS.BattleManager.RefreshAllSkills(false, false)\n` + +` pcall(function() gCS.BattleManager.RefreshAllSkills(false, false) end)\n` + ` end\n` + ` local btnMgr = L50 and L50.L50App and L50.L50App.L50Game and L50.L50App.L50Game.InteractBtnMgr\n` + ` if btnMgr then\n` + -` pcall(function() btnMgr:RemoveBtnByType(newUnit.Pid, 1) end)\n` + -` pcall(function() btnMgr:RemoveBtnByType(newUnit.Pid, 2) end)\n` + +` pcall(function() btnMgr:RemoveBtnByType(curUnit.Pid, 1) end)\n` + +` pcall(function() btnMgr:RemoveBtnByType(curUnit.Pid, 2) end)\n` + ` end\n` + ` end\n` + ` if oldUnit and oldUnit.Pid ~= spiritUnitPid then\n` + +` pcall(function() oldUnit.IsMe = false end)\n` + ` local btnMgr = L50 and L50.L50App and L50.L50App.L50Game and L50.L50App.L50Game.InteractBtnMgr\n` + ` if btnMgr and CS and CS.LX6 and CS.LX6.Interact then\n` + ` pcall(function()\n` + @@ -430,10 +425,19 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` btnInfo.target = oldUnit.PlayerObj\n` + ` btnInfo.text = "Switch Character"\n` + ` btnInfo.isAvailable = true\n` + +` local oldTemplateId = oldUnit.TemplateId or 15020967\n` + ` btnInfo.DoClick = function()\n` + -` if gSwitchSpiritManager then\n` + -` gSwitchSpiritManager:BeforeSetChangeUnit(oldUnit.Pid, false)\n` + -` end\n` + +` pcall(function()\n` + +` if gClientToGameSceneDelegate and gClientToGameSceneDelegate.AskSwitchSpirit then\n` + +` gClientToGameSceneDelegate:AskSwitchSpirit(oldTemplateId)\n` + +` elseif gSwitchSpiritManager then\n` + +` local cUnit = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit\n` + +` if cUnit and oldUnit and CS and CS.LX6 and CS.LX6.Manager and CS.LX6.Manager.SwitchSpiritManager and CS.LX6.Manager.SwitchSpiritManager.CopyNewCCMove then\n` + +` CS.LX6.Manager.SwitchSpiritManager.CopyNewCCMove(cUnit, oldUnit)\n` + +` end\n` + +` gSwitchSpiritManager:BeforeSetChangeUnit(oldUnit.Pid, false)\n` + +` end\n` + +` end)\n` + ` end\n` + ` btnMgr:AddBtn(btnInfo)\n` + ` end\n` + @@ -444,6 +448,24 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` return res\n` + ` end\n` + ` end\n` + +` local sceneImpl = GameSceneToClientImpl or (package and package.loaded and package.loaded["LX6/Service/GameSceneToClientImpl"])\n` + +` if sceneImpl and not sceneImpl._weatherRainHooked then\n` + +` sceneImpl._weatherRainHooked = true\n` + +` local origWeather = sceneImpl.SyncPlayerWeather\n` + +` sceneImpl.SyncPlayerWeather = function(weatherTypeId, nextWeatherTypeId, transitionSecond)\n` + +` if origWeather then origWeather(weatherTypeId, nextWeatherTypeId, transitionSecond) end\n` + +` pcall(function()\n` + +` if CS and CS.CTT3 and CS.CTT3.Weather and CS.CTT3.Weather.WeatherBridge then\n` + +` CS.CTT3.Weather.WeatherBridge.SetWeather(weatherTypeId, transitionSecond or 2.0)\n` + +` if weatherTypeId == 3 or weatherTypeId == 4 then\n` + +` CS.CTT3.Weather.WeatherBridge.SetGPURainActive(true)\n` + +` else\n` + +` CS.CTT3.Weather.WeatherBridge.SetGPURainActive(false)\n` + +` end\n` + +` end\n` + +` end)\n` + +` end\n` + +` end\n` + ` if gBuyHouseUtils then\n` + ` gBuyHouseUtils.CheckHasBuyTheHouse = function(houseId) return true end\n` + ` gBuyHouseUtils.CheckBuyHouseMoneyEnough = function(houseId) return true end\n` + @@ -462,41 +484,6 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` self.selectedSpirit = self.selectedSpirit or (gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit and gCS.MyPlayerManager.PlayerUnit.TemplateId) or 15020967\n` + ` if origOnShowPhoto then origOnShowPhoto(self, ...) end\n` + ` end\n` + -` local origSetMode = photoStore.SetCurrentPhotoMode\n` + -` photoStore.SetCurrentPhotoMode = function(self)\n` + -` if origSetMode then origSetMode(self) end\n` + -` if self.photoMode == 1 then\n` + -` pcall(function()\n` + -` if gCS and gCS.TransitionMgr then gCS.TransitionMgr.showMainCube = true end\n` + -` if gCS and gCS.CameraDataMgr and gCS.CameraDataMgr.cinemachineManager then\n` + -` gCS.CameraDataMgr.cinemachineManager:SwitchSelfiePhotoMode(false, 0.2)\n` + -` gCS.CameraDataMgr.cinemachineManager:SetFov(68, 0, 0, false)\n` + -` end\n` + -` end)\n` + -` else\n` + -` pcall(function()\n` + -` if gCS and gCS.TransitionMgr then gCS.TransitionMgr.showMainCube = false end\n` + -` end)\n` + -` end\n` + -` end\n` + -` local origOnClosePhoto = photoStore.OnClose\n` + -` photoStore.OnClose = function(self, ...)\n` + -` pcall(function()\n` + -` local unit = gCS and gCS.MyPlayerManager and gCS.MyPlayerManager.PlayerUnit\n` + -` if unit then\n` + -` if gCS.ClimbManager and gCS.ClimbManager.SetLayerActionStateAndCheckTransition then\n` + -` gCS.ClimbManager.SetLayerActionStateAndCheckTransition(unit, false, 42)\n` + -` end\n` + -` if MuGenStates and MuGenStates.Logic and MuGenStates.Logic.ABPVarManager and LTConfig and LTConfig.ABPVarConfig then\n` + -` MuGenStates.Logic.ABPVarManager.SetBool(unit, LTConfig.ABPVarConfig.PhoneSelfie, false)\n` + -` end\n` + -` end\n` + -` if gTakePhotoUtils and gTakePhotoUtils.PlayTakePhotoAction and LTConfig and LTConfig.TakePhotoActionConfig then\n` + -` gTakePhotoUtils.PlayTakePhotoAction(LTConfig.TakePhotoActionConfig.NormalTakePhoto)\n` + -` end\n` + -` end)\n` + -` if origOnClosePhoto then return origOnClosePhoto(self, ...) end\n` + -` end\n` + ` end\n` + ` if gLuaClient and not gLuaClient._hotkeyHooked then\n` + ` gLuaClient._hotkeyHooked = true\n` + @@ -759,8 +746,8 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` end\n` + ` if fs then\n` + ` pcall(function()\n` + -` local clothes = { fs.Cloth, fs.Bottom, fs.Gloves, fs.Shoes, fs.Sleeve, fs.Dress, fs.Bag, fs.Hood, fs.Belt, fs.Necklace }\n` + -` for _, r in ipairs(clothes) do\n` + +` local clothesSlots = { fs.Cloth, fs.Bottom, fs.Dress, fs.Bag, fs.Hood, fs.Belt, fs.Necklace }\n` + +` for _, r in ipairs(clothesSlots) do\n` + ` if r then r.enabled = not _G._clothesHidden end\n` + ` end\n` + ` if fs.SpProps then\n` + @@ -769,14 +756,8 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` if r then r.enabled = not _G._clothesHidden end\n` + ` end\n` + ` end\n` + -` if fs.allFashionRendererList then\n` + -` for i = 0, fs.allFashionRendererList.Count - 1 do\n` + -` local r = fs.allFashionRendererList[i]\n` + -` if r then r.enabled = not _G._clothesHidden end\n` + -` end\n` + -` end\n` + -` local keep = { fs.Face, fs.Hair, fs.Tail, fs.Hair01, fs.Hair02, fs.Ear }\n` + -` for _, r in ipairs(keep) do\n` + +` local keepSlots = { fs.Face, fs.Hair, fs.Hair01, fs.Hair02, fs.Ear, fs.Tail, fs.Gloves, fs.Shoes, fs.Sleeve }\n` + +` for _, r in ipairs(keepSlots) do\n` + ` if r then r.enabled = true end\n` + ` end\n` + ` end)\n` + @@ -787,9 +768,9 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` local smr = smrs[i]\n` + ` if smr then\n` + ` local n = string.lower(smr.name)\n` + -` local isBaseBody = string.find(n, "body") or string.find(n, "face") or string.find(n, "head") or string.find(n, "hair") or string.find(n, "eye") or string.find(n, "skin") or string.find(n, "shenti") or string.find(n, "tou") or string.find(n, "lian") or string.find(n, "arm") or string.find(n, "hand") or string.find(n, "leg") or string.find(n, "foot") or string.find(n, "feet") or string.find(n, "shou") or string.find(n, "bi") or string.find(n, "tui") or string.find(n, "limb") or string.find(n, "torso") or string.find(n, "base") or string.find(n, "flesh") or string.find(n, "mouth") or string.find(n, "brow") or string.find(n, "ear") or string.find(n, "nose") or string.find(n, "tooth") or string.find(n, "teeth") or string.find(n, "tongue")\n` + -` local isClothing = string.find(n, "cloth") or string.find(n, "coat") or string.find(n, "skirt") or string.find(n, "pant") or string.find(n, "dress") or string.find(n, "top") or string.find(n, "bottom") or string.find(n, "jacket") or string.find(n, "yifu") or string.find(n, "kuzi") or string.find(n, "qun") or string.find(n, "shoe") or string.find(n, "sock") or string.find(n, "hat") or string.find(n, "wa") or string.find(n, "xie") or string.find(n, "under") or string.find(n, "suit") or string.find(n, "acc") or string.find(n, "hood") or string.find(n, "belt") or string.find(n, "sleeve") or string.find(n, "glove") or string.find(n, "bag") or string.find(n, "prop") or string.find(n, "fashion")\n` + -` if isBaseBody and not (isClothing and not string.find(n, "body") and not string.find(n, "arm") and not string.find(n, "hand") and not string.find(n, "leg")) then\n` + +` local isBodyLimb = string.find(n, "face") or string.find(n, "head") or string.find(n, "hair") or string.find(n, "eye") or string.find(n, "brow") or string.find(n, "mouth") or string.find(n, "ear") or string.find(n, "tail") or string.find(n, "arm") or string.find(n, "hand") or string.find(n, "glove") or string.find(n, "sleeve") or string.find(n, "leg") or string.find(n, "foot") or string.find(n, "feet") or string.find(n, "shoe") or string.find(n, "boot") or string.find(n, "skin") or string.find(n, "flesh") or string.find(n, "shenti") or string.find(n, "tou") or string.find(n, "lian") or string.find(n, "shou") or string.find(n, "bi") or string.find(n, "tui")\n` + +` local isClothing = string.find(n, "cloth") or string.find(n, "coat") or string.find(n, "skirt") or string.find(n, "pant") or string.find(n, "dress") or string.find(n, "jacket") or string.find(n, "yifu") or string.find(n, "kuzi") or string.find(n, "qun") or string.find(n, "hood") or string.find(n, "cape") or string.find(n, "cloak") or string.find(n, "belt") or string.find(n, "bag") or string.find(n, "prop") or string.find(n, "necklace") or string.find(n, "acc")\n` + +` if isBodyLimb and not (isClothing and not string.find(n, "arm") and not string.find(n, "hand") and not string.find(n, "leg") and not string.find(n, "foot") and not string.find(n, "face")) then\n` + ` smr.enabled = true\n` + ` elseif isClothing then\n` + ` smr.enabled = not _G._clothesHidden\n` + @@ -802,7 +783,7 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` end\n` + ` end\n` + ` pcall(function()\n` + -` local tip = _G._clothesHidden and "Outfit Hidden (Base Body Only)" or "Outfit Shown"\n` + +` local tip = _G._clothesHidden and "Clothes Hidden (Body Visible)" or "Clothes Shown"\n` + ` if gDisplayMessageMgr and gDisplayMessageMgr.ShowMessageContent then\n` + ` gDisplayMessageMgr:ShowMessageContent(tip)\n` + ` end\n` + @@ -819,11 +800,22 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` if density > 0 then\n` + ` CS.CTT3.Weather.WeatherBridge.EnableExternalExpFogDensity(density)\n` + ` CS.CTT3.Weather.WeatherBridge.EnableExternalSkyFogDensity(density)\n` + +` CS.CTT3.Weather.WeatherBridge.EnableExternalExpFogStartDistance(0.0)\n` + +` CS.CTT3.Weather.WeatherBridge.EnableExternalSkyFogStartDistance(0.0)\n` + ` else\n` + ` CS.CTT3.Weather.WeatherBridge.DisableExternalExpFogDensity()\n` + ` CS.CTT3.Weather.WeatherBridge.DisableExternalSkyFogDensity()\n` + +` CS.CTT3.Weather.WeatherBridge.DisableExternalExpFogStartDistance()\n` + +` CS.CTT3.Weather.WeatherBridge.DisableExternalSkyFogStartDistance()\n` + ` end\n` + ` end\n` + +` pcall(function()\n` + +` local Color = UnityEngine.Color\n` + +` UnityEngine.RenderSettings.fog = (density > 0)\n` + +` UnityEngine.RenderSettings.fogDensity = density\n` + +` UnityEngine.RenderSettings.fogMode = UnityEngine.FogMode.ExponentialSquared\n` + +` UnityEngine.RenderSettings.fogColor = Color(0.75, 0.78, 0.82, 1.0)\n` + +` end)\n` + ` local tip = density > 0 and ("Fog Set: " .. tostring(density)) or "Fog Cleared"\n` + ` if gDisplayMessageMgr and gDisplayMessageMgr.ShowMessageContent then\n` + ` gDisplayMessageMgr:ShowMessageContent(tip)\n` + @@ -838,6 +830,14 @@ gameSwitchDefaults.map((name) => `M.${name} = true\n`).join("") + ` pcall(function()\n` + ` if CS and CS.CTT3 and CS.CTT3.Weather and CS.CTT3.Weather.WeatherBridge then\n` + ` CS.CTT3.Weather.WeatherBridge.SetWeather(wId, 2.0)\n` + +` if wId == 3 or wId == 4 then\n` + +` CS.CTT3.Weather.WeatherBridge.SetGPURainActive(true)\n` + +` else\n` + +` CS.CTT3.Weather.WeatherBridge.SetGPURainActive(false)\n` + +` end\n` + +` end\n` + +` if CS and CS.LX6 and CS.LX6.Manager and CS.LX6.Manager.AtmosphereManager and CS.LX6.Manager.AtmosphereManager.Instance then\n` + +` pcall(function() CS.LX6.Manager.AtmosphereManager.Instance:SetWeather(wId, 2.0) end)\n` + ` end\n` + ` if gCS and gCS.WeatherManager and gCS.WeatherManager.SetWeather then\n` + ` gCS.WeatherManager:SetWeather(wId)\n` + diff --git a/Ananta.Server/Ananta.App/DebugApiServer.cs b/Ananta.Server/Ananta.App/DebugApiServer.cs index 27bd337..8409368 100644 --- a/Ananta.Server/Ananta.App/DebugApiServer.cs +++ b/Ananta.Server/Ananta.App/DebugApiServer.cs @@ -900,6 +900,8 @@ internal sealed class DebugApiServer(PrivateServerConfig config, GameSessionHub state.HasExplicitWeather = true; } await GameRouter.PushSessionWeatherAsync(session); + var cmd = $"CMD:SET_WEATHER:{weatherId}"; + await session.NotifyAsync(MethodId.SyncNotice, UxSerializer.Serialize(cmd), token); session.Log.Info($"[DEBUG-API] weather set id={weatherId} transition={transition}s"); return new { ok = true, weatherId, transition }; } diff --git a/Ananta.Server/Ananta.Core/Protocol/Client4229938/WorldEntryState.cs b/Ananta.Server/Ananta.Core/Protocol/Client4229938/WorldEntryState.cs index 90e91c3..b71d8e0 100644 --- a/Ananta.Server/Ananta.Core/Protocol/Client4229938/WorldEntryState.cs +++ b/Ananta.Server/Ananta.Core/Protocol/Client4229938/WorldEntryState.cs @@ -73,6 +73,7 @@ internal sealed class WorldEntryState internal bool RestoreResourcesAfterActiveSkill { get; set; } internal int ActiveClientSkillInstanceId { get; set; } internal long ActiveSkillStartedTicks { get; set; } + internal Dictionary SkillCooldownUntilTicks { get; } = []; internal ulong ActiveWeaponInstanceId { get; set; } internal uint ActiveFightStyleId { get; set; } internal Dictionary LastWeaponBySpirit { get; } = []; diff --git a/Ananta.Server/Ananta.Handlers/Game/GameRouter.Combat.cs b/Ananta.Server/Ananta.Handlers/Game/GameRouter.Combat.cs index fe5d13b..6552461 100644 --- a/Ananta.Server/Ananta.Handlers/Game/GameRouter.Combat.cs +++ b/Ananta.Server/Ananta.Handlers/Game/GameRouter.Combat.cs @@ -38,13 +38,27 @@ internal sealed partial class GameRouter return; } - // Prevent rapid re-triggering of the same active or unique skill while the animation is executing - if (state.ActiveSkillId == req.SkillId && - (req.SkillId == weapon.ActiveSkill(style) || req.SkillId == weapon.UniqueSkill(style)) && - (Environment.TickCount64 - state.ActiveSkillStartedTicks) < 1200) + var cooldown = weapon.Cooldown(style, req.SkillId, 0f); + var nowTicks = Environment.TickCount64; + if (cooldown > 0f) { - ctx.Session.Log.Warn($"[COMBAT] ignore rapid spam of active/unique skill={req.SkillId} elapsed={Environment.TickCount64 - state.ActiveSkillStartedTicks}ms"); - return; + if (state.SkillCooldownUntilTicks.TryGetValue(req.SkillId, out var untilTicks) && nowTicks < untilTicks) + { + ctx.Session.Log.Warn($"[COMBAT] reject skill={req.SkillId} cooldown remaining={untilTicks - nowTicks}ms"); + return; + } + state.SkillCooldownUntilTicks[req.SkillId] = nowTicks + (long)(cooldown * 1000f); + } + else + { + // Prevent rapid re-triggering of the same active or unique skill while the animation is executing + if (state.ActiveSkillId == req.SkillId && + (req.SkillId == weapon.ActiveSkill(style) || req.SkillId == weapon.UniqueSkill(style)) && + (nowTicks - state.ActiveSkillStartedTicks) < 1200) + { + ctx.Session.Log.Warn($"[COMBAT] ignore rapid spam of active/unique skill={req.SkillId} elapsed={nowTicks - state.ActiveSkillStartedTicks}ms"); + return; + } } state.CombatUseCount++; @@ -93,21 +107,9 @@ internal sealed partial class GameRouter state.ActiveClientSkillInstanceId = 0; state.ActiveSkillStartedTicks = 0; - // Ordinary attacks must finish without any server-side skill-state rewrite. Re-publishing the - // whole charge/resource snapshot after each common attack can make the client save a new action - // while the previous trigger graph is still iterating, which restarts the first animation on - // every click. Only cooldown/charge abilities and ultimates need sandbox restoration. + // Do not immediately force full recharge here, allowing skills to respect their configured cooldowns. if (!restoreResources) return; - - // The private server runs an unrestricted combat sandbox: restore charges and ultimate energy - // only after the complete authored ability chain has ended, never between combo/hold stages. - await ctx.NotifyAsync(MethodId.SyncPlayerAllSkillChargeData, - CombatCodec.AllSkillCharges(state.ActiveSpiritUnitId, weapon, style)); - await ctx.NotifyAsync(MethodId.SyncFightResource, - CombatCodec.FightResource(state.ActiveSpiritUnitId, CombatCodec.UltimateResourceId, CombatCodec.UltimateResourceMax)); - await ctx.NotifyAsync(MethodId.SyncFightResourceFreeState, - CombatCodec.FightResourceFreeState(state.ActiveSpiritUnitId, CombatCodec.UltimateResourceId, false)); } Task OnSkillHit(RpcContext ctx, SceneMethods.SkillHitData hit) diff --git a/Ananta.Server/Ananta.Handlers/Game/GameRouter.Gm.cs b/Ananta.Server/Ananta.Handlers/Game/GameRouter.Gm.cs index b824187..b60722e 100644 --- a/Ananta.Server/Ananta.Handlers/Game/GameRouter.Gm.cs +++ b/Ananta.Server/Ananta.Handlers/Game/GameRouter.Gm.cs @@ -59,6 +59,12 @@ internal sealed partial class GameRouter private async Task GmTeleportXYZ(Connection conn, UxRpcMessage msg) { var args = msg.GetArgs(); + if (MathF.Abs(args.X) < 0.1f && MathF.Abs(args.Z) < 0.1f) + { + conn.Session.Log.Warn($"[GM] reject teleport to origin (0, 0, 0)"); + await conn.ReturnAsync(msg, 0); + return; + } var state = GetWorldState(msg.Context); var targetY = args.Y; if (targetY <= 10f)