5. Pallet Silo – Paletten-Lagersystem
Übersicht
Der extendedPalletSilo ist ein vollständiges Paletten-Lagersystem. Paletten werden automatisch per Physik-Trigger eingelagert, die Regale werden direkt im Spiel konfiguriert und Paletten können per Dialog an verschiedenen Positionen ausgegeben werden.
Das Rack-System erlaubt es, beliebige FillTypes zur Laufzeit zuzuweisen – ganz ohne Mod-Neustart. Die Konfiguration wird im Savegame gespeichert.
Für Spieler – So funktioniert es
Schritt 1: Regale konfigurieren
Bevor du Paletten einlagern kannst, müssen die Regale eingerichtet werden. Das passiert einmalig im Spiel.
- Zum Pallet Silo gehen und in den Spieler-Trigger treten (Bereich vor dem Regal)
- R drücken → Lager-Dialog öffnet sich
- Unten auf CONFIGURE klicken → Konfigurationsdialog öffnet sich
Im Konfigurationsdialog:
| Bereich | Funktion |
|---|---|
| Rack (links) | Wähle das Regal das du konfigurieren möchtest |
| Assignments (rechts oben) | Zeigt alle bereits zugewiesenen FillTypes dieses Regals |
| Slots info | Wie viele Slots belegt / frei sind |
| Search | FillType-Suche |
| FillType-Auswahl | Wähle den FillType den du hinzufügen möchtest |
| Visual Slots | Wie viele physische Regal-Positionen dieser FillType belegt |
| Capacity | Maximale Anzahl an Paletten für diesen FillType |
FillType hinzufügen:
- Oben links ein Regal auswählen
- Rechts einen FillType suchen und auswählen
- Slot-Anzahl einstellen
- Optional Kapazität eintragen (leer lassen = Slot-Anzahl als Limit)
- ADD drücken
FillType entfernen:
- In der Assignments-Liste den Eintrag auswählen
- REMOVE drücken (nur möglich wenn keine Paletten dieses Typs eingelagert sind)
Du kannst einem Regal mehrere FillTypes zuweisen, solange genug freie Slots vorhanden sind.
Schritt 2: Paletten einlagern
Paletten werden automatisch eingelagert sobald sie den Einlager-Trigger berühren.
- Palette auf einem Fahrzeug oder Anhänger in den Einlager-Trigger fahren
- Die Palette wird automatisch erkannt, eingelagert und das Fahrzeug-Modell verschwindet
- Im Regal erscheint ein geklontes Paletten-Modell am entsprechenden Slot
Es können nur FillTypes eingelagert werden, die einem Regal zugewiesen wurden. Nicht konfigurierte FillTypes werden mit einer Meldung abgelehnt.
Schritt 3: Paletten ausgeben
- In den Spieler-Trigger treten und R drücken
- FillType aus der Liste auswählen
- Anzahl der Paletten wählen
- Spawn-Bereich auswählen (falls mehrere vorhanden)
- SELECT klicken → Paletten erscheinen am gewählten Platz
Gespawnte Paletten werden direkt auf dem Boden platziert und können mit einem Frontlader aufgenommen werden.
Für Modder – XML Setup
Der PlaceableType FS25_SiloExtension.extendedPalletSilo ersetzt nicht den Vanilla-Silo. Er erweitert ihn.
1. Placeable-Typ
<placeable type="FS25_SiloExtension.extendedPalletSilo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../shared/xml/schema/placeable.xsd">
2. Vanilla Silo Grundstruktur
Ein gemeinsamer Storage mit supportsMultipleFillTypes="true" ist zwingend erforderlich:
<silo>
<storages>
<storage node="palletStorage"
capacity="500000"
supportsMultipleFillTypes="true"/>
</storages>
</silo>
Ohne supportsMultipleFillTypes="true" können keine verschiedenen FillTypes gleichzeitig gespeichert werden.
3. extendedPalletSilo Block
<extendedPalletSilo maxPallets="100" palletSpacing="1.5">
<!-- Einlager-Trigger (Array-Format, empfohlen): mehrere Trigger möglich, optional rack-spezifisch -->
<palletTriggers>
<trigger node="palletTrigger1"/>
<trigger node="palletTrigger2" regalId="regal_01"/>
</palletTriggers>
<!-- Alternativ: altes Einzelformat (Abwärtskompatibilität) -->
<!-- <palletTrigger node="palletTrigger"/> -->
<!-- Spieler-Trigger: Öffnet den Lager-Dialog -->
<playerTrigger node="playerTrigger"/>
<!-- Optionaler zweiter Spieler-Trigger (z. B. Rückseite des Regals) -->
<playerTrigger2 node="playerTrigger2"/>
<!-- Regal-Info-Trigger: Zeigt Belegung des verknüpften Racks im Info-Panel -->
<regalInfoTriggers>
<regal node="regalTrigger1" name="Regal A" regalId="regal_01"/>
<regal node="regalTrigger2" name="Regal B" regalId="regal_02"/>
</regalInfoTriggers>
<!-- Visuelle Slots (siehe Abschnitt 4) -->
<visualSlots>...</visualSlots>
<!-- Spawn-Bereiche für ausgegebene Paletten -->
<spawnAreas>
<spawnArea startNode="spawnStart1" endNode="spawnEnd1"
name="Am Regal" palletRotationOffset="0"/>
<spawnArea startNode="spawnStart2" endNode="spawnEnd2"
name="Draussen" palletRotationOffset="90"/>
</spawnAreas>
</extendedPalletSilo>
Parameter <extendedPalletSilo>
| Parameter | Typ | Beschreibung | Standard |
|---|---|---|---|
maxPallets | Int | Maximale Gesamtanzahl gespeicherter Paletten | 100 |
palletSpacing | Float | Abstand zwischen gespawnten Paletten in Metern | 1.5 |
logoTexture | String | Pfad zur Logo-Textur (relativ zum Mod-Verzeichnis) | – |
Parameter <trigger> (palletTriggers)
| Parameter | Typ | Beschreibung |
|---|---|---|
node | Node | Trigger-Node der eingelagerte Paletten erkennt |
regalId | String | Optional: Nur Paletten für dieses Rack annehmen. Ohne Angabe werden alle FillTypes akzeptiert. |
Mit regalId kannst du räumlich getrennte Einlager-Zonen für jedes Regal definieren – z. B. ein Trigger direkt vor Regal A, ein anderer vor Regal B.
Parameter <regal> (regalInfoTriggers)
| Parameter | Typ | Beschreibung |
|---|---|---|
node | Node | Trigger-Node |
name | String | Anzeigename im Info-Panel |
regalId | String | ID des Racks – muss mit id in <visualSlots><regal> übereinstimmen. Ohne diese Angabe werden alle Paletten angezeigt. |
Parameter <spawnArea>
| Parameter | Typ | Beschreibung | Standard |
|---|---|---|---|
startNode | Node | Startpunkt der Spawn-Linie | – |
endNode | Node | Endpunkt der Spawn-Linie | – |
name | String | Anzeigename im Ausgabe-Dialog | – |
palletRotationOffset | Float | Rotationsversatz in Grad | 0 |
palletSpace | Float | Kollisionsradius für Freiraum-Prüfung pro Spawn-Position (m) | 0.55 |
"Am Regal", "Draussen" und "Hof" werden automatisch übersetzt (DE/EN).
4. Visuelle Slots
Es gibt zwei Systeme – das Rack-System (empfohlen) und das Legacy-System (Abwärtskompatibilität). Das Framework erkennt automatisch welches vorliegt.
4a. Rack-System ✅ Empfohlen
Slots werden in Racks gruppiert. Welcher FillType in welchem Rack landet wird im Spiel konfiguriert – nicht in der XML. Das macht das System sehr flexibel.
<visualSlots>
<regal id="regal_01" name="Regal A">
<slot node="slot_01_1"/>
<slot node="slot_01_2"/>
<slot node="slot_01_3"/>
<slot node="slot_01_4"/>
</regal>
<regal id="regal_02" name="Regal B">
<slot node="slot_02_1"/>
<slot node="slot_02_2"/>
<slot node="slot_02_3"/>
<slot node="slot_02_4"/>
</regal>
<masterObjects>
<pallet node="masterPallet_flour" fillType="FLOUR"/>
<pallet node="masterPallet_sugar" fillType="SUGAR"/>
</masterObjects>
</visualSlots>
Wie es funktioniert:
- Der Modder definiert Racks mit einer festen Anzahl physischer Slot-Nodes
- Der Spieler konfiguriert im CONFIGURE-Dialog welcher FillType wie viele Slots belegt
- Die visuelle Darstellung füllt die Slots proportional zur Belegung
Vorteile:
- ✅ Kein Neustart nötig wenn sich der Spieler umentscheidet
- ✅ Konfiguration wird im Savegame gespeichert
- ✅ Mehrere FillTypes pro Regal möglich
- ✅ Kapazität frei einstellbar
Parameter <regal>
| Parameter | Typ | Beschreibung |
|---|---|---|
id | String | Eindeutige ID (wird im Savegame und für regalId der InfoTrigger verwendet) |
name | String | Anzeigename im CONFIGURE-Dialog |
Parameter <slot> (Rack-System)
| Parameter | Typ | Beschreibung |
|---|---|---|
node | Node | Transform-Node an dem die geklonte Palette verankert wird |
4b. Legacy-System (Abwärtskompatibilität)
Slots bekommen ihren FillType direkt in der XML. Geeignet für einfache Mods ohne dynamische Konfiguration.
<visualSlots>
<slot node="slot_flour_1" fillType="FLOUR"/>
<slot node="slot_flour_2" fillType="FLOUR"/>
<slot node="slot_flour_3" fillType="FLOUR"/>
<slot node="slot_sugar_1" fillType="SUGAR"/>
<slot node="slot_sugar_2" fillType="SUGAR"/>
<masterObjects>
<pallet node="masterPallet_flour" fillType="FLOUR"/>
<pallet node="masterPallet_sugar" fillType="SUGAR"/>
</masterObjects>
</visualSlots>
Wie es funktioniert:
- Slots sind fest einem FillType zugewiesen
- Anzahl sichtbarer Slots berechnet sich:
gespeicherte Paletten / maxPallets × Gesamtslots - Mindestens 1 Slot wird angezeigt sobald Paletten dieses Typs vorhanden sind
Nachteile gegenüber Rack-System:
- ❌ Kein CONFIGURE-Dialog
- ❌ FillType-Zuweisung nur über XML änderbar
Parameter <slot> (Legacy)
| Parameter | Typ | Beschreibung |
|---|---|---|
node | Node | Transform-Node für die geklonte Palette |
fillType | String | FillType-Name (z. B. FLOUR, SUGAR) |
Parameter <pallet> (masterObjects)
Gilt für beide Systeme. Das Framework erkennt für Standard-FillTypes die Modelle automatisch – masterObjects ist nur nötig wenn du eigene 3D-Modelle verwendest.
| Parameter | Typ | Beschreibung |
|---|---|---|
node | Node | Master-Palettennode (wird automatisch unsichtbar gemacht) |
fillType | String | FillType-Name dem dieser Master zugeordnet ist |
Für alle Standard-FS25 Paletten-FillTypes (FLOUR, SUGAR, EGGS, ...) lädt das Framework das Modell automatisch – du brauchst keinen masterObjects-Eintrag.
5. Template-System
Für Standard-FillTypes bei denen mehrere Palettentypen dasselbe i3d-Modell verwenden (z. B. Suppendosen, Milchflaschen) lädt das Framework automatisch das korrekte Modell und die korrekte Textur.
| FillType | i3d | Textur-Override |
|---|---|---|
RICEFLOUR | flourBoxPallet.i3d | – |
SOUPCANSCARROTS | soupCansPallet.i3d | ✅ |
SOUPCANSPARSNIP | soupCansPallet.i3d | ✅ |
SOUPCANSBEETROOT | soupCansPallet.i3d | ✅ |
SOUPCANSPOTATO | soupCansPallet.i3d | ✅ |
GOATMILK_BOTTLED | milkBottlesBoxPallet.i3d | ✅ |
BUFFALOMILK_BOTTLED | milkBottlesBoxPallet.i3d | ✅ |
6. i3d Anforderungen
palletTriggers
- Collision Group:
TRIGGER(Bit 29) - Collision Mask:
DYNAMIC_OBJECT(Bit 12)
playerTrigger / playerTrigger2
- Collision Group:
TRIGGER(Bit 29) - Collision Mask:
PLAYER(Bit 20)
regalInfoTrigger-Nodes
- Collision Group:
TRIGGER(Bit 29) - Collision Mask:
PLAYER(Bit 20)
masterObjects-Nodes
Im Giants Editor auf unsichtbar (Visibility = off) setzen. Das Framework macht sie beim Laden automatisch unsichtbar.
spawnArea-Nodes
Einfache TransformGroup-Nodes ohne Physik. Der Abstand zwischen startNode und endNode bestimmt die Gesamtlänge der Spawn-Linie.
7. Vollständiges Beispiel (Rack-System)
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<placeable type="FS25_SiloExtension.extendedPalletSilo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../shared/xml/schema/placeable.xsd">
<storeData>
<name>$l10n_PalletStorage</name>
<image>store/storePalletSilo.png</image>
<price>30000</price>
<lifetime>1000</lifetime>
<species>placeable</species>
<category>productionPoints</category>
<canBeSold>true</canBeSold>
<showInStore>true</showInStore>
</storeData>
<base>
<filename>PalletSilo.i3d</filename>
<canBeRenamed>true</canBeRenamed>
<canBeDeleted>true</canBeDeleted>
</base>
<infoTrigger triggerNode="infoTrigger"/>
<silo>
<storages>
<storage node="palletStorage" capacity="500000" supportsMultipleFillTypes="true"/>
</storages>
</silo>
<extendedPalletSilo maxPallets="50" palletSpacing="1.2">
<palletTriggers>
<trigger node="palletTrigger1"/>
<trigger node="palletTrigger2" regalId="regal_01"/>
</palletTriggers>
<playerTrigger node="playerTrigger"/>
<regalInfoTriggers>
<regal node="regalTrigger1" name="Regal A" regalId="regal_01"/>
<regal node="regalTrigger2" name="Regal B" regalId="regal_02"/>
</regalInfoTriggers>
<visualSlots>
<regal id="regal_01" name="Regal A">
<slot node="slot_01_1"/>
<slot node="slot_01_2"/>
<slot node="slot_01_3"/>
<slot node="slot_01_4"/>
</regal>
<regal id="regal_02" name="Regal B">
<slot node="slot_02_1"/>
<slot node="slot_02_2"/>
<slot node="slot_02_3"/>
<slot node="slot_02_4"/>
</regal>
<masterObjects>
<pallet node="masterPallet_flour" fillType="FLOUR"/>
<pallet node="masterPallet_sugar" fillType="SUGAR"/>
</masterObjects>
</visualSlots>
<spawnAreas>
<spawnArea startNode="spawnStart1" endNode="spawnEnd1"
name="Am Regal" palletRotationOffset="0" palletSpace="0.55"/>
<spawnArea startNode="spawnStart2" endNode="spawnEnd2"
name="Draussen" palletRotationOffset="90"/>
</spawnAreas>
</extendedPalletSilo>
<i3dMappings>
<i3dMapping id="palletStorage" node="0>3|0"/>
<i3dMapping id="palletTrigger1" node="0>4|0"/>
<i3dMapping id="palletTrigger2" node="0>4|1"/>
<i3dMapping id="playerTrigger" node="0>5"/>
<i3dMapping id="regalTrigger1" node="0>6|0"/>
<i3dMapping id="regalTrigger2" node="0>6|1"/>
<i3dMapping id="slot_01_1" node="0>7|0"/>
<i3dMapping id="slot_01_2" node="0>7|1"/>
<i3dMapping id="slot_01_3" node="0>7|2"/>
<i3dMapping id="slot_01_4" node="0>7|3"/>
<i3dMapping id="slot_02_1" node="0>8|0"/>
<i3dMapping id="slot_02_2" node="0>8|1"/>
<i3dMapping id="slot_02_3" node="0>8|2"/>
<i3dMapping id="slot_02_4" node="0>8|3"/>
<i3dMapping id="masterPallet_flour" node="0>9|0"/>
<i3dMapping id="masterPallet_sugar" node="0>9|1"/>
<i3dMapping id="spawnStart1" node="0>10|0"/>
<i3dMapping id="spawnEnd1" node="0>10|1"/>
<i3dMapping id="spawnStart2" node="0>11|0"/>
<i3dMapping id="spawnEnd2" node="0>11|1"/>
<i3dMapping id="infoTrigger" node="0>12"/>
</i3dMappings>
</placeable>
Häufige Fehler
❌ Paletten werden nicht eingelagert
Ursache: palletTrigger hat falsche Collision Mask – erkennt keine Paletten-Objekte.
Lösung: Im Giants Editor Collision Mask = DYNAMIC_OBJECT (Bit 12) setzen.
❌ FillType kann nicht eingelagert werden – Meldung „No slots configured"
Ursache: Der FillType wurde noch keinem Regal zugewiesen.
Lösung: CONFIGURE-Button im Lager-Dialog klicken und den FillType einem Regal zuweisen.
❌ Visuelle Slots bleiben leer
Ursache (Rack-System): Kein FillType für dieses Rack konfiguriert, oder kein masterObjects-Eintrag vorhanden und Auto-Detect greift nicht.
Lösung: Im CONFIGURE-Dialog FillType zuweisen. Für eigene FillTypes einen <pallet>-Eintrag in <masterObjects> hinzufügen.
❌ Info-Panel zeigt alle Paletten statt nur ein Rack
Ursache: regalId fehlt am <regal>-Eintrag in <regalInfoTriggers>.
Lösung: regalId="regal_01" eintragen – muss mit der id in <visualSlots><regal> übereinstimmen.
❌ Gespawnte Paletten stecken im Boden
Ursache: startNode der Spawn-Area liegt zu tief.
Lösung: startNode auf Bodenhöhe setzen – das Framework erhöht Y automatisch auf Geländehöhe + 0.2 m.
Nächste Schritte
- ✅ Content-Mod mit
modDependenciesauf FS25_SiloExtension einrichten - ✅ Slot-System wählen: Rack-System (empfohlen) oder Legacy
- ✅
regalInfoTriggersmitregalIdverknüpfen - ✅ i3dMappings eintragen und Trigger-Nodes im Giants Editor konfigurieren
- Optional: SiloDisplay für 3D-Textanzeige auf dem Regal einrichten