Overview
I will try to cover everything I have learned about modding Satellite Reign that seems most useful for making mods.
How to start modding Satellite Reign
How to get started:
The official 5Lives mod here has some text about how to get started: [link]
I will go over the same things here though.
You will need Microsoft Visual Studio, I think it might have to be Visual Studio 2015. 5Lives write that you also need Unity 5 or higher, I am not sure if that is true, because you get the Unity DLL files from the game anyway. Hopefully it means we can also make stuff for the game in Unity at some point, but I have not figured out how yet. Visual Studio has a Community Edition that is free.
Here is a Visual Studio solution with 4 mods, the one 5Lives has shared as an example and 3 I made. One with cheats, one with a unstuck function and one with ways to make your agents look different to try to customize them.
[link]
The different projects probably need you to manually add references to some extra DLL files. The guide from 5Lives tells us to reference:
Assembly-CSharp.dll
Assembly-CSharp-firstpass.dll
and
UnityEngine.dll
You do this by select the project you want to edit, select the branch called “references”. Right click it and click “Add Reference…”. A window opens where you can search for and select what to add, but since this is a bit custom, you need to manual add them. So click browse, then find the Satellite Reign installation folder. If you got the Steam version, its likely to be something like:
C:Program Files (x86)SteamsteamappscommonSatelliteReign
That is also the folder where you need to make a folder called “Mods” later, for the DLL you compile from this project so the game will use the mod you made.
The DLLs you need to add are not directly in the installtion folder, you need to find:
$SR INSTALLATION FOLDER$SatelliteReignWindows_DataManaged
In this folder you will find the DLL files mentioned above. I have found that it helps to also add:
UnityEngine.Networking.dll
and
UnityEngine.UI.dll
These sometimes gets used as well.
Another way to do all this, might be by using a template. I made one here:
http://dionysus.dk/devstuff/downloads/SatelliteReign/Satellite%20Reign%20Mod.zip
It needs to be put into a Visual Studio folder. Like this:
DocumentsVisual Studio 2015TemplatesProjectTemplates
Then you can make a new project, based on a template for the pause mod in visual studio when you make a new project or add a new project to your solution. Just search for Satellite Reign in the templates the next time you open Visual Studio.
After building the mod you find the DLL by selecting the build menu in VS2015 and clicking build solution or clicking F6, then you right click on the project you made the mod in, it should be in the solution explorer to the right, and click “Open Folder in File Explorer”. Open the bin folder, then the debug or release folder depending on your project settings, and a DLL should be in the folder by the same name as the project. Copy this DLL to the “Mods” folder in your Satellite Reign installation folder, and you are ready to test your mod by running Satellite Reign.
That is it for now, I will add more sections later. Have fun.
How to make a mod for Satellite Reign
I have been trying to figure out what commands to use for what, which have required a lot of trial and error to figure this out. Probably still room for improvement, but I will share what tips I have for modding so far.
First off, its good to know that this is regular C# coding and Unity coding, so if you know how to code C# and / or how to code in Unity, it should help quite a bit. Its recommendable to follow some C# guides to learn how to program in it in general.
There are many custom classes and such in this game, and those are the important ones to know, to make mods. As far as I know, its not possible to add new graphics and new sounds yet, but not sure, it might just be about knowing how to do it.
Lets go through the standard way a mod is set up in its cs file:
using System;
using System.Collections.Generic;
using UnityEngine;
These lines are about what the file might need. The first one is about needing regular C# commands, the second one is about using collections like arrays or lists, so you can store a group of certain types of objects. The last one makes sure you got Unity commands available.
Then comes:
public class ModName : ISrPlugin
{
}
This is where the mod class is made. Its public, so that it can be referenced from other classes, the ModName is the ModName, should have the same name as the project. The ISrPlugin is because this class is an ISrPlugin, and therefore uses ISrPlugin as its template. For the class to use this template it has to have certain methods like Initialize(), Update() and GetName(). The brackets make up where the class begins and ends, the same thing goes for methods, loops and other functions and methods that needs to have a group of commands.
But before any methods are made you setup the variables you want to use in the class.
Like:
private bool cheatMode = false;
The first sets the privacy level of the variable. Private means its only accessible by this class. Protected means its accessible by all classes in the same namespace, and public means accessible by all classes. The next is the type of variable, in this case a bool, short for boolean. Can be either true or false. cheatMode is the name of this variable. = false makes sure the variable starts out with a certain value. Important custom classes and variables you might need to make could be:
AgentAI: This type is what your agents are. They extend / inherit from another type called AIEntity meaning the AgentAI is an AIEntity with extra variables and methods.
AIEntity: Most things in the game are of this type. Cars, civilians, your agents, enemy agents, police, mechs, maybe even cameras and such.
CarAI: All vehicles in the game are based on the CarAI class, which like AgentAI extend / inherit from the AIEntity class.
You can make a group of classes in several ways. The two I mostly use are:
List<Type> types;
Type[] types;
The first one makes the List type of collection. The Type could be AIEntity, AgentAI and so on. The name, in this case types you can decide yourself. Its recommended to make the name make sense, maybe some abrivation of the class it contains in plural. Maybe “agents” if its a list of AgentAI.
The second one is an array. Type could again be AIEntity. The List is based on the array class, the array is a simpler version of a list, so it has fewer methods. I would recommend using lists instead, unless you know you wont need to add or remove elements from the array.
Then we have the methods.
public void Initialize()
Everything in this method is what the mod does as it starts running. I am still not sure if this means before you load or start a game or after you have entered the game itself seeing your agents and such. I am pretty sure its after the game starts. Void means this methods does not return anything to whatever runs the method. The game runs this method on its own though.
public void Update()
This is the most important method. Its a common one from Unity, and is run in every “update” of the game. Not tied to frames or seconds, this update runs as often as possible. Therefore its also important to not make the update do too much, should only do what it needs to do, and not too often.
The last method you have to have in a SR plugin is:
public string GetName()
{
return “name of mod”;
}
The GetName method is likely there to make it possible to check what plugin it is, because the game could have to deal with several mods at the same time, and maybe mods try to communicate with each other. I am not sure if that is possible though. This method has “string” instead of “void” because it has to return a string, which is a string of text. That is why we see it having a “return” line in the method. In those ” “, you can put the name you would like the rest of the game to see when it asks the mod for the name of this mod.
Any variables that might need to be initialized should do so in the Initialize() method to make sure they are ready if something in the update method needs the variable, that it is ready.
Could be something like:
types = new List<Type>();
To ensure that this list is ready to have something added to it. Or maybe you want it to also get objects added to it, like your agents or something like that.
Most things the mod does, is likely to happen in the Update() method though. Useful commands to use could be some of these.
First of there is:
if (Manager.Get().GameInProgress)
This is important, its from the tactical pause mod example 5Lives made, and it is important to ensure that your mod only checks these things while the game is running. Its not so good to try to find all your agents, because you click a mod button, before any agents exist. So I usually do everything in the update method within the brackets of the if (Manager.Get().GameInProgress).
So if you want to do something in the game, when you press keypad 7 it would look like this:
if (Manager.Get().GameInProgress)
{
if(Input.GetKeyDown(KeyCode.Keypad7))
{
// stuff to do when the player presses keypad 7.
}
}
Maybe you want to do something to all agents?
foreach (AgentAI a in AgentAI.GetAgents())
{
a.AddAmmo(50);
}
This would find all agents, and give them 50 extra ammo. If the weapon can have that much ammo.
Another option could be to use this:
foreach (AgentAI a in Manager.GetInputControl().GetSelectedAgents())
{
a.AddAmmo(50);
}
This would add 50 ammo, but only to all selected agents.
Maybe you want to do something to all selected AIs and not just your agents?
foreach (AIEntity ae in AIEntity.FindObjectsOfType(typeof(AIEntity)))
{
if(ae.IsSelected())
{
ae.m_IsControllable = true;
}
}
This goes through all AI in the game, check if the player has selected it, maybe a civilian, and then makes sure its controllable. Making the player able to give command to whatever the player has currently selected.
That is some of the basics. In the next section I will get into some more of the different classes and methods.
Satellite Reign Commands
Now for some more about how to make changes in the game and what commands and classes to look for.
The first commands I will go through, is being able to get some messages in the game, which is very useful both to help show the player what actions are happening, and to help you test the mod and find out what is going wrong, if something is going wrong.
An important class when it comes to messages is the “Manager” class, because it controls most of the managers in the game.
Manager.GetUIManager().ShowWarningPopup(“WarningPopup”, 4);
This one creates a warning message box with the message for the amount of seconds you set. In this case the message is”WarningPopup” and it is for 4 seconds. Its a red box.
Manager.GetUIManager().ShowSubtitle(“These are subtitles, you need to learn how to use subtitles”, 5);
This one creates some subtitles on the screen, You can make this one without the timer, and the message will just stay there as long as you play the game, or until new subtitles are made or you run the command:
Manager.GetUIManager().HideSubtitle();
Which then makes the subtitles go away again. They are text in the bottom of the screen.
Manager.GetUIManager().ShowBannerMessage(“Heading”, “HeadingTop”, “HeadingBottom”, 5);
This one creates some animated big text for the amounts of seconds you decide. This one is best known for when you enter a new district, and you see some big text on the screen announcing this.
Manager.GetUIManager().DoModalMessageBox(“Title”, “Message”, InputBoxUi.InputBoxTypes.MbOkcancel, “Yup”,”Nope”, clickedOk);
This one is likely the most useful. You can make a box with some text and an okay button that will not go away before you press the okay button, you can also make something happen when you press the okay button. You can make it have a cancel button as well, you can decide what text should be on the okay and cancel button, and with the action you can decide what happens if you press okay or cancel. Its also possible to make it contain a text input field and make something happen based on what text you put into it.
How to make something happen based on input from this I might make a section for later. It is a bit complicated.
Manager.GetUIManager().ShowMessagePopup(“PopUpMessage”, 3);
This is very simple, it makes a message pop up in the bottom right corner for the amount of seconds you decide.
Manager.GetUIManager().ShowBlank(“BlankText”);
Screen becomes blank showing only the text. Not sure how to make it get back to normal yet.
Manager.GetUIManager().ToggleTextWindow(“Toggle Text Window”);
Seems very useful for showing a lot of text, since this text window can scroll and such, but so far the text I have tried to make it show, is not shown. So you can just scroll through a big black box and click done when you want it to go away again.
Next is:
This helps with several things regarding controls in the game. Some useful commands:
Manager.GetInputManager().ClearSelection();
Makes nothing in the game selected by the player.
Manager.GetInputManager().DeSelect(someSelectable);
Can stop something from being selected. It needs to be the selectable of that object. Your agents, civilians, cars, cameras, doors and so on all have a selectable object / component on them.
Manager.GetInputManager().Select(AgentAI.FirstAgentAi().Selectable.GetUID(), true);
This makes it possible to make objects selected. For some reason it wants the UID of a selectable, instead of the selectable. The boolean as the second input of this method, is whether the selectable should be added to the current selection, or whether it should be the only selected object.
Manager.GetInputManager().SelectAll();
Makes everything that is controllable by the player become selected. Control-a does the same thing.
Manager.GetInputManager().GetNonPlayerSelectedEntities();
Returns a list of AIEntity that are selected but not owned by the player. Not sure though, I not found a sure way to just go through every AI the player has currently selected.
Manager.GetInputManager().GetPlayerSelectedEntities();
Returns a list of AIEntity that are selected and owned by the player. Should be all agents and hijacks that you have selected.
Manager.GetInputManager().GetSelectedAgents();
Returns a list of AgentAI of the agents the player has currently selected.
Manager.GetInputManager().GetClosestPos(position);
I used this one to help with getting agents unstuck. It gets the nearest location to a certain position. In unity games a location in a 3D games is defined by a Vector3, which is 3 values, the X, Y and Z position of a certain objects location or just a location in a 3D space.
Manager.GetInputManager().GetGroundPointUnderMouse(out position);
This one returns a bool that says whether this method could find a position under the mouse cursor, and it also has an “out” variable that makes the Vector 3 location get outputted to a Vector 3 you give this method as an input. Could be done like this:
Vector3 position;
Manager.GetInputManager().GetGroundPointUnderMouse(out position);
First you define the Vector3, then puts it as the out variable. After running that command, the position variable should be equal to the location nearest to your mouse cursor in the game.
ProgressionManager.Get().AddResearcher(100);
The progression manager can control different things regarding the progress in the game. Like this command that gives the player 100 more researchers.
District current = ProgressionManager.Get().CurrentDistrict;
Returns the district the player is currently in.
ProgressionManager.Get() can also be used to add or remove security keys for district checkpoints, it can remove researchers and add an remove bonuses for the game, districts and factions.
Manager.GetMoneyManager().OffsetFunds(1000000,true,true);
This adds one million credits to the player, if you add a minus in front I think it removes the money instead.
Manager.GetMoneyManager().SetCurrentFunds(1000000);
This makes the player have 1000000 credits. Instead of adding, this just makes it that amount, whether the player currently has more or less than this. The MoneyManager should also be able to set which ATMs are hacked and how much each bank siphons, but I have not been able to change that yet.
In the next section, I will get into how to customize names and looks of your agents.
Customizing your agents
You might want to change how agents look, their sex and their name and this is the variables to use. They have a RandomSeed, a WardrobeType, a sex and an identityId also sometimes called a nameId. Together this is all that is needed to decide how your agents look and what their name is. Each agent has an AgentAI that inherits from the AIEntity class, making it have all the AIEntity objects have, but also a few more methods and variables. To change their names and looks I use these commands and variables:
WardrobeManager.Sex sex;
int seed;
int nameId;
WardrobeManager.WardrobeType wType;
int id = agentAI.CurrentCloneableId; // The agentAI is to be one of your agents.
CloneManager.Get().GetCloneableData(id).Sex = sex;
CloneManager.Get().GetCloneableData(id).m_Sex = sex;
CloneManager.Get().GetCloneableData(id).RandomSeed = seed;
CloneManager.Get().GetCloneableData(id).m_RandomSeed = seed;
CloneManager.Get().GetCloneableData(id).IdentityId = nameId;
CloneManager.Get().GetCloneableData(id).m_IdentityID = nameId;
CloneManager.Get().GetCloneableData(id).WardrobeType = wType;
CloneManager.Get().GetCloneableData(id).m_WardrobeType = wType;
I am not sure whether its enough to just set the RandomSeed or just the m_RandomSeed and the same for all the other variables, so to be sure I set them all. You can get these data from your agents the same way.
When you have applied data like this to your agent, it will not be visible in the game yet, so you need to use this command on the agent:
agentAI.RespawnAtCurrentLocation();
If you want to get this data from some AIEntity you use these commands:
AIEntity ae;
nameId = ae.m_Identity.GetNameID();
sex = ae.m_Wardrobe.m_Sex;
seed = ae.m_Wardrobe.RandomSeed;
wType = ae.m_Wardrobe.m_WardrobeType;
I have not found a way to make AIEntity respawn yet, so that makes it difficult to change them and making the changes visible in the game.
The SpawnManager might help with it somehow, but not sure exactly how. You can use it to despawn AIEntity like this:
SpawnManager.Get().DeSpawn(ae);
Seems you can also make a copy of something you have selected at your mouse cursor location:
SpawnManager.Get().SpawnSelectedAtMouse();
It can also spawn squads, VIPs, civilians and more, but I have not tested it much yet and I am not sure what works and how yet.
There are more ways to customize like giving agents more abilities, weapons, items, and so on. I am not completely certain how to do it all, but some of it I have figured out and I might write some more about it if anyone ask me to.
Experimental code
Some code I have been experimenting with for changing pistol stats. Most of them seem to be on the ammo.
Manager.GetUIManager().ShowMessagePopup(“Setting pistol range”);
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Range = 200;
Manager.GetUIManager().ShowMessagePopup(“Setting pistol charge time. Ammo on pistol: ” + weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo.Length);
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[0].m_ChargeTime = 0;
Manager.GetUIManager().ShowMessagePopup(“Setting pistol charge every shot. Ammo on pistol: ” + weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo.Length + “. Ammo: ” + weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[0].m_Type);
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[0].m_ChargeEveryShot = false;
Manager.GetUIManager().ShowMessagePopup(“Setting pistol reload speed. Ammo on pistol: ” + weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo.Length + “. Ammo: ” + weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[0].m_Type);
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[(int)weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_DefaultAmmo].m_ReloadSpeed = 0;
Manager.GetUIManager().ShowMessagePopup(“Setting pistol reload time”);
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[(int)weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_DefaultAmmo].m_reload_time = 0;
//weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_MaxAccuracy = 1;
//weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_MinAccuracy = 1;
//weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Name = “BFG9000”;
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[(int)weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_DefaultAmmo].m_Emp = 1;
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[(int)weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_DefaultAmmo].m_MaxBeamWidth = 1;
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[(int)weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_DefaultAmmo].m_knockback_amount = 20;
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Ammo[(int)weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_DefaultAmmo].m_ProjectilesPerShot = 20;
Manager.GetUIManager().ShowMessagePopup(“Pistol upgraded”);
List<int> abil = weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Abilities.ToList();
//abil.Add(Manager.GetAbilityManager().m_AbilityStealth[0].m_ID);
//abil.Add(Manager.GetAbilityManager().m_AbilityHardwire[2].m_ID);
//abil.Add(Manager.GetAbilityManager().m_AbilityHackTarget[2].m_ID);
abil.Add(1);
abil.Add(2);
//weaponManager.m_WeaponData[(int)WeaponType.].m_Abilities.ToList();
weaponManager.m_WeaponData[(int)WeaponType.B_pistol].m_Abilities = abil.ToArray();
Manager.GetUIManager().ShowMessagePopup(“Abilities added to pistol”);
***********
To edit items in general you will probably have to look into the item manager:
Manager.GetItemManager().m_ItemDefinitions
This should give a list of all items in the game. Its item has a list of m_Modifiers, which is a list of abilities / effects each item has or provides. Should make it possible to f.ex. change how much armor, shield or heath the item gives the agent. A bit difficult to figure out how m_Modifiers work exactly, but I have been looking into testing for different items. Once a certain item is found, you can look into what modifiers it has and that should help change the items.
Useful enums:
ItemSubCategories enum: (can be found on ItemData)
Standard = 0,
Drone = 1,
WeaponAmmo = 2,
ArmorBody = 3,
ArmorHead = 4,
Shields = 5,
StealthGenerators = 6
ModifierType enum (modifiers are on all types of items, even ammo, but also seems to be used on characters and more. Also look into ModifierData5L where this can be found on)
0 NONE,
1 DamageMultiplier,
2 HealthRegenRate,
3 WeaponCountIncrease,
4 AccuracyModifier,
5 EnergyRegenRateMultiplier,
more than 50 of these
The list is very long so I will stop here. Should be easy to find once making a mod.
Itemslottypes enum: (can also be found on ItemData)
0 Gear,
1 AugmentationHead,
2 AugmentationBody,
3 AugmentationArms,
4 AugmentationLegs,
5 WeaponPistol,
6 Weapon,
7 WeaponAugmentation,
8 Max