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

549 lines
17 KiB
Lua

local UIWidgetBase = require_ex('Common/Core/UIWidgetBase')
FacMiniPowerContent = HL.Class('FacMiniPowerContent', UIWidgetBase)
local XIRANITE_BUILDINGID = "xiranite_oven_1"
local BUILDING_ICON_MAP = {
[GEnums.FacBuildingType.TravelPole] = "building_icon_travel_pole",
[GEnums.FacBuildingType.Battle] = "building_icon_battle",
[GEnums.FacBuildingType.Sign] = "building_icon_marker",
[GEnums.FacBuildingType.BusFree] = "building_icon_bus_basaband",
[GEnums.FacBuildingType.BusStart] = "building_icon_bus_sourcepillar",
[GEnums.FacBuildingType.MachineCrafter] = "building_icon_xirong_machine",
}
FacMiniPowerContent.isMonitorPower = HL.Field(HL.Boolean) << false
FacMiniPowerContent.m_chapterId = HL.Field(HL.Number) << -1
FacMiniPowerContent.m_powerInfo = HL.Field(HL.Userdata)
FacMiniPowerContent.m_buildingData = HL.Field(Cfg.Types.FactoryBuildingData)
FacMiniPowerContent.m_refreshCoroutine = HL.Field(HL.Thread)
FacMiniPowerContent.m_lastIsConsuming = HL.Field(HL.Boolean) << false
FacMiniPowerContent.m_lastPowerSavePercent = HL.Field(HL.Number) << -1
FacMiniPowerContent.m_lastPowerEnoughAnimName = HL.Field(HL.String) << ""
FacMiniPowerContent.m_lastPowerSaveAnimName = HL.Field(HL.String) << ""
FacMiniPowerContent.m_lackOfPowerAudioBaseTime = HL.Field(HL.Number) << -1
FacMiniPowerContent.m_isDirty = HL.Field(HL.Boolean) << false
FacMiniPowerContent.m_powerData = HL.Field(HL.Table)
FacMiniPowerContent.m_isSaveMaxBecameValid = HL.Field(HL.Boolean) << false
FacMiniPowerContent.m_showToastTimer = HL.Field(HL.Number) << -1
FacMiniPowerContent._OnCreate = HL.Override() << function(self)
end
FacMiniPowerContent._OnEnable = HL.Override() << function(self)
self:RefreshFacMiniPowerContent()
self:_RefreshAnimState()
self:ToggleCoroutine(true)
end
FacMiniPowerContent._OnDisable = HL.Override() << function(self)
self:ToggleCoroutine(false)
end
FacMiniPowerContent._OnDestroy = HL.Override() << function(self)
self:ToggleCoroutine(false)
self:_ClearShowToastTimer()
self.m_powerInfo = nil
end
FacMiniPowerContent.ToggleCoroutine = HL.Method(HL.Boolean) << function(self, active)
if active then
if not self.m_refreshCoroutine then
self.m_refreshCoroutine = self:_StartCoroutine(function()
while true do
coroutine.wait(UIConst.FAC_COMMON_UI_UPDATE_INTERVAL)
self:_UpdateAndRefreshAll(false)
end
end)
end
else
self.m_refreshCoroutine = self:_ClearCoroutine(self.m_refreshCoroutine)
end
end
FacMiniPowerContent._OnFirstTimeInit = HL.Override() << function(self)
end
FacMiniPowerContent._UpdateAndRefreshAll = HL.Method(HL.Boolean) << function(self, forceRefresh)
self:_UpdateMiniPowerData()
if forceRefresh or self.m_isDirty then
self:RefreshFacMiniPowerContent()
self:UpdateLackOfPowerAudio()
self.m_isDirty = false
end
end
FacMiniPowerContent._ClearShowToastTimer = HL.Method() << function(self)
if self.m_showToastTimer < 0 then
return
end
self.m_showToastTimer = self:_ClearTimer(self.m_showToastTimer)
end
FacMiniPowerContent._GetPowerInfo = HL.Method().Return(HL.Opt(HL.Userdata)) << function(self)
if self.m_chapterId < 0 then
return FactoryUtils.getCurRegionPowerInfo()
else
return FactoryUtils.getRegionPowerInfoByChapterId(self.m_chapterId)
end
end
FacMiniPowerContent._UpdateMiniPowerData = HL.Method() << function(self)
if not self.m_powerInfo then
self.m_powerData = {}
self.m_powerInfo = self:_GetPowerInfo()
end
if self.m_powerInfo ~= nil then
local powerInfo = self.m_powerInfo
if self.m_powerData.powerCost == nil or self.m_powerData.powerCost ~= powerInfo.powerCost then
self.m_powerData.powerCost = powerInfo.powerCost
self.m_isDirty = true
end
if self.m_powerData.powerGen == nil or self.m_powerData.powerGen ~= powerInfo.powerGen then
self.m_powerData.powerGen = powerInfo.powerGen
self.m_isDirty = true
end
if self.m_powerData.powerSaveCurrent == nil or self.m_powerData.powerSaveCurrent ~= powerInfo.powerSaveCurrent then
self.m_powerData.powerSaveCurrent = powerInfo.powerSaveCurrent
self.m_isDirty = true
end
if self.m_powerData.powerSaveMax == nil or self.m_powerData.powerSaveMax ~= powerInfo.powerSaveMax then
if self.m_powerData.powerSaveMax ~= nil and self.m_powerData.powerSaveMax <= 0 and powerInfo.powerSaveMax > 0 then
self.m_isSaveMaxBecameValid = true
end
self.m_powerData.powerSaveMax = powerInfo.powerSaveMax
self.m_isDirty = true
end
end
end
FacMiniPowerContent._RefreshContent = HL.Method() << function(self)
if not self.m_powerInfo then
return
end
local data = self.m_powerData
local node = self.view
local isMoving = FactoryUtils.isMovingBuilding()
local powerCost = data.powerCost + ((self.m_buildingData and not isMoving) and self.m_buildingData.powerConsume or 0)
local powerGen = data.powerGen
node.costPowerTxt.text = UIUtils.getNumString(powerCost)
node.genPowerTxt.text = string.format("/%s", UIUtils.getNumString(powerGen))
local isConsuming = powerGen < powerCost
node.costPowerTxt.color = self.m_buildingData and self.view.config.COUNT_ENOUGH_COLOR or self.view.config.COUNT_NORMAL_COLOR
if self.m_buildingData then
node.costPowerTxt.color = isConsuming and self.view.config.COUNT_NOT_ENOUGH_COLOR or self.view.config.COUNT_ENOUGH_COLOR
return
else
node.costPowerTxt.color = self.view.config.COUNT_NORMAL_COLOR
end
local restPower = data.powerSaveCurrent
local restPercent = restPower / (data.powerSaveMax > 0 and data.powerSaveMax or 1)
local emptyRestPower = restPercent <= self.view.config.POWER_SAVE_EMPTY_VALUE
node.powerSavePercentTxt.text = math.floor(restPercent * 100)
node.powerSaveBar.fillAmount = restPercent
local powerSaveColor
if emptyRestPower then
powerSaveColor = self.view.config.NO_POWER_COLOR
else
powerSaveColor = restPercent <= self.view.config.POWER_SAVE_OUT_VALUE and self.view.config.COST_SAVE_POWER_COLOR or self.view.config.NORMAL_COLOR
end
node.powerSaveBar.color = powerSaveColor
node.powerSaveIcon.color = powerSaveColor
local powerEnoughColor = isConsuming and self.view.config.NO_POWER_COLOR or self.view.config.COUNT_NORMAL_COLOR
node.powerEnoughImg.color = powerEnoughColor
node.costPowerTxt.color = powerEnoughColor
if isConsuming then
if self.m_lastPowerEnoughAnimName ~= self.view.config.POWER_ENOUGH_LOOP_ANIM_NAME then
self.m_lastPowerEnoughAnimName = self.view.config.POWER_ENOUGH_LOOP_ANIM_NAME
node.powerEnoughAnim:PlayWithTween(self.m_lastPowerEnoughAnimName)
self.m_lackOfPowerAudioBaseTime = CS.UnityEngine.Time.unscaledTime
end
else
if self.m_lastPowerEnoughAnimName ~= self.view.config.POWER_ENOUGH_NORMAL_ANIM_NAME then
self.m_lastPowerEnoughAnimName = self.view.config.POWER_ENOUGH_NORMAL_ANIM_NAME
node.powerEnoughAnim:PlayWithTween(self.m_lastPowerEnoughAnimName)
self.m_lackOfPowerAudioBaseTime = -1
end
end
local powerSaveOutValue = self.view.config.POWER_SAVE_OUT_VALUE
if restPercent <= powerSaveOutValue then
if self.m_lastPowerSaveAnimName ~= self.view.config.POWER_SAVE_LOOP_ANIM_NAME then
self.m_lastPowerSaveAnimName = self.view.config.POWER_SAVE_LOOP_ANIM_NAME
node.powerSaveAnim:PlayWithTween(self.m_lastPowerSaveAnimName)
end
else
if self.m_lastPowerSaveAnimName ~= self.view.config.POWER_SAVE_NORMAL_ANIM_NAME then
self.m_lastPowerSaveAnimName = self.view.config.POWER_SAVE_NORMAL_ANIM_NAME
node.powerSaveAnim:PlayWithTween(self.m_lastPowerSaveAnimName)
end
end
end
FacMiniPowerContent._MonitorPower = HL.Method() << function(self)
local data = self.m_powerData
if data.powerSaveMax <= 0 then
return
end
local powerCost = data.powerCost
local powerGen = data.powerGen
local isConsuming = powerGen < powerCost
local restPower = data.powerSaveCurrent
local restPercent = restPower / (data.powerSaveMax > 0 and data.powerSaveMax or 1)
local powerSaveOutValue = self.view.config.POWER_SAVE_OUT_VALUE
local powerSaveEmptyValue = self.view.config.POWER_SAVE_EMPTY_VALUE
local showText
if self.m_lastPowerSavePercent < 0 then
if not self.m_isSaveMaxBecameValid then
if restPercent <= powerSaveEmptyValue then
showText = Language.LUA_FAC_POWER_SAVE_EMPTY
else
if restPercent <= powerSaveOutValue then
showText = Language.LUA_FAC_POWER_SAVE_OUT
else
if isConsuming then
showText = Language.LUA_FAC_POWER_CONSUMING
end
end
end
else
self.m_isSaveMaxBecameValid = false
end
else
if isConsuming and not self.m_lastIsConsuming then
showText = Language.LUA_FAC_POWER_CONSUMING
end
if restPercent <= powerSaveOutValue and self.m_lastPowerSavePercent > powerSaveOutValue then
showText = Language.LUA_FAC_POWER_SAVE_OUT
end
if restPercent <= powerSaveEmptyValue and self.m_lastPowerSavePercent > powerSaveEmptyValue then
showText = Language.LUA_FAC_POWER_SAVE_EMPTY
end
end
if not string.isEmpty(showText) then
if not Utils.isInDungeon() and self.m_showToastTimer < 0 then
Notify(MessageConst.SHOW_SPECIAL_TOAST, showText)
self.m_showToastTimer = self:_StartTimer(self.view.config.WARNING_TOAST_INTERVAL, function()
self:_ClearShowToastTimer()
end)
end
end
self.m_lastIsConsuming = isConsuming
self.m_lastPowerSavePercent = restPercent
end
FacMiniPowerContent._RefreshAnimState = HL.Method() << function(self)
if not string.isEmpty(self.m_lastPowerEnoughAnimName) then
self.view.powerEnoughAnim:PlayWithTween(self.m_lastPowerEnoughAnimName)
end
if not string.isEmpty(self.m_lastPowerSaveAnimName) then
self.view.powerSaveAnim:PlayWithTween(self.m_lastPowerSaveAnimName)
end
end
FacMiniPowerContent.InitFacMiniPowerContent = HL.Method(HL.Opt(HL.Number)) << function(self, chapterId)
self.m_chapterId = chapterId ~= nil and chapterId or -1
self.m_powerInfo = nil
self.view.powerNode.gameObject:SetActive(true)
self.view.powerSaveNode.gameObject:SetActive(true)
self.view.bandwidthNode.gameObject:SetActive(false)
self.view.buildingCountNode.gameObject:SetActive(false)
self:_UpdateAndRefreshAll(true)
self:_FirstTimeInit()
end
FacMiniPowerContent.SwitchFacMiniPowerContent = HL.Method(HL.String) << function(self, buildingItemId)
local data = FactoryUtils.getItemBuildingData(buildingItemId)
self.m_buildingData = data
local inBuildingMode = FactoryUtils.isInBuildMode()
local node = self.view
node.powerSaveNode.gameObject:SetActive(not inBuildingMode)
if not inBuildingMode or not data then
node.powerNode.gameObject:SetActive(true)
node.buildingCountNode.gameObject:SetActive(false)
node.bandwidthNode.gameObject:SetActive(false)
self:RefreshFacMiniPowerContent()
self:_RefreshAnimState()
return
end
local sceneMsg = FactoryUtils.getCurSceneHandler()
local buildingMode = GameInstance.remoteFactoryManager.interact.currentBuildingMode
local inFacMain = false
local bandwidth = nil
if buildingMode then
inFacMain = buildingMode.inMainRegion
local settlementId = buildingMode.settlementId
if settlementId ~= nil then
if settlementId == "" then
bandwidth = buildingMode.bandwidth
else
bandwidth = sceneMsg:GetSettlementBandwidth(settlementId)
end
end
end
local buildingCoundNodeActive = false
local max = 0
local cur = 0
local delta = 0
if data.type == GEnums.FacBuildingType.TravelPole and not inFacMain then
buildingCoundNodeActive = true
if bandwidth then
max = bandwidth.travelPoleMax
cur = bandwidth.travelPoleCurrent
end
if buildingMode then
delta = buildingMode.deltaTravelPoleCount
end
elseif data.type == GEnums.FacBuildingType.Battle and not inFacMain then
buildingCoundNodeActive = true
if bandwidth then
max = bandwidth.battleMax
cur = bandwidth.battleCurrent
end
if buildingMode then
delta = buildingMode.deltaBattleCount
end
elseif data.type == GEnums.FacBuildingType.Sign and not inFacMain then
buildingCoundNodeActive = true
max = Tables.factoryConst.signNodeCountLimit
cur = #FactoryUtils.getPlayerAllMarkerBuildingNodeInfo()
if buildingMode then
delta = buildingMode.isMoving and 0 or 1
else
delta = 0
end
elseif data.type == GEnums.FacBuildingType.BusFree then
buildingCoundNodeActive = true
local bus, source = GameInstance.remoteFactoryManager:GetFreeBusLimitsInfoInCoreZone()
max = bus
cur = GameInstance.remoteFactoryManager:GetBuildingCountInCurCoreZone(data.id)
if buildingMode then
delta = buildingMode.isMoving and 0 or 1
else
delta = 0
end
elseif data.type == GEnums.FacBuildingType.BusStart then
buildingCoundNodeActive = true
local bus, source = GameInstance.remoteFactoryManager:GetFreeBusLimitsInfoInCoreZone()
max = source
cur = GameInstance.remoteFactoryManager:GetBuildingCountInCurCoreZone(data.id)
if buildingMode then
delta = buildingMode.isMoving and 0 or 1
else
delta = 0
end
elseif data.type == GEnums.FacBuildingType.MachineCrafter and data.id == XIRANITE_BUILDINGID then
max = GameInstance.remoteFactoryManager:GetBuildingLimitsInChapter(data.id)
if max > 0 then
buildingCoundNodeActive = true
cur = GameInstance.remoteFactoryManager:GetBuildingCountInCurMap(data.id)
if buildingMode then
delta = buildingMode.isMoving and 0 or 1
else
delta = 0
end
end
end
local newCur = cur + delta
node.curBuildingCountTxt.text = newCur
node.curBuildingCountTxt.color = newCur > max and self.view.config.COUNT_NOT_ENOUGH_COLOR or self.view.config.COUNT_ENOUGH_COLOR
node.maxBuildingCountTxt.text = string.format("/%d", max)
if buildingCoundNodeActive then
self.view.buildingIcon:LoadSprite(UIConst.UI_SPRITE_MINI_POWER, BUILDING_ICON_MAP[data.type])
end
node.buildingCountNode.gameObject:SetActive(buildingCoundNodeActive)
if not inFacMain and data.bandwidth > 0 then
node.bandwidthNode.gameObject:SetActive(true)
local max = 0
local cur = 0
local delta
if bandwidth then
max = bandwidth.max
cur = bandwidth.current
end
if buildingMode then
delta = buildingMode.deltaBandwidth
end
local new = cur + delta
node.useBandwidthTxt.text = new
node.useBandwidthTxt.color = new > max and self.view.config.COUNT_NOT_ENOUGH_COLOR or self.view.config.COUNT_ENOUGH_COLOR
node.maxBandwidthTxt.text = string.format("/%d", max)
else
node.bandwidthNode.gameObject:SetActive(false)
end
node.powerNode.gameObject:SetActive(data.powerConsume > 0)
self:RefreshFacMiniPowerContent()
self:_RefreshAnimState()
end
FacMiniPowerContent.RefreshFacMiniPowerContent = HL.Method() << function(self)
if not self.m_powerData or not self.m_powerInfo then
return
end
if self.view.gameObject.activeSelf then
self:_RefreshContent()
end
if self.isMonitorPower then
self:_MonitorPower()
end
end
FacMiniPowerContent.ClearMemorizedPowerInfo = HL.Method() << function(self)
self.m_powerInfo = nil
end
FacMiniPowerContent.UpdateLackOfPowerAudio = HL.Method() << function(self)
if self.m_lackOfPowerAudioBaseTime < -0.01 then
return
end
local animLength = self.view.powerEnoughAnim:GetClipLength(self.m_lastPowerEnoughAnimName)
if animLength == 0 then
return
end
local curTime = CS.UnityEngine.Time.unscaledTime
local elapseTime = curTime - self.m_lackOfPowerAudioBaseTime
local normalizedElapseTime = elapseTime / animLength
if normalizedElapseTime > 1 then
if self.gameObject and self.gameObject.activeInHierarchy and self.m_powerInfo and GameInstance.remoteFactoryManager:IsPlayerPositionInMainRegion() then
AudioAdapter.PostEvent(self.m_powerInfo.powerSaveCurrent == 0 and "Au_UI_HUD_PowerShortage_NoPower" or "Au_UI_HUD_PowerShortage_LowPower")
end
end
self.m_lackOfPowerAudioBaseTime = self.m_lackOfPowerAudioBaseTime + math.floor(normalizedElapseTime) * animLength
end
HL.Commit(FacMiniPowerContent)
return FacMiniPowerContent