# [Guide] Adding New Units [WIP]

Discussion in 'Modding' started by Setakat, Oct 4, 2016.

Tags:
1. ### SetakatMember

Note: This guide is a work in progress. I'm still learning the ins and outs of how Cossacks 3 implements its units, so expect this to be updated whenever I learn something new.

For this guide I'm going to be going over the basics of introducing a new unit into the game, making it trainable and configuring it so its affected by upgrades.

I'm going to be making a custom Dragoon based off the visuals of the Light Cavalry unit since I have the Early Bird DLC, and outside of the Diplomatic Center, its not used. I could have just modified the base unit, but creating a whole new unit is far more interesting and useful. If you don't have this DLC and have or want to use a different unit, go right ahead.

Preperation
First of all, grab your favourite text editor (I recommend Notepad++) and open the following files:
- data/scripts/country.script
- data/scripts/unit.script
- data/hud/hud.mat
- data/objects/units.objects

Creating the Basics
Next, we'll need to create the units .prop file. These files can be found in data/objects, and contain the visuals/animation references for our new unit. I'm going to make a copy of the 'lightcavalry.prop' file and rename it to 'cusdragoon.prop'. Once you've copied and renamed your new unit file, open it for editing.

Once opened, look for the two lines (should be 4 & 5) that start with 'CustomName' and 'BaseName'. Change these to be the id of your new unit. I'm going to go with 'cusdragoon'. Save and close the file.
Note: Its important to use the correct id that you specified for the BaseName elsewhere, as this currently appears to be the id that gets used in later files.

How do we use it?
Once we've got our prop file, we'll need to tell the game to load it. Go to units.objects and search for the line that adds your base unit, duplicate it and change the file that it points to.
In my case, I wanted to find and duplicate the line that read 'ObjectItems[*].PropertiesFileName=.\data\objects\units\lightcavalry.prop', and then edit it so it points to my 'cusdragoon.prop' file.
Once your done, save and close the file.

The new guy needs a photo
Now to set the hud icon. Switch to data/hud/hud.mat, find the section that corresponds to your base unit, duplicate it, and change the 'Material.Name' line to reference your new units id. Mine looks like this:
Code:
section.begin {refurl=.\data\hud\ref\reflibmat.mat}
Material.Name = icons.unit.cusdragoon
Material.LibTextureName = iconsunits
Material.TextureCoord.ImageW = 512
Material.TextureCoord.ImageH = 512
Material.TextureCoord.CoordX = 276
Material.TextureCoord.CoordY = 368
Material.TextureCoord.CoordW = 46
Material.TextureCoord.CoordH = 46
section.end
Save and close the file.

Setting some basic info
Next up, switch to 'data/scripts/unit.script'. Time to give our new Dragoon some properties, otherwise he'll die whenever he spawns.
Because I'm making a new Dragoon, I want to look for this line
Code:
'dragoon', 'kingmusketeer', 'dragoon18fra', 'dragoon18', 'dragoon18dip', 'lightcavalry', 'lightcavalrydip' : begin
What this does, is when a unit gets created, if its id matches any of the above, execute the following code, So lets add our new id to the end:
Code:
'dragoon', 'kingmusketeer', 'dragoon18fra', 'dragoon18', 'dragoon18dip', 'lightcavalry', 'lightcavalrydip', 'cusdragoon' : begin
Much better. Now, we could just leave it here, but because I haven't figured out how to implement training drills for him yet, lets make him a bit different from regular Dragoons. Look down a bit, you'll see a line that reads 'case objprop.sid of', and directly below that:
Code:
               'dragoon' : begin
objprop.aiforce := 10;
end;
Lets make a copy of that, change the id, boost our new soldiers health and damage, alter his training time and tweak how much he boosts our ingame score by.
Code:
               'cusdragoon' : begin
objbase.maxhp := 350;
SetObjBaseWeapon(objprop, objbase, 0, 17, 200, 300, 900, 0, 100000, gc_obj_weapon_kind_bullet, True);
SetObjBaseSearchBuildVisionScore(objprop, objbase, 900, 1000, 3, 30);
end;
I decided to drop his build time down a bit to 1000 - the third parameter in the 'SetObjBaseSearchBuildVisionScore' method call, and the score he provides to 30 - the last parameter since he'll ultimately be worse than the regular Dragoon. Save and close the file.

Assignment
Now our new Dragoon needs to know how to form a formation, be recruited by a nation, benefit from some upgrades, and show up in the spawn menu.
Code:
   _country_ClearOfficerFormations(country);
var ind : Integer;
Somewhere below that, with the rest of the cavalry formations, add 'AddOfficersFormationCavExt(country, ind, 'cusdragoon', 1);'. If you're doing an infantry unit, use the appropriate infantry formation call.

Next up, we'll assign him to a nation. I'll go for England, as they are the 1st of the nations list in the spawn menu without a cavalry unit in the 2nd Stable slot. Look for '// new units to preserve indexation put here', and below that add
Code:
      if (eng) then
_country_AddMember(country, 'cusdragoon', ind, True, gc_country_editorplace_category_cavalry, 25, gc_ai_unit_dragoon17);
Next, we need to add him to a building. Look for '// FIXED PRODUCE' and scroll down a bit. You'll find a bunch of lines starting with '_country_AddFixedProduceWithAccessControl' that add units to buildings. Since my unit is a Dragoon, I'm going to find the stable section, copy the dragoon reference, update its id to 'cusdragoon' and change its position (the number immediately after the id) from '2' to '1' so it looks something like this:
Code:
_country_AddFixedProduceWithAccessControl(country, fixedproduceind, member, 'cusdragoon', 1, 0, ind, csid+'bla', '', '');
Note: the arrays only have 64 positions available, and the 'sarrUnitsAll' array currently uses 59 of them. I haven't tested to see if it can safely be expanded out to 128.
Our new lines should look something like this:
Code:
k := k+1; sarrUnitsAll[k] := 'cusdragoon';
k := k+1; sarrUnitsShooters[k] := 'cusdragoon';
k := k+1; sarrUnitsCavalry[k] := 'cusdragoon';
In Closing...
If I've written the above correctly and haven't missed anything out (99% sure I have), and you've followed it correctly, you should be able to start up the game, go to England (or whatever nation you assigned your new unit to), select it from the spawn menu and place it down without it dying instantly.
You should also be able to throw down a bunch of buildings and train it normally, and assign it into formations.

TODO
- Figure out how to assign name/description

I hope this (not so) small guide/tutorial helps with further mod projects, and enjoy!

Last edited: Oct 6, 2016
condor_fly, Zakxaev68, Fimti and 2 others like this.
2. ### A. SoldierActive Member

Kiergath, a very talented modder in our Steam modding group already did something like this but didn't go as much detail, but still, if you wanna check out his guide:

http://steamcommunity.com/groups/cossacks3moddinggroup/discussions/0/343787283754400446/

I'm currently trying to add rotatable Blockhouses to the game and I'll post a guide about it on his behalf.

Cheers and keep up the good work.

Edit: As far as assigning descriptions and names I suggest you check the locale file(s).

As for upgrades, I think they're still located at country.script.

Last edited: Oct 4, 2016
3. ### SetakatMember

And I'm back. After a short modding session, managed to figure out how to get upgrades working.

First up, open up country.script. We're going to have to find the appropriate position to add our new unit in at. Because I've made a custom Dragoon, and put him in the second unit slot in the stable, I'm going to find a shooting unit that shares the same position. France's King's Musketeer matches, so we'll do a search for 'kingsmuskeeter', and about half way down the file, we find something promising:
Code:
   case cid of
_fra : member := 'kingsmusketeer';
else
member := '';
end;
if (member<>'') then
begin
case cid of
_fra : SetUpgStructFoodGold(upgstruct, upgplace, member, 1, 2000, 1350, True, 1, 1500, 2100, True, 1, 5000, 3300, True, 1, 10500, 4400, True, 1, 12600, 5500, True, 9, 40000, 6000, blacksmith, ''); // Korolrv_Mus
end;
end;
This stuff is a little complex, so I'm going to go over it in bulk.
First up, we check the country code. If we're creating the France country, we'll add upgrades for the King's Musketeer. Otherwise, no unit.
If we have a unit that needs upgrades, check the country code, and create the upgrade data. Since we're currently France, we'll create the upgrade data, and then set it.

The Integer, Integer, Integer, Bool pattern in the 'SetUpgStructFoodGold' sets the bonus, the food cost and then the gold cost. There's also a 'SetUpgStructFoodGoldIron', which has a 4 Integer pattern, with the 4th being the Iron Cost of the upgrade, and there is also 'SetUpgStructFoodGoldIronCoal'. The boolean value currently doesn't seem to do anything, so we'll ignore it, and set it to true since thats what every other upgrade does.

So, we'll use the country code of our Dragoons native country of England - '_eng' to add some attack and defense upgrades - but for the purpose of this tutorial, we'll won't give him any defense upgrades, but because of the way the script works, we still need to add them. I'll post my code so you can see the changes.
Code:
   case cid of
_fra : member := 'kingsmusketeer';
_eng : member := 'cusdragoon';
else
member := '';
end;
if (member<>'') then
begin
case cid of
_eng: SetUpgStructFoodGold(upgstruct, upgplace, member, 1, 2000, 100, True, 1, 1000, 300, True, 2, 500, 700, True, 0, 0, 0, True, 0, 0, 0, True, 0, 0, 0, blacksmith, '');
end;
case cid of
_eng : SetUpgStructFoodGold(upgstruct, upgplace, member, 0, 0, 0, True, 0, 0, 0, True, 0, 0, 0, True, 0, 0, 0, True, 0, 0, 0, True, 0, 0, 0, blacksmith, '');
_fra : SetUpgStructFoodGold(upgstruct, upgplace, member, 1, 2000, 1350, True, 1, 1500, 2100, True, 1, 5000, 3300, True, 1, 10500, 4400, True, 1, 12600, 5500, True, 9, 40000, 6000, blacksmith, ''); // Korolrv_Mus
end;
end;
As you can see, we've added a new 'case' statement here that sets the musket damage upgrade. Since I'm lazy I just copied the 17thc Musketeer's upgrade costs/bonus which will give our new Dragoon +4 Musket once upgraded, going from 17 to 21 damage. A bit less than the regular 17thc Dragoon, but he has some extra health to offset this.
We've also added a line to set the costs for the defense upgrade, except we've made the cost and bonus 0 for all. This effectively remove the upgrade from the unit ingame, so sadly our new Dragoon cannot be upgrades to have bonus protection against Arrows, Pikes and Swords. He'll just have to rely on his extra health to survive.

Thanks for the support. It seems I've been beaten to the punch once again, but as Kiergath said, his notes are literally a glorified scratch pad, while I've tried to (hopefully) make mine a bit more user friendly for someone without much of a background in modding or programming.
I hadn't seen a tutorial on adding new units here, and with some people creating and customizing models, and wanting to add new ones, its only a matter of time before someone wants to create a new unit ingame (or a whole stack of new units). So I decided to find out what was the bare minimum needed to get a new unit ingame, and share my discoveries with the community in advance.

Now I need to figure out how exactly the name/description works (think I've seen something relating to that here already, need to go have a look). S.T.A.L.K.E.R. was a lot easier to work with - all the configuration was defined in a single (usually) .ini style config section, not spread out over 4 different files (so far).

Last edited: Oct 6, 2016

Agreed.

5. ### FimtiNew Member

I once added 8 new units to the game but the game just stopped working, then i figured out if i removed my units from the ":=k+1" list it was all good
Didn't know the list had a 64 limit! Thanks for that information

So i wonder what the ":= k+1; sarrUnits****" script does ?

Last edited: Oct 5, 2016
6. ### SetakatMember

After a quick 2 minute test, looks like each 'sarrUnits*' array controls what global upgrades get applied to units. For instance, if I didn't add my new Dragoon to 'sarrUnitsCavalry', the x2 Cavalry build speed upgrade won't get applied to it. Same for 'sarrUnitsShooters' - don't add it here, won't be affect by musket damage/rof upgrades in the academy.

As for increasing the limit, look for 'const cMaxUnitsArr = 64;'. Next step up from 64 is 128.

And while looking at the upgrades, I finally found the source of this 'bug'
Code:
_country_AddUpgradeWithAccessControl(country, upgplace+'.18', 1, gc_upg_tooltiptype_none, gc_upg_type_lifeperc, 200{c1=150, i change base cannon hp from 25000 to 5000}...
This is the +150% artillery durability upgrade. Notice how it actually increases artillery health by 200% instead of 150% as the tooltip says.
Cannon health in C1 was 5000, not 25000, despite what the comments all over the place say. And for C3 its now 12500 (which is was what it was in C1 with the durability upgrade).
So now after doing the "+150%" durability upgrade, cannons have 37500 health, which coupled with their 75 armour basically makes them all but unkillable. Wonder if adding the multibarrel cannon and mortar so they take advantage of the artillery upgrades is a good idea...

Another thing to add to the todo list of cannon fixes. Reduce health, fix firing distances, fix upgrade values... Probably the most broken unit ingame currently - in both senses.

Got another Cossacks related project I'd rather be working on, but I'm still digging through the code, trying to fix the damn cannons.

7. ### Hugojackson18Member

Amazing guide! Thanks a lot!
I guess it's the same kind of process to add buildings?

8. ### A. SoldierActive Member

What new units did you add?

We (me and Kiergath) added Blockhouses to the game the other day so I can tell you how, altho it's a bit hard from my phone.

9. ### Hugojackson18Member

Amazing. Yes please if you can make a guide like Setakat's one for buildings, that would be amazing!

Obviously when you get back on the computer, I can imagine being it difficult from your phone haha

10. ### A. SoldierActive Member

I can still probably give you a quick tutorial in the Steam chat but a more in depth one would require a computer yes.

11. ### Hugojackson18Member

Yeah don't worry about it for now, I don't need it as I'm at work. It's just in the future, it would be nice to have a detailed guide for buildings too.

12. ### A. SoldierActive Member

Yes I just didn't get around to do it after we were able to add them, that's all.

Laziness is both a curse and a blessing sometime.

13. ### FimtiNew Member

Added Standard bearers to every nation. They carrie the nations flag, can be built in the church, can form formations 2-14 units and have the same function and stats as priest - can heal.

I do not have much knowledge of the history in 17-18th century, so the flags are based on a quick google search. Please correct me if some nations flag is completely wrong.

The tools to edit the units aren't finished, so I have not been able to change the models for each nation. I have just started to change the texture for some of them, but i am not finished.

#### Attached Files:

File size:
344 KB
Views:
84
File size:
577.5 KB
Views:
85
File size:
111.6 KB
Views:
81
• ###### FlagFormation.jpg
File size:
221.9 KB
Views:
81
Ivenend, zerr and egnaro like this.
14. ### Hugojackson18Member

This is amazing!

Fimti likes this.

16. ### AlatristéMember

Wow great. Congratulations. I would have tried

17. ### A. SoldierActive Member

Huh, I tried doing that but it turned out I needed to put out the flagman from originals in unit.script.

However you beat me with the flags, I had no idea about that.

Last edited: Oct 6, 2016
18. ### SetakatMember

Back with part 3. This is almost so easy its laughable, but I'll put it here for completions sake.

Today we're going to add unit descriptions by editing our respective languages units.txt in the 'data/locale/' folder, and then running the provided .bat file to update the language files.

Unfortunately, the 'txt_to_lng.bat' file only does a few languages, and doesn't batch convert everything, which for me, doesn't include English. Lets fix that.
Open the .bat file, and add the following lines to the very bottom.
Code:
..\..\tools\locale\editorlang.exe .\en\units.txt .\en\units.lng c
pause
If you're modifying a language other than english, change the '\en\' to the 2 character code of your language.
Since we're just doing a single file, we'll only include it in here. No need to waste time processing everything else.

Also, I like my .bat files to end in pause, so I don't start them, go off and do something else (e.g. read forums) come back and wonder if I actually ran the bat. By adding the 'pause' command, it'll wait until you press the enter key, and then exit. You probably already know this already, but if not, you'll have learnt at least 2 new things today.

Now that's that, lets add our new units description. Find your the folder for your respective language, navigate into it and open the 'units.txt' file.

There's a whole lot of stuff here, but the part that concerns me is the line that reads '@UNITS.CAV.SHOOTERS'. This is where I'll stick my new Dragoon's description, just after the Tatar's description, and before the Mercs. If your unit is a different type, find the appropriate section, and put your units description there. Don't know if it'll affect anything, but lets do it just to be safe.
Code:
    @cusdragoon
Setakat's Custom Dragoon
@cusdragoon.ext
%include(units;descr.cav.any.musket)%
%include(units;descr.canshoot)%
%include(units;descr.cantshotclose)%
%include(units;descr.params.highattack)%
%include(units;descr.combination.lowrateoffirehighbuildtime)%`
Not terribly complex. I just copied the 17thc Dragoons description, replaced the 'dragoon' id with my own and changed the units name on the second line. Once you've added this in, save the file.

Now the .bat file we modified a minute ago? Go run it, and when its finished, open Cossacks 3, pop into the editor, spawn your new unit, and hopefully you should see your units name showing up, and if you place the cursor over its training icon in whatever building spawns, and you should see its list of attributes show up in the toolkit.

Extra:
Since we've had a bit of a discussion with buildings here, building descriptions are also located in the units.txt file, just incase anyone was wondering where they were stored.

Last edited: Oct 6, 2016
Hugojackson18 likes this.
19. ### Gambler71New Member

I followed your instructions perfectly, I am sure, creating the custom dragoon. The only thing I cannot do, is see/use the upgrades in the stable if I play campaign (as I set my cusdragoon to _eng also, I tried all the Roundheads vs Cavaliers campaigns). I can build them at the stable and send them to fight etc.

In Editor and Random Map, everything works perfectly.

Anyone else face this problem?

20. ### SetakatMember

Can confirm this. I'm not too sure what might be causing it. I do know that unit/building/upgrades are customized/restricted in the campaign missions (I'm only up to the 3rd one for the English campaign), so I suspect that it might be something in the mission file that's doing it - maybe overwriting the upgrades set from country.script with preconfigured values from the mission file.
Which is in binary.
Going to need a functioning map editor to confirm if this is the case.

I only tested this in the ingame editor - sync times if I start a random or campaign map take bloody forever. I can go make a cup of tea and drink it before this game finishes syncing.