Files
Endfield-Data/LuaScripts/UI/Widgets/BuildingCommon.lua
2025-12-02 20:37:18 +07:00

692 lines
22 KiB
Lua

local SocialBuildingSource = CS.Beyond.Gameplay.Factory.SocialBuildingSource
local UIWidgetBase = require_ex('Common/Core/UIWidgetBase')
BuildingCommon = HL.Class('BuildingCommon', UIWidgetBase)
local BUILDING_BOTTOM_BG_NAME = "bg_machine_base_%d"
BuildingCommon.nodeId = HL.Field(HL.Number) << -1
BuildingCommon.buildingId = HL.Field(HL.String) << ""
BuildingCommon.buildingUiInfo = HL.Field(CS.Beyond.Gameplay.RemoteFactory.NodeUIInfo)
BuildingCommon.buildingItemId = HL.Field(HL.String) << ""
BuildingCommon.lastState = HL.Field(GEnums.FacBuildingState)
BuildingCommon.m_stateGoNodeMap = HL.Field(HL.Table)
BuildingCommon.bgRatio = HL.Field(HL.Number) << -1
BuildingCommon.m_arg = HL.Field(HL.Table)
BuildingCommon.m_social = HL.Field(CS.Beyond.Gameplay.RemoteFactory.ServerChapterInfo.ComponentHandler.Payload_Social)
BuildingCommon.m_socialBuildingSource = HL.Field(CS.Beyond.Gameplay.Factory.SocialBuildingSource)
BuildingCommon.m_showPower = HL.Field(HL.Boolean) << false
BuildingCommon.smartAlertDynamicNode = HL.Field(HL.Any)
BuildingCommon.m_smartAlertUpdate = HL.Field(HL.Number) << -1
BuildingCommon.m_smartAlertTypeIndex = HL.Field(HL.Number) << 1
BuildingCommon.m_smartAlertCheckedInPeriod = HL.Field(HL.Boolean) << false
BuildingCommon.smartAlertChangeCachePauseUpdate = HL.Field(HL.Boolean) << false
BuildingCommon._OnFirstTimeInit = HL.Override() << function(self)
self.view.closeButton.onClick:AddListener(function()
self:Close()
end)
self.view.wikiButton.onClick:AddListener(function()
local args = {}
if not string.isEmpty(self.buildingItemId) then
args.itemId = self.buildingItemId
else
args.buildingId = self.buildingId
end
Notify(MessageConst.SHOW_WIKI_ENTRY, args)
end)
self.view.moveButton.onClick:AddListener(function()
self:_MoveBuilding()
end)
self.view.delButton.onClick:AddListener(function()
self:_DelBuilding()
end)
self.view.forbiddenMoveButton.onClick:AddListener(function()
Notify(MessageConst.SHOW_TOAST, Language.LUA_FAC_FORBID_MOVE_OR_DELETE)
end)
self.view.forbiddenDelButton.onClick:AddListener(function()
Notify(MessageConst.SHOW_TOAST, Language.LUA_FAC_FORBID_MOVE_OR_DELETE)
end)
self.view.shareButton.onClick:AddListener(function()
self:_ShareBuilding()
end)
self.view.delSocialButton.onClick:AddListener(function()
self:_DelBuilding()
end)
self.view.sourceButton.onClick:AddListener(function()
self:_ShowBuildingSource()
end)
self:RegisterMessage(MessageConst.FAC_ON_MOVE_SHOW_CONTROLLER_MODE_HINT, function(text)
if text ~= nil then
self.view.controllerModeHint.gameObject:SetActive(true)
self.view.controllerModeHint.hintTxt.text = text
end
end)
self:RegisterMessage(MessageConst.FAC_ON_MOVE_HIDE_CONTROLLER_MODE_HINT, function()
self.view.controllerModeHint.gameObject:SetActive(false)
end)
end
BuildingCommon.InitBuildingCommon = HL.Method(HL.Opt(CS.Beyond.Gameplay.RemoteFactory.NodeUIInfo, HL.Table)) <<
function(self, uiInfo, arg)
self:_FirstTimeInit()
local hasUiInfo = uiInfo ~= nil
arg = arg or {}
self.m_arg = arg
local data
if hasUiInfo then
self.buildingUiInfo = uiInfo
self.nodeId = uiInfo.nodeId
self.buildingId = uiInfo.buildingId
data = Tables.factoryBuildingTable:GetValue(self.buildingId)
self.view.powerToggle:InitCommonToggle(function(isOn)
self:_OnToggleBuildingPower(isOn)
end, self.buildingUiInfo.isActive, true)
self:_UpdateBuildingState(true)
self:_StartCoroutine(function()
while true do
coroutine.step()
self:_UpdateBuildingState()
end
end)
if self.m_arg.smartAlertFuncNameList and
self.m_arg.targetCtrlInstance and
CS.Beyond.GameSetting.otherShowSmartAlert and
not Utils.isInBlackbox() then
if self.smartAlertDynamicNode == nil then
local saPrefab = self:LoadGameObject(FacConst.FAC_SMARTALERT_PREFAB_PATH)
local saObj = CSUtils.CreateObject(saPrefab, self.transform)
saObj:SetActive(false)
self.smartAlertDynamicNode = Utils.wrapLuaNode(saObj)
end
self.smartAlertDynamicNode:InitMachineSmartAlertNode()
self.m_smartAlertUpdate = LuaUpdate:Add("Tick", function(deltaTime)
self:_UpdateSmartAlert(deltaTime)
end)
end
self.m_social, self.m_socialBuildingSource = FactoryUtils.getSocialBuildingDetails(uiInfo.nodeId)
self.m_showPower = data.powerConsume > 0
and self.m_socialBuildingSource ~= SocialBuildingSource.Others
self:_InitBuildingBG(uiInfo.nodeId, data.bgOnPanel)
self:_InitBuildingOperateButtonState(uiInfo.nodeId)
else
data = arg.data
self.buildingItemId = data.itemId
self.view.moveButton.gameObject:SetActive(false)
self.view.delButton.gameObject:SetActive(false)
self.view.leftButtonDecoLine.gameObject:SetActive(false)
self.view.shareButton.gameObject:SetActive(false)
self.view.delSocialButton.gameObject:SetActive(false)
self.view.leftButtonDecoLine2.gameObject:SetActive(false)
self.view.powerToggle.gameObject:SetActive(false)
self.m_showPower = false
self:_InitBuildingCustomButtons()
if data.nodeId ~= nil then
self.m_social, self.m_socialBuildingSource = FactoryUtils.getSocialBuildingDetails(data.nodeId)
self:_InitBuildingOperateButtonState(data.nodeId)
end
end
self:_InitBuildingDescription()
if self.m_showPower then
self.view.powerNode.gameObject:SetActive(true)
self.view.decoLine.gameObject:SetActive(true)
local powerCost = FactoryUtils.getCurBuildingConsumePower(self.nodeId)
self.view.powerText.text = powerCost
else
self.view.powerNode.gameObject:SetActive(false)
self.view.decoLine.gameObject:SetActive(false)
end
self:UpdateBasicInfo(data)
self:_UpdateSocialInfo()
local ctrl = self:GetUICtrl()
ctrl.view.controllerHintPlaceholder = self.view.controllerHintPlaceholder
self.view.controllerHintPlaceholder:InitControllerHintPlaceholder({ctrl.view.inputGroup.groupId})
local extraBtnInfos = {}
if ctrl.view.formulaNode then
table.insert(extraBtnInfos, {
button = ctrl.view.formulaNode.view.openBtn,
sprite = ctrl.view.formulaNode.view.openBtnIcon.sprite,
textId = "key_hint_fac_machine_toggle_formula",
priority = 2.1,
})
end
self.view.controllerSideMenuBtn:InitControllerSideMenuBtn({
extraBtnInfos = extraBtnInfos,
})
self:_InitBuildingSwitchAreaKeyHintState()
end
BuildingCommon.UpdateBasicInfo = HL.Method(HL.Any) << function(self, data)
self.view.machineName.text = data.name
self.view.machineIcon:LoadSprite(UIConst.UI_SPRITE_FAC_BUILDING_PANEL_ICON, data.iconOnPanel)
if self.m_showPower then
self.view.powerNode.gameObject:SetActive(data.needPower)
self.view.powerNodeNeedPower.gameObject:SetActive(not data.needPower)
end
end
BuildingCommon._UpdateSocialInfo = HL.Method() << function(self)
local source = self.m_socialBuildingSource
if source == SocialBuildingSource.Invalid then
self.view.likeNode.gameObject:SetActive(false)
self.view.sourceNode.gameObject:SetActive(false)
else
local isMine = source == SocialBuildingSource.Mine
self.view.likeNode.gameObject:SetActive(isMine)
self.view.sourceNode.gameObject:SetActive(not isMine)
if isMine then
self.view.likeText.text = self.m_social.like
end
end
end
BuildingCommon._OnToggleBuildingPower = HL.Method(HL.Boolean) << function(self, isOn)
if isOn == self.buildingUiInfo.isActive then
return
end
GameInstance.mobileMotionManager:PostEventCommonShort()
self.buildingUiInfo.sender:Message_OpEnableNode(Utils.getCurrentChapterId(), self.nodeId, isOn, function()
if self.m_showPower then
self.view.powerText.text = FactoryUtils.getCurBuildingConsumePower(self.nodeId)
end
if self.m_arg.onPowerChanged then
self.m_arg.onPowerChanged(isOn)
end
end)
end
BuildingCommon._UpdateBuildingState = HL.Method(HL.Opt(HL.Boolean)) << function(self, forceUpdate)
local state = FactoryUtils.getBuildingStateType(self.nodeId)
if not forceUpdate and state == self.lastState then
return
end
if self.m_stateGoNodeMap == nil then
self.m_stateGoNodeMap = {}
end
self:_RefreshBuildingStateDisplay(state)
self.lastState = state
end
BuildingCommon._UpdateSmartAlert = HL.Method(HL.Number) << function(self, detlaTime)
if self.smartAlertChangeCachePauseUpdate or not self.gameObject.activeInHierarchy then
return
end
local periodCount = #self.m_arg.smartAlertFuncNameList + 1
if self.m_smartAlertCheckedInPeriod then
self.smartAlertDynamicNode:UpdateSmartAlertState(detlaTime)
if self.m_smartAlertTypeIndex >= periodCount then
self.m_smartAlertCheckedInPeriod = false
end
else
if self.m_smartAlertTypeIndex >= periodCount then
local alertInfo = { condition = GEnums.FacSmartAlertType.DoNotShow }
self.smartAlertDynamicNode:UpdateSmartAlertState(detlaTime, alertInfo)
else
local funcName = self.m_arg.smartAlertFuncNameList[self.m_smartAlertTypeIndex]
local targetCtrl = self.m_arg.targetCtrlInstance
local success, alertInfo = targetCtrl[funcName](targetCtrl, self.lastState)
self.m_smartAlertCheckedInPeriod = success
self.smartAlertDynamicNode:UpdateSmartAlertState(detlaTime, alertInfo)
end
end
self.m_smartAlertTypeIndex = (self.m_smartAlertTypeIndex % periodCount) + 1
end
BuildingCommon._RefreshBuildingStateDisplay = HL.Method(GEnums.FacBuildingState) << function(self, state)
if self.m_stateGoNodeMap[self.lastState] ~= nil then
self.m_stateGoNodeMap[self.lastState]:SetActive(false)
end
local showState
if state == GEnums.FacBuildingState.Idle and not string.isEmpty(self.buildingUiInfo.formulaId) and self.lastState ~= GEnums.FacBuildingState.Invalid then
showState = GEnums.FacBuildingState.Normal
else
showState = state
end
if self.m_stateGoNodeMap[showState] == nil then
if FacConst.FAC_BUILDING_STATE_TO_PREFAB_PATH[showState] ~= nil then
local statePrefab = self:LoadGameObject(FacConst.FAC_BUILDING_STATE_TO_PREFAB_PATH[showState])
local stateObj = CSUtils.CreateObject(statePrefab, self.view.stateNode)
self.m_stateGoNodeMap[showState] = stateObj
if showState == GEnums.FacBuildingState.Normal then
local _, data, customTextKey
if string.isEmpty(self.buildingId) then
local buildingId = FactoryUtils.getItemBuildingId(self.buildingItemId)
if buildingId ~= nil then
_, data = Tables.factoryBuildingTable:TryGetValue(buildingId)
end
else
_, data = Tables.factoryBuildingTable:TryGetValue(self.buildingId)
end
if data ~= nil then
customTextKey = FacConst.FAC_BUILDING_NORMAL_STATE_CUSTOM_TEXT_ID[data.type]
else
customTextKey = FacConst.FAC_NON_BUILDING_NORMAL_STATE_CUSTOM_TEXT_ID[self.buildingItemId]
end
if customTextKey ~= nil then
local text = stateObj.transform:Find("Info/Text"):GetComponent("UIText")
text.text = Language[customTextKey]
end
end
end
else
self.m_stateGoNodeMap[showState]:SetActive(true)
end
if self.m_arg.onStateChanged then
self.m_arg.onStateChanged(state)
end
end
BuildingCommon._MoveBuilding = HL.Method() << function(self)
local nodeId = self.nodeId
if not FactoryUtils.canMoveBuilding(nodeId) then
Notify(MessageConst.SHOW_TOAST, Language.LUA_FACTORY_BUILDING_MOVE_NOT_ALLOWED)
return
end
self:Close(true)
Notify(MessageConst.FAC_ENTER_BUILDING_MODE, {
nodeId = nodeId
})
end
BuildingCommon._DelBuilding = HL.Method() << function(self)
if not FactoryUtils.canDelBuilding(self.nodeId, true) then
return
end
self:Close(true)
local data = Tables.factoryBuildingTable:GetValue(self.buildingId)
local hintTxt
if data ~= nil then
hintTxt = data.delConfirmText
end
FactoryUtils.delBuilding(self.nodeId, nil, false, hintTxt)
end
BuildingCommon._ShareBuilding = HL.Method() << function(self)
if not FriendUtils.canShareBuilding() then
return
end
if not FactoryUtils.canShareBuilding(self.nodeId) then
return
end
local state = FactoryUtils.getBuildingStateType(self.nodeId)
if state ~= GEnums.FacBuildingState.Normal then
Notify(MessageConst.SHOW_TOAST, Language.LUA_FAC_SHARE_SOCIAL_BUILDING_STATE_NOT_NORMAL)
return
end
local chapterId = Utils.getCurrentChapterId()
local nodeId = self.nodeId
local customCheckFriend
local fromOtherPlayer = self.m_socialBuildingSource == SocialBuildingSource.Others and not self.m_social.preset
if fromOtherPlayer then
local ownerId = self.m_social.ownerId
customCheckFriend = function(friendInfo)
return friendInfo.roleId ~= ownerId
end
end
UIManager:Open(PanelId.FriendRequest, {
customCheckFriend = customCheckFriend,
onShareClick = function(roleId)
GameInstance.player.friendChatSystem:SendChatSocialBuilding(roleId, chapterId, nodeId, function()
Notify(MessageConst.SHOW_TOAST, Language.LUA_FRIEND_SHARE_SOCIAL_BUILDING_SUCCESS)
UIManager:Close(PanelId.FriendRequest)
self:Close()
PhaseManager:OpenPhase(PhaseId.SNS, { roleId = roleId }, nil, true)
end)
end,
})
end
BuildingCommon._ShowBuildingSource = HL.Method() << function(self)
if self.m_socialBuildingSource ~= SocialBuildingSource.Others then
return
end
Notify(MessageConst.HIDE_COMMON_HOVER_TIP)
local ownerId = self.m_social.ownerId
if self.m_social.preset then
local success, npcData = Tables.factorySocialBuildingNpcTable:TryGetValue(ownerId)
if not success then
logger.error("[SocialBuilding] ShowSource: Npc data not found, npcId: " .. tostring(ownerId))
return
end
UIManager:Open(PanelId.FacSourceDetails, { nodeId = self.nodeId, npcData = npcData })
else
GameInstance.player.friendSystem:SyncSocialFriendInfo({ ownerId }, function()
local success, ownerInfo = GameInstance.player.friendSystem:TryGetFriendInfo(ownerId)
if not success then
logger.info("[SocialBuilding] ShowSource: Owner info not found, roleId: " .. tostring(ownerId))
end
UIManager:Open(PanelId.FacSourceDetails, { nodeId = self.nodeId, ownerInfo = ownerInfo })
end)
end
end
BuildingCommon._InitBuildingBG = HL.Method(HL.Number, HL.String) << function(self, buildingNodeId, buildingBgId)
local inPortInfoList, outPortInfoList = FactoryUtils.getBuildingPortState(buildingNodeId, false)
if inPortInfoList == nil or outPortInfoList == nil then
return
end
if not string.isEmpty(buildingBgId) and not self.view.config.USE_CUSTOM_BG then
local inPortCount, outPortCount = #inPortInfoList, #outPortInfoList
if not GameInstance.remoteFactoryManager.unlockSystem.systemUnlockedBelt or
not GameInstance.remoteFactoryManager:IsWorldPositionInMainRegion(self.buildingUiInfo.nodeHandler.transform.worldPosition) then
inPortCount, outPortCount = 0, 0
end
local inBottomBGName = string.format(BUILDING_BOTTOM_BG_NAME, inPortCount)
local outBottomBGName = string.format(BUILDING_BOTTOM_BG_NAME, outPortCount)
self.view.leftPart:LoadSprite(UIConst.UI_SPRITE_FAC_MACHINE_BG, inBottomBGName)
self.view.rightPart:LoadSprite(UIConst.UI_SPRITE_FAC_MACHINE_BG, outBottomBGName)
local buildingBg = self:LoadSprite(UIConst.UI_SPRITE_FAC_MACHINE_BG, buildingBgId)
if buildingBg ~= nil then
self.view.machineBg.sprite = buildingBg
if self.view.config.NEED_RESIZE_BOTTOM_BG then
local originalWidth = self.view.machineBgRect.rect.width
self.view.machineBg:SetNativeSize()
local currentWidth = self.view.machineBgRect.rect.width
if currentWidth ~= originalWidth then
local ratio = currentWidth / originalWidth * self.view.config.MACHINE_TO_BOTTOM_RATIO
local originalBottomSize = self.view.bottomBgRect.sizeDelta
self.view.bottomBgRect.sizeDelta = Vector2(originalBottomSize.x * ratio, originalBottomSize.y)
local originalPartSize = self.view.leftPartRect.sizeDelta
self.view.leftPartRect.sizeDelta = Vector2(originalPartSize.x * ratio, originalPartSize.y)
self.view.rightPartRect.sizeDelta = Vector2(originalPartSize.x * ratio, originalPartSize.y)
self.bgRatio = ratio
end
end
end
end
end
BuildingCommon._InitBuildingDescription = HL.Method() << function(self)
if self.config.SHOW_BUILDING_DESCRIPTION then
self.view.machineDescNode.gameObject:SetActiveIfNecessary(true)
local itemData
if string.isEmpty(self.buildingId) then
itemData = Tables.itemTable:GetValue(self.buildingItemId)
else
itemData = FactoryUtils.getBuildingItemData(self.buildingId)
end
if itemData ~= nil then
self.view.descText.text = itemData.desc
end
else
self.view.machineDescNode.gameObject:SetActiveIfNecessary(false)
end
end
BuildingCommon._InitBuildingOperateButtonState = HL.Method(HL.Number) << function(self, nodeId)
local isOthersSocialBuilding = self.m_socialBuildingSource == SocialBuildingSource.Others
local canMove, canDel = FactoryUtils.canMoveBuilding(nodeId), FactoryUtils.canDelBuilding(nodeId)
local needMoveBtn = self.view.moveButton.gameObject.activeSelf
and not isOthersSocialBuilding
local needDelBtn = self.view.delButton.gameObject.activeSelf
and not isOthersSocialBuilding
self.view.moveButton.gameObject:SetActive(needMoveBtn and canMove)
self.view.forbiddenMoveButton.gameObject:SetActive(needMoveBtn and not canMove)
self.view.delButton.gameObject:SetActive(needDelBtn and canDel)
self.view.forbiddenDelButton.gameObject:SetActive(needDelBtn and not canDel)
self.view.leftButtonDecoLine.gameObject:SetActive(needDelBtn and needMoveBtn)
local showShareBtn = FactoryUtils.canShareBuilding(nodeId)
local needDelSocialBtn = isOthersSocialBuilding
self.view.shareButton.gameObject:SetActive(showShareBtn)
self.view.delSocialButton.gameObject:SetActive(needDelSocialBtn and canDel)
local showDecoLine2 = showShareBtn
self.view.leftButtonDecoLine2.gameObject:SetActive(showDecoLine2)
end
BuildingCommon._InitBuildingCustomButtons = HL.Method() << function(self)
local leftButtonValid, rightButtonValid = false, false
if self.m_arg.customLeftButtonOnClicked ~= nil then
self.view.moveButton.onClick:RemoveAllListeners()
self.view.moveButton.onClick:AddListener(function()
self.m_arg.customLeftButtonOnClicked()
end)
self.view.moveButton.gameObject:SetActive(true)
leftButtonValid = true
end
if self.m_arg.customRightButtonOnClicked ~= nil then
self.view.delButton.onClick:RemoveAllListeners()
self.view.delButton.onClick:AddListener(function()
self.m_arg.customRightButtonOnClicked()
end)
self.view.delButton.gameObject:SetActive(true)
rightButtonValid = true
end
self.view.leftButtonDecoLine.gameObject:SetActive(leftButtonValid and rightButtonValid)
end
BuildingCommon._InitBuildingSwitchAreaKeyHintState = HL.Method() << function(self)
local needShowHint = self.config.SHOW_SWITCH_AREA_KEY_HINT
if not needShowHint then
self.view.switchAreaKeyHint.overrideValidState = CS.Beyond.UI.CustomUIStyle.OverrideValidState.ForceNotValid
end
end
BuildingCommon.Close = HL.Method(HL.Opt(HL.Boolean)) << function(self, skipAnim)
if not skipAnim then
if PhaseManager:GetTopPhaseId() == PhaseId.FacMachine then
PhaseManager:PopPhase(PhaseId.FacMachine)
end
else
PhaseManager:ExitPhaseFast(PhaseId.FacMachine)
end
end
BuildingCommon.ClearSmartAlertUpdate = HL.Method() << function(self)
if self.m_arg.smartAlertFuncNameList and
self.m_arg.targetCtrlInstance and
CS.Beyond.GameSetting.otherShowSmartAlert and
not Utils.isInBlackbox() then
self.m_smartAlertUpdate = LuaUpdate:Remove(self.m_smartAlertUpdate)
if self.smartAlertDynamicNode ~= nil then
self.smartAlertDynamicNode:RestoreAlertState()
end
end
end
BuildingCommon.ChangeBuildingStateDisplay = HL.Method(GEnums.FacBuildingState) << function(self, state)
if state == nil then
return
end
if state == self.lastState then
return
end
if self.m_stateGoNodeMap == nil then
self.m_stateGoNodeMap = {}
end
self:_RefreshBuildingStateDisplay(state)
self.lastState = state
end
HL.Commit(BuildingCommon)
return BuildingCommon