Difference between revisions of "Creating a game extension for Vortex"

From Nexus Mods Wiki
Jump to: navigation, search
m (Getting Set Up)
m
Line 25: Line 25:
 
For the info file, create a new JSON file called "info.json" and fill it with the following information:
 
For the info file, create a new JSON file called "info.json" and fill it with the following information:
 
<pre>{
 
<pre>{
   "name": "Game: Elex",
+
   "name": "Game: Bloodstained: Ritual of the Night",
 
   "author": "Pickysaurus",
 
   "author": "Pickysaurus",
 
   "version": "0.0.1",
 
   "version": "0.0.1",
   "description": "Support for Elex"
+
   "description": "Support for Bloodstained: Ritual of the Night"
 
}</pre>
 
}</pre>
 
''Note: Using a version less than 1.0.0 will flag this extension as Beta in the Vortex UI.''
 
''Note: Using a version less than 1.0.0 will flag this extension as Beta in the Vortex UI.''
Line 101: Line 101:
 
|-
 
|-
 
|queryPath
 
|queryPath
|We want to fill this with the root directory of the game. In this example we'll be using the "findGame" function (discussed later) to allow us to check for the correct folder.
+
|We want to fill this with the root directory of the game. In this example, we'll be using the "findGame" function (discussed later) to allow us to check for the correct folder.
 
|-
 
|-
 
|supportedTools  
 
|supportedTools  
Line 119: Line 119:
 
|-
 
|-
 
|setup
 
|setup
|This property is optional, but is used if we need to make the game folder ready to accept mods. In this example we need to create the "~mods" folder using the prepareForModding function.
+
|This property is optional but is used if we need to make the game folder ready to accept mods. In this example, we need to create the "~mods" folder using the prepareForModding function.
 
|-
 
|-
 
|environment
 
|environment

Revision as of 07:59, 1 August 2019

Info.png
Notice
Work in progress

This guide will explain how to create a very basic game extension for Vortex, touching on where to start with some of the more advanced features. It requires a basic understanding of Javascript/programming. I also recommend you use an application with syntax highlighting, such as Visual Studio Code or Notepad++ for the coding sections of the guide.

Getting Set Up

To get started, you first need a version of Vortex to work with. I recommend using the current release of Vortex installed at the default location. If you're familiar with Github and other development tools you can also follow the instructions on the Vortex Github to clone the repository and build a development environment. To keep things simple, we'll be using the first option.

You'll also need to gather some information about the game you want to support before starting. This information will help us build our extension.

  • Which game store(s) are you able to get this game from?
  • Do the game stores have any useful meta-data we can use? (SteamApp ID, Epic store codename, GOG app ID, registry key etc)
  • What is the structure of the game directory? Where is the main EXE file?
  • Where should mods be installed? Are there multiple different ways to install mods?
  • How are mod archives usually structured? How consistent are they?

If you can't answer most of these questions, you may have problems creating a completely functional extension.

Creating your extension

A basic game extension consists of 3 files an info file, a game image and a javascript file. First, we will need a folder for our extension. If you're using a regular installation of Vortex, navigate to AppData\Roaming\Vortex\plugins. If you're using a Github repository, you can create this folder at vortex\extensions\games. For consistency, give your folder the same name as your game with no spaces, prefixed with "game-" e.g. "game-bloodstainedritualofthenight". Now, open this folder and we're ready to get set up.


For the game image, we recommend taking the game tile from Nexus Mods, however, if you're not able to do this you can use something else. Just ensure it's the same ratio as the other images inside Vortex. It's also important that you name it "gameart", as this will help us find it later.


For the info file, create a new JSON file called "info.json" and fill it with the following information:

{
  "name": "Game: Bloodstained: Ritual of the Night",
  "author": "Pickysaurus",
  "version": "0.0.1",
  "description": "Support for Bloodstained: Ritual of the Night"
}

Note: Using a version less than 1.0.0 will flag this extension as Beta in the Vortex UI.


Finally, we'll create the main javascript file called "index.js". Inside the file, add the following basic code.

//Import some assets from Vortex we'll need.
const path = require('path');
const { fs, log, util } = require('vortex-api');

function main(context) {
	//This is the main function Vortex will run when detecting the game extension. 
	
	return true
}

module.exports = {
    default: main,
  };

With this code in place, your extension will now be recognised by Vortex (a restart will be required) but does not do anything. You can check the "Extensions" tab in advanced mode to see that it is loading without errors.


Registering your game

Now we have the basic information in place, we need to tell Vortex that we're adding a new game. First, we'll want to add some additional constants to the top of the index.js. In our example game, all mods are contained in ".pak" files.

// Nexus Mods domain for the game. e.g. nexusmods.com/bloodstainedritualofthenight
const GAME_ID = 'bloodstainedritualofthenight';

// All mods will be .pak files
const MOD_FILE_EXT = ".pak";

Next, add the following code to your index.js above the "return true" line inside the "main" function and change it according to the instructions below:

context.registerGame({
    id: GAME_ID,
    name: 'Bloodstained: Ritual of the Night',
    mergeMods: true,
    queryPath: findGame,
    supportedTools: [],
    queryModPath: () => 'BloodstainedRotN/Content/Paks/~mods',
    logo: 'gameart.jpg',
    executable: () => 'BloodstainedROTN.exe',
    requiredFiles: [
      'BloodstainedRotN.exe',
      'BloodstainedROTN/Binaries/Win64/BloodstainedRotN-Win64-Shipping.exe'
    ],
    setup: prepareForModding,
    environment: {
      SteamAPPId: '411300',
    },
    details: {
      steamAppId: 411300,
    },
  });


Property Description
id This can be filled with the constant we defined in the previous step.
name The full title of your game, this will be how it appears inside Vortex.
mergeMods This defines if mods will be installed to the same folder (merged) or installed to their own folders.
queryPath We want to fill this with the root directory of the game. In this example, we'll be using the "findGame" function (discussed later) to allow us to check for the correct folder.
supportedTools See: Defining tools
queryModPath This is where we tell Vortex how to find the mods folder.
logo Make sure this matches the name of your gameart file.
executable This is where we tell Vortex how to find the main game executable, so we'll be able to launch the game.
requiredFiles Fill this with an array of files that must be present for the game to run. It's sensible to limit this to core EXE files.
setup This property is optional but is used if we need to make the game folder ready to accept mods. In this example, we need to create the "~mods" folder using the prepareForModding function.
environment This is optional, but if the game must be run through steam you should include the SteamAppId property as shown above.
details We can store the SteamAppId here in case we need it, you can also add other details we may need.


Game detection

Now we need to create the "findGame" function mentioned earlier. This will be what Vortex uses to discover the game during a search. You can use different methods (or a combination) to detect the game. The most common instances are SteamApp ID and registry key.

Find our game with Steam:

function findGame() {
  return util.steam.findByAppId('692850')
      .then(game => game.gamePath);
}

Find our game from the registry:

//Add this to the top of the file
const winapi = require('winapi-bindings');

function findGame() {
    const instPath = winapi.RegGetValue(
      'HKEY_LOCAL_MACHINE',
      'SOFTWARE\\WOW6432Node\\GOG.com\\Games\\2129244347',
      'PATH');
    if (!instPath) {
      throw new Error('empty registry key');
    }
    return Promise.resolve(instPath.value);
}

Find our game from the Epic launcher:

function findGame() {
      return util.epicGamesLauncher.isGameInstalled('Jaguar')
      .then(epic => epic
        ? { launcher: 'epic', addInfo: 'Jaguar' }
        : undefined);
}

Using both Steam and registry methods together:

//Add this to the top of the file
const winapi = require('winapi-bindings');

function findGame() {
  try {
    const instPath = winapi.RegGetValue(
      'HKEY_LOCAL_MACHINE',
      'SOFTWARE\\WOW6432Node\\GOG.com\\Games\\2129244347',
      'PATH');
    if (!instPath) {
      throw new Error('empty registry key');
    }
    return Promise.resolve(instPath.value);
  } catch (err) {
    return util.steam.findByAppId('464920')
      .then(game => game.gamePath);
  }
}

Mod installation patterns

Mod installers

Publishing your extension

Advanced options

Defining tools

Requiring an external modding tool

Multiple install patterns