DLL Modding Guide, Lesson 2 - Reading the Game's Code

Next Lesson - Creating a New Power

Previous Lesson - Setting Things Up

Table of Contents

In this lesson, we’ll start on our mod proper by creating a new power. To do that, we’ll need to know what a power in SoFG actually looks like in the code, and there’s no better way to learn that than by reading one of the base game’s powers. Thankfully, we can do that without even leaving Visual Studio.

Take a look at the Solution Explorer again and click the outlined arrow to the left of “References” to show all the references this project is using. Last time, you added Assembly-CSharp.dll as a reference, so that should now be in the reference list. Right-click it and select “View in Object Browser”.

This will add a new tab on the top-left called “Object Browser” and highlight Assembly-CSharp on the list of all the items we can look at. Expand it using the arrow on the left, then expand Assets.Code under it.

This will give you a list of every single data structure unique to SoFG (except the ones in Assets.Code.DivineEntities, which is cut content as this time, and Assets.Code.Modding, which don’t need to look at right now).

Scroll all the way down to P\_EyesInShadow, right-click it, and select Find All References. This should add some new expandable text on the bottom of the screen. Expand it until you see “No references found to ‘P\_EyesInShadow’”, then double-click that text.

With this, you should see She Who Will Feast’s Eyes in the Shadows power, as coded into the game:

As the tab on top says, it’s decompiled. This means this isn’t the actual words the developer typed in, but a reconstruction of them based on how it actually works in game. This means it might be harder to read due to changes in names, optimizations and no comments, but it still does what it says it does.

We’ll take this chance to get familiar with the absolute basics of C# programming. Going from top to bottom of this screenshot, here’s what everything means (skipping over the using line and the namespace for now):

```
“public class P\_EyesInShadow : Power”

```

* This means we’re creating a new class called P\_EyesInShadow. A class is a type of object in C# that can store other data (“**properties**”) and do things we tell it to (“**functions**”). The use of “: Power” at the end means that “P\_EyesInShadow” is a **subclass** of the Power class, and has all the properties and functions that it has.
* Finally, “public” means that things in other namespaces can use that class. In SoFG, “public” also has a special meaning for properties – they get saved and loaded when the game gets saved and loaded. Conventional wisdom is to make everything private unless it absolutely has to be public, but for our purposes you’ll want basically every class and property you make to be public unless you want it to reset when you reload the game.
* After that line comes a curly bracket. In C#, curly brackets means that everything within the curly brackets is part of the thing right before the curly brackets. In this case, that means all the stuff below “public class P\_EyesInShadow : Power” is part of the class P\_EyesInShadow.

```
public P\_EyesInShadow(Map map)
 : base(map)
{
}

```

* This is a special kind of function called a **constructor**, which means we can use it to create new **instances** of P\_EyesInShadow – everything here is just setting out what a P\_EyesInShadow is, and we can make actual versions of this power elsewhere. Like all functions, it starts with whether it’s public or something else, then comes the function’s name (for constructors, the exact same as the class), and then comes some parentheses.
* Inside those parentheses are any **parameters** the function needs to do its job – in this case, an instance of the class Map. That means, when using this constructor, you’ll need to give it the game’s map so the power can read everything going on in the game. As a general convention, classes start with an uppercase letter and parameters and properties a lowercase letter, so “Map map” refers to a Map called “map”. We could just as easily say “Map myFirstParameter”, though it’s less clean to read.
* “: base” is something unique for subclasses. Here, that means it will do all the things in the parent class Power’s constructor before doing its own stuff. It has “map” in parentheses because, like P\_EyesInShadow’s constructor, we can’t use Power’s constructor without giving it a Map – in this case, the same one we’re being given in P\_EyesInShadow’s constructor. If we changed that Map’s name to myFirstParameter, this bit would read “: base(myFirstParameter)”
* The curly brackets are empty, which means this constructor only does the stuff done in Power’s constructor – nothing new.

We can take a look at what that “: base(map)” bit did by decompiling Power like we did P\_EyesInShadow:

Here you can see what "base(map)" actually does, as well as taking a look at the functions that P\_EyesInShadow will be overriding later. Again, if we replaced “Map map” with “Map myFirstProperty”, we would replace “this.map = map” with “map = myFirstProperty”. We need to say “this.map” in this case because it’s written exactly the same as the parameter, and we need to confirm that we’re talking about the property we want to store instead of the parameter we just got passed.

```
public override string getName()
{
 return "Eyes in the Shadows";
}

```

* This is a more normal kind of function. “public” means it can be used by things outside P\_EyesInShadow or Power.
* “string” means the function will **return** a data structure called a string – basically a piece of text. Whatever piece of code is calling the function can then use what got returned for its own purposes – in this case, to display the name in the UI.
* “override” means it’s replacing a **virtual** function in Power (remember the 'return “Default Name”' function from our decompiled Power class?). This is useful to make different subclasses behave differently – for example, if we have a list of powers and we want to get all their names, a P\_EyesInShadow will give us the name “Eyes in the Shadows” even if we’re just treating it as a Power instead of a P\_EyesInShadow. Most player-facing things in SoFG work this way – subclasses with overridden functions to make them unique.
* A semicolon (;) is how C# knows that that line is over, and whatever happens next is part of a new line. You need to put a semicolon at the end of every line that doesn’t have curly brackets connected to it.
* Note that functions still have to have parentheses after them, even if you’re not passing anything in using them.

```
public override Sprite getIconFore()
{
 return map.world.iconStore.enshadow;
}

```

* A Sprite is basically an image, and Eyes in the Shadows uses the same image as the Enshadow challenge. This function basically reads “return enshadow, which is a Sprite property stored in iconStore, which is an IconStore property stored in world, which is a World property stored in map, which is a Map property stored in this class” (because it’s a Power, and as we saw Powers have a Map property called “map” at the beginning).

We’ll be using P\_EyesInShadow as the basis for our own new power, so we can now create our new class. Rename Class1.cs to P\_ThanosSnap.cs for our own ease of use, delete “public class Class1” and its curly brackets, then paste the entire P\_EyesInShadow class where that text used to be – starting from “public class P\_EyesInShadow” and going right to the last curly bracket.

Note that this automatically caused “using Assets.Code” to appear at the top of your .cs file. Just having Assets.Code as a reference doesn’t automatically mean that every .cs file you make will know about everything in the Assets.Code namespace (a.k.a. the SoFG stuff) – for that, we need to tell it this particular .cs file is “using” the Assets.Code namespace, which Visual Studio has helpfully done for us (add it yourself if not, in the same format as the other using lines at the top). Namespaces are automatically using themselves, so there’s no need to write “using ShadowsThanosSnap” when making classes inside the ShadowsThanosSnap namespace.

This concludes Lesson 2. With this, you should be able to read the base game’s code, and you should be all set to do actual coding. In the next lesson, we do actual coding!

Next Lesson - Creating a New Power

Previous Lesson - Setting Things Up

Table of Contents