Files
Endfield-Data/LuaScripts/UI/Panels/SpaceshipStation/SpaceshipStationCtrl.lua
2026-01-31 21:42:01 +07:00

742 lines
23 KiB
Lua

local uiCtrl = require_ex('UI/Panels/Base/UICtrl')
local PANEL_ID = PanelId.SpaceshipStation
SpaceshipStationCtrl = HL.Class('SpaceshipStationCtrl', uiCtrl.UICtrl)
SpaceshipStationCtrl.s_messages = HL.StaticField(HL.Table) << {
[MessageConst.SPACESHIP_ON_SET_ROOM_STATION_SUCC] = 'OnSetRoomStationSucc',
[MessageConst.ON_SPACESHIP_HEAD_NAVI_TARGET_CHANGE] = 'OnHeadCellNaviTargetChange',
}
SpaceshipStationCtrl.m_roomId = HL.Field(HL.String) << ''
SpaceshipStationCtrl.m_isControlCenter = HL.Field(HL.Boolean) << false
SpaceshipStationCtrl.m_charEffectCells = HL.Field(HL.Forward('UIListCache'))
SpaceshipStationCtrl.m_getCharCell = HL.Field(HL.Function)
SpaceshipStationCtrl.m_maxStationCharNum = HL.Field(HL.Number) << -1
SpaceshipStationCtrl.m_maxLvStationCharNum = HL.Field(HL.Number) << -1
SpaceshipStationCtrl.m_isScrollInit = HL.Field(HL.Boolean) << true
SpaceshipStationCtrl.m_skillNodes = HL.Field(HL.Table)
SpaceshipStationCtrl.m_nowNaviHeadCell = HL.Field(HL.Userdata)
SpaceshipStationCtrl.OnCreate = HL.Override(HL.Any) << function(self, arg)
self.view.closeBtn.onClick:AddListener(function()
PhaseManager:PopPhase(PhaseId.SpaceshipStation)
end)
self.view.confirmBtn.onClick:AddListener(function()
self:_OnClickConfirm()
end)
self.view.resetBtn.onClick:AddListener(function()
self:_OnClickReset()
end)
local roomId = arg.roomId
self.m_roomId = roomId
self.m_isControlCenter = roomId == Tables.spaceshipConst.controlCenterRoomId
self:_InitFilter()
self:_InitSort()
self.m_getCharCell = UIUtils.genCachedCellFunction(self.view.charScrollList)
self:BindInputPlayerAction("ss_char_detail", function()
if self.m_nowNaviHeadCell then
self.m_nowNaviHeadCell:ShowTips()
end
end)
self.view.charScrollList.onUpdateCell:AddListener(function(obj, csIndex)
self:_OnUpdateCell(self.m_getCharCell(obj), LuaIndex(csIndex))
end)
self.view.charScrollList.getCellName = function(csIndex)
local charInfo = self.m_curCharInfos[LuaIndex(csIndex)]
return "Char-" .. charInfo.id
end
self.m_charEffectCells = UIUtils.genCellCache(self.view.charEffectCell)
local spaceship = GameInstance.player.spaceship
local room = spaceship.rooms:get_Item(roomId)
self.m_maxStationCharNum = room.maxStationCharNum
self.m_maxLvStationCharNum = room.maxLvStationCount
local roomType = SpaceshipUtils.getRoomTypeByRoomId(roomId)
local roomTypeData = Tables.spaceshipRoomTypeTable[roomType]
self.view.nameTxt.text = roomTypeData.name
self.view.bigBgIcon:LoadSprite(UIConst.UI_SPRITE_SPACESHIP_ROOM, roomTypeData.bg .. "_shallow")
local color = UIUtils.getColorByString(roomTypeData.color)
self.view.colorBg.color = color
self.view.colorDeco.color = color
self.view.colorDeco.gameObject:SetActive(true)
self.view.lvDotNode:InitLvDotNode(room.lv, spaceship:GetRoomMaxLvByType(room.type), color)
self:_UpdateCharacters()
self:_UpdateStationInfos()
self:BindInputPlayerAction("ss_char_skill_detail",function()
if self.m_skillNodes then
for i, v in pairs(self.m_skillNodes) do
v:TriggerSkillHint()
end
end
end)
self.view.controllerHintPlaceholder:InitControllerHintPlaceholder({self.view.inputGroup.groupId})
end
SpaceshipStationCtrl.OnHeadCellNaviTargetChange = HL.Method(HL.Opt(HL.Userdata)) << function(self, cell)
self.m_nowNaviHeadCell = cell
self:_OnCellSelectedChanged(cell.m_charId, cell.view.button)
end
SpaceshipStationCtrl._OnCellSelectedChanged = HL.Method(HL.String, HL.Any) << function(self, charId, target)
local chosenIndex = lume.find(self.m_chosenCharIdList, charId)
if chosenIndex then
InputManagerInst:SetBindingText(target.hoverConfirmBindingId, Language.key_hint_common_unselect)
else
InputManagerInst:SetBindingText(target.hoverConfirmBindingId, Language.key_hint_common_select)
end
end
SpaceshipStationCtrl.m_filterTags = HL.Field(HL.Table)
local FilterType = {
Skill = 1,
WorkState = 2,
}
SpaceshipStationCtrl._InitFilter = HL.Method() << function(self)
local inited = false
local filterTagGroups = {
{
title = Language.LUA_SPACESHIP_FILTER_TITLE_SKILL,
tags = {},
},
{
title = Language.LUA_SPACESHIP_FILTER_TITLE_WORK_STATE,
tags = {
{
name = Language.LUA_SPACESHIP_FILTER_TITLE_WORK_STATE_NONE,
type = FilterType.WorkState,
isWorking = false,
isResting = false,
},
{
name = Language.LUA_SPACESHIP_FILTER_TITLE_WORK_STATE_RESTING,
type = FilterType.WorkState,
isWorking = false,
isResting = true,
},
{
name = Language.LUA_SPACESHIP_FILTER_TITLE_WORK_STATE_WORKING,
type = FilterType.WorkState,
isWorking = true,
isResting = false,
},
},
},
}
for t, v in pairs(Tables.spaceshipRoomTypeTable) do
table.insert(filterTagGroups[1].tags, {
name = v.name,
type = FilterType.Skill,
roomType = GEnums.SpaceshipRoomType.__CastFrom(t),
order = t,
})
end
table.sort(filterTagGroups[1].tags, Utils.genSortFunction({"order"}, true))
self.m_filterTags = nil
self.view.filterBtn:InitFilterBtn({
tagGroups = filterTagGroups,
onConfirm = function(tags)
if not inited then
return
end
self:_ApplyFilter(tags)
end,
getResultCount = function(tags)
return self:_GetContentFilterResultCount(tags)
end,
sortNodeWidget = self.view.sortNode,
})
inited = true
end
SpaceshipStationCtrl._ApplyFilter = HL.Method(HL.Opt(HL.Table)) << function(self, tags)
self.m_filterTags = tags
self:_GenCurCharInfos()
self:_UpdateCharacters(true)
end
SpaceshipStationCtrl._IsFilterValid = HL.Method(HL.Table, HL.Opt(HL.Table)).Return(HL.Boolean) << function(self, info, tags)
tags = tags or self.m_filterTags
if not tags then
return true
end
local groups = {}
for _, v in ipairs(tags) do
local list = groups[v.type]
if not list then
list = {}
groups[v.type] = list
end
table.insert(list, v)
end
for _, list in pairs(groups) do
local isPass
for _, v in ipairs(list) do
if v.type == FilterType.Skill then
if info.char:HasSkillForRoom(v.roomType) then
isPass = true
break
end
elseif v.type == FilterType.WorkState then
if v.isWorking == info.char.isWorking and v.isResting == info.char.isResting then
isPass = true
break
end
end
end
if not isPass then
return false
end
end
return true
end
SpaceshipStationCtrl._GetContentFilterResultCount = HL.Method(HL.Table).Return(HL.Number) << function(self, tags)
local count = 0
for _, v in ipairs(self.m_allCharInfos) do
if self:_IsFilterValid(v, tags) then
count = count + 1
end
end
return count
end
SpaceshipStationCtrl._InitSort = HL.Method() << function(self)
local sortOptions = {
{
name = Language.LUA_SPACESHIP_CHAR_SORT_DEFAULT,
decKeys = { "chosenSortId", "isCurRoomSortId", "workingStateSortId", "stamina", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "id" },
incKeys = { "reverseChosenSortId", "isCurRoomSortId", "workingStateSortId", "stamina", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "id" },
},
{
name = Language.LUA_SPACESHIP_CHAR_SORT_STAMINA,
decKeys = { "chosenSortId", "stamina", "isCurRoomSortId", "workingStateSortId", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "id" },
incKeys = { "reverseChosenSortId", "stamina", "isCurRoomSortId", "workingStateSortId", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "id" },
},
{
name = Language.LUA_SPACESHIP_CHAR_SORT_SKILL,
decKeys = { "chosenSortId", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "isCurRoomSortId", "workingStateSortId", "stamina", "id" },
incKeys = { "reverseChosenSortId", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "isCurRoomSortId", "workingStateSortId", "stamina", "id" },
},
{
name = Language.LUA_SPACESHIP_CHAR_SORT_WORKING_STATE,
decKeys = { "chosenSortId", "workingStateSortId", "stamina", "isCurRoomSortId", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "id" },
incKeys = { "reverseChosenSortId", "workingStateSortId", "stamina", "isCurRoomSortId", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "id" },
},
}
if self.m_isControlCenter then
table.insert(sortOptions, {
name = Language.LUA_SPACESHIP_CHAR_SORT_FRIENDSHIP,
decKeys = { "chosenSortId", "friendship", "isCurRoomSortId", "workingStateSortId", "stamina", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "id" },
incKeys = { "reverseChosenSortId", "friendship", "isCurRoomSortId", "workingStateSortId", "stamina", "validSkillCount", "validSkillCountIgnoreUnlock", "maxSkillSortId", "id" },
showFriendship = true,
})
end
self.view.sortNode:InitSortNode(sortOptions, function(data, isIncremental)
self:_ApplySortOption(data, isIncremental, true)
end, 0, nil, true, self.view.filterBtn)
end
SpaceshipStationCtrl._ApplySortOption = HL.Method(HL.Opt(HL.Table, HL.Boolean, HL.Boolean)) << function(self, sortData, isIncremental, needUpdateList)
sortData = sortData or self.view.sortNode:GetCurSortData()
if isIncremental == nil then
isIncremental = self.view.sortNode.isIncremental
end
local spaceship = GameInstance.player.spaceship
for _, info in ipairs(self.m_curCharInfos) do
local chosenIndex = lume.find(self.m_chosenCharIdList, info.id)
if chosenIndex then
info.chosenSortId = math.maxinteger - chosenIndex
info.reverseChosenSortId = -info.chosenSortId
else
info.chosenSortId = 0
info.reverseChosenSortId = 0
end
info.friendship = info.char.friendship
info.stamina = spaceship:GetCharCurStamina(info.id)
info.isCurRoomSortId = info.char.stationedRoomId == self.m_roomId and 1 or 0
if string.isEmpty(info.char.stationedRoomId) then
info.workingStateSortId = 1
else
info.workingStateSortId = info.char.isWorking and -1 or 0
end
end
local keys = isIncremental and sortData.incKeys or sortData.decKeys
table.sort(self.m_curCharInfos, Utils.genSortFunction(keys, isIncremental))
self.m_showFriendship = keys.showFriendship == true
self.m_curCharInfoReverseMap = {}
for k, v in ipairs(self.m_curCharInfos) do
self.m_curCharInfoReverseMap[v.id] = k
end
if needUpdateList then
self.m_isScrollInit = true
self.view.charScrollList:UpdateCount(#self.m_curCharInfos)
end
end
SpaceshipStationCtrl.m_allCharInfos = HL.Field(HL.Table)
SpaceshipStationCtrl.m_allCharInfoReverseMap = HL.Field(HL.Table)
SpaceshipStationCtrl.m_curCharInfos = HL.Field(HL.Table)
SpaceshipStationCtrl.m_curCharInfoReverseMap = HL.Field(HL.Table)
SpaceshipStationCtrl.m_chosenCharIdList = HL.Field(HL.Table)
SpaceshipStationCtrl._GenAllCharInfos = HL.Method() << function(self)
self.m_allCharInfos = {}
self.m_chosenCharIdList = {}
self.m_allCharInfoReverseMap = {}
local spaceship = GameInstance.player.spaceship
local room = spaceship.rooms:get_Item(self.m_roomId)
local roomType = room.type
for _, id in pairs(room.stationedCharList) do
table.insert(self.m_chosenCharIdList, id)
end
local index = 1
for id, char in pairs(spaceship.characters) do
local info = {
id = id,
char = char,
validSkillCount = 0,
validSkillCountIgnoreUnlock = 0,
maxSkillSortId = math.mininteger,
}
local haveData, charSkillData = Tables.spaceshipCharSkillTable:TryGetValue(id)
if haveData then
for _, v in pairs(charSkillData.skillList) do
local skillId = v.skillId
local skillData = Tables.spaceshipSkillTable[skillId]
if skillData.roomType == roomType then
info.validSkillCountIgnoreUnlock = info.validSkillCountIgnoreUnlock + 1
if char.skills:ContainsValue(skillId) then
info.validSkillCount = info.validSkillCount + 1
end
if skillData.sortId > info.maxSkillSortId then
info.maxSkillSortId = skillData.sortId
end
end
end
end
self.m_allCharInfos[index] = info
self.m_allCharInfoReverseMap[id] = index
index = index + 1
end
end
SpaceshipStationCtrl._GenCurCharInfos = HL.Method() << function(self)
self.m_curCharInfos = {}
for _, v in ipairs(self.m_allCharInfos) do
if self:_IsFilterValid(v) then
table.insert(self.m_curCharInfos, v)
end
end
self:_ApplySortOption()
end
SpaceshipStationCtrl.m_showFriendship = HL.Field(HL.Boolean) << false
SpaceshipStationCtrl._UpdateCharacters = HL.Method(HL.Opt(HL.Boolean)) << function(self, notGen)
if not notGen then
self:_GenAllCharInfos()
self:_GenCurCharInfos()
end
local count = #self.m_curCharInfos
self.m_isScrollInit = true
self.view.charScrollList:UpdateCount(count)
self.view.charListEmptyNode.gameObject:SetActive(count == 0)
end
SpaceshipStationCtrl._OnUpdateCell = HL.Method(HL.Forward("SSCharHeadCell"), HL.Number) << function(self, cell, index)
local indexOfLineHead = index - ((index - 1) % self.view.charScrollList.countPerLine)
local contentScreenRect = UIUtils.getUIRectOfRectTransform(self.view.content, self.uiCamera)
local charInfo = self.m_curCharInfos[index]
cell:InitSSCharHeadCell({
charId = charInfo.id,
targetRoomId = self.m_roomId,
onClick = function()
self:_OnClickChar(index)
self:_OnCellSelectedChanged(self.m_curCharInfos[index].id, cell.view.button)
end,
groupId = self.view.inputGroup.groupId,
padding = {
bottom = self.view.transform.rect.height - contentScreenRect.yMax,
left = self.view.charListNode.rect.width + contentScreenRect.x * 2
},
})
self:_UpdateCharCellChooseState(charInfo.id, cell)
local chosenIndex = lume.find(self.m_chosenCharIdList, charInfo.id)
cell:SetChooseState(chosenIndex)
local showFriendship = self.m_isControlCenter or self.m_showFriendship
cell.view.friendshipNode.gameObject:SetActive(showFriendship)
if index == 1 and self.m_isScrollInit then
InputManagerInst.controllerNaviManager:SetTarget(cell.view.button)
self.m_isScrollInit = false
self:OnHeadCellNaviTargetChange(cell)
end
end
SpaceshipStationCtrl._UpdateCharChooseState = HL.Method(HL.String) << function(self, charId)
local index = self.m_curCharInfoReverseMap[charId]
if not index then
return
end
local cell = self.m_getCharCell(index)
if cell then
self:_UpdateCharCellChooseState(charId, cell)
end
end
SpaceshipStationCtrl._UpdateCharCellChooseState = HL.Method(HL.String, HL.Forward("SSCharHeadCell")) << function(self, charId, cell)
local chosenIndex = lume.find(self.m_chosenCharIdList, charId)
cell:SetChooseState(chosenIndex)
end
SpaceshipStationCtrl._OnClickChar = HL.Method(HL.Number) << function(self, index)
local charInfo = self.m_curCharInfos[index]
self:_ToggleChooseChar(charInfo.id)
end
SpaceshipStationCtrl._UpdateStationInfos = HL.Method() << function(self)
local spaceship = GameInstance.player.spaceship
local room = spaceship.rooms:get_Item(self.m_roomId)
local roomLvTable = SpaceshipUtils.getRoomLvTableByType(room.type)
local roomTypeData = Tables.spaceshipRoomTypeTable[room.type]
local attrs = SpaceshipUtils.preCalcRoomAttrs(self.m_roomId, self.m_chosenCharIdList)
self.view.ssRoomEffectInfoNode:InitSSRoomEffectInfoNode({
attrInfoList = attrs,
color = UIUtils.getColorByString(roomTypeData.color),
})
local contentScreenRect = UIUtils.getUIRectOfRectTransform(self.view.content, self.uiCamera)
local padding = {
bottom = self.view.transform.rect.height - contentScreenRect.yMax,
right = self.view.charEffectNode.rect.width - self.view.effectPadding.rect.width + contentScreenRect.x
}
self.m_skillNodes = {}
self.m_charEffectCells:Refresh(self.m_maxLvStationCharNum, function(cell, index)
local charId = self.m_chosenCharIdList[index]
cell.gameObject.name = "Cell-" .. index
cell.indexTxt.text = index
local isEmpty = string.isEmpty(charId)
local isLocked = index > self.m_maxStationCharNum
if isEmpty then
if isLocked then
local needLv
for k = room.lv + 1, room.maxLv do
local roomLvData = roomLvTable[k]
if roomLvData.stationMaxCount >= index then
needLv = k
break
end
end
cell.lockedTxt.text = string.format(Language.LUA_SPACESHIP_ROOM_UNLOCK_STATION_HINT, roomTypeData.name, needLv)
cell.simpleStateController:SetState("Locked")
else
cell.simpleStateController:SetState("Empty")
end
else
cell.simpleStateController:SetState("Normal")
cell.headCell:InitSSCharHeadCell({
charId = charId,
targetRoomId = self.m_roomId,
onClick = function()
cell.headCell:ShowTips()
end,
padding = padding,
})
cell.headCell.view.friendshipNode.gameObject:SetActive(self.m_isControlCenter)
cell.charSkillNode:InitSSCharSkillNode(charId, self.m_roomId, true)
table.insert(self.m_skillNodes, cell.charSkillNode)
cell.delBtn.onClick:RemoveAllListeners()
cell.delBtn.onClick:AddListener(function()
self:_ToggleChooseChar(charId)
end)
if not cell.warnCells then
cell.warnCells = UIUtils.genCellCache(cell.skillEffectWarnCell)
end
local warnTextList = {}
local char = spaceship.characters:get_Item(charId)
if not string.isEmpty(char.stationedRoomId) and char.stationedRoomId ~= self.m_roomId then
local roomType = SpaceshipUtils.getRoomTypeByRoomId(char.stationedRoomId)
local data = Tables.spaceshipRoomTypeTable[roomType]
table.insert(warnTextList, {
state = "InOtherRoom",
text = Language.LUA_SPACESHIP_CHAR_STATION_WARNING_LEAVE_ROOM,
roomColor = SpaceshipUtils.getRoomColor(char.stationedRoomId),
roomName = data.name
})
end
local info = self.m_allCharInfos[self.m_allCharInfoReverseMap[charId]]
if info.validSkillCount == 0 then
table.insert(warnTextList, {
state = "NoSkill",
text = Language.LUA_SPACESHIP_CHAR_STATION_WARNING_NO_SKILL,
})
end
if not string.isEmpty(char.stationedRoomId) and not char.isWorking then
table.insert(warnTextList, {
state = "IsResting",
text = Language.LUA_SPACESHIP_CHAR_STATION_WARNING_REST,
})
end
cell.warnCells:Refresh(#warnTextList, function(warnCell, warnIndex)
local warnInfo = warnTextList[warnIndex]
warnCell.simpleStateController:SetState(warnInfo.state)
warnCell.text.text = warnInfo.text
if warnInfo.roomName then
warnCell.roomBG.gameObject:SetActive(true)
warnCell.roomBG.color = warnInfo.roomColor
warnCell.roomName.text = warnInfo.roomName
else
warnCell.roomBG.gameObject:SetActive(false)
end
end)
end
end)
local curCount = #self.m_chosenCharIdList
self.view.stationCountDotNode:InitLvDotNode(curCount, self.m_maxStationCharNum)
self.view.stationCountTxt.text = string.format(Language.LUA_SPACESHIP_STATION_CHAR_COUNT_FORMAT, curCount, self.m_maxStationCharNum)
end
SpaceshipStationCtrl._ToggleChooseChar = HL.Method(HL.String) << function(self, charId)
local chosenIndex = lume.find(self.m_chosenCharIdList, charId)
if chosenIndex then
table.remove(self.m_chosenCharIdList, chosenIndex)
self:_UpdateCharChooseState(charId)
for _, v in ipairs(self.m_chosenCharIdList) do
self:_UpdateCharChooseState(v)
end
else
local curCount = #self.m_chosenCharIdList
if curCount >= self.m_maxStationCharNum then
Notify(MessageConst.SHOW_TOAST, Language.LUA_SPACESHIP_STATION_CHAR_MAX)
return
end
table.insert(self.m_chosenCharIdList, charId)
self:_UpdateCharChooseState(charId)
Utils.triggerVoice("sim_assign_work", charId)
end
self:_UpdateStationInfos()
end
SpaceshipStationCtrl._OnClickReset = HL.Method() << function(self)
local oldChars = self.m_chosenCharIdList
self.m_chosenCharIdList = {}
for _, v in ipairs(oldChars) do
self:_UpdateCharChooseState(v)
end
self:_UpdateStationInfos()
end
SpaceshipStationCtrl.OnSetRoomStationSucc = HL.Method(HL.Table) << function(self, _)
PhaseManager:PopPhase(PhaseId.SpaceshipStation)
end
SpaceshipStationCtrl._OnClickConfirm = HL.Method() << function(self)
local spaceship = GameInstance.player.spaceship
local room = spaceship.rooms:get_Item(self.m_roomId)
local notChanged = #self.m_chosenCharIdList == room.stationedCharList.Count
if notChanged then
for k, id in pairs(room.stationedCharList) do
if self.m_chosenCharIdList[LuaIndex(k)] ~= id then
notChanged = false
break
end
end
end
if notChanged then
PhaseManager:PopPhase(PhaseId.SpaceshipStation)
return
end
GameInstance.player.spaceship:SetRoomStation(self.m_roomId, self.m_chosenCharIdList)
end
HL.Commit(SpaceshipStationCtrl)