FAQs - LionShield/Kingdoms-and-Castles-Toolkit GitHub Wiki
dnSpy is the best tool to use to decompile the game. Just download it and then open ~\steamapps\common\Kingdoms and Castles\KingdomsAndCastles_Data\Managed\Assembly-CSharp.dll
[AvalonianILSpy]https://github.com/icsharpcode/AvaloniaILSpy] is the same but for Unix-like systems
Open your Steam Library and then find Kingdoms and Castles
- Right click
- Manage
- Local Files
- Browse...
Either download the mod using https://steamworkshopdownloader.io/ or subscribe to the mod and then navigate to ~\steamapps\workshop\content\569480\MOD_ID_NUMBER
where the mod ID number is found in the URL of the mod's workshop page
For example the ID for KingdomRenderer is 2306848108
Use the official Harmony2 wiki here. Harmony is not made for Kingdoms and Castles specifically but works with all C# (Unity) games. It was originally made for Rimworld so tutorials for using Harmony there may also be useful for here. Prefixing and Postfixing will be the two functions you likely use the most as they allow you to edit how a method in the game runs (By editing its inputs or its results)
If you are not using AssetBundles then your file system will look like:
~\steamapps\common\Kingdoms and Castles\KingdomsAndCastles_Data\mods\MOD_NAME
├──MyCSFile.cs
├──MyOtherCSFile.cs
├──output.txt
└──info.json
If you are using AssetBundles then either:
~\steamapps\common\Kingdoms and Castles\KingdomsAndCastles_Data\mods\MOD_NAME
├──MyCSFile.cs
├──MyOtherCSFile.cs
├──output.txt
├──info.json
├──linux
│ ├──linux
│ ├──linux.manifest
│ ├──linux.manifest.meta
│ ├──linux.meta
│ └──<other_weirdly_named_files>
├──osx
│ ├──osx
│ ├──osx.manifest
│ ├──osx.manifest.meta
│ ├──osx.meta
│ └──<other_weirdly_named_files>
├──win32
│ ├──win32
│ ├──win32.manifest
│ ├──win32.manifest.meta
│ ├──win32.meta
│ └──<other_weirdly_named_files>
└──win64
├──win64
├──win64.manifest
├──win64.manifest.meta
├──win64.meta
└──<other_weirdly_named_files>
or
~\steamapps\common\Kingdoms and Castles\KingdomsAndCastles_Data\mods\MOD_NAME
├──MyCSFile.cs
├──MyOtherCSFile.cs
├──output.txt
├──info.json
└──AssetBundle
├──linux
│ ├──linux
│ ├──linux.manifest
│ ├──linux.manifest.meta
│ ├──linux.meta
│ └──<other_weirdly_named_files>
├──osx
│ ├──osx
│ ├──osx.manifest
│ ├──osx.manifest.meta
│ ├──osx.meta
│ └──<other_weirdly_named_files>
├──win32
│ ├──win32
│ ├──win32.manifest
│ ├──win32.manifest.meta
│ ├──win32.meta
│ └──<other_weirdly_named_files>
└──win64
├──win64
├──win64.manifest
├──win64.manifest.meta
├──win64.meta
└──<other_weirdly_named_files>
The second file system is cleaner but when loading AssetBundles instead of doing assetBundle = KCModHelper.LoadAssetBundle(_helper.modPath, "my_assetbundle_name");
you will need to do assetBundle = KCModHelper.LoadAssetBundle($"{_helper.modPath}/AssetBundle", "my_assetbundle_name");
output.txt
is generated by the game and contains logs from your mod's helper object.
info.json
is used by the game to show mod information about your mod when it is loaded locally (So when you are making it). When it is downloaded from the Steam Workshop this file is not used and info you supplied when uploading the mod is used instead. (Optional)
MyCSFile.cs
is a C# (C-Sharp) file that you made that contains your mod's code. You can have as many of these as you like. Kingdoms and Castles takes uncompiled .cs files not compiled dlls.
When creating my AssetBundle it is not generating all of the folders (linux, osx, win32, win64) or the files inside are malformed. What do I do?
Try these methods and if they don't work then ask in the Discord:
Make sure that you have Unity2019.4.31f1 installed. Open this link to to install it unityhub://2019.4.31f1/bd5abf232a62.
Try uninstalling Unity and reinstalling it
The following code is from the Cannon mod and is a guide only.
// This code initialises all of the needed info to add the cannon building to the game. It is called in "public void Preload(KCModHelper _helper)"
private void InitCannon()
{
bCannon = cannonPrefab.AddComponent<Building>();
bCollider = cannonPrefab.transform.Find("Offset").Find("cannon").gameObject
.AddComponent<BuildingCollider>();
bCollider.Building = bCannon;
pdCannon = cannonPrefab.AddComponent<ProjectileDefense>();
pdCannon.b = bCannon;
pdCannon.projectilePrefab = cbProjectile;
pdCannon.AttackTime = 15f;
pdCannon.AttackRange = 5f;
pdCannon.rangeIncreasePerHeight = 3f;
bCannon.UniqueName = "cannon";
bCannon.customName = "Cannon"; // For WorkerUI Tile Display
bCannon.WorkersForFullYield = 4;
bCannon.BuildAllowedWorkers = 6;
bCannon.size = Vector3.one;
bCannon.placementSounds = new string[] {"castleplacement"};
bCannon.SelectionSounds = new string[] {"BuildingSelectCastleGate"};
bCannon.skillUsed = "Ballisteer";
bCannon.JobCategory = JobCategory.Ballista;
bCannon.CategoryName = "projectiletopper";
bCannon.ignoreRoadCoverageForPlacement = true;
ResourceAmount cost = new ResourceAmount();
cost.Set(FreeResourceType.Tree, 45);
cost.Set(FreeResourceType.Stone, 10);
cost.Set(FreeResourceType.Gold, 35);
cost.Set(FreeResourceType.IronOre, 10);
SetField<Building>("Cost", bFlags, bCannon, cost);
cannon = cannonPrefab.AddComponent<Cannon>();
cannon.b = bCannon;
cannon.pd = pdCannon;
cannon.flag = cannonPrefab.transform.Find("Offset").Find("cannon").Find("flag").gameObject;
cannon.veteranDecor = cannonPrefab.transform.Find("Offset").Find("cannon").Find("cannon_veteran");
cannon.RotateParent = cannonPrefab.transform.Find("Offset").Find("cannon").Find("cannon_top");
}
// To make the cannon appear in the build UI, add translation
```cs
[HarmonyPatch(typeof(GameState))]
[HarmonyPatch("Awake")]
public static class InternalPrefabsPatch
{
static void Postfix(GameState __instance)
{
__instance.internalPrefabs.Add(inst.bCannon);
}
}
[HarmonyPatch(typeof(BuildUI))]
[HarmonyPatch("Start")]
public static class BuildUIPatch
{
static void Postfix(BuildUI __instance)
{
__instance.AddBuilding(__instance.CastleTab, __instance.CastleTabVR, __instance.CastleTabConsole,
"cannon", "chamberofwar", Vector3.one);
}
}
[HarmonyPatch(typeof(LocalizationManager))]
[HarmonyPatch("GetTranslation")]
public static class LocalizationManagerPatch
{
static void Postfix(string Term, ref string __result)
{
if (Term == "Building cannon FriendlyName")
__result = "Cannon";
else if (Term == "Building cannon Description")
__result = "Cannon that goes boom boom...";
else if (Term == "Building cannon ThoughtOnBuilt")
__result = "Cannon is really loud, but I feel much safer.";
}
}
https://discord.gg/kingdomsandcastles
The Kingdoms and Castles discord does not allow link sharing. To avoid the automatic filter replace the dots (.
) in the URL with spaces (
)
If it is on GitHub simply download it as a zip and open it.
If it is not on GitHub but instead the steam workshop either:
Download the mod using https://steamworkshopdownloader.io/ and read the code there
Or Subscribe to it on the workshop then once it has downloaded go to ~\steamapps\workshop\content\569480\<mod_id>
where the mod_id
can be found in the URL of the workshop page for the mod. (To get the URL inside steam: Right click the background "Copy Page URL" and paste it somewhere to read it)
The game does not allow mods to reference certain libraries for safety reasons. To remove this safety feature download Unlocker by Zat on the worksohop.
The full list of banned libraries are: (WIP)
System.IO
-
System.Console
(Depends onSystem.IO
)