Adding New Buildings


Part I: Basic implementation of the building.


Initial notes:
- I tried this with another building first, but for the purpose of this guide I'll use HugoJackson18's castle which is available to all of you. Get it here: https://drive.google.com/file/d/0B6-HjHGVgDRmR2oxczhaTW5tNUE/view
- You will also need a text editor, I use sublime text, but you could use notepad ++ as well.
- We'll keep it simple, and just add the building to the mission nation, so it can be placed in game in the editor.
- We will use the blockhouse as a reference to copy files from. This will speed up the implementation of the building greatly.
- It is best that you use the same name everywhere for the building, it will be less confusing, and you'll make less mistakes. So, let's name this building "miscas".

Basic steps:
1. Extract the castle.osm and castl_diffuse.dds from the .rar you downloaded. Rename both, to miscas.osm and miscas.dds

2. Put miscas.osm into Cossacks 3\data\actors\buildings\mis\

3. Put miscas.dds into Cossacks 3\data\materials\buildings\mis\

4. Copy Cossacks 3\data\actors\buildings\mis\misblg.actor and paste it in the same folder. Rename it to miscas.actor

5. Open Cossacks 3\data\actors\buildings\mis\miscas.actor. Replace all the lines where it says "LoadFromFile = .\data\actors\buildings\mis\misblg." with 'miscas'. Pay attention here, since we don't have a 'death stage' for this building (yet) ensure you replace following 2 lines properly:

LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\misblg_death1.osm
LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\misblg_death2.osm


Ensure the _death part is gone:

LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\miscas.osm

Then save your file.
Note: If you do have deathstages/buildstages for your building, then you would add those .osm file names here. (See step 24.)

6. Open Cossacks 3\data\actors\actors.lib. Find (CTRL+F) 'Misblg'. Copy the section:

section.begin {refurl=.\data\actors\ref\refactors.lib; refkey=buildings}
   LODActorName = misblg
   LODActorFileName = .\data\actors\buildings\mis\misblg.actor
section.end


Paste it at the bottom of the file and replace both instances of 'misblg' with 'miscas'

section.begin {refurl=.\data\actors\ref\refactors.lib; refkey=buildings}
   LODActorName = miscas
   LODActorFileName = .\data\actors\buildings\mis\miscas.actor
section.end


Save the file.

7. Open Cossacks 3\data\materials\buildings\buildings.mat . Find 'misblg' Copy the section. Paste it at the bottom and ensure the names are changed to:

section.begin {refurl=.\data\materials\ref\refbuilding.mat}
   Material.Name = miscas
   Material.Texture.image = .\data\materials\buildings\mis\miscas.dds
   Material.Texture.textureformat = tfDefault
section.end


Save the file.

8. Find Cossacks 3\data\objects\buildings\misblg.prop , copy it and rename the copy to miscas.prop

9. Open Cossacks 3\data\objects\buildings\miscas.prop , find and replace all instances of 'misblg' with 'miscas'. Save the file.

10. Open Data\objects\buildings\buildings.objects , and find the line:

ObjectItems[*].PropertiesFileName=.\data\objects\buildings\misblg.prop

Copy it, paste it just before section.end at the bottom and change misblg to miscas. Save.

11. Open data\scripts\lib\units.script. Find following line: "//if (mis) then". The mission nation buildings are right below it. Find the following line and add the 'miscas' to it so it looks like this:

            case objprop.sid of
               'misblg', 'misblg2', 'miscas' : begin


You could ofcourse also copy the entire 'misblg' section, paste it under it and make adjustments to the building properties here ( HP, price, etc) . Let's not bother with that for now.

12. Open data\scripts\lib\country.script and find '// MEMBERS'.
The mission nation is right below it. Copy the line with 'misblg' and paste it under it. Change the name to miscas.

_country_AddMember(country, 'miscas', ind, True, gc_country_editorplace_category_buildings, 15, gc_ai_unit_none);
 

13. Open Data\hud\hud.mat . Find:

section.begin {refurl=.\data\hud\ref\reflibmat.mat}
   Material.Name = icons.bld.eurtow
   Material.LibTextureName = icons
   Material.TextureCoord.ImageW = 1024
   Material.TextureCoord.ImageH = 512
   Material.TextureCoord.CoordX = 230
   Material.TextureCoord.CoordY = 92
   Material.TextureCoord.CoordW = 46
   Material.TextureCoord.CoordH = 46
section.end


Copy it, paste at the bottom and change to:
Material.Name = icons.bld.miscas
Save.

14. Now we have done the bare minimum to get a new building in game, it should be placeable in the editor. So test if you did everything right. Go into the editor, look for the 'originals' nation and if you did everything right, your new building should be there.
 

Additional notes:
- I urge everyone to take a copy of your \Steam\steamapps\common\Cossacks 3 folder, and copy it on your desktop. Work on this copy, so an update from a patch doesn't overwrite your files or when you derp you don't have to reinstall files.

- Take advantage of the external editor , rather than using the internal editor. If you mess up, you will get a black screen with the ingame editor, and you will be none the wiser what happened. If you use the external editor, the debug log will tell you that something has gone wrong, and usually what has gone wrong. Sometimes it will even tell you in which file and which line there is something wrong.
I made at least 3 mistakes while doing this , in one occasion I simply forgot to save my changes, and without the debug screen, you could spend an hour trying to figure it out.

- Yes, the building is rotated wrong, and many many more things will be needed to get this building setup properly, but these were just the basic steps on how to get the new building ingame. Build points will have to be setup, collision mask, collision box, smokepoints, text description, building properties, decals and then later assign it to a proper nation, add it to the peasants building menu,....but that's for the next parts of the guide.


Part II: Adding a description, rotate/scale, smoke points and ground texture


Notes:
- Get the new castle files here: https://drive.google.com/file/d/0B6-HjHGVgDRmekpCV3cyY3NGd3c/view
- [Optional] Since we used the name 'miscas' in the first part of the guide, rename the files you just downloaded to 'miscas' to keep it simple in the naming:

If you don't rename them, then make sure you use the correct names when implementing.


15. We'll start simple, with a description for the building. I have no interest in translating it to every language ingame, so we'll add the description in the 'en' folder.
Find: Cossacks 3\data\locale\en\units.txt
Open it and add at the bottom of the file:

    @miscas
Castle
    @miscas.ext
%def%Fortification.
%include(units;descr.canshoot)%
%pos%Can only be destroyed by cannons, ships, grenadiers or archers.


Save the file.

Next go to Cossacks 3\data\locale\txt_to_lng.bat . Open it (rightclick->open as) and at the bottom add following line:

..\..\tools\locale\editorlang.exe .\en\units.txt .\en\units.lng c

Save and close.
Now run the batch file by double clicking on it.

If you did everything right in the editor it should show 'Castle' now instead of 'miscas'
 

16. Lets rotate the building a bit, and rescale it a bit aswell just so you know how. Put the castle model (miscas.osm) from castle_02.zip into your Cossacks 3\data\actors\buildings\mis\ folder because Hugo seems to have rotated the model in the second pack. Just overwrite the existing one.
Next: Go to Cossacks 3\data\objects\buildings\miscas.prop
Open it and at the bottom find following lines and adjust:

scaleproperty : section.begin {refurl=.\data\objects\ref\refbuilding.prop; refkey=scaleproperty}
   DefaultScale.X = 0.4
   DefaultScale.Y = 0.4
   DefaultScale.Z = 0.4
section.end

directionupproperty : section.begin {refurl=.\data\objects\ref\refbuilding.prop; refkey=directionupproperty}
   DefaultRollAngle = 315
section.end

 

17. Lets work a bit on the 'selection box', because this was based on the misblg, which is smaller.
This will also help with the collision so we don't have soldiers strolling on the inner courtyard.


Load up the editor (editor.exe) . We'll place the building right here (Add a player in Advanced - Player -> Add a player, and select "Race" buildings.)
Then go to Layer - Players (CTRL+ALT+U)-> Click on "buildings". A tree will open will all the buildings. Place the building on the map. Press the spacebar to stop placing.
Now go to View- Universal manipulator, and tick on "Bounding box and CustAABBinSP" in the top section.

When dragging over the building to select it, you will instantly see the blockhouse selection box appear. We have to fix this up to match this new building.
We'll do this manually. Go to Cossacks 3\data\objects\buildings\miscas.prop and add:

collisionmeshproperty : section.begin {refurl=.\data\objects\ref\refbuilding.prop; refkey=collisionmeshproperty}
   CustomBoundingAABBMin.X = -2.55
   CustomBoundingAABBMin.Y = 0.00
   CustomBoundingAABBMin.Z = -2.55
   CustomBoundingAABBMax.X = 2.55
   CustomBoundingAABBMax.Y = 3.00
   CustomBoundingAABBMax.Z = 2.55
section.end

 

It's not perfect but at least the box is larger now and easier to select. You can tweak the numbers more, but I'm sure GSC will release a tool/script to get these values more accurately.

Note: Don't make the selection box too high, or you'll have situations where a small building behind this building becomes unselectable without rotating the camera. (= Don't include the tower in the box)


18. Let's put a ground texture under the building now (Decal)
Get the ground texture (miscasd.dds) from the castle_02.zip and put it in:
Cossacks 3\data\terrain\decals\buildings\

Open Cossacks 3\data\terrain\decals\decals.lib
At the bottom paste following :

section.begin {refkey=default}
   name = miscasd
   Decal.material.libmaterialname = miscasd
   Decal.SummerLibMaterialName = miscasd
   Decal.width = 12
   Decal.height = 12
   section.end

 

Open Cossacks 3\data\terrain\decals\decals.mat
Same thing, add:

section.begin {refkey=default}
   Material.Name = miscasd.dds
   Material.Texture.image = .\data\terrain\decals\buildings\miscasd.dds
section.end

 

Go to Cossacks 3\data\game\var\objcustom.cfg
Add at the bottom before section.end :

   [*] : struct.begin
      sid = miscas
      Decal : struct.begin
         scale = 20
         offx = 0
         offy = 0
         angle = 0 //I think it needs 180 here, i forgot to change/test
      struct.end
   struct.end


Looking nice already now:


19. Lets add some smoke points now so its more visible if it is under attack.
Cossacks 3\data\game\var\objcustom.cfg
Find the section we just added in previous step.
Add following:

   [*] : struct.begin
      sid = miscas
      Decal : struct.begin
         scale = 20
         offx = 0
         offy = 0
         angle = 0
      struct.end
      SmokePoints : struct.begin
         [*] : struct.begin
            px = -0.34
            py = 2.40
            pz = -1.41
            nx = -0.70710676908493
            ny = 0
            nz = 0.70710676908493
         struct.end
         [*] : struct.begin
            px = 0.09
            py = 2.00
            pz = -1.10
            nx = 0.70710676908493
            ny = 0
            nz = 0.70710676908493
         struct.end
      struct.end
   struct.end

 

It's not perfect, but doing this manually is tedious. I wont add anymore smoke points because of this.
I'm sure gsc will release an editor/Script to add these.
Note: You can see these points in the editor, if you select the building, and then go to Scripts-> Smokepointshowpickedbuilding.
In this same file you can add exit points, but since the castle doesn't really have an 'open' door for units to come out, I won't.


Part III: Adding Collision mask, Shot points, Properties, Build and Death Stages.



20. Let's setup the collision mask .
In editor you can see the collision mask by going to View - Collision.

Go to Cossacks 3\data\objects\buildings\miscas.prop and add:

collisionmaskproperty : section.begin {refurl=.\data\objects\ref\refbuilding.prop; refkey=collisionmaskproperty}
   Priority = 101
   Mask : struct.begin
      [*] = 0000000010000000
      [*] = 0000000111000000
      [*] = 0000001111100000
      [*] = 0000011111110000
      [*] = 0000111111111000
      [*] = 0001111111111100
      [*] = 0011111111111110
      [*] = 0111111111111111
      [*] = 0011111111111110
      [*] = 0001111111111100
      [*] = 0000111111111000
      [*] = 0000011111110000
      [*] = 0000001111100000
      [*] = 0000000111000000
      [*] = 0000000010000000
   struct.end
section.end

 

21. Now, although it's using the properties of the blockhouse, it can't shoot yet untill we add shotpoints.
Go to Cossacks 3\data\game\var\objcustom.cfg and add to the 'miscas' section:


      ShotPoints : struct.begin
         [*] : struct.begin
            x = -0.10
            y = 2.10
            z = -1.10
            bcustomdir = True
            minangle = 1
            maxangle = 89
         struct.end
         [*] : struct.begin
            x = -0.34
            y = 2.42
            z = -1.41
            bcustomdir = True
            minangle = 90
            maxangle = 179
         struct.end
         [*] : struct.begin
            x = -0.10
            y = 2.10
            z = -1.10
            bcustomdir = True
            minangle = 180
            maxangle = 269
         struct.end
         [*] : struct.begin
            x = -0.34
            y = 2.42
            z = -1.41
            bcustomdir = True
            minangle = 270
            maxangle = 360
         struct.end
      struct.end

 

They are not perfect, but it's too tedious to do this manually. It will be able to shoot in all directions now.


22. Let's add it to a peasants build menu in the mis nation.
Go to Cossacks 3\data\scripts\lib\country.script. Search for // MEMBERS and scroll down a few lines untill you see:

      var member : String = 'peaaus';
      var fixedproduceind : Integer = _country_GetFixedProduceIndexBySID(cid, member, bAddIfNotExist);
      if (fixedproduceind<>-1) then
      begin
         _country_AddFixedProduceWithAccessControl(country, fixedproduceind, member, 'misblg', 6, 0, ind, '', '', '');
         _country_AddFixedProduceWithAccessControl(country, fixedproduceind, member, 'misblg2', 7, 0, ind, '', '', '');
         _country_AddFixedProduceWithAccessControl(country, fixedproduceind, member, 'miscas', 8, 0, ind, '', '', '');
      end;


Make sure to add the line with 'miscas' as shown above.


23. Lets give our building its own properties now.
Go to Cossacks 3\data\scripts\lib\units.script
Find:

            case objprop.sid of
               'misblg', 'misblg2', 'miscas' : begin


Now delete the , 'miscas' part which we added in previous part of the guide.

Add following under the miscommandcenter section:

               'miscas' : begin
                  SetObjBuildingBaseSettings(objprop, False, 500, gc_obj_usage_tower); {capture,score,usage->will show bombard area icon}
                  SetObjBasePrice(objbase, 0, 5000, 5000, 15000, 2500, 2500); {food, wood, stone, gold, iron, coal}
                  SetObjBuildingProperties(objprop, objbase, 50000, 4500, 300); {hitpoints,buildtime,costpercent}
                  SetObjBaseMaterialCanKill(objprop, gc_obj_material_building, gc_obj_material_body, gc_obj_material_wood, gc_obj_material_woodwall, gc_obj_material_iron, gc_obj_material_building); {is building, and can kill everything listed after}
                  //{SetObjBaseWeapon(objprop, objbase, 0{index}, 55{damage}, 25{pause}, 200{minradius}, 550{maxradius}, 350{detectradiusmin}, 550{detectradiusmax}, gc_obj_weapon_kind_bullet, True{bsearchminattackradius});
                  //objprop.weapon[0].weaponsid := 'SHOTBLOCKHOUSE'; {other weapon ids can be found in : Cossacks 3\data\scripts\lib\weapon.script }
                  //objprop.weapon[0].cost[gc_resource_type_iron] := 3; {cost per shot}
                  //objprop.weapon[0].cost[gc_resource_type_coal] := 3; {cost per shot}
                  //objprop.weapon[0].fxshot := 'shotmusketpoint'; {visuals}
                  SetObjBaseWeapon(objprop, objbase, 0{index}, 1000{damage}, 200{pause}, 550{minradius}, 1200{maxradius}, 550{detectradiusmin}, 50000{detectradiusmax}, gc_obj_weapon_kind_cannonball, True{bsearchminattackradius});
                  objprop.weapon[0].weaponsid := 'PPOINTTTOW';
                  objprop.weapon[0].cost[gc_resource_type_iron] := 5; {cost per shot}
                  objprop.weapon[0].cost[gc_resource_type_coal] := 10; {cost per shot}
                  objbase.weapon[0].dispertion := _misc_PixelsToTiles(75); {inaccuracy}
                  objprop.weapon[0].fxshot := 'shottower'; {visuals}
                  objprop.bartprepare := True; {shows loading bar in gui between shots}
                  objprop.consume[gc_resource_type_gold] := 500; {maintenance cost}
                  objprop.bmercenary := True;  {will mutiny if no more gold}
                  objprop.bturnoff := True; {stops shooting if no resources}
                  objprop.searchradius := _misc_PixelsToTiles(1000);
                  objprop.vision := 4; {how far it clears fog of war}
                  objprop.bshowdelay := True;
                  objprop.explradius := _misc_PixelsToTiles(1);
                  objprop.farm := 150; {adds 150 pop cap}
                  objprop.bslowdeath := True;
               end;

 

It shoots like a tower now, rather than a blockhouse, I left the blockhouse weapons in there though, just in case you want those.

24. Let's add the build and deathstages now.
24.1 Grab following files you downloaded and renamed:
miscas1.osm, miscas2.osm, miscas3.osm, miscas4.osm, miscas_death1.osm, miscas_death2.osm
Put all these in Cossacks 3\data\actors\buildings\mis\

24.2  Go to Cossacks 3\data\actors\buildings\mis\miscas.actor
We'll add the buildstages and deathstage files here, adjust so it looks like this:

section.begin {refurl=.\data\actors\ref\refbuilding.actor}
   ActorList.Items[0].Name = miscas.mesh
   ActorList.Items[0].LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\miscas.osm
   ActorList.Items[*] : struct.begin {refurl=.\data\actors\ref\refbuilding.actor; refkey=.ActorList.Items[0]}
      Name = miscas1.mesh
      LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\miscas1.osm
   struct.end
   ActorList.Items[*] : struct.begin {refurl=.\data\actors\ref\refbuilding.actor; refkey=.ActorList.Items[0]}
      Name = miscas2.mesh
      LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\miscas2.osm
   struct.end
   ActorList.Items[*] : struct.begin {refurl=.\data\actors\ref\refbuilding.actor; refkey=.ActorList.Items[0]}
      Name = miscas3.mesh
      LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\miscas3.osm
   struct.end
   ActorList.Items[*] : struct.begin {refurl=.\data\actors\ref\refbuilding.actor; refkey=.ActorList.Items[0]}
      Name = miscas4.mesh
      LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\miscas4.osm
   struct.end
   ActorList.Items[*] : struct.begin {refurl=.\data\actors\ref\refbuilding.actor; refkey=.ActorList.Items[0]}
      Name = miscas_death1.mesh
      LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\miscas_death1.osm
   struct.end
   ActorList.Items[*] : struct.begin {refurl=.\data\actors\ref\refbuilding.actor; refkey=.ActorList.Items[0]}
      Name = miscas_death2.mesh
      LODList.Items[0].MeshObjects.LoadFromFile = .\data\actors\buildings\mis\miscas_death2.osm
   struct.end
section.end

 

24.3 Grab the miscas.dds file from the castle_02.zip we renamed and put it in Cossacks 3\data\materials\buildings\mis\
 

25. Time to try in the editor. It should be fully operational now. It can be built, it can shoot, it can be attacked.
 

Additional notes:
- There are actually scripts to visually adjust the selection box:

// Go to Script and look at all the AABB options there. Use the hotkeys to resize the box to match the building.
// Hotkeys: CTRL/ALT+F1-F12
// You will want to rotate the building often to see that it matches the walls roughly.
// Sadly no way to save these points apparently or I simply haven't figured out how. If someone feels like figuring this out, please do, it would save a lot of time.

 

- I Would have added an art depot index in the properties so it would add space for cannons, but the gui is very derpy:

Not impossible to change, but not really related to this guide.


Credits:

- HugoJackson18 for the building; version 3 of the building can be found here : https://drive.google.com/file/d/0B6-HjHGVgDRmMnljbWZCRW9Eb2s/view
- Setakat for the guide on cloning units, which has been helpful to make this somewhat easier to figure out.