diff --git a/l10n/l10n_de.xml b/l10n/l10n_de.xml
index d8fab79..af5bf4f 100644
--- a/l10n/l10n_de.xml
+++ b/l10n/l10n_de.xml
@@ -52,6 +52,14 @@
+
+
+
+
+
+
+
+
diff --git a/l10n/l10n_en.xml b/l10n/l10n_en.xml
index fd00485..0164034 100644
--- a/l10n/l10n_en.xml
+++ b/l10n/l10n_en.xml
@@ -52,6 +52,14 @@
+
+
+
+
+
+
+
+
diff --git a/l10n/l10n_fr.xml b/l10n/l10n_fr.xml
index ec7c1e6..39da2b4 100644
--- a/l10n/l10n_fr.xml
+++ b/l10n/l10n_fr.xml
@@ -52,6 +52,14 @@
+
+
+
+
+
+
+
+
diff --git a/modDesc.xml b/modDesc.xml
index 306aee1..86aec33 100644
--- a/modDesc.xml
+++ b/modDesc.xml
@@ -11,10 +11,14 @@
+
diff --git a/scripts/HP_AppearanceMenu.lua b/scripts/HP_AppearanceMenu.lua
index a2348a3..c868c4e 100644
--- a/scripts/HP_AppearanceMenu.lua
+++ b/scripts/HP_AppearanceMenu.lua
@@ -219,6 +219,10 @@ function HP_AppearanceMenu:syncSelectionFromDraft()
end
function HP_AppearanceMenu:open()
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then
+ hpamPrint("Appearance menu unavailable: Hired Helper Tool is active and HelperProfiles is disabled.")
+ return false
+ end
self:init()
if HP_ASBridge ~= nil and HP_ASBridge.reload ~= nil then HP_ASBridge:reload() end
self:buildDraftFromBridge()
diff --git a/scripts/HP_Compatibility.lua b/scripts/HP_Compatibility.lua
new file mode 100644
index 0000000..8aa7b1a
--- /dev/null
+++ b/scripts/HP_Compatibility.lua
@@ -0,0 +1,76 @@
+-- HP_Compatibility.lua (FS25_HelperProfiles)
+-- Central runtime guard for helper-roster mods that cannot safely coexist.
+
+HP_Compatibility = HP_Compatibility or {
+ checked = false,
+ blocked = false,
+ conflictMod = nil,
+ warningLogged = false
+}
+
+local LOG = "[FS25_HelperProfiles/Compatibility] "
+local CONFLICT_NAMES = {"FS25_HiredHelperTool", "HiredHelperTool"}
+
+local function isLoadedByName(name)
+ local loaded = rawget(_G, "g_modIsLoaded")
+ if type(loaded) == "table" and loaded[name] == true then
+ return true
+ end
+
+ if g_modManager ~= nil and type(g_modManager.getModByName) == "function" then
+ local ok, mod = pcall(g_modManager.getModByName, g_modManager, name)
+ if ok and type(mod) == "table" then
+ return mod.isLoaded == true or mod.isActive == true or mod.isSelected == true
+ end
+ end
+
+ return false
+end
+
+function HP_Compatibility:detect()
+ self.checked = true
+ self.blocked = false
+ self.conflictMod = nil
+
+ for _, name in ipairs(CONFLICT_NAMES) do
+ if isLoadedByName(name) then
+ self.blocked = true
+ self.conflictMod = name
+ break
+ end
+ end
+
+ if self.blocked and not self.warningLogged then
+ self.warningLogged = true
+ print(LOG .. "HelperProfiles disabled for this session: incompatible mod detected (" .. tostring(self.conflictMod) .. "). Disable either HelperProfiles or Hired Helper Tool and reload the save.")
+ end
+
+ return self.blocked
+end
+
+function HP_Compatibility:isBlocked()
+ if not self.checked then
+ self:detect()
+ end
+ return self.blocked == true
+end
+
+function HP_Compatibility:getReason()
+ if not self:isBlocked() then return nil end
+ return "incompatible-helper-roster-mod:" .. tostring(self.conflictMod or "unknown")
+end
+
+function HP_Compatibility:loadMap()
+ self.checked = false
+ self.warningLogged = false
+ self:detect()
+end
+
+function HP_Compatibility:deleteMap()
+ self.checked = false
+ self.blocked = false
+ self.conflictMod = nil
+ self.warningLogged = false
+end
+
+addModEventListener(HP_Compatibility)
diff --git a/scripts/HP_RosterExpansion.lua b/scripts/HP_RosterExpansion.lua
index b8368ff..06ca2d0 100644
--- a/scripts/HP_RosterExpansion.lua
+++ b/scripts/HP_RosterExpansion.lua
@@ -67,22 +67,6 @@ local function getByIndex(manager, index)
return manager.indexToHelper ~= nil and manager.indexToHelper[index] or nil
end
-local function isKnownExternalExpansionLoaded()
- local loaded = rawget(_G, "g_modIsLoaded")
- if type(loaded) == "table" then
- if loaded.FS25_HiredHelperTool == true or loaded.HiredHelperTool == true then return true end
- end
- if g_modManager ~= nil and type(g_modManager.getModByName) == "function" then
- for _, name in ipairs({"FS25_HiredHelperTool", "HiredHelperTool"}) do
- local ok, mod = pcall(g_modManager.getModByName, g_modManager, name)
- if ok and type(mod) == "table" and (mod.isLoaded == true or mod.isActive == true or mod.isSelected == true) then
- return true
- end
- end
- end
- return false
-end
-
local function invalidateRosterCache()
if HelperProfiles ~= nil then
HelperProfiles._defaultOrderRefs = nil
@@ -110,11 +94,11 @@ function HP_RosterExpansion:tryExpand(reason)
local manager = g_helperManager
local before = getCount(manager)
- if isKnownExternalExpansionLoaded() then
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then
self.completed = true
- self.result = "external-expansion-mod"
+ self.result = "blocked-incompatible-mod"
invalidateRosterCache()
- log("Known external helper expansion detected; no helpers injected: reason=%s helpers=%d", tostring(reason), before)
+ log("HelperProfiles roster disabled because Hired Helper Tool is active: reason=%s helpers=%d", tostring(reason), before)
return true
end
diff --git a/scripts/HP_UI.lua b/scripts/HP_UI.lua
index f0a2296..1d297a8 100644
--- a/scripts/HP_UI.lua
+++ b/scripts/HP_UI.lua
@@ -140,7 +140,13 @@ end
-- ===== Public configuration setters =========================================
function HP_UI:setVisible(value) self.visible = value and true or false end
-function HP_UI:toggle() self.visible = not self.visible end
+function HP_UI:toggle()
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then
+ self.visible = false
+ return
+ end
+ self.visible = not self.visible
+end
function HP_UI:setAnchor(anchor)
anchor = string.upper(anchor or "")
diff --git a/scripts/HP_WorkerAppearance.lua b/scripts/HP_WorkerAppearance.lua
index 734fbe5..3873784 100644
--- a/scripts/HP_WorkerAppearance.lua
+++ b/scripts/HP_WorkerAppearance.lua
@@ -320,6 +320,7 @@ function HP_WorkerAppearance:installHooks()
end
function HP_WorkerAppearance:update(dt)
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then return end
self.scanTimer = (self.scanTimer or 0) + (dt or 0)
if self.scanTimer >= 1000 then
self.scanTimer = 0
@@ -329,6 +330,10 @@ function HP_WorkerAppearance:update(dt)
end
function HP_WorkerAppearance:loadMap()
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then
+ hpwaPrint("Disabled because Hired Helper Tool is active.")
+ return
+ end
self:installHooks()
self:patchLoadedVehicles()
end
diff --git a/scripts/HelperProfiles.lua b/scripts/HelperProfiles.lua
index 8019c31..8d6b5e0 100644
--- a/scripts/HelperProfiles.lua
+++ b/scripts/HelperProfiles.lua
@@ -125,6 +125,7 @@ end
-- Once the idle managed roster order has been cached, keep returning that complete roster
-- even while GIANTS removes active workers from availableHelpers.
function HelperProfiles:getProfiles()
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then return {} end
local available = _getHelpersRaw()
-- Only establish the stable managed roster while every helper is idle.
@@ -429,6 +430,10 @@ end
-- Expecting FS25 style callback with key status (1 on press).
function HelperProfiles:onCycleAction(actionName, keyStatus)
if keyStatus ~= 1 then return end -- press only
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then
+ self:_flash(hpI18n("hp_incompatible_hired_helper_tool", "HelperProfiles is disabled because Hired Helper Tool is active."), 2.5)
+ return
+ end
self:cycleSelectionDebounced(1)
end
@@ -511,6 +516,7 @@ end
-- FS lifecycle
----------------------------------------------------------------------
function HelperProfiles:update(dt)
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then return end
if not HelperProfiles._hooksDone then
hookOnce()
end
diff --git a/scripts/RegisterPlayerActionEvents.lua b/scripts/RegisterPlayerActionEvents.lua
index 6993735..63aaefe 100644
--- a/scripts/RegisterPlayerActionEvents.lua
+++ b/scripts/RegisterPlayerActionEvents.lua
@@ -97,16 +97,16 @@ end
local function _registerPlayerAction(field, inputAction, target, callback, label)
if HelperProfiles[field] ~= nil then return end
if g_inputBinding == nil or inputAction == nil then
- print(LOG .. "❌ Failed to register " .. tostring(label) .. " (player): input action unavailable")
+ print(LOG .. "Failed to register " .. tostring(label) .. " (player): input action unavailable")
return
end
local ok, id = g_inputBinding:registerActionEvent(inputAction, target, callback, false, true, false, true)
if ok and id then
HelperProfiles[field] = id
_setActionEventLowPriority(id, true)
- print(LOG .. "✅ Registered " .. tostring(label) .. " (player)")
+ print(LOG .. "Registered " .. tostring(label) .. " (player)")
else
- print(LOG .. "❌ Failed to register " .. tostring(label) .. " (player)")
+ print(LOG .. "Failed to register " .. tostring(label) .. " (player)")
end
end
@@ -160,27 +160,27 @@ end
local function _addVehicleAction(vehicle, spec, inputAction, target, callback, label, loggedFlagName)
if inputAction == nil then
- print(LOG .. "❌ Failed to register " .. tostring(label) .. " (vehicle): input action unavailable")
+ print(LOG .. "Failed to register " .. tostring(label) .. " (vehicle): input action unavailable")
return nil
end
local _, id = vehicle:addActionEvent(spec.actionEvents, inputAction, target, callback, false, true, false, true)
if id ~= nil then
_setActionEventLowPriority(id, true)
if loggedFlagName == "cycle" and not _loggedVehicleCycle then
- print(LOG .. "✅ Registered " .. tostring(label) .. " (vehicle)")
+ print(LOG .. "Registered " .. tostring(label) .. " (vehicle)")
_loggedVehicleCycle = true
elseif loggedFlagName == "toggle" and not _loggedVehicleToggle then
- print(LOG .. "✅ Registered " .. tostring(label) .. " (vehicle)")
+ print(LOG .. "Registered " .. tostring(label) .. " (vehicle)")
_loggedVehicleToggle = true
elseif loggedFlagName == "mode" and not _loggedVehicleMode then
- print(LOG .. "✅ Registered " .. tostring(label) .. " (vehicle)")
+ print(LOG .. "Registered " .. tostring(label) .. " (vehicle)")
_loggedVehicleMode = true
elseif loggedFlagName == "appearance" and not _loggedVehicleAppearanceMenu then
- print(LOG .. "✅ Registered " .. tostring(label) .. " (vehicle)")
+ print(LOG .. "Registered " .. tostring(label) .. " (vehicle)")
_loggedVehicleAppearanceMenu = true
end
else
- print(LOG .. "❌ Failed to register " .. tostring(label) .. " (vehicle)")
+ print(LOG .. "Failed to register " .. tostring(label) .. " (vehicle)")
end
return id
end
@@ -260,7 +260,7 @@ if HP_AppearanceBindingsScreen ~= nil then
local inputAction = InputAction ~= nil and InputAction.HP_CLEAR_ALL_BINDINGS or nil
if screen == nil or g_inputBinding == nil or g_inputBinding.registerActionEvent == nil or inputAction == nil then
- print(LOG .. "❌ Failed to register HP_CLEAR_ALL_BINDINGS (appearance dialog): input action unavailable")
+ print(LOG .. "Failed to register HP_CLEAR_ALL_BINDINGS (appearance dialog): input action unavailable")
return
end
@@ -282,9 +282,9 @@ if HP_AppearanceBindingsScreen ~= nil then
if g_inputBinding.setActionEventActive ~= nil then
g_inputBinding:setActionEventActive(id, true)
end
- print(LOG .. "✅ Registered HP_CLEAR_ALL_BINDINGS (appearance dialog)")
+ print(LOG .. "Registered HP_CLEAR_ALL_BINDINGS (appearance dialog)")
else
- print(LOG .. "❌ Failed to register HP_CLEAR_ALL_BINDINGS (appearance dialog)")
+ print(LOG .. "Failed to register HP_CLEAR_ALL_BINDINGS (appearance dialog)")
end
end
diff --git a/scripts/gui/HP_AppearanceBindingsScreen.lua b/scripts/gui/HP_AppearanceBindingsScreen.lua
index f95f1b9..4f34766 100644
--- a/scripts/gui/HP_AppearanceBindingsScreen.lua
+++ b/scripts/gui/HP_AppearanceBindingsScreen.lua
@@ -89,6 +89,8 @@ local function getPresetLabelById(presetId)
return tostring(presetId)
end
+local isHelperActive
+
function HP_AppearanceBindingsScreen:getHelperBindingLabel(helperRow)
if helperRow == nil then return nil end
@@ -106,6 +108,7 @@ function HP_AppearanceBindingsScreen:getHelperListLabel(helperRow)
local link = self.draftLinks ~= nil and self.draftLinks[normalizeName(helperRow.name)] or nil
local bindingLabel = self:getHelperBindingLabel(helperRow)
+ local label
if link ~= nil and bindingLabel ~= nil and bindingLabel ~= "" then
local displayName = link.displayName
@@ -118,14 +121,18 @@ function HP_AppearanceBindingsScreen:getHelperListLabel(helperRow)
baseLabel = baseLabel .. " (" .. hpFormat("hp_slot_label", "slot: %s", tostring(helperRow.name)) .. ")"
end
- return baseLabel .. " [" .. hpI18n("hp_state_bound", "BOUND") .. "] " .. bindingLabel
+ label = baseLabel .. " [" .. hpI18n("hp_state_bound", "BOUND") .. "] " .. bindingLabel
+ else
+ -- Important: when a persisted binding is cleared in the draft, the visible
+ -- slot label must revert to the real HelperProfiles slot name immediately.
+ label = tostring(helperRow.name or helperRow.baseName or helperRow.label or "") .. " [" .. hpI18n("hp_state_unbound", "UNBOUND") .. "]"
+ end
+
+ if isHelperActive(helperRow.helper) then
+ label = label .. " [" .. hpI18n("hp_state_active_read_only", "ACTIVE / READ-ONLY") .. "]"
end
- -- Important: when a persisted binding is cleared in the draft, the visible
- -- slot label must revert to the real HelperProfiles slot name immediately.
- -- Do not reuse helperRow.displayName here, because that may have been
- -- derived from the previously persisted AvatarSwitcher binding.
- return tostring(helperRow.name or helperRow.baseName or helperRow.label or "") .. " [" .. hpI18n("hp_state_unbound", "UNBOUND") .. "]"
+ return label
end
local function getHelperDisplayName(helper, idx)
@@ -139,6 +146,48 @@ local function getHelperDisplayName(helper, idx)
return fallback, fallback
end
+local function cloneLink(link)
+ if type(link) ~= "table" then return nil end
+ return {
+ name = link.name,
+ displayName = link.displayName,
+ presetId = link.presetId or link.selectedPresetId,
+ selectedPresetId = link.selectedPresetId or link.presetId,
+ category = link.category,
+ characterId = link.characterId,
+ }
+end
+
+local function linksEqual(a, b)
+ if a == nil or b == nil then return a == b end
+ return tostring(a.name or "") == tostring(b.name or "")
+ and tostring(a.displayName or "") == tostring(b.displayName or "")
+ and tostring(a.presetId or a.selectedPresetId or "") == tostring(b.presetId or b.selectedPresetId or "")
+ and tostring(a.category or "") == tostring(b.category or "")
+ and tostring(a.characterId or "") == tostring(b.characterId or "")
+end
+
+local function linkMapsEqual(a, b)
+ a = a or {}
+ b = b or {}
+ for key, value in pairs(a) do
+ if not linksEqual(value, b[key]) then return false end
+ end
+ for key, value in pairs(b) do
+ if not linksEqual(value, a[key]) then return false end
+ end
+ return true
+end
+
+isHelperActive = function(helper)
+ if helper == nil then return false end
+ if HelperProfiles ~= nil and HelperProfiles.isHelperActive ~= nil then
+ local ok, active = pcall(HelperProfiles.isHelperActive, HelperProfiles, helper)
+ if ok then return active == true end
+ end
+ return helper.inUse == true
+end
+
local function getHelpers()
local rows = {}
local list = HelperProfiles ~= nil and HelperProfiles.getProfiles ~= nil and HelperProfiles:getProfiles() or {}
@@ -164,6 +213,7 @@ function HP_AppearanceBindingsScreen.new(target, customMt)
self.categoryRows = {}
self.presetRows = {}
self.draftLinks = {}
+ self.originalLinks = {}
self.selectedHelperIndex = 1
self.selectedCategoryIndex = 1
@@ -177,6 +227,7 @@ end
function HP_AppearanceBindingsScreen:refreshDirtyState()
+ self.appearanceDirty = not linkMapsEqual(self.draftLinks, self.originalLinks)
self.dirty = self.appearanceDirty == true
end
@@ -247,17 +298,12 @@ function HP_AppearanceBindingsScreen:reloadData(reloadBridge)
end
self.draftLinks = {}
+ self.originalLinks = {}
if HP_ASBridge ~= nil and HP_ASBridge.getLinksSnapshot ~= nil then
local snap = HP_ASBridge:getLinksSnapshot() or {}
for k, link in pairs(snap) do
- self.draftLinks[k] = {
- name = link.name,
- displayName = link.displayName,
- presetId = link.presetId or link.selectedPresetId,
- selectedPresetId = link.selectedPresetId or link.presetId,
- category = link.category,
- characterId = link.characterId,
- }
+ self.draftLinks[k] = cloneLink(link)
+ self.originalLinks[k] = cloneLink(link)
end
end
@@ -405,6 +451,35 @@ function HP_AppearanceBindingsScreen:getSelectedPresetRow()
return self.presetRows[clamp(self.selectedPresetIndex or 1, 1, #self.presetRows)]
end
+function HP_AppearanceBindingsScreen:isHelperRowReadOnly(helperRow)
+ return helperRow ~= nil and isHelperActive(helperRow.helper)
+end
+
+function HP_AppearanceBindingsScreen:showActiveSlotReadOnly(helperRow)
+ local slot = helperRow ~= nil and (helperRow.slot or helperRow.name) or "?"
+ self:setStatus(hpFormat(
+ "hp_error_active_slot_read_only",
+ "Slot %s is active. Release the worker before changing its appearance binding.",
+ tostring(slot)
+ ))
+end
+
+function HP_AppearanceBindingsScreen:restoreActiveDraftLinks()
+ local restored = 0
+ for _, helperRow in ipairs(self.helperRows or {}) do
+ if self:isHelperRowReadOnly(helperRow) then
+ local key = normalizeName(helperRow.name)
+ local original = self.originalLinks ~= nil and self.originalLinks[key] or nil
+ local draft = self.draftLinks ~= nil and self.draftLinks[key] or nil
+ if not linksEqual(original, draft) then
+ self.draftLinks[key] = cloneLink(original)
+ restored = restored + 1
+ end
+ end
+ end
+ return restored
+end
+
function HP_AppearanceBindingsScreen:updateDetailText()
local helperRow = self:getSelectedHelperRow()
local category = self:getSelectedCategoryId()
@@ -415,6 +490,14 @@ function HP_AppearanceBindingsScreen:updateDetailText()
detail = hpFormat("hp_detail_selected", "Selected: %s | %s | %s [%s]", tostring(helperRow.displayName or helperRow.name), tostring(category or "-"), tostring(presetRow.label or presetRow.id), tostring(presetRow.id))
end
+ if helperRow ~= nil and self:isHelperRowReadOnly(helperRow) then
+ detail = hpFormat(
+ "hp_detail_active_read_only",
+ "Slot %s is active and read-only. Release the worker before rebinding it.",
+ tostring(helperRow.slot or helperRow.name or "?")
+ )
+ end
+
if self.detailText ~= nil then self.detailText:setText(detail) end
local status = self.actionMessage
@@ -443,6 +526,10 @@ function HP_AppearanceBindingsScreen:onClickBindAppearance(sender)
self:setStatus(hpI18n("hp_error_no_helper_selected", "Cannot bind: no helper selected"))
return
end
+ if self:isHelperRowReadOnly(helperRow) then
+ self:showActiveSlotReadOnly(helperRow)
+ return
+ end
if presetRow == nil or presetRow.id == nil or presetRow.id == "" then
self:setStatus(hpI18n("hp_error_no_appearance_selected", "Cannot bind: no appearance selected"))
return
@@ -475,6 +562,10 @@ end
function HP_AppearanceBindingsScreen:onClickClearBinding(sender)
local helperRow = self:getSelectedHelperRow()
if helperRow == nil then return end
+ if self:isHelperRowReadOnly(helperRow) then
+ self:showActiveSlotReadOnly(helperRow)
+ return
+ end
self.draftLinks[normalizeName(helperRow.name)] = nil
self.appearanceDirty = true
self:refreshDirtyState()
@@ -484,10 +575,45 @@ function HP_AppearanceBindingsScreen:onClickClearBinding(sender)
end
function HP_AppearanceBindingsScreen:onClickClearAllBindings(sender)
- self.draftLinks = {}
- self.appearanceDirty = true
- self:refreshDirtyState()
- self.actionMessage = hpI18n("hp_status_draft_clear_all", "All draft bindings cleared. Press Save to persist.")
+ local activeKeys = {}
+ local activeCount = 0
+ for _, helperRow in ipairs(self.helperRows or {}) do
+ if self:isHelperRowReadOnly(helperRow) then
+ activeKeys[normalizeName(helperRow.name)] = true
+ activeCount = activeCount + 1
+ end
+ end
+
+ local clearedCount = 0
+ for key, _ in pairs(self.draftLinks or {}) do
+ if activeKeys[key] ~= true then
+ self.draftLinks[key] = nil
+ clearedCount = clearedCount + 1
+ end
+ end
+
+ if clearedCount > 0 then
+ self.appearanceDirty = true
+ self:refreshDirtyState()
+ if activeCount > 0 then
+ self.actionMessage = hpFormat(
+ "hp_status_draft_clear_all_skipped_active",
+ "Cleared %d available binding(s); %d active slot(s) were left unchanged. Press Save to persist.",
+ clearedCount, activeCount
+ )
+ else
+ self.actionMessage = hpI18n("hp_status_draft_clear_all", "All draft bindings cleared. Press Save to persist.")
+ end
+ elseif activeCount > 0 then
+ self.actionMessage = hpFormat(
+ "hp_status_clear_all_active_only",
+ "No available bindings were cleared; %d active slot(s) remain read-only.",
+ activeCount
+ )
+ else
+ self.actionMessage = hpI18n("hp_status_no_bindings_to_clear", "No bindings to clear.")
+ end
+
if self.helperTable ~= nil then self.helperTable:reloadData() end
self:updateDetailText()
end
@@ -505,8 +631,23 @@ function HP_AppearanceBindingsScreen:onClickBack(sender)
end
function HP_AppearanceBindingsScreen:saveBindings(closeAfterSave)
+ local restoredActive = self:restoreActiveDraftLinks()
+ if restoredActive > 0 then
+ self.actionMessage = hpFormat(
+ "hp_status_active_changes_skipped",
+ "Ignored appearance changes for %d active slot(s). Release those workers before rebinding them.",
+ restoredActive
+ )
+ if self.helperTable ~= nil then self.helperTable:reloadData() end
+ end
+
+ self:refreshDirtyState()
if self.dirty ~= true then
- self:setStatus(hpI18n("hp_status_ready", "Ready"))
+ if restoredActive == 0 then
+ self:setStatus(hpI18n("hp_status_ready", "Ready"))
+ else
+ self:updateDetailText()
+ end
if closeAfterSave == true then self:close() end
return true
end
@@ -522,7 +663,10 @@ function HP_AppearanceBindingsScreen:saveBindings(closeAfterSave)
return false
end
- self.appearanceDirty = false
+ self.originalLinks = {}
+ for key, link in pairs(self.draftLinks or {}) do
+ self.originalLinks[key] = cloneLink(link)
+ end
self:refreshDirtyState()
if HP_WorkerAppearance ~= nil and HP_WorkerAppearance.refreshActiveWorkers ~= nil then
HP_WorkerAppearance:refreshActiveWorkers()
@@ -591,6 +735,10 @@ function HP_AppearanceBindingsGui:loadDialog()
end
function HP_AppearanceBindingsGui:open()
+ if HP_Compatibility ~= nil and HP_Compatibility:isBlocked() then
+ hpPrint("Appearance binding UI unavailable: Hired Helper Tool is active and HelperProfiles is disabled.")
+ return false
+ end
if not self.loaded then self:loadDialog() end
if self.loaded and g_gui ~= nil then
self.dialog = g_gui:showDialog("HP_AppearanceBindingsDialog")