Back to Index Page generated: Aug 1, 2026, 4:49:47 AM

Expansion System Map

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Adds a local system map, accessible from the F7 screen, showing sun, planets, moons and main stations. Adds a local system map, accessible from the F7 screen, showing sun, planets, moons and main stations.
Identifier oolite.oxp.phkb.SystemMap oolite.oxp.phkb.SystemMap
Title System Map System Map
Category Miscellaneous Miscellaneous
Author phkb phkb
Version 0.7 0.7
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
  • oolite.oxp.Svengali.Library:1.10.3
  • oolite.oxp.Svengali.Library:1.10.3
  • Optional Expansions
    Conflict Expansions
    Information URL https://wiki.alioth.net/index.php/System_Map n/a
    Download URL https://wiki.alioth.net/img_auth.php/c/cb/SystemMap_0.7.oxz n/a
    License CC-BY-SA-NC 4.0 CC-BY-SA-NC 4.0
    File Size n/a
    Upload date 1782910536

    Relationships Diagram

    Documentation

    Also read http://wiki.alioth.net/index.php/System%20Map

    readme.txt

    System Map
    by phkb
    
    This mod adds a "System Map" view to either the F7 System Data screen (for Oolite 1.92) or the F4 Interfaces screen.
    To access the map on the F7 screen, simply press "S". On the F4 Interfaces screen, select the "View system map" item.
    
    What is shown
    =============
    The system map will show the following items for the current system:
        Sun
        Witchpoint beacon
        All planets and moons
        Most non-mobile stations with traffic
        Your current position
    
    The main station will the coloured blue to distinguish it from other stations.
    
    Planets are numbered in the following way:
        The main planet is "1".
        Other planets are numbered from 2-9 based on their distance from the sun.
    
    Planets can be either green (for a normal planet) or purple (for a gas giant).
    
    If the PlanetFall/PlanetFall2 mod is installed, planets and moons that have landing points will be marked with a hexagon.
    
    The map will show the position the various entities in relation to one another.
    
    Note: Changing the system viewed on the F7 screen will not show the system map for that system. The system map will only show the map for the current system.
    Note: The system map is unavailable in interstellar space.
    
    Map controls
    ============
    When accessed from the F7 screen, the following controls are available:
        Arrow keys: Rotate the map in the given direction.
        Ctrl+Arrow keys: Move the map up/down/left/right on the screen
        Page Up/Down: Zoom in/out.
        F: Change the current map focus.
        R: Reset the map back to the initial view.
        H: Hide the control information
    
    When access from the F4 Interfaces screen, the following menu will be available:
    
        Movement>>: Switch to the movement controls
        Move Up: Move the map up the screen
        Move Down: Move the map down the screen
        Move Left: Move the map to the left
        Move Right: Move the map to the right
        Rotation>>: Switch to the rotation controls
        Rotate Up: Rotate the map up
        Rotate Down: Rotate the map down
        Rotate Left: Rotate the map to the left
        Rotate Right: Rotate the map to the right
        Zoom In: Zoom the map in
        Zoom Out: Zoom the map out
        Change Focus: Changes the current map focus.
        Reset View: Reset the map back to the initial view
        Hide Controls: Hide most of the controls
        Show Controls: Un-hide all the controls.
    
    When you rotate the map, it will continue to rotate in the given direction until you issue another rotation command.
    
    Changing the map focus will change the color of all entities to grey except for the focused entity. The name of the focused entity will be displayed at the top of the screen. Repeating the focus command will cycle through all entities and then return to "None", when no entities are the focus. Resetting the view will also reset the focus.
    
    3rd Party access
    ================
    It is possible for other mods to add extra points of interest to the map. To do so, use the following code:
    
      var sm = worldScripts.SystemMap;
      
      // if you have an ship/station entity you want to show
      sm.$addCustomMarker({
        ent: myCustomShip,
        map: "markerimage.png",
        col: 1
      });
      
      // if you just want to mark a position
      var myPos = Vector3D(0.0, 0.0, 0.5).fromCoordinateSystem("wpu")
      sm.$addCustomMarker({
        pos: myPos,
        map: "markerimage.png",
        col: 2
      });
    
    When using the "ent" (entity) option, and this item becomes the map focus, the text displayed for it will follow the following logic:
        If a "displayName" property has been included in the definition for the marker, that will be used.
        If the entity has a displayName, that will be used.
        Otherwise, the entity name will be used.
    
    When using the "pos" (position) option, and this item becomes the map focus, the text displayed for it will follow the following logic:
        if a "displayName" property has been included in the definition for the marker, that will be used.
        The text "Point of interest" will be used.
    
    When included, the "map" should be an image in the Textures folder, 128x128 in size. Included with the System Map OXP are:
        map_planet.png
        map_planet_1-9.png
        map_planet_pf1-9.png
        map_moon.png
        map_moon_pf.png
        map_point.png
        map_question.png
        map_station.png
    
    Some others can be found in the Library OXP.
    
    If "map" is not included, it will default to "map_station.png".
    
    When included, the "col" should be a number between 0-9
        0 or not included: white
        1: red
        2: green
        3: blue
        4: purple
        5: gray
        6: aqua
        7: amber
        8: gold
        9: UV
        10: brown
        11: dark gray
        12: yellow
    
    Requirements
    ============
    The Library OXP is a requirement of this mod.
    
    Settings
    ========
    There is one setting available via Library Config.
    
    Value - Display units: This value allows the units used on the map to be changed. The available options are:
        0 = OU (1 OU roughly equals the distance between the planet and sun in Lave in an unmodified game)
        1 = km (default)
        2 = m
        3 = CZ (Cavezzi) (1 CZ = 0.47929218 m)
    
    License
    =======
    This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 4.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/
    
    Version History
    ===============
    0.7
    - Added distance to player to focused entity.
    - Distance unit type can be selected with Library Config.
    - For planets and moons that have a beacon attached (eg via Planetary Compass), the beacon label will be used for the display name.
    - Switched to using the custom marker system for the Tianve Pulsar.
    
    0.6
    - Added current system name to the title of the System Map screen, to make it clear it's for the current system only.
    
    0.5
    - Added some more error checks for the custom markers.
    - Reordered the way items are added to the array, so similar items (eg planets, stations) are always grouped together.
    - Added compatibility with PlanetFall v1.
    
    0.4
    - Tweak to script name to try to fix missing interface entry.
    
    0.3
    - Initial release.
    

    Equipment

    This expansion declares no equipment.

    Ships

    This expansion declares no ships.

    Models

    This expansion declares no models.

    Scripts

    Path
    Scripts/system_map.js
    "use strict";
    this.name = "Lib_SystemMap";
    this.author = "phkb";
    this.copyright = "2026 phkb";
    this.description = "Adds a system map, accessible from the F7 screen.";
    this.licence = "CC BY-NC-SA 4.0";
    
    this._exitScreen = "GUI_SCREEN_SYSTEM_DATA";
    this._custom = [];
    this._hint = false;
    this._distanceUnits = ["[systemmap_distance_ou]", "[systemmap_distance_km]", "[systemmap_distance_m]", "[systemmap_distance_cz]"];
    this._unitSelected = 1;
    
    this._libSettings = {
        Name: this.name,
        Display: expandDescription("[systemmap_display]"),
        Alias: expandDescription("[systemmap_alias]"),
        Alive: "_libSettings",
        SInt: {
            S0: { Name: "_unitSelected", Def: 1, Min: 0, Max: 3, Desc: expandDescription("[systemmap_units]") },
            Info: expandDescription("[systemmap_sint_info]")
        },
    };
    
    //-------------------------------------------------------------------------------------------------------------
    this.$addCustomMarker = function (obj) {
        if (!obj.ent && !obj.pos) {
            log(this.name, "No entity (obj.ent) or position (obj.pos) specified. Unable to add marker.");
            return;
        }
        if (!obj.map || obj.map == "") obj.map = "map_station.png";
        if (obj.hasOwnProperty("col") && isNaN(obj.col)) {
            log(this.name, "Invalid color (obj.col) value. Must be an integer between 0 and 12.");
            return;
        }
        obj._updated = false;
        if (obj.hasOwnProperty("displayName")) {
            obj._orig_displayName = obj.displayName;
            obj._updated = true;
        }
        this._custom.push(obj);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
        if (oolite.compareVersion("1.91") <= 0) {
            setExtraGuiScreenKeys(this.name, {
                guiScreen: "GUI_SCREEN_SYSTEM_DATA",
                registerKeys: { "systemkey": [{ key: "s" }] },
                callback: this.$localSystemMap.bind(this)
            });
    
            if (worldScripts.ContextualHelp) {
                worldScripts.ContextualHelp.$addHelpTextToGuiScreen(this.name, "GUI_SCREEN_SYSTEM_DATA", "\n" + expandDescription("[systemmap_helper]"));
            }
        } else {
            this.$initInterface(player.ship.dockedStation);
            this._exitScreen = "GUI_SCREEN_INTERFACES";
        }
    
        if (missionVariables.SystemMap_Units) this._unitSelected = parseInt(missionVariables.SystemMap_Units);
        // register our settings
        worldScripts.Lib_Config._registerSet(this._libSettings);
    
        // if the tianve pulsar isn't installed, delete the function that would otherwise run every jump
        if (!worldScripts["oolite-tianve"]) {
            delete this.shipExitedWitchspace;
        }
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerWillSaveGame = function () {
        missionVariables.SystemMap_Units = this._unitSelected;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipWillEnterWitchspace = function () {
        this._custom.length = 0;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipExitedWitchspace = function () {
        // add in the tianve pulsar, if installed
        if (galaxyNumber == 0 && system.ID == 246 && worldScripts["oolite-tianve"]) {
            var ve = system.allVisualEffects;
            for (var i = 0; i < ve.length; i++) {
                if (ve[i].dataKey == "tianve_pulsar_flashers") {
                    this.$addCustomMarker({ map: "lib_starmap_i8.png", pos: ve[i].position, col: 6, displayName: expandDescription("[systemmap_pulsar]") + this.$getDistance(ve[i].position) });
                    break;
                }
            }
        }
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipDockedWithStation = function (station) {
        if (oolite.compareVersion("1.91") > 0) {
            this.$initInterface(station);
        }
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.guiScreenChanged = function (to, from) {
        if (guiScreen == "GUI_SCREEN_SYSTEM_DATA" && oolite.compareVersion("1.91") <= 0 && !this._hint) {
            this._hint = true;
            player.consoleMessage(expandDescription("[systemmap_helper]"))
        }
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$initInterface = function $initInterface(station) {
        station.setInterface(this.name, {
            title: expandDescription("[systemmap_title]"),
            category: expandDescription("[systemmap_category]"),
            summary: expandDescription("[systemmap_summary]"),
            callback: this.$localSystemMap.bind(this)
        });
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$localSystemMap = function () {
        var p = player.ship;
        if (!p.docked) return; // only while docked
    
        if (system.isInterstellarSpace) {
            // inform player you can't access screen in interstellar space
            mission.runScreen({
                title: expandDescription("[systemmap_title]"),
                message: expandDescription("[systemmap_interstellar]"),
                exitScreen: this._exitScreen
            });
            return;
        }
    
        // make sure the planetary compass names have been run.
        if (worldScripts["planetaryCompass_worldScript.js"]) {
            worldScripts["planetaryCompass_worldScript.js"].$setUpNames();
        }
    
        // if xenon installed and active, pick the appropriate background
        var xenon = null;
        if (worldScripts.XenonUI) {
            var found = true;
            var lib = worldScripts.Lib_GUI;
            if (lib.$cur != "XenonUI") found = false;
            if (found) {
                var xui = worldScripts.XenonUI;
                xenon = { name: "xenon_" + xui._ratio + (xui._amber ? "_amber" : "") + ".png", height: 546 };
            }
        }
    
        var stn_found = false;
        if (p.docked && p.dockedStation.isMainStation) stn_found = true;
    
        // create array and add the sun
        var name = "";
    
        //if (system)
        var sini = [{ map: "lib_starmap_0.png", ent: system.sun, col: 12, displayName: this.$getName(system.sun) + this.$getDistance(system.sun.position) }];
    
        // add in the witchpoint
        var wp = system.shipsWithRole("buoy-witchpoint")[0];
        if (wp) {
            sini.push({ map: "lib_starmap_2.png", ent: wp, displayName: expandDescription("[systemmap_witchpoint]") + this.$getDistance(wp.position) });
        }
    
        // add in the players location
        if (p.docked && p.dockedStation.hasRole("planetFall2_surface")) {
            sini.push({ map: "map_point.png", pos: p.dockedStation.linkedVE.position, col: 1, displayName: expandDescription("[systemmap_yourlocation]") });
        } else {
            sini.push({ map: "map_point.png", ent: p, col: 1, displayName: expandDescription("[systemmap_yourlocation]") })
        }
    
        // add the main planet
        var pf = this.$planetHasLandingSpots(system.mainPlanet);
        if (system.mainPlanet.isGasGiant || system.mainPlanet.solarGasGiant) {
            sini.push({ map: "map_planet_1.png", ent: system.mainPlanet, col: 4, displayName: this.$getName(system.mainPlanet) + this.$getDistance(system.mainPlanet.position) });
        } else {
            sini.push({ map: "map_planet_" + (pf ? "pf" : "") + "1.png", ent: system.mainPlanet, col: 2, displayName: this.$getName(system.mainPlanet) + this.$getDistance(system.mainPlanet.position) });
        }
    
        // add all the planets and moons (except for the main planet)
        function plfn(entity) { return entity.isPlanet && !entity.isMainPlanet; }
    
        var pl = system.filteredEntities(this, plfn, system.sun);
        var p_count = 2;
        for (var i = 0; i < pl.length; i++) {
            pf = this.$planetHasLandingSpots(pl[i]);
            if (!pl[i].hasAtmosphere) {
                sini.push({ map: "map_moon" + (pf ? "_pf" : "") + ".png", ent: pl[i], col: 10, displayName: this.$getName(pl[i]) + this.$getDistance(pl[i].position) });
            } else {
                if (p_count > 9) {
                    if (pl[i].solarGasGiant || pl[i].isGasGiant) {
                        sini.push({ map: "map_planet.png", ent: pl[i], col: 4, displayName: this.$getName(pl[i]) + this.$getDistance(pl[i].position) });
                    } else {
                        sini.push({ map: "map_planet" + (pf ? "_pf" : "") + ".png", ent: pl[i], col: 2, displayName: this.$getName(pl[i]) + this.$getDistance(pl[i].position) });
                    }
                } else {
                    if (pl[i].solarGasGiant || pl[i].isGasGiant) {
                        sini.push({ map: "map_planet_" + p_count + ".png", ent: pl[i], col: 4, displayName: this.$getName(pl[i]) + this.$getDistance(pl[i].position) });
                    } else {
                        sini.push({ map: "map_planet_" + (pf ? "pf" : "") + p_count + ".png", ent: pl[i], col: 2, displayName: this.$getName(pl[i]) + this.$getDistance(pl[i].position) });
                    }
                }
                p_count += 1;
            }
        }
    
        // add the main station
        sini.push({ map: "map_station.png", ent: system.mainStation, col: 3, displayName: this.$getName(system.mainStation) + this.$getDistance(system.mainStation.position) });
    
        // add all the main stations (except for the actual main station)
        function stfn(entity) {
            return entity.isShip &&
                entity.hasNPCTraffic && // only stations with traffic
                (entity.scanClass != "CLASS_ROCK" || entity.beaconCode != null) && // only rock hermits with a beacon
                (["hunter", "neutral", "private"].indexOf(entity.allegiance) == -1 || entity.beaconCode != null) && // only hunter/neutral/private stations with a beacon          
                !entity.hasRole("planetFall2_surface") && // not planetfall locations
                !entity.isMainStation && // not the main station
                entity.maxSpeed == 0; // must not be moving
        }
    
        var stns = system.filteredEntities(this, stfn, system.mainPlanet);
        for (var i = 0; i < stns.length; i++) {
            if (p.docked && stns[i] == p.dockedStation) stn_found = true;
            sini.push({ map: "map_station.png", ent: stns[i], displayName: this.$getName(stns[i]) + this.$getDistance(stns[i].position) });
        }
    
        // make sure the players current station is on the map.
        if (stn_found == false) {
            if (p.docked && !p.dockedStation.hasRole("planetFall2_surface")) {
                sini.push({ map: "map_station.png", ent: p.dockedStation, col: 5, displayName: this.$getName(p.dockedStation) });
            }
        }
    
        // add any custom items
        if (this._custom.length > 0) {
            for (var i = 0; i < this._custom.length; i++) {
                var pos = p.position;
                if (this._custom[i].hasOwnProperty("ent")) pos = this._custom[i].ent.position;
                if (this._custom[i].hasOwnProperty("pos")) pos = this._custom[i].pos;
    
                if (this._custom[i]._updated == false) {
                    this._custom[i].displayName = this.$getName(this._custom[i].ent) + this.$getDistance(pos);
                } else {
                    this._custom[i].displayName = this._custom[i]._orig_displayName + this.$getDistance(pos);
                }
                sini.push(this._custom[i]);
            }
        }
    
        worldScripts.Lib_Starmap._start({
            ini: sini,
            title: expandDescription("[systemmap_screen_title]"),
            exit: this._exitScreen,
            viewControls: true,
            background: xenon,
            exitText: expandDescription("[systemmap_close]")
        });
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$getDistance = function (pos) {
        var dist = player.ship.position.distanceTo(pos);
        if (Math.round(dist) == 0) return "";
        return expandDescription(this._distanceUnits[this._unitSelected], { dist: dist });
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$getName = function (entity) {
        if (entity.isPlanet && !entity.isMainPlanet) {
            var beacon = this.$checkForBeacon(entity);
            if (beacon && beacon.beaconLabel && beacon.beaconLabel != "") {
                return beacon.beaconLabel;
            }
        }
        if (entity.displayName && entity.displayName != "") {
            return entity.displayName;
        } else if (entity.name && entity.name != "") {
            return entity.name;
        }
        return "";
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$checkForBeacon = function (entity) {
        var beacons = this.$findEntitiesWithBeacons(entity);
        if (beacons.length == 0) return null;
        return beacons[0];
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$findEntitiesWithBeacons = function (entity) {
        function _beacons(ent) {
            return !(ent.isPlayer) &&
                (ent.beaconCode != "" && ent.beaconCode != null) &&
                (ent.displayName != "Jump Marker") &&
                (ent.AI != "EscortDeck_AI.plist");
        }
        return system.filteredEntities(this, _beacons, entity, 1000);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$planetHasLandingSpots = function (planet) {
        if (!worldScripts.PlanetFall2 && !worldScripts.PlanetFall) return false;
        if (worldScripts.PlanetFall) {
            return !(planet.hasOwnProperty("PFNoLand") || planet.hasOwnProperty("solarGasGiant") || planet.hasOwnProperty("isGasGiant"));
        }
        return (worldScripts.PlanetFall2.$getPlanetLandingSites(planet).length > 0);
    }