Editing Modding Tutorials/Plague Gun (1.1)

Jump to navigation Jump to search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
This is a tutorial for taking an item [[mod]] from conception all the way to completion, touching on most systems involved in RimWorld modding and explaining each step.
+
This tutorial is a rewrite of the [[Plague Gun/Introduction|original]] by Jecrell ({{LudeonThread|33219}}), updated to 1.1 by [[User:Dninemfive|dninemfive]].
  
 
== Introduction ==
 
== Introduction ==
  
In this tutorial we will be using most of the tools available to a Rimworld [[Modding|modder]] to create a custom weapon, known as the Plague Gun.
+
In this tutorial we will be using most of the tools available to a Rimworld modder to create a custom weapon, known as the Plague Gun.
  
This weapon will, when its shots hit a living target, have a chance to apply the [[Plague]] hediff ("health difference") to that target.
+
This weapon will, when its shots hit a living target, have a chance to apply the Plague hediff ("health difference") to that target.
  
 
To do this, we will create XML ThingDefs for the gun and projectile, create a C# assembly which determines what happens when the projectile hits a target, and link that behavior back to the XML.
 
To do this, we will create XML ThingDefs for the gun and projectile, create a C# assembly which determines what happens when the projectile hits a target, and link that behavior back to the XML.
Line 29: Line 29:
 
|}
 
|}
  
For more detailed recommendations, see [[Modding Tutorials/Recommended software|here]].<br>For help setting up Notepad++, see [https://www.youtube.com/watch?v=EBvum8NiGx8 here].
+
For more detailed recommendations, see [[Modding Tutorials/Recommended software|here]].
  
 
== XML Stage ==
 
== XML Stage ==
Line 41: Line 41:
 
#* On GOG, you can find it by right-clicking the game in your games list > Manage Installation > Show Folder
 
#* On GOG, you can find it by right-clicking the game in your games list > Manage Installation > Show Folder
 
#** By default it will be located at <code>C:\Program Files (x86)\GOG Galaxy\Games\RimWorld</code> if you bought it through GOG on Windows.
 
#** By default it will be located at <code>C:\Program Files (x86)\GOG Galaxy\Games\RimWorld</code> if you bought it through GOG on Windows.
# Create a <code>Mods</code> folder (if it doesn't already exist).
+
# Create a mod folder.{{br}}<small>RimWorld>Mods>PlagueGun</small>
<br /><nowiki /><!--
 
--><small>RimWorld>Mods>PlagueGun</small>
 
 
#* Go into the Mods folder.
 
#* Go into the Mods folder.
 
#* Make a new folder with our mod's title: '''PlagueGun'''
 
#* Make a new folder with our mod's title: '''PlagueGun'''
# Inside '''PlagueGun''', make an '''About''' folder.
+
# Inside '''PlagueGun''', make an '''About''' folder.{{br}}<small>RimWorld>Mods>PlagueGun>About</small>
<br /><nowiki /><!--
+
# Inside the '''About''' folder, make a new text file and rename it About.xml.{{br}}<small>RimWorld>Mods>PlagueGun>About>About.xml</small>
--><small>RimWorld>Mods>PlagueGun>About</small>
 
# Inside the '''About''' folder, make a new text file and rename it About.xml.
 
<br /><nowiki /><!--
 
--><small>RimWorld>Mods>PlagueGun>About>About.xml</small>
 
 
#* You will need a good text editor to make a proper XML file -- see [[#Required Items|required items]]. I always make a .txt file first and change it to .xml. If you can't rename your file's type, make sure you have filetypes visible in your operating system's file view settings.
 
#* You will need a good text editor to make a proper XML file -- see [[#Required Items|required items]]. I always make a .txt file first and change it to .xml. If you can't rename your file's type, make sure you have filetypes visible in your operating system's file view settings.
#* [[About.xml]] is the file that shows your mod in the mod list inside the RimWorld game. It is also used when creating a Workshop upload for Steam.
+
#* About.xml is the file that shows your mod in the mod list inside the RimWorld game. It is also used when creating a Workshop upload for Steam.
 
#* At the top of an XML file, always include this for RimWorld. It basically just gives the game some info about how to read the file. <source lang = "xml"><?xml version="1.0" encoding="utf-8"?></source> ''Note: the'' version '' tag should always be "1.0". It has no relation with the current RimWorld version.''
 
#* At the top of an XML file, always include this for RimWorld. It basically just gives the game some info about how to read the file. <source lang = "xml"><?xml version="1.0" encoding="utf-8"?></source> ''Note: the'' version '' tag should always be "1.0". It has no relation with the current RimWorld version.''
 
#* Then add the MetaData tags for the Workshop and in-game Mod list.<source lang ="xml"><ModMetaData>
 
#* Then add the MetaData tags for the Workshop and in-game Mod list.<source lang ="xml"><ModMetaData>
Line 66: Line 60:
 
</source>
 
</source>
 
#* Save the file.
 
#* Save the file.
# Add a Preview.png or Preview.jpeg to your '''About''' folder.
+
# Add a Preview.png or Preview.jpeg to your '''About''' folder.{{br}}<small>RimWorld>Mods>PlagueGun>About>Preview.png</small>
<br /><nowiki /><!--
 
--><small>RimWorld>Mods>PlagueGun>About>Preview.png</small>
 
 
#* This lets users see what your mod looks like in the RimWorld mod list or on the Steam Workshop.
 
#* This lets users see what your mod looks like in the RimWorld mod list or on the Steam Workshop.
 
#* The conventional dimensions to fit the preview image on Steam are 640x360. The image must be smaller than 1mb.  
 
#* The conventional dimensions to fit the preview image on Steam are 640x360. The image must be smaller than 1mb.  
 
#* Example: [[File:Preview.png]]
 
#* Example: [[File:Preview.png]]
# Make a '''Defs''' folder in your Mod's directory.
+
# Make a '''Defs''' folder in your Mod's directory.{{br}}<small>RimWorld>Mods>PlagueGun>Defs</small>
<br /><nowiki /><!--
 
--><small>RimWorld>Mods>PlagueGun>Defs</small>
 
 
#* RimWorld will read your XML files in any subdirectory of '''Defs'''. You can name your directories however you like under that folder. Defs>StrangeNewAlienGuns>MyGuns.xml will work. For the purposes of this tutorial, however, we will use the RimWorld standard structure.
 
#* RimWorld will read your XML files in any subdirectory of '''Defs'''. You can name your directories however you like under that folder. Defs>StrangeNewAlienGuns>MyGuns.xml will work. For the purposes of this tutorial, however, we will use the RimWorld standard structure.
 
#* What are Defs? Main article: [[Modding Tutorials/XML Defs|Defs]]
 
#* What are Defs? Main article: [[Modding Tutorials/XML Defs|Defs]]
 
#** RimWorld uses things called Defs (short for "definitions") like blueprints for in-game objects. Instead of using hidden C# code, RimWorld will look up an XML Def and copy it to the game world. This makes things easier for us, the modders. Everything from characters, animals, floors, damages, buildings, and even diseases in RimWorld use Defs. We're going to make Defs for our Plague Gun and Plague Bullet.
 
#** RimWorld uses things called Defs (short for "definitions") like blueprints for in-game objects. Instead of using hidden C# code, RimWorld will look up an XML Def and copy it to the game world. This makes things easier for us, the modders. Everything from characters, animals, floors, damages, buildings, and even diseases in RimWorld use Defs. We're going to make Defs for our Plague Gun and Plague Bullet.
# Make a new '''ThingDefs''' folder in your '''Defs''' folder.
+
# Make a new '''ThingDefs''' folder in your '''Defs''' folder.{{br}}<small>RimWorld>Mods>PlagueGun>Defs>ThingDefs</small>
<br /><nowiki /><!--
+
# Make a new text file in your '''ThingDefs''' folder, and change it to RangedWeapon_PlagueGun.xml.{{br}}<small>RimWorld>Mods>PlagueGun>Defs>ThingDefs>RangedWeapon_PlagueGun.xml</small>
--><small>RimWorld>Mods>PlagueGun>Defs>ThingDefs</small>
 
# Make a new text file in your '''ThingDefs''' folder, and change it to RangedWeapon_PlagueGun.xml.
 
<br /><nowiki /><!--
 
--><small>RimWorld>Mods>PlagueGun>Defs>ThingDefs>RangedWeapon_PlagueGun.xml</small>
 
 
#* This file will contain the blueprints (ThingDefs) for our new gun and bullets.
 
#* This file will contain the blueprints (ThingDefs) for our new gun and bullets.
 
#* Next we will fill out our XML file by copying an existing revolver's ThingDef and a revolver bullet ThingDef.
 
#* Next we will fill out our XML file by copying an existing revolver's ThingDef and a revolver bullet ThingDef.
Line 110: Line 96:
 
=== Completed Example ===
 
=== Completed Example ===
  
''Note'': The example is up-to-date for [[Version|1.3]] and will likely be outdated in the future. The above steps should always be relevant.
+
''Note'': The example is up-to-date for [[Version|1.1]] and will likely be outdated in the future. The above steps should always be relevant.
 
<source lang ="xml">
 
<source lang ="xml">
 
<?xml version="1.0" encoding="utf-8" ?>
 
<?xml version="1.0" encoding="utf-8" ?>
Line 122: Line 108:
 
     </graphicData>
 
     </graphicData>
 
     <projectile>
 
     <projectile>
 +
      <flyOverhead>false</flyOverhead>
 
       <damageDef>Bullet</damageDef>
 
       <damageDef>Bullet</damageDef>
 
       <damageAmountBase>12</damageAmountBase>
 
       <damageAmountBase>12</damageAmountBase>
Line 137: Line 124:
 
       <graphicClass>Graphic_Single</graphicClass>
 
       <graphicClass>Graphic_Single</graphicClass>
 
     </graphicData>
 
     </graphicData>
    <uiIconScale>1.4</uiIconScale>
 
 
     <soundInteract>Interact_Revolver</soundInteract>
 
     <soundInteract>Interact_Revolver</soundInteract>
    <thingSetMakerTags><li>RewardStandardQualitySuper</li></thingSetMakerTags>
 
 
     <statBases>
 
     <statBases>
 
       <WorkToMake>4000</WorkToMake>
 
       <WorkToMake>4000</WorkToMake>
Line 153: Line 138:
 
       <li>Revolver</li>
 
       <li>Revolver</li>
 
     </weaponTags>
 
     </weaponTags>
    <weaponClasses>
 
      <li>RangedLight</li>
 
    </weaponClasses>
 
 
     <costList>
 
     <costList>
 
       <Steel>30</Steel>
 
       <Steel>30</Steel>
Line 206: Line 188:
  
 
# Open your compiler of choice for C#.
 
# Open your compiler of choice for C#.
#* This tutorial will assume you're using Visual Studio Community Edition, a free Windows-based compiler for C# code.
+
#* This tutorial will assume you're using Visual Studio Community edition, a free Windows-based compiler for C# code.
 
# Make a new Visual C# Class Library .NET Framework project. Name it PlagueGun. Make its directory RimWorld>Mods>PlagueGun>Source
 
# Make a new Visual C# Class Library .NET Framework project. Name it PlagueGun. Make its directory RimWorld>Mods>PlagueGun>Source
 
#* File → New → Project → Class Library (.NET Framework).
 
#* File → New → Project → Class Library (.NET Framework).
Line 215: Line 197:
 
#* Forgetting to do this will cause lots of errors.
 
#* Forgetting to do this will cause lots of errors.
 
#* Select Yes when it asks you if you're sure to change the framework.
 
#* Select Yes when it asks you if you're sure to change the framework.
# While still in Properties, go to the '''Build''' tab.
+
# Go to the '''Build''' tab.
 
# Change the output path to be RimWorld\Mods\PlagueGun\Assemblies
 
# Change the output path to be RimWorld\Mods\PlagueGun\Assemblies
 
#* All .dll files will go into this directory when we "build" our code library.
 
#* All .dll files will go into this directory when we "build" our code library.
Line 224: Line 206:
 
#* This doesn't have to all be the same as your namespace, but it doesn't hurt to be consistent.
 
#* This doesn't have to all be the same as your namespace, but it doesn't hurt to be consistent.
 
# In the main option bar at the top of the visual studio (File, Edit, View...), click Project, and click Add Reference.
 
# In the main option bar at the top of the visual studio (File, Edit, View...), click Project, and click Add Reference.
# Click Browse at the bottom right corner of the window and go to RimWorld\RimWorldWin64_Data\Managed
+
# Click Browse and go to RimWorld\RimWorldWin64_Data\Managed
 
# Add references to Assembly-CSharp.dll, UnityEngine.dll, and UnityEngine.CoreModule.dll.
 
# Add references to Assembly-CSharp.dll, UnityEngine.dll, and UnityEngine.CoreModule.dll.
 
#* In 1.1 the Unity DLLs were split up and are no longer all contained in the same module.
 
#* In 1.1 the Unity DLLs were split up and are no longer all contained in the same module.
Line 251: Line 233:
 
#* These tell the code you're working with RimWorld. Without these, our code will not be able to understand references to RimWorld code.
 
#* These tell the code you're working with RimWorld. Without these, our code will not be able to understand references to RimWorld code.
 
# Add a namespace line. By default, this is your project name. Take note - you will need this to connect to XML later.<source lang="csharp">
 
# Add a namespace line. By default, this is your project name. Take note - you will need this to connect to XML later.<source lang="csharp">
namespace TST_PlagueGun
+
namespace TST_PlagueGun;
{
 
}
 
 
</source>
 
</source>
 
#* '''Note:''' ''Using a prefix on the namespace is not required, but it's good for consistency and in the rare case they may overlap - such as when multiple people follow the same tutorial to learn how to mod.''
 
#* '''Note:''' ''Using a prefix on the namespace is not required, but it's good for consistency and in the rare case they may overlap - such as when multiple people follow the same tutorial to learn how to mod.''
  
 
=== Connecting XML and C#, Part 1 ===
 
=== Connecting XML and C#, Part 1 ===
{{Main|Modding Tutorials/DefModExtension}}
 
 
 
# First, let's add a way to read XML data into your assembly.
 
# First, let's add a way to read XML data into your assembly.
# Rename public class Class1 to ModExtension_PlagueBullet and make it inherit DefModExtension. As a reminder, inheritance looks like this:<source lang="csharp">
+
# Rename public class Class1 to ModExtension_Plaguebullet and make it inherit DefModExtension. As a reminder, inheritance looks like this:<source lang="csharp">
 
public class ModExtension_PlagueBullet : DefModExtension
 
public class ModExtension_PlagueBullet : DefModExtension
{
 
}
 
 
</source>
 
</source>
 
#* '''Note:''' Renaming things in an IDE like Visual Studio is best done by pressing F2 or right-clicking the item/name. Doing it like that will change all occurrences of that thing, so everything that references your namespace or Class1 will now use the new name.
 
#* '''Note:''' Renaming things in an IDE like Visual Studio is best done by pressing F2 or right-clicking the item/name. Doing it like that will change all occurrences of that thing, so everything that references your namespace or Class1 will now use the new name.
Line 281: Line 257:
 
</modExtensions>
 
</modExtensions>
 
</source>
 
</source>
#* '''Note:''' Note the XML tags match the names of the fields in the C# class. This allows the XML to provide data to the program. When the mod is loaded, the XML will be read, and used to fill in the corresponding fields.
+
#* '''Note:''' This is the key intuition of pretty much this entire tutorial. The fields you set in classes exposed to XML, like ModExtensions, are directly and automatically filled by the base game by their names. Notice the exact correspondence between addHediffChance and hediffToAdd between the C# and XML.
 
#* Additionally, take care to note you can set the value of addHediffChance to any valid floating point number and it will be reflected in-game. The value given in C# is only the default value if unset.
 
#* Additionally, take care to note you can set the value of addHediffChance to any valid floating point number and it will be reflected in-game. The value given in C# is only the default value if unset.
  
Line 287: Line 263:
 
# Let's make the actual projectile. For this tutorial, we're going to make a new projectile that checks for impact and adds a Hediff (health differential - poison, toxins, implants, anything).
 
# Let's make the actual projectile. For this tutorial, we're going to make a new projectile that checks for impact and adds a Hediff (health differential - poison, toxins, implants, anything).
 
# First, create a new .cs file by right-clicking the PlagueGun part of the Solution Explorer and selecting Add > New Item.
 
# First, create a new .cs file by right-clicking the PlagueGun part of the Solution Explorer and selecting Add > New Item.
#* '''Note:''' in C#, you can have multiple class definitions in a single file. We're just making a new file for organizational purposes.
+
#* '''Note:''' in C#, you can have multiple class definitions in a single file. However, it's much easier to navigate when you have a separate file for separate concepts.
 +
#* I tend to only keep closely related classes (such as ThingComps and their associated CompProperties) together in the same file; in most cases, you should only have one or two classes per file.
 
# Make your new class inherit the Bullet class (a child of the Projectile class), so the game will treat your new projectile like a bullet and not throw (fun) errors. <source lang="csharp">
 
# Make your new class inherit the Bullet class (a child of the Projectile class), so the game will treat your new projectile like a bullet and not throw (fun) errors. <source lang="csharp">
 
public class Projectile_PlagueBullet : Bullet
 
public class Projectile_PlagueBullet : Bullet
 
</source>
 
</source>
 
# First, let's connect our new projectile to the relevant ModExtension: <source lang="csharp">
 
# First, let's connect our new projectile to the relevant ModExtension: <source lang="csharp">
public ModExtension_PlagueBullet Props => def.GetModExtension<ModExtension_PlagueBullet>();
+
public ModExtension_PlagueBullet Props => base.def.GetModExtension<ModExtension_PlagueBullet>();
 
</source>
 
</source>
 
#* This line is a Property, basically a method which doesn't take any arguments, and can generally speaking be treated as a variable. See [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties this article] for more details.
 
#* This line is a Property, basically a method which doesn't take any arguments, and can generally speaking be treated as a variable. See [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties this article] for more details.
 +
#* It also isn't ''strictly'' necessary, but do you really want to retype or copy-and-paste the right-hand side of that expression over and over?
 
# Now, let's start the actual core code of this mod. Let's begin by overriding the Impact method on the base Bullet class, like so: <source lang="csharp">
 
# Now, let's start the actual core code of this mod. Let's begin by overriding the Impact method on the base Bullet class, like so: <source lang="csharp">
protected override void Impact(Thing hitThing, bool blockedByShield = false)
+
protected override void Impact(Thing hitThing)
 
</source>
 
</source>
 
#* The <code>override</code> keyword tells the compiler that we're replacing the functionality of the <code>Impact</code> method from the <code>Bullet</code> class we're inheriting from.
 
#* The <code>override</code> keyword tells the compiler that we're replacing the functionality of the <code>Impact</code> method from the <code>Bullet</code> class we're inheriting from.
 
# First, let's call the base version of this method so we don't need to rewrite all the logic about damaging a pawn - we only care about adding the hediff ''after'' damage occurs. <source lang="csharp">
 
# First, let's call the base version of this method so we don't need to rewrite all the logic about damaging a pawn - we only care about adding the hediff ''after'' damage occurs. <source lang="csharp">
base.Impact(hitThing, blockedByShield);
+
base.Impact(hitThing);
 
</source>
 
</source>
 
# Next, we check to make sure the ModExtension was properly loaded, that we hit something, and that what we hit was a [[Pawns|Pawn]].<source lang="csharp">
 
# Next, we check to make sure the ModExtension was properly loaded, that we hit something, and that what we hit was a [[Pawns|Pawn]].<source lang="csharp">
Line 312: Line 290:
 
</source>
 
</source>
 
#* <code>Rand</code> is the base game's randomness generation class. <code>Value</code> grabs the next random number between 0 and 1 and updates the class.
 
#* <code>Rand</code> is the base game's randomness generation class. <code>Value</code> grabs the next random number between 0 and 1 and updates the class.
 +
#* You could avoid declaring the <code>rand</code> variable (i.e. doing <code>if (Rand.Value <= Props.addHediffChance)</code>), since it's not used later, but there's no harm in declaring it.
 
# If a hediff is applied, we want to alert the player, so we create a message in the top-left of the screen.<source lang="csharp">
 
# If a hediff is applied, we want to alert the player, so we create a message in the top-left of the screen.<source lang="csharp">
 
Messages.Message("TST_PlagueBullet_SuccessMessage".Translate(
 
Messages.Message("TST_PlagueBullet_SuccessMessage".Translate(
Line 345: Line 324:
 
         public ModExtension_PlagueBullet Props => base.def.GetModExtension<ModExtension_PlagueBullet>();
 
         public ModExtension_PlagueBullet Props => base.def.GetModExtension<ModExtension_PlagueBullet>();
  
         protected override void Impact(Thing hitThing, bool blockedByShield = false)
+
         protected override void Impact(Thing hitThing)
 
         {
 
         {
             base.Impact(hitThing, blockedByShield);
+
             base.Impact(hitThing);
 
             if (Props != null && hitThing != null && hitThing is Pawn hitPawn)
 
             if (Props != null && hitThing != null && hitThing is Pawn hitPawn)
 
             {
 
             {
Line 402: Line 381:
 
         public ModExtension_PlagueBullet Props => base.def.GetModExtension<ModExtension_PlagueBullet>();
 
         public ModExtension_PlagueBullet Props => base.def.GetModExtension<ModExtension_PlagueBullet>();
  
         protected override void Impact(Thing hitThing, bool blockedByShield = false)
+
         protected override void Impact(Thing hitThing)
 
         {
 
         {
             base.Impact(hitThing, blockedByShield);
+
             base.Impact(hitThing);
 
             if (Props != null && hitThing != null && hitThing is Pawn hitPawn)
 
             if (Props != null && hitThing != null && hitThing is Pawn hitPawn)
 
             {
 
             {
Line 436: Line 415:
  
 
Just compile and test your work; the plague will be properly applied and everything.
 
Just compile and test your work; the plague will be properly applied and everything.
 
'''Note:''' Code you write on your own should not look like this - for one thing, it should be well-commented so that others (even if it's just you in the future) know exactly what you're trying to do and how you're doing it. The code [https://github.com/dninemfive/PlagueGun/blob/master/PlagueGun/Projectile_PlagueBullet.cs in the repo] is probably over-commented and designed for a general audience but I recommend reviewing it.
 
  
 
== Localization ==
 
== Localization ==
 
...well, almost. If you did test the gun just now, you'll have seen that the text was all distorted, using special characters which looked like the normal ones instead of text you expected. This is because of the use of <code>.Translate()</code> on keys which do not have translations in the language database. We just need to add those, and we'll be all set!
 
...well, almost. If you did test the gun just now, you'll have seen that the text was all distorted, using special characters which looked like the normal ones instead of text you expected. This is because of the use of <code>.Translate()</code> on keys which do not have translations in the language database. We just need to add those, and we'll be all set!
  
# First, create a bunch of folders, starting in the root of your mod folder:
+
# First, create a bunch of folders, starting in the root of your mod folder:{{br}}<small>Languages>English>Keyed</small>
<br /><nowiki /><!--
+
# Next, create a new file called PlagueGun_Keys.xml, with our favorite header.
--><small>Languages>English>Keyed</small>
 
# Next, create a new file called PlagueGun_Keys.xml, with our favorite header.<source lang="xml">
 
<?xml version="1.0" encoding="utf-8"?>
 
</source>
 
 
# This will be really quick. Add the opening and closing <code><LanguageData></code> tags:<source lang="xml">
 
# This will be really quick. Add the opening and closing <code><LanguageData></code> tags:<source lang="xml">
 
<LanguageData>
 
<LanguageData>
Line 473: Line 446:
  
 
== Next Steps ==
 
== Next Steps ==
This concludes this tutorial. Congratulations on making it this far; you now have a solid understanding of XML and C# modding, and of connecting these two. There's a lot more to learn, especially on the C# end, so make sure to practice. If you have any questions don't hesitate to hit up the [https://discord.gg/UTaMDWc Discord]#mod-development or the [https://ludeon.com/forums/index.php?board=14.0 forums] for help.
+
This concludes this tutorial. Congratulations on making it this far; you now have a solid understanding of XML and C# modding, and of connecting these two. There's a lot more to learn, especially on the C# end, so make sure to practice. If you have any questions don't hesitate to hit up the [https://discord.gg/rimworld Discord]#mod-development or the [https://ludeon.com/forums/index.php?board=14.0 forums] for help.
  
 
As for this mod, you might want to add custom textures or sounds. For your next, you might want to try messing around with [[Modding Tutorials/Harmony|Harmony]] or see other [[Modding Tutorials|tutorials]] for inspiration.
 
As for this mod, you might want to add custom textures or sounds. For your next, you might want to try messing around with [[Modding Tutorials/Harmony|Harmony]] or see other [[Modding Tutorials|tutorials]] for inspiration.
Line 482: Line 455:
 
* [[Modding Tutorials/Harmony|Harmony]]
 
* [[Modding Tutorials/Harmony|Harmony]]
 
* [[Modding_Tutorials/Mod_folder_structure#The_Languages_folder|Language support]]
 
* [[Modding_Tutorials/Mod_folder_structure#The_Languages_folder|Language support]]
 
== History ==
 
* This tutorial is a rewrite of the [[Plague Gun/Introduction|original]] by Jecrell (see also original forum {{LudeonThread|33219}})
 
  
 
[[Category: Modding tutorials]]
 
[[Category: Modding tutorials]]
 
[[Category: Modding]]
 
[[Category: Modding]]

Please note that all contributions to RimWorld Wiki are considered to be released under the CC BY-SA 3.0 (see RimWorld Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

Cancel Editing help (opens in new window)