Modding Maps

### STF Map Concepts

Each in STF is made by 2 sets of major resources -- a Tiled tile map (type .tmx) and a map database that contains all the data that is assigned to the objects in the tile map. For example, a galactic map and its jump routes are determined by a map\_X.db database which links to either version 1 galactic tile map (world\_map.tmx) or the larger and expanded version 2 galactic tile map (world\_map2.tmx). Each quadrant's layout, jumps and zones are determined by a tile map (maps/region\_X\_map\_1.tmx files) and additional data in the same map\_X.db database.

The components of map generation in STF are:

* the galactic maps layouts (./modversion/maps/world\_map.tmx=v1 default map & world\_map2.tmx=v2 default map )
	+ the files do not contain ANY gates connections/edges info at all => we must generate them in table map\_x.MapGate (this is one of the most important tables!)
* the quadrant maps layouts (all the ./modversion/maps/region\_x\_map\_1.tmx with x in [1,74] also see table data.Region column tmxPath):
	+ \_id in table mapquadrant references [objects].name in world map if you export tmx in json
	+ regionId in table mapquadrant references the tmx file to be used (ex in old default map Orion Expanse quadrant \_id=25 uses regionId=2)
* data.Region table : driver table for all the quadrant assignment to their layouts (.tmx)
	+ quad danger (data.Region fields minLevel and MaxLevel are added together)
	+ respawnDice => 40% of economies will be this type
	+ restorePurge => Default Faction Owner, 0 for random weighted
	+ respawn =1=> starting quadrants

```
select mq.name
from mapquadrant mq, region r
where mq.regionid=r.\_id
# and r.respawn =1
Dixye Maelstrom
Thog's Loop
Orion Expanse
Briens Corridor
Garrick Void
Fifth Pass
Cadrino Belt
Hyperion Abyss
Infinite Drift

```

* data.RegionMapWorld table: all the positions/coordinates of planets from all quad map layouts
* data.RegionMapGate table: all the positions/coordinates of gates from all quad map layouts
* data.RegionMapData table: quad layout max tiles (30x30 -> 70x70)
* all the other tables described in Map Database Modding

For Python users I highly recommend: https://networkx.org/documentation/stable/

The game constructs a full graph of the world map using Nodes=quadrants & Edges=gates.

A v1-default-map-like should have 90 gates/edges and 63 quadrants/nodes as an example.

**Important notes:**

* **4 gates/edges max per quadrant/node , even the full graph has this property**
* BE CAREFUL when modifying static/story quads (or any zone that has a storyId >0 for that matter) like:
	+ quad \_id=42=>Alzean Core
	+ quad \_id=31=>Farfallen Rim (FFR)
	+ quad \_id=9=>Cirm Sector
	+ this list could change with new STF updates

```
getNodes = "select \_id from mapquadrant order by 1"
getEdges = "select quadrant1\_id, quadrant2\_id from mapgate"

```

In order to create a pseudo random map the following steps are performed (very simplistic educated guess description)

1. some nodes and edges will be set to inactive (see below how to detect them) => subgraph to be shown => create MapGate, MapQuadrant accordingly (they contain full graph info with only the subgraph being active =1)
2. reconstruct the map\_x.MapRouteDistance accordingly using the subgraph
3. populate the MapZone, MapPlanet tables for the subgraph only -- Note :not all planets defined in the quad layout have to be shown , some of them can be hidden (if they do not exist in map\_x.MapPlanet corresponding columns regionId worldId -- see difference with data.RegionMapWorld )
4. populate table MapResourceQuadrant (quad \_id with RareTradeGoods)

```
--- for Point 1: gates/edges nodes/quads being active ---
getNodes = "select \_id from mapquadrant where active = 1 order by 1"
getEdges = "select quadrant1\_id, quadrant2\_id from mapgate where active =1"

```

=> the FINAL result is the player seed map

### Example 1: Modify coordinates of quadrants w/o changing gates/edges data

Use Tiled , open one of the existing world\_map (tmx), modify the node/quadrants coordinates as you like(snap to grid is important=>X,Y = multiple of 38).

Make sure that gate lines don't intersect (I haven't tested this to see if it crashes STF)

Make sure you copy your modded world\_map.tmx file in the ./modversion/maps/ folder

Test your mod.

### Example 2: Modify coordinates of quadrants and change gates/edges data (no changes to the quadrants layouts, planets or zones)

Use Tiled , open one of the existing world\_map (tmx), modify the node/quadrants coordinates as you like(snap to grid is important=>X,Y = multiple of 38).

Make sure you copy your modded world\_map.tmx file in the ./modversion/maps/ folder

Recreate/Update the map\_x.MapGate (all gates either active and inactive -- 1 row for each edge in the full graph => number of full graph edges = number of rows in MapGate table) and

recreate/update the map\_x.MapQuadrant(all nodes either active and inactive -- 1 row for each quadrant in the full graph => number of full graph nodes = number of rows in MapQuadrant table):

* remember the max 4 gates per quad rule!
* reposition the quadrant\_dir1 and quadrant\_dir2 directions of gates accordingly (1=North, 2=East, 3 South, 4=West)

Ex: edge (25,28) has dir1 = 1 and dir2 = 3 => we use the northern gate in quad 25 and we arrive in southern gate in quad 28

edge(7,28) has dir1 = 1 and dir2 = 4 => we use the northern gate in quad 7 and we arrive in western gate in quad 28

edge(33,25) has dir1 = 4 and dir2 =2 => we use the western gate in quad 33 and we arrive in eastern gate in quad 25

So per node you need to be careful not to override directions (count of dir value in [1,2,3,4] for a given node should be 0 or 1 but never >1)

* if you wish modify the following:
	+ the gate names
	+ gate length --> for a realistic distance a good rule of thumb: math.floor(math.sqrt( x\*x + y\*y )/38) with 38=tmx file tile dimension and x, y = distances between nodes on X,Y axis
	+ gates danger
* reconstruct the map\_x.MapRouteDistance using whichever algorithm you like (I used Breadth-first\_search for example)

Copy your modded map db in %LOCALAPPDATA%\StarTradersFrontiersMods\

Test your mod.

### Tiled files (.tmx) structure in json

Tiled is cool and you can use it to export your map in json format for further manipulation.

This file contains only the nodes(quadrant locations) and not the edges(gates connections).

**Important note:** importing an enriched STF map json(with edges/gates) works as long as the structure is respected.

```
{ "compressionlevel":-1,
 "height":50,
 "infinite":false,
 "layers":[
 {
 "draworder":"topdown",
 "id":1,
 "name":"Quadrants",
 "objects":[
 {
 "height":38,
 "id":1,
 "name":"4", -> this is the relevant info that references \_id in mapquadrant
 "rotation":0,
 "type":"",
 "visible":true,
 "width":38,
 "x":1638, -> this is x coord of quadrant \_id =4 (Les Ecumes Pass in v1 default map)
 "y":1289 -> this is y coord of quadrant \_id =4 (Les Ecumes Pass in v1 default map)
 },

```

....................

```
 {
 "height":38,
 "id":63,
 "name":"63",
 "rotation":0,
 "type":"",
 "visible":true,
 "width":38,
 "x":2696.53,
 "y":1699.78
 }],
 "opacity":1,
 "type":"objectgroup",
 "visible":true,
 "x":0,
 "y":0
 },
 {
 "compression":"zlib",
 "data":"eJztwSEBAAAAAiBX+H+qNwxAAwAAAAAAAAAAAAAAAAAAAAAAAMCDAQVJABc=",
 "encoding":"base64",
 "height":50,
 "id":2,
 "name":"QuadrantTiles",
 "opacity":1,
 "type":"tilelayer",
 "visible":true,
 "width":100,
 "x":0,
 "y":0
 },
 {
 "compression":"zlib",
 "data":"eJztwSEBAAAAAiBX+H+qNwxAAwAAAAAAAAAAAAAAAAAAAAAAAMCDAQVJABc=",
 "encoding":"base64",
 "height":50,
 "id":3,
 "name":"GateTiles",
 "opacity":1,
 "type":"tilelayer",
 "visible":true,
 "width":100,
 "x":0,
 "y":0
 }],
 "nextlayerid":4,
 "nextobjectid":64,
 "orientation":"orthogonal",
 "renderorder":"right-down",
 "tiledversion":"1.6.0",
 "tileheight":38,
 "tilesets":[
 {
 "columns":20,
 "firstgid":1,
 "image":"system.png", -> DO NOT change this entry it will crash STF
 "imageheight":128,
 "imagewidth":768,
 "margin":0,
 "name":"system",
 "spacing":0,
 "tilecount":60,
 "tileheight":38,
 "tilewidth":38
 }],
 "tilewidth":38,
 "type":"map",
 "version":"1.6",
 "width":100
}

```