1. Bulk Silo – XML Setup
Übersicht
Diese Seite erklärt wie du ein eigenes Gebäude mit dem extendedSilo System einrichtest. Das System besteht aus zwei Teilen: der modDesc.xml deines Content-Mods und der Placeable-XML des Gebäudes.
Der PlaceableType FS25_SiloExtension.extendedSilo ersetzt nicht den Vanilla-Silo. Er erweitert ihn. Du behältst alle Vanilla-Features (UnloadingStation, LoadingStation, Storage) und bekommst zusätzlich das Box-System.
1. Dependency in modDesc.xml
Damit dein Mod das Framework nutzen kann, muss FS25_SiloExtension als Abhängigkeit deklariert werden:
<modDesc>
<!-- ... -->
<modDependencies>
<modDependency modName="FS25_SiloExtension"/>
</modDependencies>
<!-- ... -->
</modDesc>
Das Spiel stellt dann sicher, dass das Framework vor deinem Mod initialisiert ist.
storeItems, l10n und deine i3d/XML-Dateien bleiben vollständig in deinem Content-Mod. Das Framework stellt nur die Lua-Logik bereit.
2. Placeable-Typ verwenden
In deiner Placeable-XML (z. B. MySilo.xml):
<placeable type="FS25_SiloExtension.extendedSilo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../shared/xml/schema/placeable.xsd">
Der Typ muss immer mit dem Mod-Präfix angegeben werden: FS25_SiloExtension.extendedSilo
3. Vanilla Silo Grundstruktur
Das System baut auf der Vanilla silo-Specialization auf. Du brauchst mindestens:
- Storages – eine pro Box (werden von der Vanilla-Silo-Logik für Savegame-Persistenz genutzt)
- UnloadingStation mit einem UnloadTrigger pro Box
- LoadingStation für das Auslagern
<silo>
<!-- Ein Storage pro Box -->
<storages>
<storage node="storage1" fillTypes="WHEAT" capacity="200000" supportsMultipleFillTypes="false" isExtension="false"/>
<storage node="storage2" fillTypes="BARLEY" capacity="200000" supportsMultipleFillTypes="false" isExtension="false"/>
</storages>
<!-- Auslagern -->
<loadingStation node="loadingStation" fillTypeCategories="BULK">
<loadTrigger triggerNode="loadingTrigger" fillLitersPerSecond="2000" fillTypeCategories="BULK" autoStart="true"/>
</loadingStation>
<!-- Einlagern – ein Trigger pro Box, storageIndex entspricht dem Index in <boxes> -->
<unloadingStation>
<unloadTrigger fillTypes="WHEAT" exactFillRootNode="unloadTrigger1" storageIndex="1"/>
<unloadTrigger fillTypes="BARLEY" exactFillRootNode="unloadTrigger2" storageIndex="2"/>
<effectNodes>
<effectNode effectNode="pipeEffect1" materialType="pipe" effectClass="PipeEffect"/>
<effectNode effectNode="pipeEffect2" materialType="pipe" effectClass="PipeEffect"/>
</effectNodes>
</unloadingStation>
<!-- Box-System -->
<boxSystem>
<playerTrigger node="boxPlayerTrigger"/>
<boxes>
<box storageIndex="1" name="Box 1" effectNode="pipeEffect1"/>
<box storageIndex="2" name="Box 2" effectNode="pipeEffect2"/>
</boxes>
</boxSystem>
</silo>
Parameter <boxSystem>
| Parameter | Typ | Beschreibung |
|---|---|---|
playerTrigger#node | Node | Trigger-Node für Spieler/Fahrzeug-Erkennung (Einlagern-Dialog) |
Parameter <box>
| Parameter | Typ | Beschreibung |
|---|---|---|
storageIndex | Int | Index des zugehörigen Vanilla-Storage (1-basiert) |
name | String | Anzeigename im Box-Dialog |
effectNode | Node | i3d-Node des PipeEffects für diese Box (→ PipeEffects) |
Der storageIndex in <box> und in <unloadTrigger> muss übereinstimmen! Box 1 → storageIndex="1", der erste <unloadTrigger> ebenfalls mit storageIndex="1".
4. i3dMappings
Alle Nodes müssen in den <i3dMappings> eingetragen sein:
<i3dMappings>
<!-- Storages (Vanilla-Silo) -->
<i3dMapping id="storage1" node="0>5|0|0"/>
<i3dMapping id="storage2" node="0>5|1|0"/>
<!-- Unload Trigger (Einlagern) -->
<i3dMapping id="unloadTrigger1" node="0>3|0"/>
<i3dMapping id="unloadTrigger2" node="0>3|1"/>
<!-- Loading Station (Auslagern) -->
<i3dMapping id="loadingStation" node="0>4"/>
<i3dMapping id="loadingTrigger" node="0>4|0"/>
<!-- Box Player Trigger -->
<i3dMapping id="boxPlayerTrigger" node="0>6"/>
<!-- PipeEffects -->
<i3dMapping id="pipeEffect1" node="0>5|0|1"/>
<i3dMapping id="pipeEffect2" node="0>5|1|1"/>
<!-- FillPlane (optional) -->
<i3dMapping id="fillPlane1" node="0>7|0"/>
<!-- Info Trigger -->
<i3dMapping id="infoTrigger" node="0>8"/>
</i3dMappings>
Die Node-Pfade (0>5|0|0 etc.) sind Beispiele – du musst sie an deine i3d-Struktur anpassen!
5. Vollständiges Beispiel
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<placeable type="FS25_SiloExtension.extendedSilo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../shared/xml/schema/placeable.xsd">
<storeData>
<name>$l10n_Silo</name>
<functions>
<function>$l10n_function_Silo</function>
</functions>
<image>store/storeSilo.png</image>
<price>50000</price>
<lifetime>1000</lifetime>
<species>placeable</species>
<category>productionPoints</category>
<canBeSold>true</canBeSold>
<showInStore>true</showInStore>
</storeData>
<base>
<filename>MySilo.i3d</filename>
<canBeRenamed>true</canBeRenamed>
<canBeDeleted>true</canbeDeleted>
</base>
<infoTrigger triggerNode="infoTrigger"/>
<silo>
<storages>
<storage node="storage1" fillTypes="WHEAT" capacity="200000" supportsMultipleFillTypes="false" isExtension="false"/>
<storage node="storage2" fillTypes="BARLEY" capacity="200000" supportsMultipleFillTypes="false" isExtension="false"/>
<storage node="storage3" fillTypes="CANOLA" capacity="200000" supportsMultipleFillTypes="false" isExtension="false"/>
</storages>
<loadingStation node="loadingStation" fillTypeCategories="BULK">
<loadTrigger triggerNode="loadingTrigger" fillLitersPerSecond="2000" fillTypeCategories="BULK" autoStart="true"/>
</loadingStation>
<unloadingStation>
<unloadTrigger fillTypes="WHEAT" exactFillRootNode="unloadTrigger1" storageIndex="1"/>
<unloadTrigger fillTypes="BARLEY" exactFillRootNode="unloadTrigger2" storageIndex="2"/>
<unloadTrigger fillTypes="CANOLA" exactFillRootNode="unloadTrigger3" storageIndex="3"/>
<effectNodes>
<effectNode effectNode="pipeEffect1" materialType="pipe" effectClass="PipeEffect"/>
<effectNode effectNode="pipeEffect2" materialType="pipe" effectClass="PipeEffect"/>
<effectNode effectNode="pipeEffect3" materialType="pipe" effectClass="PipeEffect"/>
</effectNodes>
</unloadingStation>
<boxSystem>
<playerTrigger node="boxPlayerTrigger"/>
<boxes>
<box storageIndex="1" name="Box Weizen" effectNode="pipeEffect1">
<fillPlane node="fillPlane1" minY="0.0" maxY="3.5" changeVisibility="true"/>
</box>
<box storageIndex="2" name="Box Gerste" effectNode="pipeEffect2">
<fillPlane node="fillPlane2" minY="0.0" maxY="3.5" changeVisibility="true"/>
</box>
<box storageIndex="3" name="Box Raps" effectNode="pipeEffect3"/>
</boxes>
</boxSystem>
</silo>
<i3dMappings>
<i3dMapping id="storage1" node="0>5|0|2"/>
<i3dMapping id="storage2" node="0>5|1|2"/>
<i3dMapping id="storage3" node="0>5|2|2"/>
<i3dMapping id="unloadTrigger1" node="0>3|0"/>
<i3dMapping id="unloadTrigger2" node="0>3|1"/>
<i3dMapping id="unloadTrigger3" node="0>3|2"/>
<i3dMapping id="loadingStation" node="0>4"/>
<i3dMapping id="loadingTrigger" node="0>4|0"/>
<i3dMapping id="boxPlayerTrigger" node="0>6"/>
<i3dMapping id="pipeEffect1" node="0>5|0|1"/>
<i3dMapping id="pipeEffect2" node="0>5|1|1"/>
<i3dMapping id="pipeEffect3" node="0>5|2|1"/>
<i3dMapping id="fillPlane1" node="0>7|0"/>
<i3dMapping id="fillPlane2" node="0>7|1"/>
<i3dMapping id="infoTrigger" node="0>8"/>
</i3dMappings>
</placeable>
6. i3d Anforderungen
boxPlayerTrigger
Der boxPlayerTrigger-Node muss im Giants Editor als Trigger konfiguriert sein:
- Collision Group:
TRIGGER(Bit 29) - Collision Mask:
PLAYER(Bit 20)
Die Kollisionsmaske für VEHICLE und FILLABLE wird automatisch zur Laufzeit vom Framework ergänzt – du musst nur PLAYER im Giants Editor setzen.
unloadTrigger Nodes
Die exactFillRootNode-Nodes der UnloadTrigger müssen:
- Collision Group:
FILLABLE(Bit 30) gesetzt haben
Vanilla-Anforderung – ohne dieses Flag gibt Giants eine Warnung aus und der Trigger wird nicht geladen.
Häufige Fehler
❌ "Unknown type 'extendedSilo'"
Ursache: Der PlaceableType wurde ohne Mod-Präfix angegeben.
Lösung:
<!-- FALSCH -->
<placeable type="extendedSilo">
<!-- RICHTIG -->
<placeable type="FS25_SiloExtension.extendedSilo">
❌ "Missing collision group FILLABLE"
Ursache: Der exactFillRootNode des UnloadTriggers hat kein FILLABLE-Flag.
Lösung: Im Giants Editor den Node auswählen → Collision Group → Bit 30 (FILLABLE) aktivieren.
❌ Box-Dialog öffnet sich nicht
Ursache: boxPlayerTrigger-Node hat falsche Collision-Maske oder Node-Pfad stimmt nicht.
Lösung:
- i3dMapping für
boxPlayerTriggerprüfen - Im Giants Editor Collision Group = TRIGGER (Bit 29), Collision Mask = PLAYER (Bit 20) setzen
- Sicherstellen dass der Node als Trigger konfiguriert ist (nicht als statisches Objekt)
Nächste Schritte
- ✅ Content-Mod mit
modDependenciesauf FS25_SiloExtension einrichten - ✅ Placeable-XML mit
boxSystemkonfigurieren - ✅ i3dMappings eintragen
- Im Giants Editor Trigger-Nodes korrekt konfigurieren
- Optional: FillPlane für Füllstand-Visualisierung einrichten
- Optional: SiloDisplay für 3D-Textanzeige einrichten