Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
03f91ab
Add WORLD movement action UI adapter
SimGamerJen Aug 9, 2026
fbf5ba7
Load WORLD movement action UI
SimGamerJen Aug 9, 2026
9ce96f1
Add COME HERE and FOLLOW actions to WORLD screen
SimGamerJen Aug 9, 2026
7d62db2
Fix appearance binding GUI atlas rendering
SimGamerJen Aug 11, 2026
7eac0ab
Fix roster manager GUI atlas rendering
SimGamerJen Aug 11, 2026
ee3e5fa
Harden management GUI profiles against atlas bleed
SimGamerJen Aug 11, 2026
f4a47b9
Merge management UI texture fixes
SimGamerJen Aug 12, 2026
34d981c
Add HelperProfiles API v7 scoped preferred hire
SimGamerJen Aug 30, 2026
11305de
Add temporary HelperProfiles API v7 test build
SimGamerJen Aug 30, 2026
0a47d0d
Remove temporary API v7 test build workflow
SimGamerJen Aug 30, 2026
073d0db
Set HelperProfiles API metadata for 2.1.1.0
SimGamerJen Aug 30, 2026
52ae036
Add HelperProfiles 2.1.1.0 release workflow
SimGamerJen Aug 30, 2026
d24f557
Release HelperProfiles 2.1.1.0
github-actions[bot] Aug 30, 2026
fbd8be2
Harden HelperProfiles 2.1.1.0 release refresh
SimGamerJen Aug 30, 2026
ba0b966
Trigger corrected HelperProfiles 2.1.1.0 refresh
SimGamerJen Aug 30, 2026
0fa7633
Fix HelperProfiles 2.1.1.0 refresh workflow
SimGamerJen Aug 30, 2026
571ff91
Correct HelperProfiles 2.1.1.0 release metadata
github-actions[bot] Aug 30, 2026
578204a
Merge stable HelperProfiles 2.1.1.0 into World Workers alpha
SimGamerJen Aug 30, 2026
1f6c39b
Merge stable HelperProfiles 2.1.1.0 into World Workers alpha
SimGamerJen Aug 30, 2026
ce54d95
Preserve HelperProfiles 2.1.1.0 release notes on alpha line
SimGamerJen Sep 3, 2026
8058177
Preserve HelperProfiles 2.1.1.0 release workflow on alpha line
SimGamerJen Sep 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions .github/workflows/release-2.1.1.0.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
name: Release HelperProfiles 2.1.1.0

on:
workflow_dispatch:
push:
branches:
- main
paths:
- .github/workflows/release-2.1.1.0.yml

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Repair stable release metadata
shell: bash
run: |
set -euo pipefail
python - <<'PY'
from pathlib import Path
import re
import xml.etree.ElementTree as ET

path = Path('modDesc.xml')
text = path.read_text(encoding='utf-8')
before, marker, changelog = text.partition(' <changelog>')
if not marker:
raise SystemExit('Missing changelog section')

german_lines = [
'Version 2.1.1.0:',
'- Textur-Atlas-Artefakte und Layout-Darstellungsfehler in den Ansichten Erscheinungsbilder und Helferliste wurden behoben.',
'- Integration API v7 wurde hinzugefügt; der bestehende Helferlisten- und Identitätsvertrag bleibt erhalten.',
'- Kompatible Mods wie Remote Dispatcher können einen Helfer vorübergehend und gezielt für einen einzelnen Einstellvorgang anfordern.',
'- Gezielte Anforderungen schlagen kontrolliert fehl, wenn ein Helfer fehlt, nicht im Kader ist oder bereits aktiv ist; es wird kein anderer Helfer stillschweigend eingesetzt.',
'- Gezielte Anforderungen ändern weder den normal ausgewählten Helfer noch den Einstellungsmodus von HelperProfiles.',
''
]
german_block = '\n'.join(german_lines)

# Remove the accidentally inserted German 2.1.1.0 block from EN.
changelog = changelog.replace(german_block, '', 1)

# Add it to the German changelog if it is not already present there.
de_match = re.search(r'<de><!\[CDATA\[(.*?)\]\]></de>', changelog, flags=re.S)
if de_match is None:
raise SystemExit('Missing German changelog')
de_body = de_match.group(1)
if 'Textur-Atlas-Artefakte' not in de_body:
replacement = '<de><![CDATA[\n' + german_block + de_body.lstrip('\n') + ']]></de>'
changelog = changelog[:de_match.start()] + replacement + changelog[de_match.end():]

text = before + marker + changelog
path.write_text(text, encoding='utf-8')

compat = Path('scripts/HP_Compatibility.lua')
ctext = compat.read_text(encoding='utf-8')
ctext = ctext.replace(
'caused the 2.1.1.0 alpha to scan every loaded mod on every frame.',
'caused the 2.1.0.0 alpha to scan every loaded mod on every frame.'
)
compat.write_text(ctext, encoding='utf-8')

root = ET.parse('modDesc.xml').getroot()
if root.findtext('version') != '2.1.1.0':
raise SystemExit('Unexpected modDesc version')

repaired = path.read_text(encoding='utf-8')
_, _, repaired_changelog = repaired.partition(' <changelog>')
en = re.search(r'<en><!\[CDATA\[(.*?)\]\]></en>', repaired_changelog, flags=re.S).group(1)
de = re.search(r'<de><!\[CDATA\[(.*?)\]\]></de>', repaired_changelog, flags=re.S).group(1)
if 'Textur-Atlas-Artefakte' in en:
raise SystemExit('German release notes still present in English changelog')
if not de.lstrip().startswith('Version 2.1.1.0:'):
raise SystemExit('German changelog does not start with 2.1.1.0')

api = Path('scripts/HP_IntegrationAPI.lua').read_text(encoding='utf-8')
for wanted in ['apiVersion = 7', 'modVersion = "2.1.1.0"', 'supportsScopedPreferredHire = true']:
if wanted not in api:
raise SystemExit('Missing API v7 marker: ' + wanted)
PY

- name: Commit metadata corrections
shell: bash
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add modDesc.xml scripts/HP_Compatibility.lua
if ! git diff --cached --quiet; then
git commit -m "Correct HelperProfiles 2.1.1.0 release metadata"
git push origin HEAD:main
fi

- name: Validate package inputs
shell: bash
run: |
set -euo pipefail
test -f docs/releases/2.1.1.0.md
python - <<'PY'
import xml.etree.ElementTree as ET
for path in ['modDesc.xml', 'gui/HP_AppearanceBindingsScreen.xml', 'gui/HP_RosterManagerScreen.xml', 'gui/guiProfiles.xml']:
ET.parse(path)
PY

- name: Build Farming Simulator mod package
shell: bash
run: |
set -euo pipefail
rm -f FS25_HelperProfiles.zip
zip -r FS25_HelperProfiles.zip modDesc.xml icon_helperProfiles.dds gui l10n scripts -x '*.DS_Store' '*__MACOSX*'
python - <<'PY'
import zipfile
import xml.etree.ElementTree as ET
with zipfile.ZipFile('FS25_HelperProfiles.zip', 'r') as archive:
names = set(archive.namelist())
required = {
'modDesc.xml', 'icon_helperProfiles.dds',
'gui/HP_AppearanceBindingsScreen.xml', 'gui/HP_RosterManagerScreen.xml',
'scripts/HelperProfiles.lua', 'scripts/HP_RosterState.lua',
'scripts/HP_RosterFilter.lua', 'scripts/HP_RosterManagerScreen.lua',
'scripts/HP_TabbedManagement.lua', 'scripts/HP_IntegrationAPI.lua'
}
missing = sorted(required - names)
if missing:
raise SystemExit('Missing required package files: ' + ', '.join(missing))
root = ET.fromstring(archive.read('modDesc.xml'))
if root.findtext('version') != '2.1.1.0':
raise SystemExit('Unexpected packaged version')
PY

- name: Publish or refresh GitHub release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
TAG='2.1.1.0'
if gh release view "$TAG" >/dev/null 2>&1; then
gh release edit "$TAG" --title 'HelperProfiles 2.1.1.0' --notes-file docs/releases/2.1.1.0.md
gh release upload "$TAG" FS25_HelperProfiles.zip --clobber
else
gh release create "$TAG" FS25_HelperProfiles.zip --target main --title 'HelperProfiles 2.1.1.0' --notes-file docs/releases/2.1.1.0.md
fi
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@

**FS25 HelperProfiles** is a single-player helper-management mod for Farming Simulator 25. It expands the standard helper roster to 20 permanent worker identities, provides deterministic helper selection, adds per-save ON/OFF roster management, displays an autosizing helper overlay, and supports save-specific AvatarSwitcher appearance bindings.

> **Current version:** `2.1.0.0`
> **Current version:** `2.1.1.0`
> **Game:** Farming Simulator 25
> **Multiplayer:** Not supported

## Highlights in 2.1.1.0

- Fixes Helper Management texture-atlas bleed and layout rendering in the appearance and roster screens.
- Adds **Integration API v7** while retaining the existing A–T roster and identity contract.
- Adds a temporary, scoped preferred-worker hire capability for compatible mods such as **Remote Dispatcher**.
- Scoped worker requests are fail-closed: missing, OFF-roster or already-active workers are rejected rather than silently replaced.
- Scoped requests do not change the worker selected in the normal HelperProfiles overlay or the active hiring mode.

## Highlights in 2.1.0.0

- Expands the managed helper identity pool from **A–J** to **A–T**.
Expand Down Expand Up @@ -33,6 +41,7 @@
- Optional read-only HelperPayroll role information.
- Per-save roster availability stored independently from appearance and payroll data.
- Console commands for selection, diagnostics, roster management and overlay configuration.
- Integration API v7 for compatible companion mods, including scoped preferred-worker hiring.

## Screenshots

Expand Down Expand Up @@ -351,6 +360,13 @@ Confirm HelperPayroll `0.4.2.0` or later is enabled for the same savegame and th

## Version History

### Version 2.1.1.0

- Fixed Helper Management atlas/layout rendering issues.
- Added Integration API v7 with scoped preferred-worker hiring.
- Preserved the existing roster/identity API contract for compatible integrations.
- Added fail-closed named-worker requests without changing normal HelperProfiles selection.

### Version 2.1.0.0

- Expanded the helper identity pool to A–T.
Expand All @@ -371,7 +387,7 @@ Confirm HelperPayroll `0.4.2.0` or later is enabled for the same savegame and th

## Development Status

Version `2.1.0.0` is the validated release of the A–T identity pool, per-save roster availability manager and tabbed Helper Management interface.
Version `2.1.1.0` is the current stable maintenance release of the A–T identity pool, per-save roster availability manager and tabbed Helper Management interface, with Integration API v7 available for compatible companion mods.

A future HelperPayroll update may optionally filter or mark OFF-roster workers in its Workers tab while preserving payroll history and assignments.

Expand Down
29 changes: 29 additions & 0 deletions docs/releases/2.1.1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# HelperProfiles 2.1.1.0

HelperProfiles 2.1.1.0 is a stable maintenance and integration update for the validated 2.1.x A–T helper roster.

## Changes

- Fixed texture-atlas bleed and layout rendering in the Helper Management appearance and roster screens.
- Added **Integration API v7** while retaining the existing permanent-slot, identity and roster-state API contract.
- Added temporary **scoped preferred-worker hiring** for compatible companion mods such as Remote Dispatcher.
- Scoped worker requests are fail-closed: a missing, OFF-roster or already-active worker is rejected rather than silently replaced by another worker.
- Scoped requests do not change the worker selected in the normal HelperProfiles overlay and do not change the user's HelperProfiles hiring mode.

## Remote Dispatcher integration

Remote Dispatcher can use API v7 to bind a prepared vehicle to a specific HelperProfiles worker. The preference exists only for the synchronous helper-hire call and is then released immediately. HelperProfiles remains the owner of the roster and normal worker-selection behaviour outside that scope.

Remote Dispatcher remains optional; HelperProfiles does not require it.

## Compatibility

- Single-player only.
- AvatarSwitcher remains optional.
- HelperPayroll remains optional.
- Hired Helper Tool remains incompatible because it also owns the helper roster.
- Existing HelperProfiles 2.1.0.0 save data and per-save roster/appearance files remain compatible.

## Installation

Download `FS25_HelperProfiles.zip` and place it directly in the Farming Simulator 25 mods folder. Do not unpack it.
20 changes: 8 additions & 12 deletions gui/HP_AppearanceBindingsScreen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@
</BoxLayout>
<ThreePartBitmap profile="fs25_lineSeparatorTopHighlighted" position="45px -119px" size="1105px 2px" />

<Bitmap profile="hpHeaderBox" id="helperHeaderBox" position="45px -135px" size="300px 50px">
<GuiElement id="helperHeaderBox" position="45px -135px" size="300px 50px">
<Text profile="hpHeaderLeft" position="10px 0px" size="250px 40.77px" text="$l10n_hp_header_helper_binding_state" />
<ThreePartBitmap profile="fs25_lineSeparatorBottom" position="0px 2px" />
</Bitmap>
</GuiElement>

<SmoothList profile="hpList" id="helperTable" position="50px -190px" size="290px 270px" focusInit="onOpen" focusChangeTop="nil" focusChangeBottom="nil">
<ListItem profile="hpListItem" name="helperRowTemplate" size="290px 40.77px">
Expand All @@ -37,10 +36,9 @@
<Slider profile="fs25_listSlider" size="6px 262px" dataElementId="helperTable" id="helperSlider" />
</ThreePartBitmap>

<Bitmap profile="hpHeaderBox" id="categoryHeaderBox" position="385px -135px" size="265px 50px">
<GuiElement id="categoryHeaderBox" position="385px -135px" size="265px 50px">
<Text profile="hpHeaderLeft" position="10px 0px" size="235px 40.77px" text="$l10n_hp_header_category" />
<ThreePartBitmap profile="fs25_lineSeparatorBottom" position="0px 2px" />
</Bitmap>
</GuiElement>

<SmoothList profile="hpList" id="categoryTable" position="390px -190px" size="255px 270px" focusChangeTop="nil" focusChangeBottom="nil">
<ListItem profile="hpListItem" name="categoryRowTemplate" size="255px 40.77px">
Expand All @@ -52,11 +50,10 @@
<Slider profile="fs25_listSlider" size="6px 262px" dataElementId="categoryTable" id="categorySlider" />
</ThreePartBitmap>

<Bitmap profile="hpHeaderBox" id="presetHeaderBox" position="695px -135px" size="455px 50px">
<GuiElement id="presetHeaderBox" position="695px -135px" size="455px 50px">
<Text profile="hpHeaderLeft" position="10px 0px" size="265px 40.77px" text="$l10n_hp_header_appearance" />
<Text profile="hpHeaderRight" position="285px 0px" size="155px 40.77px" text="$l10n_hp_header_preset_id" />
<ThreePartBitmap profile="fs25_lineSeparatorBottom" position="0px 2px" />
</Bitmap>
</GuiElement>

<SmoothList profile="hpList" id="presetTable" handleFocus="true" selectedWithoutFocus="false" position="700px -190px" size="445px 270px" focusChangeTop="nil" focusChangeBottom="nil">
<ListItem profile="hpListItem" name="presetRowTemplate" size="445px 40.77px">
Expand All @@ -69,11 +66,10 @@
<Slider profile="fs25_listSlider" size="6px 262px" dataElementId="presetTable" id="presetSlider" />
</ThreePartBitmap>

<Bitmap profile="hpDetailBox" id="detailBox" position="45px -470px" size="1105px 145px">
<GuiElement id="detailBox" position="45px -470px" size="1105px 145px">
<Text profile="hpMetaText" id="detailText" position="10px 8px" size="1085px 35px" text="$l10n_hp_detail_select" textLayoutMode="scrolling" />
<Text profile="hpMetaText" id="statusText" position="10px -38px" size="1085px 35px" text="$l10n_hp_status_ready" textLayoutMode="scrolling" />
<ThreePartBitmap profile="fs25_lineSeparatorBottom" position="0px 2px" />
</Bitmap>
</GuiElement>

</GuiElement>

Expand Down
10 changes: 4 additions & 6 deletions gui/HP_RosterManagerScreen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@
</BoxLayout>
<ThreePartBitmap profile="fs25_lineSeparatorTopHighlighted" position="45px -119px" size="1105px 2px" />

<Bitmap profile="hpHeaderBox" id="rosterHeaderBox" position="45px -135px" size="1105px 50px">
<GuiElement id="rosterHeaderBox" position="45px -135px" size="1105px 50px">
<Text profile="hpHeaderLeft" position="10px 0px" size="55px 40.77px" text="$l10n_hp_roster_header_slot" />
<Text profile="hpHeaderLeft" position="75px 0px" size="210px 40.77px" text="$l10n_hp_roster_header_worker" />
<Text profile="hpHeaderLeft" position="295px 0px" size="270px 40.77px" text="$l10n_hp_roster_header_appearance" />
<Text profile="hpHeaderLeft" position="575px 0px" size="170px 40.77px" text="$l10n_hp_roster_header_role" />
<Text profile="hpHeaderLeft" position="755px 0px" size="140px 40.77px" text="$l10n_hp_roster_header_work_state" />
<Text profile="hpHeaderLeft" position="905px 0px" size="185px 40.77px" text="$l10n_hp_roster_header_roster" />
<ThreePartBitmap profile="fs25_lineSeparatorBottom" position="0px 2px" />
</Bitmap>
</GuiElement>

<SmoothList profile="hpList" id="rosterTable" position="50px -190px" size="1095px 345px" focusInit="onOpen" focusChangeTop="nil" focusChangeBottom="nil">
<ListItem profile="hpListItem" name="rosterRowTemplate" size="1095px 40.77px">
Expand All @@ -47,11 +46,10 @@
<Slider profile="fs25_listSlider" size="6px 337px" dataElementId="rosterTable" id="rosterSlider" />
</ThreePartBitmap>

<Bitmap profile="hpDetailBox" id="detailBox" position="45px -545px" size="1105px 110px">
<GuiElement id="detailBox" position="45px -545px" size="1105px 110px">
<Text profile="hpMetaText" id="detailText" position="10px 8px" size="1085px 35px" text="$l10n_hp_roster_detail" textLayoutMode="scrolling" />
<Text profile="hpMetaText" id="statusText" position="10px -38px" size="1085px 35px" text="$l10n_hp_status_ready" textLayoutMode="scrolling" />
<ThreePartBitmap profile="fs25_lineSeparatorBottom" position="0px 2px" />
</Bitmap>
</GuiElement>
</GuiElement>

<BoxLayout profile="fs25_dialogButtonBox" size="1170px 60px">
Expand Down
2 changes: 2 additions & 0 deletions gui/HP_WorldWorkerScreen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
<BoxLayout profile="fs25_dialogButtonBox" size="1170px 60px">
<Button profile="buttonBack" text="CLOSE" onClick="onClickBack" />
<Button profile="buttonExtra1" id="placeMoveButton" text="PLACE HERE" onClick="onClickPlaceHere" />
<Button profile="buttonExtra1" id="comeHereButton" text="COME HERE" onClick="onClickComeHere" />
<Button profile="buttonExtra1" id="followButton" text="FOLLOW" onClick="onClickFollowToggle" />
<Button profile="hpButtonClearAll" text="FACE ME" onClick="onClickFaceMe" />
<Button profile="hpButtonClear" text="REMOVE" onClick="onClickRemove" />
</BoxLayout>
Expand Down
3 changes: 3 additions & 0 deletions gui/guiProfiles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@

<Profile name="hpList" extends="emptyPanel" with="anchorStretchingYLeft pivotTopLeft" />

<!-- Retained for compatibility. Management screens now use plain GuiElement containers for these regions. -->
<Profile name="hpHeaderBox" extends="emptyPanel" with="anchorStretchingYLeft pivotTopLeft">
<imageSliceId value="gui.empty" />
<imageColor value="$preset_hpColorListHeaderBackground"/>
</Profile>

<Profile name="hpDetailBox" extends="emptyPanel" with="anchorStretchingYLeft pivotTopLeft">
<imageSliceId value="gui.empty" />
<imageColor value="0 0 0 0.45"/>
</Profile>

Expand Down
Loading