Skip to content

javascript Overview

ghost-ng edited this page Jan 29, 2026 · 2 revisions

JavaScript Scripting Overview

Civilization VII uses JavaScript (compiled from TypeScript) for scripting, replacing Lua from previous Civilization games. Scripts handle map generation, age transitions, UI functionality, and gameplay events.

Script Types

Map Generation Scripts

Located in maps/ directories, these scripts generate terrain, place resources, and set up the map.

Loaded via modinfo:

<MapGenScripts>
    <Item>maps/my-map-script.js</Item>
</MapGenScripts>

Required Events:

engine.on("RequestMapInitData", requestMapData);
engine.on("GenerateMap", generateMap);

Scenario/Gameplay Scripts

Handle game events during age transitions and gameplay scenarios.

Loaded via modinfo:

<ScenarioScripts>
    <Item>scripts/my-gameplay-script.js</Item>
</ScenarioScripts>

UI Scripts

Handle user interface, panels, and visual elements.

Loaded via modinfo:

<UIScripts>
    <Item>ui/my-panel.js</Item>
</UIScripts>

Global Objects Reference

Core Game Objects

Object Description
Game Current game state, rules, turn info, age
Players Collection of all players
Units Unit management and creation
Cities City management
Armies Army/commander management
GameInfo Database table access
GameplayMap Map data and queries
GameContext Context info (local player, etc.)

Map Generation Objects

Object Description
TerrainBuilder Set terrain, features, elevations
ResourceBuilder Place and manage resources
MapCities City placement on map

Configuration Objects

Object Description
Configuration Game/map configuration values
Database Direct database operations, hash creation

UI Objects

Object Description
UI UI control and player interface
Locale Localization/text composition
engine Engine event system
ContextManager UI context/screen management

Engine Event System

The engine object handles communication between scripts and the game engine.

Subscribing to Events

// Subscribe to event
engine.on("EventName", callbackFunction);

// With context binding
engine.on("EventName", this.myHandler, this);

Calling Engine Functions

engine.call("FunctionName", parameters);

Complete Engine Events Reference

Map Generation Events

Event Description Parameters
RequestMapInitData Request map initialization data -
GenerateMap Generate the map -

Age Transition Events

Event Description Parameters
RequestAgeInitializationParameters Age transition starting initParams (numMajorPlayers, outgoingAge, incomingAge)
GenerateAgeTransition Generate age transition content -

Game State Events

Event Description Parameters
GameStarted Game has started -
TurnBegin Turn begins playerId
TurnEnd Turn ends playerId
LocalPlayerTurnBegin Local player turn starts -
LocalPlayerTurnEnd Local player turn ends -

Unit Events

Event Description Parameters
UnitAddedToMap Unit placed on map unitId
UnitRemovedFromMap Unit removed from map unitId
UnitMoved Unit movement complete unitId, x, y
UnitMovementPointsChanged Unit MP changed unitId, data
UnitPromoted Unit gained promotion unitId, promotionType

City Events

Event Description Parameters
CityAddedToMap City placed on map cityId
CityRemovedFromMap City removed cityId
CitySelectionChanged Selected city changed cityId
CityPopulationChanged Population changed cityId, population
CityProductionCompleted Production finished cityId, productionType

Construction Events

Event Description Parameters
DistrictAddedToMap District placed districtInfo
ConstructibleAddedToMap Building/improvement placed constructibleInfo
RouteAddedToMap Road/route placed routeInfo

Plot Events

Event Description Parameters
PlotVisibilityChanged Plot visibility updated plotIndex
PlotEffectAddedToMap Effect added to plot effectInfo
PlotEffectRemovedFromMap Effect removed effectInfo

UI Events

Event Description Parameters
InputAction Input received actionData
CameraChanged Camera position changed cameraInfo
UpdateFrame Frame update tick -
EndFrame Frame ended -
UIGameLoadingProgressChanged Loading progress progress

Network Events

Event Description Parameters
NetworkDisconnected Lost connection -
NetworkReconnected Connection restored -
UserRequestClose User requested close -

Audio Events

Event Description Parameters
AudioEventReturned Audio event completed tag

Example: Age Transition Script

function requestInitializationParameters(initParams) {
    console.log("Players:", initParams.numMajorPlayers);
    console.log("Old Age:", initParams.outgoingAge);
    console.log("New Age:", initParams.incomingAge);

    // Modify parameters if needed
    engine.call("SetAgeInitializationParameters", initParams);
}

function generateTransition() {
    console.log("Generating age transition!");

    // Get all players
    const players = Players.getEverAlive();
    for (const player of players) {
        // Process each player's transition
        console.log("Processing player:", player.id);
    }
}

engine.on("RequestAgeInitializationParameters", requestInitializationParameters);
engine.on("GenerateAgeTransition", generateTransition);

Game Object API

The Game object provides access to current game state and rules.

// Current age (as hash)
const currentAge = Game.age;

// Compare ages
if (Game.age == Database.makeHash("AGE_EXPLORATION")) {
    // In Exploration Age
}

// Placement rules
const validLocation = Game.PlacementRules.getValidOceanNavalLocation(playerId);

// Economic rules (adjust for game speed)
const adjustedGold = Game.EconomicRules.adjustForGameSpeed(3000);

Game Properties

Property Type Description
Game.age Hash Current age hash
Game.turn Integer Current turn number
Game.PlacementRules Object Placement validation methods
Game.EconomicRules Object Economy adjustment methods

GameInfo Database Access

Access database tables directly through GameInfo:

// Iterate all entries in a table
for (const resource of GameInfo.Resources) {
    console.log(resource.ResourceType);
}

// Lookup by type string
const unitInfo = GameInfo.Units.lookup("UNIT_WARRIOR");

// Lookup by hash
const hash = Database.makeHash("UNIT_WARRIOR");
const unitInfo = GameInfo.Units.lookup(hash);

// Get metadata
const resourceInfo = GameInfo.Resources.lookup(resourceType);
const index = resourceInfo.$index;    // Internal index
const typeHash = resourceInfo.$hash;  // Type hash

Common GameInfo Tables

Table Content
GameInfo.Units Unit definitions
GameInfo.Buildings Building definitions
GameInfo.Civilizations Civilization definitions
GameInfo.Leaders Leader definitions
GameInfo.Resources Resource definitions
GameInfo.Features Map feature definitions
GameInfo.Feature_NaturalWonders Natural wonder list
GameInfo.Technologies Technology definitions
GameInfo.Civics Civic definitions
GameInfo.Ages Age definitions
GameInfo.Resource_Distribution Resource placement rules
GameInfo.Unit_ShadowReplacements Unit upgrades for age transitions
GameInfo.MapIslandBehavior Island map behavior
GameInfo.Terrains Terrain definitions
GameInfo.Biomes Biome definitions

Players API

Getting Players

// Get specific player by ID
const player = Players.get(playerId);

// Get all ever-alive players (includes eliminated)
const playerList = Players.getEverAlive();

// Get local player
const localPlayer = Players.get(GameContext.localObserverID);

// Iterate all players
for (const player of Players.getEverAlive()) {
    if (player.isAlive) {
        console.log("Active player:", player.id);
    }
}

Player Properties

const player = Players.get(playerId);

// Basic info
player.id                    // Player ID
player.civilizationType      // Civilization hash
player.leaderType           // Leader hash
player.isAlive              // Is still in game
player.isMajor              // Is major civilization
player.isHuman              // Is human player

// Player components (sub-objects)
player.Cities               // City management
player.Units                // Unit management
player.Treasury             // Gold balance
player.DiplomacyTreasury    // Influence balance
player.AdvancedStart        // Age transition cards
player.Diplomacy            // Diplomatic relations

// Custom properties (for mods)
player.getProperty("PROPERTY_NAME");
player.setProperty("PROPERTY_NAME", value);

Player Cities Component

const cities = player.Cities;

// Get city IDs
const cityIds = cities.getCityIds();

// Get cities collection
const cityList = cities.getCities();

// Get capital
const capital = cities.getCapital();

// Find closest city to location
const nearest = cities.findClosest(location);

// City count
const count = cities.getCityCount();

Player Units Component

const units = player.Units;

// Get all unit IDs
const unitIds = units.getUnitIds();

// Get buildable unit type (considering unlocks)
const unitType = units.getBuildUnit("UNIT_WARRIOR");

// Unit shadows (for age transitions)
const shadows = units.getUnitShadows();

Units API

Getting and Creating Units

// Get unit by ID
const unit = Units.get(unitId);

// Create a unit
const result = Units.create(playerId, {
    Type: unitType,      // Unit type hash or string
    Location: location,  // {x, y} or plot index
    Validate: true       // Validate placement (optional)
});

if (result.Success && result.ID) {
    console.log("Created unit:", result.ID);
    const newUnit = Units.get(result.ID);
}

// Move unit to location
Units.setLocation(unitId, newLocation);

// Delete unit
Units.destroy(unitId);

Unit Properties

const unit = Units.get(unitId);

// Basic info
unit.id                  // Unit ID
unit.name                // Display name
unit.type                // Unit type hash
unit.location            // Current location {x, y}
unit.owner               // Owner player ID
unit.movementPoints      // Remaining movement
unit.maxMovementPoints   // Maximum movement

// Army/commander info
unit.armyId              // Army ID (if in army)
unit.isCommanderUnit     // Is a commander
unit.isArmyCommander     // Is army commander
unit.isFleetCommander    // Is fleet commander

// Components
unit.Experience          // Experience component
unit.Combat              // Combat component

// Custom properties (for mods)
unit.getProperty("PROPERTY_NAME");
unit.setProperty("PROPERTY_NAME", value);

Armies API

// Get army by ID
const army = Armies.get(armyId);

// Army properties
army.id                  // Army ID
army.commanderId         // Commander unit ID
army.location            // Current location

// Get units in army
const unitIds = army.getUnitIds();

// Create army with commander
const result = Armies.create(playerId, commanderUnitId);

Cities API

// Get city by ID
const city = Cities.get(cityId);

// Basic info
city.id                  // City ID
city.name                // City name
city.location            // Location {x, y}
city.owner               // Owner player ID
city.population          // Current population
city.isCapital           // Is capital city
city.isTown              // Is a town (no build queue)

// Components
city.Trade               // Trade component
city.Production          // Production component
city.Growth              // Growth component

// Trade connection check
city.Trade?.isConnectedToOwnersCapitalByLand();
city.Trade?.isConnectedToOwnersCapitalBySea();

// Change settlement type
city.changeHasBuildQueue(-1);  // Regress to town
city.changeHasBuildQueue(1);   // Upgrade to city

GameplayMap API

// Map dimensions
const width = GameplayMap.getGridWidth();
const height = GameplayMap.getGridHeight();
const totalPlots = GameplayMap.getPlotCount();

// Plot queries by coordinates
const terrain = GameplayMap.getTerrainType(x, y);
const resource = GameplayMap.getResourceType(x, y);
const feature = GameplayMap.getFeatureType(x, y);
const biome = GameplayMap.getBiomeType(x, y);
const elevation = GameplayMap.getElevation(x, y);
const continent = GameplayMap.getContinentType(x, y);

// Hemisphere info
const hemisphere = GameplayMap.getHemisphere(x);
const primaryHemisphere = GameplayMap.getPrimaryHemisphere();

// Landmass info
const landmassId = GameplayMap.getLandmassId(x, y);
const landmassRegionId = GameplayMap.getLandmassRegionId(x, y);

// Index conversions
const index = GameplayMap.getIndexFromXY(x, y);
const location = GameplayMap.getLocationFromIndex(index);

// Adjacency
const neighbors = GameplayMap.getAdjacentPlots(x, y);

// Visibility
const isVisible = GameplayMap.isPlotVisible(playerId, x, y);
const isRevealed = GameplayMap.isPlotRevealed(playerId, x, y);

// Random (deterministic from seed)
const seed = GameplayMap.getRandomSeed();

TerrainBuilder API

For map generation scripts:

// Set terrain
TerrainBuilder.setTerrainType(x, y, terrainType);
TerrainBuilder.setBiomeType(x, y, biomeType);
TerrainBuilder.setElevation(x, y, elevation);

// Set features
TerrainBuilder.setFeatureType(x, y, featureType);
TerrainBuilder.canHaveFeature(x, y, featureType);

// Feature with parameters
TerrainBuilder.setFeatureType(x, y, featureParam);
TerrainBuilder.canHaveFeatureParam(x, y, featureParam);

// Generate procedural maps
TerrainBuilder.generatePoissonMap(seed, avgDistance, smoothing);
TerrainBuilder.generateFractal(seed, octaves, persistence);

// Random numbers (seeded)
const roll = TerrainBuilder.getRandomNumber(max, "description");

// Store data for later processing
TerrainBuilder.storeWaterData();

// Continent assignment
TerrainBuilder.setContinentType(x, y, continentType);

ResourceBuilder API

// Set resources
ResourceBuilder.setResourceType(x, y, resourceType);
ResourceBuilder.canHaveResource(x, y, resourceType, strict);

// Query resources
const counts = ResourceBuilder.getResourceCounts(playerId);  // -1 for all players
const generated = ResourceBuilder.getGeneratedMapResources();

// Age validation
ResourceBuilder.isResourceValidForAge(resourceType, ageType);
ResourceBuilder.isResourceRequiredForAge(resourceType, ageType);
ResourceBuilder.isResourceClassRequiredForLegacyPath(resourceType);

// Landmass assignment
ResourceBuilder.getResourceLandmass(resourceIndex);

// Resource balancing
const cuts = ResourceBuilder.getBestMapResourceCuts(newResources, numToCut);

Database Utilities

// Create hash from string
const hash = Database.makeHash("TYPE_STRING");

// Compare with database values
if (Game.age == Database.makeHash("AGE_EXPLORATION")) {
    // In Exploration Age
}

if (player.civilizationType == Database.makeHash("CIVILIZATION_ROME")) {
    // Playing as Rome
}

Configuration API

// Game configuration
const speed = Configuration.getGameValue("SpeedType");
const difficulty = Configuration.getGameValue("Handicap");
const mapSize = Configuration.getGameValue("MapSize");

// Map configuration
const mapScript = Configuration.getMapValue("Script");
const requests = Configuration.getMapValue("RequestedNaturalWonders");
const temperature = Configuration.getMapValue("Temperature");
const rainfall = Configuration.getMapValue("Rainfall");

// User configuration
const userConfig = Configuration.getUser();
userConfig.firstTimeTutorialEnabled;
userConfig.setFirstTimeTutorialEnabled(false);
userConfig.saveCheckpoint();

Locale/Localization

// Compose localized text from LOC key
const text = Locale.compose("LOC_UNIT_WARRIOR_NAME");  // "Warrior"

// With parameters
const text = Locale.compose("LOC_CITY_FOUNDED", cityName);

Logging and Debugging

// Console logging (appears in logs)
console.log("Info message");
console.warn("Warning message");
console.error("Error message");

// Debug with values
console.log("Player ID:", playerId, "City count:", cityCount);

Logs appear in: %LOCALAPPDATA%\Firaxis Games\Sid Meier's Civilization VII\Logs\


Module System

Scripts use ES6 module imports:

// Import from other modules
import { functionName } from '../path/to/module.js';
import { shuffle, randomElement } from './map-utilities.js';
import * as MapUtils from './map-utilities.js';

// Export functions for use by other scripts
export function myFunction() { }
export const myVariable = 42;
export { myFunction, myVariable };

// Default export
export default class MyClass { }

UI Custom Events

UI scripts use custom DOM events:

// Creating custom events
class MyEvent extends CustomEvent {
    constructor(data) {
        super("my-event-name", {
            bubbles: true,
            cancelable: true,
            detail: { data }
        });
    }
}

// Dispatching events
window.dispatchEvent(new CustomEvent("user-interface-loaded-and-ready"));
window.dispatchEvent(new MyEvent({ value: 42 }));

// Listening for events
window.addEventListener("engine-input", handleInput);
window.addEventListener("my-event-name", (event) => {
    console.log("Received:", event.detail);
});

Interface Modes

import { InterfaceMode } from '../interface-modes/interface-modes.js';

// Switch interface mode
InterfaceMode.switchTo("INTERFACEMODE_DEFAULT");
InterfaceMode.switchTo("INTERFACEMODE_PAUSE_MENU");
InterfaceMode.switchTo("INTERFACEMODE_SCREENSHOT");
InterfaceMode.switchTo("INTERFACEMODE_SELECTION");

// Check current mode
if (InterfaceMode.isInInterfaceMode("INTERFACEMODE_PAUSE_MENU")) {
    // Game is paused
}

// Register custom mode handler
class MyInterfaceMode {
    transitionTo(oldMode, newMode, context) {
        // Called when switching to this mode
        console.log("Entering my mode from:", oldMode);
    }

    transitionFrom(oldMode, newMode) {
        // Called when leaving this mode
        console.log("Leaving my mode for:", newMode);
    }

    allowsHotKeys() {
        return true;  // Allow hotkeys in this mode
    }

    handleInput(inputData) {
        // Handle input while in this mode
        return false;  // Return true if handled
    }
}

InterfaceMode.addHandler("INTERFACEMODE_MY_MODE", new MyInterfaceMode());

Common Patterns

Iterating All Plots

const width = GameplayMap.getGridWidth();
const height = GameplayMap.getGridHeight();

for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
        const terrain = GameplayMap.getTerrainType(x, y);
        // Process each plot
    }
}

Finding Valid Locations

function findValidCityLocation(playerId) {
    const player = Players.get(playerId);
    const capital = player.Cities.getCapital();

    // Search outward from capital
    const neighbors = GameplayMap.getAdjacentPlots(capital.location.x, capital.location.y);

    for (const plot of neighbors) {
        if (isValidForCity(plot.x, plot.y)) {
            return plot;
        }
    }
    return null;
}

Safe Property Access

// Use optional chaining for components that may not exist
const isConnected = city.Trade?.isConnectedToOwnersCapitalByLand() ?? false;

// Check before accessing
if (player.Diplomacy) {
    const relations = player.Diplomacy.getRelationsWith(otherPlayerId);
}

Error Handling

try {
    const result = Units.create(playerId, { Type: unitType, Location: loc });
    if (!result.Success) {
        console.error("Failed to create unit:", result.Error);
    }
} catch (error) {
    console.error("Exception creating unit:", error);
}

See Also

Clone this wiki locally