Zum Inhalt

Spielmechaniken

In base/content/game_mechanics/game_mechanics/ liegen die Spielsysteme des Basisspiels: Zeit und Wetter, Städte, das Unternehmen, Darlehen, Industrien, Emissionen, Benachrichtigungen, Subventionen, Erfolge, Feierlichkeiten und die Spaßelemente (Luftschiffe, UFOs, Feuerwerk). Jedes System besteht aus einem Game-Script und Ressourcen, die das Skript zur Laufzeit einsammelt. Ein Mod kann Ressourcen derselben Art hinzufügen. Diese Seite listet die Game-Scripts des Basisspiels auf und erklärt die Systeme, die ein Mod am ehesten erweitert: Benachrichtigungen, Subventionen, Unternehmensboni und Wirtschaften. Wie du selbst ein Game-Script schreibst, steht unter Scripting.

Die Game-Scripts des Basisspiels

Das Basisspiel hat 28 Game-Scripts (.gs.lua), das Deluxe-DLC bringt eines mit. Die Ordner liegen unterhalb von base/content/ (beim DLC dlcs/urbangames_deluxe_upgrade_pack/content/) und sind hier um den doppelten Zip-Ordner gekürzt. Die Beschreibungen ergeben sich aus den Events, die ein Skript abonniert, und aus seinen Zustands-Records.

Ordner Datei Was es steuert
game_mechanics/achievements/ achievements.gs.lua Erfolge; reagiert auf Events zu Konstruktionen, Lieferungen, Stufenaufstiegen, Linien und Bauvorschlägen
game_mechanics/arrival_tracker/ arrivaltracker.gs.lua zählt Personen und Güter, die an ihrem Ziel ankommen, für Filter, die anderer Code mit den Events onCreatePersonFilter und onCreateCargoFilter anlegt
game_mechanics/celebrations/ celebrations.gs.lua Feierlichkeiten, wenn eine Stadt oder das Unternehmen aufsteigt (OnLevelUp), und bei neuen Linienverbindungen
game_mechanics/company/ company.gs.lua den Zustand des Unternehmens: Genehmigungen, Begrünen von Industrien (MakeGreen), Marketingkampagnen, neue Industrien (spawnIndustry)
game_mechanics/company/ company_progression.gs.lua Erfahrung und Rang des Unternehmens (company_growth.script) sowie den Faktor für Ticketpreise (OnCalcTicketPrice)
game_mechanics/company/explorations/ exploration_plane.gs.lua das Erkundungsflugzeug einer Prospektion (startProspection, endProspection)
game_mechanics/emission/ emissions.gs.lua Lärm und Verschmutzung von Industrien, Stationen und Lagerhäusern
game_mechanics/finance/ loan.gs.lua Darlehen (Obtain, Repay)
game_mechanics/fun_elements/ fireworks.gs.lua Feuerwerk über Städten (startFireworkForTown)
game_mechanics/fun_elements/ fun_elements.gs.lua Luftschiffe für Marketingkampagnen und alle zwei bis vier Jahre ein UFO
game_mechanics/game_time/ game_time.gs.lua Tageszeit und Bewölkung (SetMode, SkipPhase)
game_mechanics/industries/ industries.gs.lua Ausbau und Schließung von Industrien
game_mechanics/notifications/ notifications.gs.lua die Liste der Benachrichtigungen
game_mechanics/notifications/ availability_notifications.gs.lua einmal im Jahr Benachrichtigungen über neu verfügbare Fahrzeuge und Konstruktionen
game_mechanics/subventions/ subventions.gs.lua Subventionen: Erscheinen, Fortschritt, Erfüllung und Scheitern
game_mechanics/towns/ town.gs.lua Bewertung der Städte, Marketingkampagnen und Ruf (towns.script)
game_mechanics/towns/ town_cargo.gs.lua Wachstum der Städte und ihren Güterbedarf (town_growth.script)
gui/context_helper/ context_helper.gs.lua ein einziges Flag: ob nach initNewGameFromMap der Willkommensbildschirm erscheint
gui/hud/ cargo_flow.gs.lua geladene und entladene Güter für die Anzeige im HUD
gui/hud/ greenification_display.gs.lua HUD-Anzeige begrünter Industrien
gui/hud/ happy_change_display.gs.lua HUD-Anzeige von Änderungen der Zufriedenheit (OnHappyChange)
gui/hud/ marketing_display.gs.lua HUD-Anzeige laufender Marketingkampagnen
industries/ industry_workers.gs.lua höhere Produktivität einer Industrie durch ankommende Arbeiter
landmarks/ landmarks.gs.lua Baufortschritt von Wahrzeichen durch gelieferte Güter (ItemsAboutToBeConsumed)
mission/ mission.gs.lua das Missionsskript, mission_sim.script mit gameScriptMode = "Mission"
mission/ guide_system.gs.lua dasselbe Skript mit gameScriptMode = "GuideSystem" für den Spielführer
terrain/ reforestation.gs.lua nachwachsende Bäume, wenn advancedOptions.isReforestationActive gesetzt ist
vehicle/ vehicle_modifier.gs.lua Modifikatoren für Geschwindigkeit, Lärm, Verschmutzung und Komfort von Fahrzeugen (ChangeModifier)
DLC fun_elements/ balloon.gs.lua den Heißluftballon (spawnBalloon) und seine Benachrichtigung

Viele dieser Skripte nennen in einem Kommentar am Anfang Konsolenbefehle, in subventions.script.tl etwa api.cmd.sendCommand(api.cmd.makeScriptingSendEventCmd("", "Subvention", "_debugSpawn", { })). Damit kannst du ein System schnell in der Konsole im Spiel ausprobieren.

Benachrichtigungen

Ein Benachrichtigungstyp besteht aus zwei Dateien mit demselben Basisnamen: einer generischen Ressource vom Typ notification und einer .script.tl, die einen NotificationType zurückgibt. Das Spiel hat 33 davon. 21 liegen in game_mechanics/notifications/types/, die übrigen neben dem System, das sie verschickt (company/, landmarks/, towns/, mission/). Mission 05 bringt drei weitere mit, das Deluxe-DLC eine.

Der Ballon aus dem Deluxe-DLC ist ein vollständiges Beispiel. Die Ressource, dlcs/urbangames_deluxe_upgrade_pack/content/fun_elements/fun_elements/balloon_notification.res.lua:

function data()
    return {
        type = "notification",
        data = {
            guiType = "Info",
            label = _("Hot Air Balloon Sighting"),
            initiallyIgnoredType = false,
        },
    }
end
Feld Bedeutung
guiType "Info", "Caution", "Problem", "Opportunity" oder "Achievement" (NotificationGuiData.Type); fehlt die Ressource, gilt "Unknown"
label Name des Typs im Filter des Protokolls „Benachrichtigungen“ (Notifications, notification_log.tl)
initiallyIgnoredType bei true ist der Typ in einem neuen Spiel zunächst ausgeblendet
simUpdateScript optional, "<file>@updateData": eine Funktion vom Typ NotificationSimType, die das Game-Script für Benachrichtigungen im Engine-Zustand aufruft; ihr Ergebnis wird als simParams der Benachrichtigung gespeichert

Ein Beispiel aus dem Basisspiel ist industry_close.res.lua mit simUpdateScript = "::/game_mechanics/notifications/types/industry_close.sim.script@updateData". Dessen updateData merkt sich den Namen der Industrie, solange es sie noch gibt. Die Ressourcen von Mission 05 haben nur guiType.

Das Skript, gekürzt aus balloon_notification.script.tl im selben Ordner:

local data : NotificationType<BalloonSpottedParam> = {}

data.useDataState = function(notificationParam : BalloonSpottedParam) : NotificationGuiData
    local nameState = engine_react_util.useStepStateTimer(function() : string
        -- ... der Name von notificationParam.townEntity ...
    end)

    return {
        title = _("Hot Air Balloon Sighting"),
        description = lang_util.format(_("People report that they have spotted a hot air balloon near {townName}"), {
            townName = nameState:old()
        }),
        icon = resolve("vehicle_balloon.tga"),
        wouldClick = notification_util.makeDefaultWouldClick({notificationParam.townEntity}),
        onClick = notification_util.makeDefaultOnClick({notificationParam.townEntity}),
    }
end

return data

useDataState(params, simParams) läuft in der GUI als Teil eines Recipes und gibt NotificationGuiData zurück: Titel, Text, Icon und optional einen Fortschrittsbalken, ein HUD-Icon, Sounds und die Klick-Handler. Laut Kommentar in der Definition soll die Funktion der letzte State im Recipe sein, ohne weiteren abhängigen State.

Eine Benachrichtigung zeigst du an, indem du das Event Notifications/add schickst. Aus balloon.script.tl:

api.cmd.sendCommand(api.cmd.makeScriptingSendEventCmd("", "Notifications", "add", {
    type = resolve("balloon_notification.script"),
    params = {
        entity = entity_util.makeEntityAndRevision0(balloon.entity),
        townEntity = entity_util.makeEntityAndRevision0(townEntity),
    },
    autoDismissDuration = notification_util.defaultAutoDismissDurationMs,
}))

type ist der Spielpfad des Skripts ohne .lua. notification_util.tl findet die Ressource, indem es .script durch .res ersetzt. Deshalb brauchen beide Dateien denselben Basisnamen. params kommen in useDataState an. autoDismissDuration blendet die Benachrichtigung nach so vielen Millisekunden aus (Standard 60000). Laut Kommentar in Notification ist das nicht dasselbe wie das Verwerfen. Alle Felder stehen in Notification.

Solange das Game-Script für Benachrichtigungen pausiert ist, verwirft es add-Events. Pausiert ist es zu Beginn einer Mission (initMission); das Game-Script der Mission schickt in seinen ersten beiden Updates Notifications/pause mit true und danach mit false. Eine Benachrichtigung, die vorher abgeschickt wird, geht verloren. Missionen können außerdem Typen mit notificationFilter ausblenden (Missionen), was das Missionsskript als updateIgnoredTypes weitergibt.

Die Bohrungs-Benachrichtigung aus Mission 05 zeigt die dauerhafte Art. Sie bleibt bestehen, solange eine Bedingung gilt, und ist an Entitäten gebunden. mods/release/urbangames_campaign_mission_05/content/mission/mission/tasks/drilling/drilling.tl schickt sie mit updatePersistent und entfernt sie mit removePersistent:

local persistentNotifications : PersistentNotifications = {
    type = "urbangames_campaign_mission_05::/mission/tasks/drilling/mission_drilling_notification.script",
    entitiesAndParam = {{
        entities = entity_util.makeEntityAndRevision0Array(getEntititesForNotification(entity)),
        param = notificationParams,
    }},
    passOnlyParam = true,
}
api.cmd.sendCommand(api.cmd.makeScriptingSendEventCmd("", "Notifications", "updatePersistent", persistentNotifications))

Wenn die Bohrung endet, entfernt die Aufgabe die dauerhafte Benachrichtigung und schickt mit add eine normale. Die Records sind PersistentNotifications und RemovePersistentNotifications, die Hilfsfunktionen stehen in notification_util.

Subventionen

Ein Subventionstyp ist eine generische Ressource vom Typ subvention, die auf ein Skript zeigt. Das Basisspiel hat vier davon in game_mechanics/subventions/ (deliver_cargo, deliver_cargo_town, deliver_passengers, deliver_workers), Mission 06 fügt deliver_visitors hinzu. Aus mods/release/urbangames_campaign_mission_06/content/subventions/subventions/deliver_visitors/deliver_visitors.res.lua:

function data()
return {
    type = "subvention",
    data = {
        scriptFile = "urbangames_campaign_mission_06::/subventions/deliver_visitors/deliver_visitors.script@deliver_visitors",
        icons = {
            fallback = "urbangames_campaign_mission_06::/subventions/deliver_visitors/deliver_visitors.tga",
        }
    }
}
end

scriptFile nennt eine Tabelle in der Skriptdatei; das Skript endet mit return { deliver_visitors = ret }. icons (SubventionIcons) kann auch proposed, active, complete und failed enthalten. Die ausgelieferten Dateien setzen nur fallback.

Die Tabelle ist ein SubventionScript. Das Game-Script für Subventionen ruft ihre Funktionen über den Namen auf:

Funktion Aufgerufen
canSpawn() um zu entscheiden, ob der Typ gerade erscheinen darf; deliver_visitors gibt true zurück, solange es ein Wahrzeichen ohne Subvention gibt
onSpawn() beim zufälligen Erscheinen; gibt die Daten der Subvention und eine UID zurück
spawnSpecific(param) wenn ein Skript diesen Typ mit vorgegebenen Zielen anfordert (siehe unten)
isComplete, onComplete, onFailure, onAccept, onUpdate, shouldDespawn, onDespawn während die Subvention angeboten oder aktiv ist
eventsToHandle, handleEvent für Spiel-Events, die der Typ braucht, zum Beispiel Ankünfte
getNotificationParams, getNotificationData, getNotificationMissedData für die Benachrichtigungen zur Subvention
getCardData, getRelevantEntities, getRelevantEntityNames für das Subventionsfenster

Die Daten, die ein Typ zurückgibt, folgen ISubvention.ISubventionData (ISubvention): Belohnungen oder Strafen für upfront, complete und failure (Geld, Ruf, Erfahrung der Stadt), dazu toDeliver, delivered und die Laufzeiten.

Das Game-Script lässt Subventionen zufällig erscheinen. Es sammelt mit getAllOfType("subvention") alle Ressourcen vom Typ subvention ein, behält die, deren canSpawn() true zurückgibt, und wählt eine davon aus. Der Abstand hängt von advancedOptions.subventionMode in der Basiskonfiguration ab: 0 schaltet Subventionen ab, 1, 2, 3 und 4 ergeben etwa 12, 6, 3 und 1 Monat, beim höchsten Unternehmensrang bis zum Doppelten (subvention_util.tl). Im Karten-Editor läuft das nicht. Mission 06 zeigt, dass auch der Typ eines Mods in diese Auswahl kommt, denn deliver_visitors hat ein funktionierendes canSpawn.

Ein Skript kann einen Typ auch gezielt erscheinen lassen. Die Missionsaufgabe subsidies des Basisspiels (base/content/mission/mission/tasks/subsidies/subsidies.tl) macht das so, und Mission 06 übergibt ihr deliver_visitors mit einem Wahrzeichen als target:

api.cmd.sendCommand(api.cmd.makeScriptingSendEventCmd("", "Subvention", "subventionSpawn", { name = subsidy[1], specific = subsidy[2] }))

name ist die Ressource ("urbangames_campaign_mission_06::/subventions/deliver_visitors/deliver_visitors.res"), specific enthält die Parameter für spawnSpecific. expireDurationProposed = -1 heißt, dass das Angebot nicht verfällt. Die Parameter-Records der Basistypen stehen in specific_subvention. Das Event Subvention/setPause mit true oder false hält das zufällige Erscheinen an und setzt es fort.

Unternehmensboni

Das Menü „Boni“ schaltet Dinge nach Unternehmensrang frei. Jeder Bonus hat einen Genehmigungsschlüssel, und rankAndPermits listet Paare {rank, permits}: Bei jedem dieser Ränge erhält das Unternehmen so viele zusätzliche Genehmigungen, die zusammengezählt werden (company_util.tl). Eine Genehmigung ist verbraucht, sobald der Spieler den Bonus baut oder startet. Wahrzeichen und das Hauptquartier sind Konstruktionen mit diesen Metadaten und werden unter Wahrzeichen beschrieben. Daneben gibt es drei weitere Arten.

Prospektionen sind generische Ressourcen vom Typ company_exploration, 12 davon liegen in game_mechanics/company/explorations/. Aus exploration_clay.res.lua:

function data()
return {
    type = "company_exploration",
    data = {
        cargoType = "::/cargos/clay/clay.cargo",
        icon = "game_mechanics/company/explorations/exploration_clay.tga",
        previewIcon = nil,
        lockedIcon = "game_mechanics/company/explorations/exploration_clay_locked.tga",
        rankAndPermits = {
            {3, 1},
        },
        requiredTags = {
            "OUTPUT_CLAY",
        },
        menuCategory = {
            categories = {
                {
                    category = "prospections",
                    order = 2000,
                },
            },
        },
    }
}
end

Das Baumenü (construction_react_util.tl) bietet eine Prospektion nur an, wenn eine Industrie der aktuellen Wirtschaft jedes Tag aus requiredTags in den tags ihrer placementParams hat. Die Prospektion ist dann ein Bonus der Kategorie PROSPECTION, und exploration_plane.gs.lua lässt das Erkundungsflugzeug fliegen. Statt eigener rankAndPermits kann sich eine Prospektion einen Genehmigungsschlüssel mit anderen teilen: exploration_grain.res.lua und exploration_vegetables.res.lua setzen permitKey = "::/game_mechanics/company/permitKeys/permit_key_farm.res". Die Felder stehen in Exploration.

Genehmigungsschlüssel sind generische Ressourcen vom Typ company_permit_key, drei davon liegen in game_mechanics/company/permitKeys/. Ein Schlüssel gibt mehreren Boni einen gemeinsamen Vorrat an Genehmigungen. Aus marketing.res.lua:

function data()
return {
    type = "company_permit_key",
    data = {
        name = _("Marketing"),
        rankAndPermits = {{4,1}},
        cooldownInSeconds = 5 * 4 * 365.25, -- 5 years
    }
}
end

hq.res.lua (Name „Headquarters“, {{1,1}}) ist der Schlüssel von landmarks/hq/hq/headquarter.con.lua, marketing.res.lua der des Werkzeugs „Marketingkampagne“ (Marketing Campaign) und permit_key_farm.res.lua (Name „Industry“) der beiden Farm-Prospektionen. Mit cooldownInSeconds kommt eine verbrauchte Genehmigung nach dieser Zeit zurück. Ein Bonus nennt seinen Schlüssel mit permitKey in den Unternehmens-Metadaten. Fehlt der Eintrag, ist der Ressourcenname des Bonus selbst sein Schlüssel (PermitKeyDesc).

Mechanik-Boni sind Werkzeuge oder Konstruktionen mit perkCategory = "MECHANICS" in ihren Unternehmens-Metadaten (CompanyMetadata.ConstructionDesc). Die „Reinigungsanlage“ (Cleaning Plant) ist eine Konstruktion, aus game_mechanics/game_mechanics/emission/pollution_cleanup_facility.con.lua:

constr.metadata = {
    company = {
        perkCategory = "MECHANICS",
        rankAndPermits = {
            {10, 15},
        },
    },
}

Die Werkzeuge „Industriebegrünung“ (Industry Greenification) und „Marketingkampagne“ (gui/gui/construction/tools/industry_greenify_tool.script.tl, marketing_campaign_tool.script.tl) sind Bauwerkzeuge, die dieselben Metadaten mit company_metadata.constructionDesc.make{ perkCategory = "MECHANICS", ... } setzen. Das Werkzeug „Industriebegrünung“ verwendet eine einfache Zeichenkette als Schlüssel (permitKey = "ECO_INDUSTRY") und erhält bei den Rängen 3, 6, 9, 12 und 15 je eine Genehmigung.

Das Basisspiel sammelt Prospektionen und Genehmigungsschlüssel mit getAllOfType ein. Eine Ressource desselben Typs aus einem Mod müsste also neben denen des Basisspiels erscheinen. Kein ausgelieferter Mod fügt eine hinzu, deshalb ist das nicht getestet.

Wirtschaften

Eine Wirtschaft (.eco.lua) legt fest, welche Industrien und Gütertypen ein Spiel verwendet und wie der Kartengenerator die Industrien platziert. Das Basisspiel hat fünf in base/content/economy/economy/: all, temperate, dry, tropic und subarctic. Die Missionen 02, 04, 06, 07 und 08 bringen eigene mit. Ein Klima nennt seine Standardwirtschaft im Feld economy (Klimas). Die für das Spiel gewählte Wirtschaft landet in baseConfig.economyId (base/content/base/base/mod.script.tl). Skripte lesen sie mit api.res.economyRep.get(api.res.economyRep.find(api.res.getBaseConfig().economyId)).

Das Ende von base/content/economy/economy/temperate.eco.lua:

return {
    desc = {
        name = _("Temperate"),
        icon = "temperate.tga"
    },
    category = "temperate.eco",
    cargoCategories = cargoCategories,
    waterIndustryFraction = 6.0 / 41.0,
    placementParams = placementParams,
    cargoRequiredIndustries = cargoRequiredIndustries,
    companyRankRequiredIndustries = companyRankRequiredIndustries,
    townLevels2CargoInfos = placementparamsutil.getDefaultTownLevels2CargoInfos(),
    defaultIndustryProductivity = 0.58,
    industryPlacementFallbacks = {
        oil_platform = "oil_well",
        sand_excavator = "sand_pit",
    },
}
Feld Bedeutung
desc, order, visible Name und Icon, Sortierreihenfolge und ob die Wirtschaft im Menü wählbar ist; die Wirtschaft von Mission 04 setzt visible = false
category das Tag, das Industrien und Gütertypen in ihrer categoryList führen müssen, um in dieser Wirtschaft vorzukommen
placementParams ein Eintrag pro Industrie, mit dem placementTag der Industrie als Schlüssel (siehe unten)
cargoCategories ein Eintrag pro Güterkategorie: tier, landUses, requiredIndustryTags, townConsumptionFactor
townLevels2CargoInfos pro Stadtlevel die Güterstufen und die Flächennutzung, nach denen Städte zu fragen beginnen
cargoRequiredIndustries pro Gut die Industrien seiner Lieferkette, jeweils mit einem Faktor
companyRankRequiredIndustries pro Unternehmensrang die Industrien, die der Rang auf der Karte braucht
industryPlacementFallbacks Ersatzindustrie, falls eine Industrie nicht platziert werden kann; hier eine Ölquelle an Land statt der Ölplattform
waterIndustryFraction, defaultIndustryProductivity Anteil der Industrien auf dem Wasser, Produktivität zu Beginn

Die Bedeutung der letzten fünf Zeilen ist aus Feldnamen und Werten abgeleitet. Die Definition (EconomyDesc) kommentiert nur desc, order, visible und category.

placementParams stammt aus placementparamsutil.getAllParams() in base/content/economy/economy/placementparamsutil.lua. Der erste Eintrag:

brewery = {
    buildOrder = 190,
    initWeight = 10,
    tags = { "INPUT_GRAIN", "INPUT_GLASS" },
    distanceWeights = {
        TOWN = CLOSE,
    },
    weights = {
        biome0 = BIOME_VERY_FAR,
        biome1 = BIOME_CLOSE,
        biome2 = BIOME_CLOSE,
        biome3 = BIOME_CLOSE,
        biome4 = BIOME_VERY_FAR,
    },
    requiredIndustryTags = {"glass_works", "farm"},
    tier = 1,
},

Der Schlüssel brewery ist der placementTag von industries/brewery/brewery/brewery.con.lua (Industrien). tags beschreiben, was die Industrie verbraucht und liefert (INPUT_*, OUTPUT_*); auf diese Tags prüfen die Prospektionen. distanceWeights ziehen die Industrie zu Städten oder zu Industrien mit bestimmten Tags hin (positiv) oder halten sie fern (negativ). Die Datei definiert die Werte von VERY_CLOSE = 2 bis VERY_FAR = -2. weights bewerten die Biom-Masken biome0 bis biome4, von BIOME_BEST = -8000 bis BIOME_VERY_FAR = 4000. requiredIndustryTags nennt die Industrien, die für diese vorhanden sein müssen, hier ihre Zulieferer. buildOrder und initWeight legen die Reihenfolge und das Anfangsgewicht beim Platzieren fest. allowedOnLand und allowedOnWater kennzeichnen Industrien auf dem Wasser wie oil_platform. Was tier bewirkt, ist nicht dokumentiert. Der Record ist PlacementParams.

Jede Wirtschaft geht von der vollständigen Liste aus und entfernt, was sie nicht braucht. Aus temperate.eco.lua:

local placementParams = placementparamsutil.getAllParams()

placementParams.cement_plant = nil
placementParams.paper_mill = nil
-- ...
local cargoCategories = placementparamsutil.getCargoCategories()
cargoCategories.cement = nil
cargoCategories.books = nil
-- ...
placementparamsutil.removeTags(placementParams, {"OUTPUT_RUBBER"})

Fehlt ein Eintrag, platziert der Kartengenerator diese Industrie nicht. Welche Konstruktionen und Gütertypen der Spieler sieht, wird an anderer Stelle entschieden: Die postRunFn des Basisspiels blendet jede Industrie und jeden Gütertyp aus, deren categoryList die category der Wirtschaft nicht enthält, außer in der Wirtschaft all (mod.script.tl). Die categoryList eines Gütertyps ist unter Gütertypen beschrieben.

Eine neue Industrie braucht beides: ihre .con.lua mit isIndustry = true, einem placementTag und den Kategorien der Wirtschaft in categoryList, und einen Eintrag in placementParams unter diesem Tag. Ohne den Eintrag gibt es die Industrie, aber die Wirtschaft platziert sie nicht. So hat pharmacy.con.lua aus Mission 04 placementTag = "pharmacy", aber keinen Eintrag in der Wirtschaft der Mission. Kein ausgelieferter Mod ergänzt eine Wirtschaft des Basisspiels. Nach dem Aufbau der Dateien zu urteilen, müsste ein loadEconomy-Modifier in runFn funktionieren. Diese Skizze ist nicht getestet:

function data()
return {
    runFn = function(captureParams, configDict, allModParams)
        addModifier("loadEconomy", function(fileName, data)
            if data.category == "temperate.eco" and data.placementParams then
                data.placementParams.jdoe_cider_press = {
                    buildOrder = 195,
                    initWeight = 10,
                    tags = { "INPUT_FRUIT" },
                    distanceWeights = { TOWN = 1 },
                    requiredIndustryTags = { "farm" },
                    tier = 1,
                }
            end
            return data
        end)
    end,
}
end

Die eigene Wirtschaft von Mission 04 behält category = "temperate.eco". Die Industrien und Gütertypen des Basisspiels, die diese Kategorie führen, bleiben dort also sichtbar. Ein Mod, der wie die Missionen eine ganze eigene Wirtschaft mitbringt, kann mit require "::/economy/placementparamsutil.lua" von placementparamsutil.getAllParams() ausgehen und die Tabelle anpassen. Das Repository ist api.res.economyRep.

Offizielles Wiki: Climates, Construction types, Cargo.