Skip to content
3 changes: 3 additions & 0 deletions gui/HP_AppearanceBindingsScreen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<Button profile="fs25_subCategorySelectorTabbedTab" id="managementTabs[2]" text="$l10n_hp_title_roster_manager" onClick="onClickOpenRosterManager">
<ThreePartBitmap profile="fs25_subCategorySelectorTabbedTabBg" name="background" />
</Button>
<Button profile="fs25_subCategorySelectorTabbedTab" id="managementTabs[3]" text="WORLD" onClick="onClickOpenWorldManager">
<ThreePartBitmap profile="fs25_subCategorySelectorTabbedTabBg" name="background" />
</Button>
</BoxLayout>
<ThreePartBitmap profile="fs25_lineSeparatorTopHighlighted" position="45px -119px" size="1105px 2px" />

Expand Down
3 changes: 3 additions & 0 deletions gui/HP_RosterManagerScreen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<Button profile="fs25_subCategorySelectorTabbedTab" id="managementTabs[2]" text="$l10n_hp_title_roster_manager" onClick="onClickRosterTab">
<ThreePartBitmap profile="fs25_subCategorySelectorTabbedTabBg" name="background" />
</Button>
<Button profile="fs25_subCategorySelectorTabbedTab" id="managementTabs[3]" text="WORLD" onClick="onClickOpenWorldManager">
<ThreePartBitmap profile="fs25_subCategorySelectorTabbedTabBg" name="background" />
</Button>
</BoxLayout>
<ThreePartBitmap profile="fs25_lineSeparatorTopHighlighted" position="45px -119px" size="1105px 2px" />

Expand Down
64 changes: 64 additions & 0 deletions gui/HP_WorldWorkerScreen.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<GUI onOpen="onOpen" onClose="onClose" onCreate="onCreate">
<Bitmap profile="dialogFullscreenBg" id="dialogBg" />
<GuiElement profile="fs25_dialogBg" id="dialogElement" size="1220px 700px">
<ThreePartBitmap profile="fs25_dialogBgMiddle" />
<ThreePartBitmap profile="fs25_dialogBgTop" />
<ThreePartBitmap profile="fs25_dialogBgBottom" />

<GuiElement profile="fs25_dialogContentContainer">
<Text profile="dialogTitle" text="Helper Management" id="dialogTitleElement" position="0px -30px" />

<BoxLayout profile="fs25_subCategorySelectorTabbedBox" id="managementTabBox" position="45px -72px" size="1105px 46px">
<Button profile="fs25_subCategorySelectorTabbedTab" id="managementTabs[1]" text="APPEARANCES" onClick="onClickAppearances">
<ThreePartBitmap profile="fs25_subCategorySelectorTabbedTabBg" name="background" />
</Button>
<Button profile="fs25_subCategorySelectorTabbedTab" id="managementTabs[2]" text="ROSTER" onClick="onClickRoster">
<ThreePartBitmap profile="fs25_subCategorySelectorTabbedTabBg" name="background" />
</Button>
<Button profile="fs25_subCategorySelectorTabbedTab" id="managementTabs[3]" text="WORLD" onClick="onClickWorldTab">
<ThreePartBitmap profile="fs25_subCategorySelectorTabbedTabBg" name="background" />
</Button>
</BoxLayout>
<ThreePartBitmap profile="fs25_lineSeparatorTopHighlighted" position="45px -119px" size="1105px 2px" />

<Bitmap profile="hpHeaderBox" id="worldHeaderBox" position="45px -135px" size="1105px 50px">
<Text profile="hpHeaderLeft" position="10px 0px" size="55px 40.77px" text="SLOT" />
<Text profile="hpHeaderLeft" position="75px 0px" size="260px 40.77px" text="WORKER" />
<Text profile="hpHeaderLeft" position="345px 0px" size="170px 40.77px" text="ROSTER" />
<Text profile="hpHeaderLeft" position="525px 0px" size="135px 40.77px" text="WORK" />
<Text profile="hpHeaderLeft" position="670px 0px" size="225px 40.77px" text="WORLD STATUS" />
<Text profile="hpHeaderLeft" position="905px 0px" size="185px 40.77px" text="POSITION X, Z" />
<ThreePartBitmap profile="fs25_lineSeparatorBottom" position="0px 2px" />
</Bitmap>

<SmoothList profile="hpList" id="worldTable" position="50px -190px" size="1095px 345px" focusInit="onOpen" focusChangeTop="nil" focusChangeBottom="nil">
<ListItem profile="hpListItem" name="worldRowTemplate" size="1095px 40.77px">
<Text profile="hpRowCellLeft" position="12px 0px" size="50px 40.77px" name="Slot" />
<Text profile="hpRowCellLeft" position="77px 0px" size="255px 40.77px" name="Worker" textLayoutMode="scrolling" />
<Text profile="hpRowCellLeft" position="347px 0px" size="165px 40.77px" name="RosterState" />
<Text profile="hpRowCellLeft" position="527px 0px" size="130px 40.77px" name="WorkState" />
<Text profile="hpRowCellLeft" position="672px 0px" size="220px 40.77px" name="WorldState" />
<Text profile="hpRowCellLeft" position="907px 0px" size="175px 40.77px" name="Position" />
</ListItem>
</SmoothList>

<ThreePartBitmap profile="fs25_listSliderBox" position="1155px -190px" size="12px 345px">
<Slider profile="fs25_listSlider" size="6px 337px" dataElementId="worldTable" id="worldSlider" />
</ThreePartBitmap>

<Bitmap profile="hpDetailBox" id="detailBox" position="45px -545px" size="1105px 110px">
<Text profile="hpMetaText" id="detailText" position="10px 8px" size="1085px 35px" text="Select a worker to manage their world presence." textLayoutMode="scrolling" />
<Text profile="hpMetaText" id="statusText" position="10px -38px" size="1085px 35px" text="Ready" textLayoutMode="scrolling" />
<ThreePartBitmap profile="fs25_lineSeparatorBottom" position="0px 2px" />
</Bitmap>
</GuiElement>

<BoxLayout profile="fs25_dialogButtonBox" size="1170px 60px">
<Button profile="buttonBack" text="CLOSE" onClick="onClickBack" />
<Button profile="buttonExtra1" text="PLACE HERE" onClick="onClickPlaceHere" />
<Button profile="hpButtonClearAll" text="MOVE HERE" onClick="onClickMoveHere" />
<Button profile="hpButtonClear" text="REMOVE" onClick="onClickRemove" />
</BoxLayout>
</GuiElement>
</GUI>
14 changes: 9 additions & 5 deletions scripts/HP_SlotRegistry.lua
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,14 @@ if HP_RosterState == nil and source ~= nil then
source((g_currentModDirectory or "") .. "scripts/HP_RosterState.lua")
end

-- Install the shared two-tab management controller early. It waits until both
-- Install the shared management controller early. It waits until the three
-- GUI screen classes are available before applying its lightweight wrappers.
if HP_TabbedManagement == nil and source ~= nil then
source((g_currentModDirectory or "") .. "scripts/HP_TabbedManagement.lua")
end

-- Alpha world-worker services are deliberately sourced from the stable slot
-- registry so the permanent A-T identity model is available before they load.
-- The runtime manager waits until the helper roster and appearance bridge are
-- ready before it restores any persisted world representations.
-- World-worker services are sourced from the stable slot registry so the
-- permanent A-T identity model is available before they load.
if HP_WorldState == nil and source ~= nil then
source((g_currentModDirectory or "") .. "scripts/HP_WorldState.lua")
end
Expand All @@ -162,3 +160,9 @@ end
if HP_WorldWorkerPlayerAccess == nil and source ~= nil then
source((g_currentModDirectory or "") .. "scripts/HP_WorldWorkerPlayerAccess.lua")
end
if HP_WorldWorkerScreen == nil and source ~= nil then
source((g_currentModDirectory or "") .. "scripts/HP_WorldWorkerScreen.lua")
end
if HP_WorldWorkerInput == nil and source ~= nil then
source((g_currentModDirectory or "") .. "scripts/HP_WorldWorkerInput.lua")
end
112 changes: 72 additions & 40 deletions scripts/HP_TabbedManagement.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-- HP_TabbedManagement.lua (FS25_HelperProfiles)
-- Presents the appearance-binding and roster-management dialogs as one
-- two-tab management workflow while preserving staged changes between tabs.
-- Presents appearance, roster and world-worker management dialogs as one
-- three-tab management workflow while preserving staged changes between tabs.

if HP_TabbedManagement ~= nil then return end

Expand All @@ -9,7 +9,8 @@ HP_TabbedManagement = {
sessionId = 0,
openFromTab = {
appearance = false,
roster = false
roster = false,
world = false
}
}

Expand All @@ -26,11 +27,8 @@ local function configureTabs(screen, activeIndex)
local background = tab.getDescendantByName ~= nil
and tab:getDescendantByName("background") or nil

if background ~= nil then
background.getIsSelected = function() return selected end
end
if background ~= nil then background.getIsSelected = function() return selected end end
tab.getIsSelected = function() return selected end

if tab.invalidateLayout ~= nil then tab:invalidateLayout() end
end
end
Expand All @@ -43,16 +41,13 @@ end

local function beginOpen(tabName, fromTab)
local isTabSwitch = fromTab == true
if not isTabSwitch then
HP_TabbedManagement.sessionId = HP_TabbedManagement.sessionId + 1
end
if not isTabSwitch then HP_TabbedManagement.sessionId = HP_TabbedManagement.sessionId + 1 end
HP_TabbedManagement.openFromTab[tabName] = isTabSwitch
end

local function shouldResume(screen, tabName)
local fromTab = HP_TabbedManagement.openFromTab[tabName] == true
HP_TabbedManagement.openFromTab[tabName] = false

return fromTab
and screen._hpTabbedDataLoaded == true
and screen._hpTabbedSessionId == HP_TabbedManagement.sessionId
Expand All @@ -63,6 +58,24 @@ local function markLoaded(screen)
screen._hpTabbedSessionId = HP_TabbedManagement.sessionId
end

local function openAppearance(screen)
if HP_AppearanceBindingsGui == nil or HP_AppearanceBindingsGui.open == nil then return end
screen:close()
HP_AppearanceBindingsGui:open(true)
end

local function openRoster(screen)
if HP_RosterManagerGui == nil or HP_RosterManagerGui.open == nil then return end
screen:close()
HP_RosterManagerGui:open(true)
end

local function openWorld(screen)
if HP_WorldWorkerGui == nil or HP_WorldWorkerGui.open == nil then return end
screen:close()
HP_WorldWorkerGui:open(true)
end

local function patchAppearanceScreen()
local screenClass = HP_AppearanceBindingsScreen
if screenClass == nil or screenClass._hpTabbedManagementPatched == true then return false end
Expand All @@ -81,26 +94,18 @@ local function patchAppearanceScreen()
self.reloadData = function() end
originalOpen(self, ...)
self.reloadData = originalReloadData

if self.reloadLists ~= nil then self:reloadLists() end
if self.updateDetailText ~= nil then self:updateDetailText() end
else
originalOpen(self, ...)
end

markLoaded(self)
configureTabs(self, 1)
end

function screenClass:onClickAppearanceTab(sender)
configureTabs(self, 1)
end

function screenClass:onClickOpenRosterManager(sender)
if HP_RosterManagerGui == nil or HP_RosterManagerGui.open == nil then return end
self:close()
HP_RosterManagerGui:open(true)
end
function screenClass:onClickAppearanceTab(sender) configureTabs(self, 1) end
function screenClass:onClickOpenRosterManager(sender) openRoster(self) end
function screenClass:onClickOpenWorldManager(sender) openWorld(self) end

screenClass._hpTabbedManagementPatched = true
return true
Expand All @@ -124,27 +129,44 @@ local function patchRosterScreen()
self.reloadData = function() end
originalOpen(self, ...)
self.reloadData = originalReloadData

if self.rosterTable ~= nil then self.rosterTable:reloadData() end
if self.updateDetailText ~= nil then self:updateDetailText() end
else
originalOpen(self, ...)
end

markLoaded(self)
configureTabs(self, 2)
end

function screenClass:onClickRosterTab(sender)
configureTabs(self, 2)
function screenClass:onClickRosterTab(sender) configureTabs(self, 2) end
function screenClass:onClickAppearances(sender) openAppearance(self) end
function screenClass:onClickOpenWorldManager(sender) openWorld(self) end

screenClass._hpTabbedManagementPatched = true
return true
end

local function patchWorldScreen()
local screenClass = HP_WorldWorkerScreen
if screenClass == nil or screenClass._hpTabbedManagementPatched == true then return false end

local originalSetup = screenClass.onGuiSetupFinished
function screenClass:onGuiSetupFinished(...)
originalSetup(self, ...)
configureTabs(self, 3)
end

function screenClass:onClickAppearances(sender)
if HP_AppearanceBindingsGui == nil or HP_AppearanceBindingsGui.open == nil then return end
self:close()
HP_AppearanceBindingsGui:open(true)
local originalOpen = screenClass.onOpen
function screenClass:onOpen(...)
originalOpen(self, ...)
markLoaded(self)
configureTabs(self, 3)
end

function screenClass:onClickWorldTab(sender) configureTabs(self, 3) end
function screenClass:onClickAppearances(sender) openAppearance(self) end
function screenClass:onClickRoster(sender) openRoster(self) end

screenClass._hpTabbedManagementPatched = true
return true
end
Expand Down Expand Up @@ -172,26 +194,36 @@ local function patchGuiManagers()
HP_RosterManagerGui._hpTabbedManagementPatched = true
end

return HP_AppearanceBindingsGui ~= nil
and HP_AppearanceBindingsGui._hpTabbedManagementPatched == true
and HP_RosterManagerGui ~= nil
and HP_RosterManagerGui._hpTabbedManagementPatched == true
if HP_WorldWorkerGui ~= nil
and HP_WorldWorkerGui._hpTabbedManagementPatched ~= true
and type(HP_WorldWorkerGui.open) == "function" then
local originalOpen = HP_WorldWorkerGui.open
function HP_WorldWorkerGui:open(fromTab)
beginOpen("world", fromTab)
return originalOpen(self)
end
HP_WorldWorkerGui._hpTabbedManagementPatched = true
end

return HP_AppearanceBindingsGui ~= nil and HP_AppearanceBindingsGui._hpTabbedManagementPatched == true
and HP_RosterManagerGui ~= nil and HP_RosterManagerGui._hpTabbedManagementPatched == true
and HP_WorldWorkerGui ~= nil and HP_WorldWorkerGui._hpTabbedManagementPatched == true
end

function HP_TabbedManagement:update(dt)
if self.installed then return end

local appearanceReady = patchAppearanceScreen()
or (HP_AppearanceBindingsScreen ~= nil
and HP_AppearanceBindingsScreen._hpTabbedManagementPatched == true)
or (HP_AppearanceBindingsScreen ~= nil and HP_AppearanceBindingsScreen._hpTabbedManagementPatched == true)
local rosterReady = patchRosterScreen()
or (HP_RosterManagerScreen ~= nil
and HP_RosterManagerScreen._hpTabbedManagementPatched == true)
or (HP_RosterManagerScreen ~= nil and HP_RosterManagerScreen._hpTabbedManagementPatched == true)
local worldReady = patchWorldScreen()
or (HP_WorldWorkerScreen ~= nil and HP_WorldWorkerScreen._hpTabbedManagementPatched == true)
local managersReady = patchGuiManagers()

if appearanceReady and rosterReady and managersReady then
if appearanceReady and rosterReady and worldReady and managersReady then
self.installed = true
hpPrint("Two-tab helper management workflow installed")
hpPrint("Three-tab helper management workflow installed")
end
end

Expand Down
Loading