[Guide] Adding New Units [WIP]

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

  1. Setakat

    Setakat Member

    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.
    Lets start with formations. Look for the following two lines
    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', '', '');
    Now, upgrades. Look for '// UPGRADE + UPGRADEPLACE + UPGRADEENABLE + UPGRADELINKS'. Below this, it'll create some arrays, and below that, it'll add units to them. We want to add our new Dragoon to the bottom of the following arrays: 'sarrUnitsAll', 'sarrUnitsShooters', 'sarrUnitsCavalry'.
    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!

    Part 2 - Training Upgrades
    Part 3 - Adding Descriptions
     
    Last edited: Oct 6, 2016
    condor_fly, Zakxaev68, Fimti and 2 others like this.
  2. A. Soldier

    A. Soldier Active 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. Setakat

    Setakat Member

    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;
          AddUpgradePack(country, upgstruct, ctypeProtection, gc_upg_tooltiptype_horsedef, 1, 2, ind, linkind);
       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;
          AddUpgradePack(country, upgstruct, ctypeDamageBullet, gc_upg_tooltiptype_shooterdmg, 1, 1, ind, linkind);
          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;
          AddUpgradePack(country, upgstruct, ctypeProtection, gc_upg_tooltiptype_horsedef, 1, 2, ind, linkind);
       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.

    Click here to review Part 1
    Or Click here for Part 3 - Adding Descriptions



    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
  4. A. Soldier

    A. Soldier Active Member

    Agreed.
     
  5. Fimti

    Fimti New 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. Setakat

    Setakat Member

    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. Hugojackson18

    Hugojackson18 Member

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

    A. Soldier Active 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. Hugojackson18

    Hugojackson18 Member

    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. Soldier

    A. Soldier Active 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. Hugojackson18

    Hugojackson18 Member

    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. Soldier

    A. Soldier Active 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. Fimti

    Fimti New 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:

    Ivenend, `zerr and egnaro like this.
  14. Hugojackson18

    Hugojackson18 Member

    This is amazing!
     
    Fimti likes this.
  15. Kamilow

    Kamilow Well-Known Member

  16. Alatristé

    Alatristé Member

    Wow great. Congratulations. I would have tried
     
  17. A. Soldier

    A. Soldier Active 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. Setakat

    Setakat Member

    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. Gambler71

    Gambler71 New 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. Setakat

    Setakat Member

    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.
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice