Files
Endfield-Data/LuaScripts/Phase/FacMachine/PhaseFacMachine.lua
2025-12-02 20:37:18 +07:00

574 lines
16 KiB
Lua

local phaseBase = require_ex('Phase/Core/PhaseBase')
local PHASE_ID = PhaseId.FacMachine
PhaseFacMachine = HL.Class('PhaseFacMachine', phaseBase.PhaseBase)
PhaseFacMachine.s_messages = HL.StaticField(HL.Table) << {
[MessageConst.FAC_OPEN_BUILDING_PANEL] = {'OpenBuildingPanel', false},
[MessageConst.FAC_OPEN_BUILDING_PANEL_ALTER] = {'OpenBuildingPanelAlter', false},
[MessageConst.FAC_OPEN_LOGISTIC_PANEL] = {'OpenLogisticPanel', false},
[MessageConst.FAC_OPEN_NEAREST_BUILDING_PANEL] = {'OpenNearestBuildingPanel', false},
}
local ReservePanelIds = {
PanelId.Joystick,
PanelId.LevelCamera,
}
local NeedClosePanelIds = {
PanelId.Formula,
PanelId.FacMarkerManagePopup,
}
local QuestState = CS.Beyond.Gameplay.MissionSystem.QuestState
PhaseFacMachine.curPanelId = HL.Field(HL.Number) << -1
PhaseFacMachine.curPanelItem = HL.Field(HL.Forward("PhasePanelItem"))
PhaseFacMachine.curNodeId = HL.Field(HL.Any)
PhaseFacMachine.m_panelArg = HL.Field(HL.Any)
PhaseFacMachine.m_panelBuildingDataId = HL.Field(HL.Any)
PhaseFacMachine.m_hidePanelKey = HL.Field(HL.Number) << -1
PhaseFacMachine.m_isDoingOut = HL.Field(HL.Boolean) << false
PhaseFacMachine.curUIInfo = HL.Field(CS.Beyond.Gameplay.RemoteFactory.NodeUIInfo)
PhaseFacMachine.m_curBuildingPos = HL.Field(Vector3)
PhaseFacMachine.m_curBuildingRadius = HL.Field(HL.Number) << 0
PhaseFacMachine.m_isHalfPanel = HL.Field(HL.Boolean) << false
PhaseFacMachine.m_updateKey = HL.Field(HL.Number) << -1
PhaseFacMachine.m_tickInitialized = HL.Field(HL.Boolean) << false
PhaseFacMachine.OpenBuildingPanel = HL.StaticMethod(HL.Table) << function(args)
local isForbid, forbidReason = Utils.isForbiddenWithReason(ForbidType.ForbidInteractFacBuilding)
if isForbid then
Notify(MessageConst.SHOW_RADIO, { GameAction.RadioRuntimeData(forbidReason.radioId, true, 0) })
return
end
local nodeId = args.nodeId
local buildingSyncNode = FactoryUtils.getBuildingNodeHandler(nodeId)
if buildingSyncNode and not GameInstance.player.guide.skipAllGuide then
if PhaseFacMachine.CheckPanelUnlockedState(buildingSyncNode.templateId, buildingSyncNode.instKey, args.customArg) == false then
return
end
end
args.isBuilding = true
Notify(MessageConst.FAC_BUILD_EXIT_CUR_MODE, true)
if args.skipAnim then
PhaseManager:OpenPhaseFast(PhaseId.FacMachine, args)
else
PhaseManager:OpenPhase(PhaseId.FacMachine, args)
end
end
PhaseFacMachine.OpenBuildingPanelAlter = HL.StaticMethod(HL.Table) << function(args)
local nodeId, customArg, buildingId = unpack(args)
local buildingSyncNode = FactoryUtils.getBuildingNodeHandler(nodeId)
if buildingSyncNode and not GameInstance.player.guide.skipAllGuide then
if PhaseFacMachine.CheckPanelUnlockedState(buildingSyncNode.templateId, buildingSyncNode.instKey, customArg) == false then
return
end
end
PhaseFacMachine.OpenBuildingPanel({
nodeId = nodeId,
customArg = customArg,
panelBuildingDataId = buildingId,
})
end
PhaseFacMachine.OpenLogisticPanel = HL.StaticMethod(HL.Table) << function(args)
local buildingSyncNode = FactoryUtils.getBuildingNodeHandler(args.nodeId)
if buildingSyncNode and not GameInstance.player.guide.skipAllGuide then
if PhaseFacMachine.CheckPanelUnlockedState(buildingSyncNode.templateId, buildingSyncNode.instKey, args.customArg) == false then
return
end
end
args.isBuilding = false
PhaseManager:OpenPhase(PhaseId.FacMachine, args)
end
PhaseFacMachine.OpenNearestBuildingPanel = HL.StaticMethod(HL.Table) << function(arg)
local buildingId, ignoreCull = unpack(arg)
local isOpen, phase = PhaseManager:IsOpen(PhaseId.FacMachine)
if isOpen then
local buildingData = Tables.factoryBuildingTable[buildingId]
local buildingType = buildingData.type
local panelName = unpack(FacConst.FACTORY_BUILDING_UI_MAP[buildingType])
local panelId = PanelId[panelName]
if phase.curPanelId == panelId then
return
end
PhaseManager:ExitPhaseFast(PhaseId.FacMachine)
end
local succ, targetNodeId = FactoryUtils.findNearestBuilding(buildingId, ignoreCull)
if not succ then
logger.error("OpenNearestBuildingPanel 失败,找不到建筑", buildingId)
return
end
PhaseFacMachine.OpenBuildingPanel({
nodeId = targetNodeId,
skipAnim = true,
ignoreDist = true,
})
end
PhaseFacMachine._OnInit = HL.Override() << function(self)
PhaseFacMachine.Super._OnInit(self)
local nodeId = self.arg.nodeId
self.curNodeId = nodeId
local chapterId = Utils.getCurrentChapterId()
local slotId = CSFactoryUtil.GetBlueprintSlotId(chapterId, nodeId)
if slotId > 0 then
self.curPanelId = PanelId.FacPendingBuilding
self.m_isHalfPanel = false
self.m_panelArg = { slotId = CSFactoryUtil.GetBlueprintSlotId(chapterId, nodeId) }
return
end
if self.arg.isBuilding then
local panelBuildingDataId = self.arg.panelBuildingDataId
local customArg = self.arg.customArg
local buildingSyncNode = FactoryUtils.getBuildingNodeHandler(nodeId)
local buildingId = buildingSyncNode.templateId
local buildingData = Tables.factoryBuildingTable[buildingId]
local buildingType
if buildingSyncNode.nodeType == GEnums.FCNodeType.Special:GetHashCode() then
buildingType = buildingData.type
else
_, buildingType = CSFactoryUtil.GetFacBuildingType(buildingSyncNode.nodeType)
end
if nodeId then
local needRepairItems = nil
local predefinedParam = buildingSyncNode.predefinedParam
if predefinedParam then
local common = predefinedParam.common
if common then
if common.needRepair then
needRepairItems = common.repairNeedItem
end
end
end
if needRepairItems then
local unRepair = buildingSyncNode.isNeedRepair
if unRepair then
self.curPanelId = PanelId.FacRepairBuilding
self.m_isHalfPanel = true
self.m_panelArg = { needRepairItems = needRepairItems, nodeId = nodeId }
return
end
end
end
local panelBuildingType
if panelBuildingDataId then
panelBuildingType = Tables.factoryBuildingTable[panelBuildingDataId or buildingId].type
else
panelBuildingDataId = buildingId
panelBuildingType = buildingType
end
local panelName, isHalfPanel = unpack(FacConst.FACTORY_BUILDING_UI_MAP[panelBuildingType])
local panelId = PanelId[panelName]
self.curPanelId = panelId
self.m_isHalfPanel = isHalfPanel
self.curNodeId = nodeId
self.curUIInfo = GameInstance.remoteFactoryManager.uiInfoProvider:GetBuildingUIInfo(buildingType)
if self.curUIInfo then
if not self.arg.ignoreDist then
self.m_curBuildingPos = CSFactoryUtil.GetBuildingModelPosition(buildingSyncNode)
end
local width = buildingData.range.width
local depth = buildingData.range.depth
self.m_curBuildingRadius = math.sqrt(width * width + depth * depth) / 2
if customArg and customArg.subIndex then
self.curUIInfo:SetupChapterIdAndNodeId(Utils.getCurrentChapterId(), nodeId, customArg.subIndex)
else
self.curUIInfo:SetupChapterIdAndNodeId(Utils.getCurrentChapterId(), nodeId)
end
if not customArg then
customArg = { uiInfo = self.curUIInfo }
else
customArg.uiInfo = self.curUIInfo
end
else
if not customArg then
customArg = { nodeId = nodeId }
else
customArg.nodeId = nodeId
end
end
self.m_panelBuildingDataId = panelBuildingDataId
self.m_panelArg = customArg
else
self.m_panelArg = self:_ParseNonBuildingPanelArgs(self.arg)
end
self:_StartFbAndTickUpdate()
end
PhaseFacMachine._ParseNonBuildingPanelArgs = HL.Method(HL.Table).Return(HL.Table) << function(self, args)
local result = {}
if args == nil then
return result
end
local nodeId = args.nodeId
local nodeHandler = FactoryUtils.getBuildingNodeHandler(nodeId)
if nodeHandler == nil then
return result
end
local templateId = nodeHandler.templateId
local panelId = FacConst.FACTORY_NON_BUILDING_UI_MAP[templateId]
if panelId == nil then
return result
end
local nodeType = nodeHandler.nodeType
if nodeType == GEnums.FCNodeType.BoxConveyor:GetHashCode() then
self.curUIInfo = GameInstance.remoteFactoryManager.uiInfoProvider:GetConveyorUIInfo()
self.curUIInfo:SetupChapterIdAndNodeId(Utils.getCurrentChapterId(), nodeId, args.index)
elseif nodeType == GEnums.FCNodeType.BoxRouterM1:GetHashCode() or nodeType == GEnums.FCNodeType.BoxBridge:GetHashCode() then
self.curUIInfo = GameInstance.remoteFactoryManager.uiInfoProvider:GetLogisticUIInfo(templateId)
self.curUIInfo:SetupChapterIdAndNodeId(Utils.getCurrentChapterId(), nodeId)
elseif nodeType == GEnums.FCNodeType.FluidConveyor:GetHashCode() then
self.curUIInfo = GameInstance.remoteFactoryManager.uiInfoProvider:GetPipeUIInfo()
self.curUIInfo:SetupChapterIdAndNodeId(Utils.getCurrentChapterId(), nodeId)
elseif nodeType == GEnums.FCNodeType.FluidRouterM1:GetHashCode() or nodeType == GEnums.FCNodeType.FluidBridge:GetHashCode() then
self.curUIInfo = GameInstance.remoteFactoryManager.uiInfoProvider:GetFluidUnitUIInfo(templateId)
self.curUIInfo:SetupChapterIdAndNodeId(Utils.getCurrentChapterId(), nodeId)
elseif nodeType == GEnums.FCNodeType.BoxValve:GetHashCode() then
self.curUIInfo = GameInstance.remoteFactoryManager.uiInfoProvider:GetBoxValveUIInfo()
self.curUIInfo:SetupChapterIdAndNodeId(Utils.getCurrentChapterId(), nodeId)
elseif nodeType == GEnums.FCNodeType.FluidValve:GetHashCode() then
self.curUIInfo = GameInstance.remoteFactoryManager.uiInfoProvider:GetFluidValveUIInfo()
self.curUIInfo:SetupChapterIdAndNodeId(Utils.getCurrentChapterId(), nodeId)
end
self.curPanelId = PanelId[panelId]
self.m_curBuildingPos = GameUtil.playerPos
self.m_curBuildingRadius = 1
self.m_isHalfPanel = false
result.uiInfo = self.curUIInfo
result.index = args.index
return result
end
PhaseFacMachine._StartFbAndTickUpdate = HL.Method() << function(self)
if self.curUIInfo and not self.m_tickInitialized and not self.m_isDoingOut then
self.curUIInfo.sender:Message_HSFB(Utils.getCurrentChapterId(), false, { self.curNodeId })
self.curUIInfo:Update(true)
self.m_updateKey = LuaUpdate:Add("Tick", function()
self:_Update()
end)
self.m_tickInitialized = true
end
end
PhaseFacMachine._StopFbAndTickUpdate = HL.Method() << function(self)
if self.curUIInfo and self.m_tickInitialized then
self.m_updateKey = LuaUpdate:Remove(self.m_updateKey)
self.curUIInfo.sender:Message_HSFB(Utils.getCurrentChapterId(), true, { self.curNodeId })
self.m_tickInitialized = false
end
end
PhaseFacMachine.PrepareTransition = HL.Override(HL.Number, HL.Boolean, HL.Opt(HL.Number)) << function(self, transitionType, fastMode, anotherPhaseId)
if transitionType == PhaseConst.EPhaseState.TransitionIn then
if self.curPanelId and not fastMode and self.curPanelId ~= PanelId.FacMachineCrafter then
UIManager:PreloadPanelAsset(self.curPanelId, PHASE_ID)
end
if self.m_isHalfPanel and anotherPhaseId == PhaseId.Level then
Notify(MessageConst.SET_PHASE_LEVEL_TRANSITION_RESERVE_PANELS, ReservePanelIds)
end
end
end
PhaseFacMachine._DoPhaseTransitionIn = HL.Override(HL.Boolean, HL.Opt(HL.Table)) << function(self, fastMode, args)
if self.m_panelArg.uiInfo ~= nil and string.isEmpty(self.m_panelArg.uiInfo.nodeHandler.templateId) then
PhaseManager:ExitPhaseFast(PhaseId.FacMachine)
return
end
self.m_isDoingOut = false
local reservePanelIds = self.m_isHalfPanel and ReservePanelIds or nil
self.m_hidePanelKey = UIManager:ClearScreen(reservePanelIds)
CS.Beyond.Gameplay.Audio.AudioRemoteFactoryBridge.OnUnitUiOpened(self.curNodeId, self.m_panelBuildingDataId)
self.curPanelItem = self:CreatePhasePanelItem(self.curPanelId, self.m_panelArg)
if self.m_isHalfPanel then
Notify(MessageConst.ENTER_LEVEL_HALF_SCREEN_PANEL_MODE)
end
if self.m_panelBuildingDataId then
CS.Beyond.Gameplay.Conditions.OnBuildingPanelOpen.Trigger(self.m_panelBuildingDataId, false)
end
end
PhaseFacMachine._DoPhaseTransitionOut = HL.Override(HL.Boolean, HL.Opt(HL.Table)) << function(self, fastMode, args)
self.m_isDoingOut = true
Notify(MessageConst.HIDE_ITEM_TIPS)
Notify(MessageConst.EXIT_LEVEL_HALF_SCREEN_PANEL_MODE)
Notify(MessageConst.HIDE_COMMON_HOVER_TIP)
Notify(MessageConst.RESET_DROP_HIGHLIGHT)
for _, panelId in pairs(NeedClosePanelIds) do
if UIManager:IsOpen(panelId) then
UIManager:Close(panelId)
end
end
CS.Beyond.Gameplay.Audio.AudioRemoteFactoryBridge.OnUnitUiClosed(self.curNodeId, self.m_panelBuildingDataId)
end
PhaseFacMachine._DoPhaseTransitionOutAfterItems = HL.Override(HL.Boolean, HL.Opt(HL.Table)) << function(self, fastMode, args)
self.m_hidePanelKey = UIManager:RecoverScreen(self.m_hidePanelKey)
end
PhaseFacMachine._DoPhaseTransitionBehind = HL.Override(HL.Boolean, HL.Opt(HL.Table)) << function(self, fastMode, args)
end
PhaseFacMachine._DoPhaseTransitionBackToTop = HL.Override(HL.Boolean, HL.Opt(HL.Table)) << function(self, fastMode, args)
if self.curPanelId == PanelId.FacPendingBuilding then
self.curPanelItem.uiCtrl:RefreshList(true)
end
end
PhaseFacMachine._OnActivated = HL.Override() << function(self)
self:_StartFbAndTickUpdate()
if self.m_panelBuildingDataId and not self.m_isDoingOut then
CS.Beyond.Gameplay.Conditions.OnBuildingPanelOpen.Trigger(self.m_panelBuildingDataId, true)
end
if self.curNodeId and not self.m_isDoingOut then
local isOthers, isPreset = FactoryUtils.getBuildingSocialSourceInfo(self.curNodeId)
if isOthers and not isPreset then
CS.Beyond.Gameplay.Conditions.OnOtherPlayerSocialBuildingPanelOpen.Trigger()
end
end
end
PhaseFacMachine._OnDeActivated = HL.Override() << function(self)
self:_StopFbAndTickUpdate()
end
PhaseFacMachine._OnDestroy = HL.Override() << function(self)
self:_StopFbAndTickUpdate()
if self.curPanelItem ~= nil then
self:RemovePhasePanelItem(self.curPanelItem)
end
end
PhaseFacMachine._Update = HL.Method() << function(self)
local nodeValid = false
if self.curUIInfo then
nodeValid = self.curUIInfo.nodeHandler and self.curUIInfo.nodeHandler.valid
if nodeValid then
self.curUIInfo:Update()
end
end
local needExit = not nodeValid
if not needExit then
if self.m_curBuildingPos and not LuaSystemManager.factory.inTopView then
local playerPos = GameUtil.playerPos
local dist = (playerPos - self.m_curBuildingPos).magnitude
if dist > self.m_curBuildingRadius + FacConst.BUILDING_PANEL_AUTO_CLOSE_RANGE then
needExit = true
end
end
end
if needExit then
if PhaseManager.m_curState == Const.PhaseState.Idle and PhaseManager:GetTopPhaseId() == PhaseId.FacMachine then
self.m_curBuildingPos = nil
PhaseManager:PopPhase(PhaseId.FacMachine)
Notify(MessageConst.FAC_UPDATE_INTERACT_OPTION, true)
end
end
end
PhaseFacMachine.CheckPanelUnlockedState = HL.StaticMethod(HL.String, HL.String, HL.Opt(HL.Table)).Return(HL.Boolean) << function(buildingId, instKey, args)
local subIndex = args and args.subIndex or -1
return not CSFactoryUtil.CheckIsBuildingInteractLocked(buildingId, instKey, true, subIndex)
end
HL.Commit(PhaseFacMachine)