Modding Tutorial No. 4: Upgrades

Welcome to the fourth entry of our modding blog where we post a new mod every week and explain how we did it. We've mentioned before that four things use attribute definitions; stances, factions, upgrades and faction skills. We've already covered stances and factions, so for this week we'll be looking at how to define new upgrade types.

Upgrades are, like all other entities, defined in .xnt files, as described in our first tutorial. Let's take a look at one of the default upgrade .xnts. farm_production upgrade Upgrades::Production farm cattlefarm mine 0.5 -0.5  200        0         0

So what do we have here? The "class" and "type" definitions that are necessary for all entities, the "article", a list of "objtype"s, a list of "attribute"s, a "portrait", and some "cost" variables. In addition to those, there are a few more options...  where the class and type are XML attributes that match the upgrade we need's class and type. If an upgrade has a prerequisite, the prerequisite will be destroyed when this upgrade is purchased and this upgrade will take up its slot. It's most commonly used to create another tier of upgrade, for example Medic 2 in a brigade or Library 2 in a city. Upgrades::Sanitation2::NAME which is why it shows up as "Sewers" instead of as "Sanitation II". Note that the  is included in the definition here; the "name" points directly to the string you want to use, no additional tags required for substrings. slavetrading it won't be able to be built until something (in the default game, only the faction skill "slave trading") gives the entity the slavetrading attribute. Of particular note are the riveraccess and openwateraccess attributes; any city on a river has the riveraccess attribute and any ports to the larger sea have the openwateraccess attribute. Use these if you want your upgrade to only be visible in cities next to the water. mercenarypost2 if the next upgrade is mercenarypost2.
 * "article", just like in stances and factions, is the base for the string we'll need to create; in the case of upgrades, we need to create a  and   string based off the article.
 * "objtype"s, like in stances, say what type of object this is an upgrade for: brigade, fort, city, cattlefarm, mine or farm (Fisheries and Vineyards are classified as "farm" and Lumber Camps are included with "mine")
 * "attribute" also works the same way it does for stances; you say what type of bonus it gives in "attrtype", the operation it applies it with, and the value of the bonus (for a more thorough analysis of attributes, search tutorial #2 for "attribute" with quotes).
 * "portrait" is an atlas reference to the image used to represent the upgrade. As we've seen before, atlas references can be switched to point to image files by setting atlas to "FILE:" and sprite to the path of the image.
 * "costwood", "costgold", "costgoldinitial" and "costxp" (not seen in that example) are how much it costs to get the upgrade in wood, gold or experience. Note that brigades will never get wood and buildings will never get experience; if you add those costs to the wrong upgrade, things won't work. The difference between "costgold" and "costgoldinitial" is that "costgoldinitial" is a single-time cost from your stockpile, while "costgold" is an ongoing expense per week.
 * "subclass" can be one of three things: "basic", which is the normal type of upgrade you'd get if you didn't define a subclass at all, "wall" which means that the upgrade will take up a building's wall slot instead of a regular upgrade slot, and "general". "general" is strange because it's not an upgrade at all; if you purchase an upgrade with that subtype, the upgrade will immediately destroy itself and spawn a general with a random name and portrait and the attributes defined for the upgrade. If the object has no general attached, the new general will automatically attach itself to the brigade.
 * "scalecosttoobject" will make an upgrade's cost more in larger cities
 * "prereq" is an entity reference to another upgrade. An entity reference is a way for an entity to point to another one: it looks something like
 * An unfortunate side effect of prereqs is that, if building the upgrade takes time, while the upgrade is being built the city doesn't have the bonus of the old upgrade nor the bonus of the new one. That is why "inprogattribute" can be defined the same way as "attribute"; an upgrade with "inprogattribute"s defined uses those while the new upgrade is under construction, allowing you to keep the benefits of the old upgrade going.
 * "name" is an optional addition to tiered upgrades. Normally if an upgrade has a prereq, its name will show up as the same as its prereqs name but with a number added at the end. Defining a name lets you point to a unique string used for that tier if you wanted it to look a little different from its predecessor. For example, the second tier of sanitation has
 * "requiredattribute"s are attributes the object will need to have in order for the upgrade to be purchased. If the attribute's status on the object is 0, the upgrade won't be purchaseable; otherwise, it will be. For example, if an upgrade has
 * "defaultnext" is the type name of the next tier of the upgrade; it enables the "upgrade to next level" button and says what upgrade it changes to. It looks like

So, let's have a look at creating two types of upgrade. The first will be a simple one for resource buildings. Instead of anything that can increase production of whatever resource, let's create one that tweaks things to that they produce food more food in the winter. While it may seem a bit unbalanced, keep in mind this upgrade will take up a resource building's only upgrade slot, so it does come with a price.

So what do we have to do to create that upgrade? We'll create a new .xnt copied from the one above and change the "type" to "farm_wintering" so that we have a unique entity. Next we'll change the article to point to Upgrades::ResourceWintering and create a .str file with  and   strings. Next, we get rid of the reference to invalid objtypes, in this case mine, but we'll want to keep farm and cattlefarm (even though that includes logging camps; we'll deal with that elsewhere). Then come the attributes.

Now, from the list of attributes found here, we can see the types that we'll want. Removing the previous attributes, we'll add in one for attrtype="winteroutput". To get an idea of what we want the upgrade bonus to be, we can look at the default building entities in Longbow's Google Drive; keeping in mind that the same attribute difference will be applied to all farms and cattlefarms this upgrade is valid for, I decided on two things. First, that we would be using op="add"; since the fishery's output is 0, a multiplier would leave its winter protection as 0. Since I was adding, I decided I would add 0.5 food per worker; it leaves winter somewhat below most seasons for most buildings, but not TOO far behind. So our final attribute definition there looks like 0.5 . That leaves the portrait and the costs. The portrait can be made to point to a .png file, and I think we should leave the costs at 200 wood and no gold to leave this competitive with the other upgrades. And that's our resource upgrade!

farm_wintering upgrade Upgrades::ResourceWintering farm cattlefarm 0.5  200        0         0

But that's not all to be made this week. We haven't really covered brigade upgrades nor tiered upgrades; so let's create another upgrade, a tiered brigade upgrade. One upgrade that we had in Rome but removed from III for balance concerns is the brigade size upgrade; we can create a mod to bring it back.

So we create another mod with its own upgrade .xnt; we can copy the wintering one to use as a base. So we change the type to "fame", the article to "Upgrades::Fame", define the needed strings, remove all objtypes but one and swap that one to "brigade", change the attribute list to a 0.5 mult attribute to numunits, and point the portrait to a new image. Then we change "costwood" to "costxp", since brigades use xp instead of wood; most higher-end upgrades start at 1000 XP, so we'll go with that. We'll also add a slight gold cost, to help mitigate the fact that a brigade with this is effectively more than one brigade. Not much, just 10, so it's still cheaper than buying another even if it's a cheap unit like skirmishers.

Next we do something we didn't in the last upgrade and add a "defaultnext" tag. The next upgrade doesn't exist yet, but when it does, we'll call it "fame2", so our new tag should look like fame2 . This will ensure that the "increase upgrade to next level" button appears over the upgrade's portrait and that the game can set up the "upgrade available" icon over brigades when it has enough xp to make the leap; this is entirely optional, though, the game will function just fine with multi-tiered upgrades that lack defaultnext definitions, you'll just lack these bonus features, so it is possible to have more than one possible next tier from a previous upgrade.

So now we actually want to define our next tier of upgrade. This will be a seperate entity from the first tier, so it will have to be placed outside the  block, which is a slight problem since a single .xnt file needs to be entirely inside one valid XML block. We could create a new .xnt file for it, but we don't have to. Let's go to the start of the file and create a  starting block instead, and add   to the end to close it. Now we can have as many  definitions inside of this .xnt file as we want, so long as they're all between those two.

So let's copy our entire fame entity block (from  all the way to  ) and paste it just before the. We'll change this copy's type to fame2, its cost to 2000 xp, and its attribute to be a full 1.0 numunits multiplier. Next, we need to remove the "defaultnext" tag and create a "prereq" tag; the prereq tells the game what upgrade this is a higher-tier upgrade of, letting it know not to let the player get it unless they have to lesser tier and letting it know which upgrade to replace with the new one. The prereq tag is an entity reference, which is similar to the atlas references we've been using to point at images, but instead points at other entities. It has the target entity's class and type as attributes: ours should look like  Note the slash at the end, necessary because the prereq doesn't have anything "inside" the block and seperate closing block.

Normally an upgrade has the same name as its predecessor with a number added to it; however you can define custom names by adding a "name" tag that'll point to a string to use instead. Let's do that. We can add Upgrades::Fame2::NAME and create the  string in our mod's string file. Now, instead of Famous Officer II, we can make it Legendary Officer, a clear improvement.

The final .xnt file looks like this: fame upgrade Upgrades::Fame brigade 0.5  1000        10         fame2 fame2 upgrade Upgrades::Fame Upgrades::Fame2::NAME brigade 1.0  2000        10         

And that's how you make upgrade entities!