Zum Hauptinhalt springen

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.

Kernkonzept

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.

  1. Zum Pallet Silo gehen und in den Spieler-Trigger treten (Bereich vor dem Regal)
  2. R drücken → Lager-Dialog öffnet sich
  3. Unten auf CONFIGURE klicken → Konfigurationsdialog öffnet sich

Im Konfigurationsdialog:

BereichFunktion
Rack (links)Wähle das Regal das du konfigurieren möchtest
Assignments (rechts oben)Zeigt alle bereits zugewiesenen FillTypes dieses Regals
Slots infoWie viele Slots belegt / frei sind
SearchFillType-Suche
FillType-AuswahlWähle den FillType den du hinzufügen möchtest
Visual SlotsWie viele physische Regal-Positionen dieser FillType belegt
CapacityMaximale Anzahl an Paletten für diesen FillType

FillType hinzufügen:

  1. Oben links ein Regal auswählen
  2. Rechts einen FillType suchen und auswählen
  3. Slot-Anzahl einstellen
  4. Optional Kapazität eintragen (leer lassen = Slot-Anzahl als Limit)
  5. ADD drücken

FillType entfernen:

  1. In der Assignments-Liste den Eintrag auswählen
  2. REMOVE drücken (nur möglich wenn keine Paletten dieses Typs eingelagert sind)
tipp

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.

  1. Palette auf einem Fahrzeug oder Anhänger in den Einlager-Trigger fahren
  2. Die Palette wird automatisch erkannt, eingelagert und das Fahrzeug-Modell verschwindet
  3. Im Regal erscheint ein geklontes Paletten-Modell am entsprechenden Slot
Voraussetzung

Es können nur FillTypes eingelagert werden, die einem Regal zugewiesen wurden. Nicht konfigurierte FillTypes werden mit einer Meldung abgelehnt.


Schritt 3: Paletten ausgeben

  1. In den Spieler-Trigger treten und R drücken
  2. FillType aus der Liste auswählen
  3. Anzahl der Paletten wählen
  4. Spawn-Bereich auswählen (falls mehrere vorhanden)
  5. SELECT klicken → Paletten erscheinen am gewählten Platz
tipp

Gespawnte Paletten werden direkt auf dem Boden platziert und können mit einem Frontlader aufgenommen werden.


Für Modder – XML Setup

Wichtig

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>
warnung

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>

ParameterTypBeschreibungStandard
maxPalletsIntMaximale Gesamtanzahl gespeicherter Paletten100
palletSpacingFloatAbstand zwischen gespawnten Paletten in Metern1.5
logoTextureStringPfad zur Logo-Textur (relativ zum Mod-Verzeichnis)

Parameter <trigger> (palletTriggers)

ParameterTypBeschreibung
nodeNodeTrigger-Node der eingelagerte Paletten erkennt
regalIdStringOptional: Nur Paletten für dieses Rack annehmen. Ohne Angabe werden alle FillTypes akzeptiert.
Rack-spezifische Trigger

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)

ParameterTypBeschreibung
nodeNodeTrigger-Node
nameStringAnzeigename im Info-Panel
regalIdStringID des Racks – muss mit id in <visualSlots><regal> übereinstimmen. Ohne diese Angabe werden alle Paletten angezeigt.

Parameter <spawnArea>

ParameterTypBeschreibungStandard
startNodeNodeStartpunkt der Spawn-Linie
endNodeNodeEndpunkt der Spawn-Linie
nameStringAnzeigename im Ausgabe-Dialog
palletRotationOffsetFloatRotationsversatz in Grad0
palletSpaceFloatKollisionsradius für Freiraum-Prüfung pro Spawn-Position (m)0.55
Spawn-Area Namen

"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:

  1. Der Modder definiert Racks mit einer festen Anzahl physischer Slot-Nodes
  2. Der Spieler konfiguriert im CONFIGURE-Dialog welcher FillType wie viele Slots belegt
  3. 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>

ParameterTypBeschreibung
idStringEindeutige ID (wird im Savegame und für regalId der InfoTrigger verwendet)
nameStringAnzeigename im CONFIGURE-Dialog

Parameter <slot> (Rack-System)

ParameterTypBeschreibung
nodeNodeTransform-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)

ParameterTypBeschreibung
nodeNodeTransform-Node für die geklonte Palette
fillTypeStringFillType-Name (z. B. FLOUR, SUGAR)

Parameter <pallet> (masterObjects)

Gilt für beide Systeme. Das Framework erkennt für Standard-FillTypes die Modelle automatischmasterObjects ist nur nötig wenn du eigene 3D-Modelle verwendest.

ParameterTypBeschreibung
nodeNodeMaster-Palettennode (wird automatisch unsichtbar gemacht)
fillTypeStringFillType-Name dem dieser Master zugeordnet ist
Auto-Detect

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.

FillTypei3dTextur-Override
RICEFLOURflourBoxPallet.i3d
SOUPCANSCARROTSsoupCansPallet.i3d
SOUPCANSPARSNIPsoupCansPallet.i3d
SOUPCANSBEETROOTsoupCansPallet.i3d
SOUPCANSPOTATOsoupCansPallet.i3d
GOATMILK_BOTTLEDmilkBottlesBoxPallet.i3d
BUFFALOMILK_BOTTLEDmilkBottlesBoxPallet.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

  1. ✅ Content-Mod mit modDependencies auf FS25_SiloExtension einrichten
  2. ✅ Slot-System wählen: Rack-System (empfohlen) oder Legacy
  3. regalInfoTriggers mit regalId verknüpfen
  4. ✅ i3dMappings eintragen und Trigger-Nodes im Giants Editor konfigurieren
  5. Optional: SiloDisplay für 3D-Textanzeige auf dem Regal einrichten