<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://rimworldwiki.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Killathon</id>
	<title>RimWorld Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://rimworldwiki.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Killathon"/>
	<link rel="alternate" type="text/html" href="https://rimworldwiki.com/wiki/Special:Contributions/Killathon"/>
	<updated>2026-04-05T21:18:05Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.8</generator>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_MendingJob&amp;diff=175592</id>
		<title>Modding Tutorials/Code MendingJob</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_MendingJob&amp;diff=175592"/>
		<updated>2026-02-20T00:34:18Z</updated>

		<summary type="html">&lt;p&gt;Killathon: Minor cleanup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Example Mending Job}}&lt;br /&gt;
{{BackToTutorials}}&lt;br /&gt;
&lt;br /&gt;
This is a basic RimWorld mod tutorial for having a pawn mend a piece of apparel or gear to learn the basics of Jobs, JobDrivers, and Toils. &lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
In this tutorial you will:&lt;br /&gt;
&lt;br /&gt;
* Create a basic job to allow a pawn to mend apparel or weapons&lt;br /&gt;
* Create a basic FloatMenuOptionProvider to order pawns to take the job&lt;br /&gt;
* Learn how Jobs, JobDrivers, and Toils relate to one another in pawn behavior&lt;br /&gt;
&lt;br /&gt;
[[File:Example_Mending_FloatMenuOptionProvider.png|none|border]]&lt;br /&gt;
&lt;br /&gt;
== Recommended Reading ==&lt;br /&gt;
For this tutorial, you are expected to have already familiarized yourself with setting up a solution, with the basics of how a FloatMenuOptionProvider functions, and how to set up a mod. If you have not yet reviewed these details, all of these topics can be found below:&lt;br /&gt;
* [[Modding_Tutorials/Mod_Folder_Structure|Mod Folder Structure]]&lt;br /&gt;
* [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]]&lt;br /&gt;
* [[Modding_Tutorials/Decompiling_source_code|Decompiling Source Code]]&lt;br /&gt;
* [[Modding_Tutorials/Code_FloatMenuOptionProvider|Example FloatMenuOptionProvider]]&lt;br /&gt;
&lt;br /&gt;
== Sample Repository ==&lt;br /&gt;
A working implementation of this mod can be found [https://github.com/RWDevathon/ExampleMending in this GitHub repository]. You can use it to compare against your work or as a basis for modification! The repository contains comments explaining each part, if you prefer learning by seeing the larger picture. The comments in the repository will be explained in greater detail here.&lt;br /&gt;
&lt;br /&gt;
== Folder Setup ==&lt;br /&gt;
&lt;br /&gt;
First, you will want to create the files and folders necessary for this mod:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Mods&lt;br /&gt;
└ MyModFolder&lt;br /&gt;
  ├ About&lt;br /&gt;
  │ ├ About.xml&lt;br /&gt;
  │ └ Preview.png&lt;br /&gt;
  ├ Assemblies&lt;br /&gt;
  ├ Defs&lt;br /&gt;
  │ └ Example_JobDefs.xml&lt;br /&gt;
  ├ Languages&lt;br /&gt;
  │ ├ English&lt;br /&gt;
  │   └ Keyed&lt;br /&gt;
  │     ├ FloatMenuOptions.xml&lt;br /&gt;
  └ Source&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check out the [[Modding_Tutorials/Mod_Folder_Structure|mod folder structure guide]] for more information about individual folders.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
&lt;br /&gt;
=== Overview of Jobs, JobDrivers, and Toils ===&lt;br /&gt;
&lt;br /&gt;
RimWorld's handling of Pawn behavior is all done through Jobs, regardless of whether that Pawn is a player colonist, a wild animal, or a hostile mechanoid. Jobs can be assigned through various means, and for this tutorial we are only focusing on Jobs which are assigned directly by players to their colonists. Jobs represent tasks to be completed by a pawn, such as building a structure from start to finish or putting on a new pair of pants or just moving from point A to point B.&lt;br /&gt;
&lt;br /&gt;
A Job's actual behavior is handled by a JobDriver, the C# worker class responsible for determining how the job is to be completed, under what conditions it should be aborted, if the job can even be legally started, and what the results of the job are. All Jobs have JobDefs defined in xml to handle most of the data inputs such as various strings to be used when doing the job. It is up to the JobDriver to decide what to do with this data. A JobDriver breaks down the Job into what are called Toils. A Toil represents a singular element, or subtask, of a Job.&lt;br /&gt;
&lt;br /&gt;
The lifecycle of our Job is as such:&lt;br /&gt;
* Our FloatMenuOptionProvider will offer an option to the player to order a Pawn to mend a piece of apparel or a weapon, creaing a Job from a JobDef.&lt;br /&gt;
* The JobDef, defined in xml, specifies basic data and what JobDriver to use, and RW creates the Job from this data.&lt;br /&gt;
* The JobDriver specified in our JobDef will be initiated and will try to reserve the apparel/weapon so no one else touches it while the Job is in progress.&lt;br /&gt;
* The JobDriver, assuming it successfully reserved the gear, will then create a series of Toils for the Pawn to complete, one after the other.&lt;br /&gt;
* The Pawn will complete each Toil, one immediately following the last, until every Toil is complete or the Job is cancelled/completed.&lt;br /&gt;
* Once finished, the Job is destroyed and the Pawn is assigned a new Job depending on their normal behavior. For drafted Pawns, that's waiting for player input. For undrafted Pawns, that's their work/personal assignments.&lt;br /&gt;
'''A Pawn always has a Job. Even downed, despawned, and dead Pawns have Jobs.''' The complexity of Jobs differs greatly, obviously, but each follows these basic steps.&lt;br /&gt;
&lt;br /&gt;
=== Create your solution ===&lt;br /&gt;
&lt;br /&gt;
The first step of assigning jobs to pawns to repair damaged gear is to set up the solution and work on assigning jobs via C#. Assuming you have completed both the [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]] and [[Modding_Tutorials/Code_FloatMenuOptionProvider|Example FloatMenuOptionProvider]] tutorials, this should be straightforward.&lt;br /&gt;
&lt;br /&gt;
Place a newly created solution in the Source folder with an appropriate name, and configure it to build to the Assemblies folder.&lt;br /&gt;
&lt;br /&gt;
=== Create the FloatMenuOptionProvider subclass ===&lt;br /&gt;
&lt;br /&gt;
In order to give a pawn a job to mend apparel or weapons, we must first create the methods responsible for identifying them and determining whether they are valid targets for mending. FloatMenuOptionProvider gives us a number of methods and variables we can adjust and work with in order to establish our goal. For the purposes of this tutorial, we will assume that only one pawn will be assigned the job at a time, and that they can mend any and all apparel or gear, regardless of whether the player can craft that gear normally or not.&lt;br /&gt;
&lt;br /&gt;
We will begin by making our subclass, and overriding the GetSingleOptionFor method that targets a Thing (Note: This is different than in the previous tutorial, which overrode the method for targeting a Pawn) with conditions checking whether the Thing clicked on is an Apparel item or whether it has an equippable comp on it (which all weapons have):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
using RimWorld;&lt;br /&gt;
using Verse;&lt;br /&gt;
using Verse.AI;&lt;br /&gt;
&lt;br /&gt;
namespace ExampleMendingJob&lt;br /&gt;
{&lt;br /&gt;
    public class FloatMenuOptionProvider_MendingExample : FloatMenuOptionProvider&lt;br /&gt;
    {&lt;br /&gt;
        protected override bool Drafted =&amp;gt; true;&lt;br /&gt;
&lt;br /&gt;
        protected override bool Undrafted =&amp;gt; true;&lt;br /&gt;
&lt;br /&gt;
        protected override bool Multiselect =&amp;gt; false;&lt;br /&gt;
&lt;br /&gt;
        protected override FloatMenuOption GetSingleOptionFor(Thing clickedThing, FloatMenuContext context)&lt;br /&gt;
        {&lt;br /&gt;
            if (clickedThing is Apparel || clickedThing.HasComp&amp;lt;CompEquippable&amp;gt;())&lt;br /&gt;
            {&lt;br /&gt;
                return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(&amp;quot;Example_MendItem&amp;quot;.Translate(clickedThing.Label), () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                }), context.FirstSelectedPawn, clickedThing);&lt;br /&gt;
            }&lt;br /&gt;
            return null;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is enough to ensure the float menu option will appear in game only on apparel/weapons, albeit not doing anything if selected.&lt;br /&gt;
&lt;br /&gt;
As before, it is highly recommended that you [[Modding_Tutorials/Decompiling_source_code|decompile]] the &amp;lt;code&amp;gt;FloatMenuOptionProvider&amp;lt;/code&amp;gt; class so that you can learn all of the properties and methods that you can override. In this example, we are only overriding a small handful of them in order to compile and run the code.&lt;br /&gt;
&lt;br /&gt;
=== Translation Keys ===&lt;br /&gt;
&lt;br /&gt;
As mentioned in the previous tutorial, it is important to provide translation keys for strings included in code that are going to be presented to players so that other languages can translate the text without recreating the entire assembly. For this tutorial, we only need one key, included below:&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- 0 is the first argument passed to translate, which is the gear clicked on in this case. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_MendItem&amp;gt;Mend {0}&amp;lt;/Example_MendItem&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hiding Unnecessary Options ===&lt;br /&gt;
&lt;br /&gt;
Given that players interact with apparel and weapons relatively frequently, it would be annoying to include a mend option on the menu on every single float menu for a piece of gear that is right-clicked on when a single player pawn is selected. We also must account for cases where assigning a job to mend apparel makes no sense because it cannot be completed or would be immediately complete.&lt;br /&gt;
&lt;br /&gt;
Here are four cases where we should definitely hide the option:&lt;br /&gt;
* The Thing we clicked on does not use hit points at all (ie. it is indestructible). While this should NOT ever be the case for apparel, this is a cheap condition computationally, which can save performance if done before later checks when the player right-clicks on items like steel, silver, or other indestructible Things.&lt;br /&gt;
* The Thing we clicked on has full health already.&lt;br /&gt;
* The selected Pawn cannot reach the Thing, and thus could not mend the item if they were given the job. If we did not check this, the job we create in the next step might error!&lt;br /&gt;
* The item is on fire, which should prevent it from being mended.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
public class FloatMenuOptionProvider_MendingExample : FloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    protected override bool Drafted =&amp;gt; true;&lt;br /&gt;
&lt;br /&gt;
    protected override bool Undrafted =&amp;gt; true;&lt;br /&gt;
&lt;br /&gt;
    protected override bool Multiselect =&amp;gt; false;&lt;br /&gt;
&lt;br /&gt;
    // This is where we define the FloatMenuOption that we want to display to players (and in this case, what choosing the option does).&lt;br /&gt;
    // Note that returning null here is safe, and will simply display no option. It can be a useful fallback in case TargetThingValid/TargetPawnValid are returning true incorrectly.&lt;br /&gt;
    protected override FloatMenuOption GetSingleOptionFor(Thing clickedThing, FloatMenuContext context)&lt;br /&gt;
    {&lt;br /&gt;
        // It is always wise to put computationally cheaper conditions before more expensive ones, given that float menu option providers will run on most inputs.&lt;br /&gt;
        if (!clickedThing.def.useHitPoints || (clickedThing.MaxHitPoints &amp;lt;= clickedThing.HitPoints) || !context.FirstSelectedPawn.CanReach(clickedThing, PathEndMode.Touch, Danger.Deadly) || clickedThing.IsBurning())&lt;br /&gt;
        {&lt;br /&gt;
            return null;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (clickedThing is Apparel || clickedThing.HasComp&amp;lt;CompEquippable&amp;gt;())&lt;br /&gt;
        {&lt;br /&gt;
        }&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is not a comprehensive list of all potential cases where the option should be hidden, but it should reduce or prevent errors and useless job assignments.&lt;br /&gt;
&lt;br /&gt;
=== Assigning Jobs ===&lt;br /&gt;
&lt;br /&gt;
With our conditions settled, it's now time to provide the FloatMenuOption that will assign the job to mend gear to the Pawn. Prioritized tasks - those given by the player directly to pawns over their normal work assignments - can be created using a helpful utility method called FloatMenuUtility.DecoratePrioritizedTask:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
public class FloatMenuOptionProvider_MendingExample : FloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    protected override bool Drafted =&amp;gt; true;&lt;br /&gt;
&lt;br /&gt;
    protected override bool Undrafted =&amp;gt; true;&lt;br /&gt;
&lt;br /&gt;
    protected override bool Multiselect =&amp;gt; false;&lt;br /&gt;
&lt;br /&gt;
    protected override FloatMenuOption GetSingleOptionFor(Thing clickedThing, FloatMenuContext context)&lt;br /&gt;
    {&lt;br /&gt;
        // It is always wise to put computationally cheaper conditions before more expensive ones, given that float menu option providers will run on most inputs.&lt;br /&gt;
        if (!clickedThing.def.useHitPoints || (clickedThing.MaxHitPoints &amp;lt;= clickedThing.HitPoints) || !context.FirstSelectedPawn.CanReach(clickedThing, PathEndMode.Touch, Danger.Deadly) || clickedThing.IsBurning())&lt;br /&gt;
        {&lt;br /&gt;
            return null;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (clickedThing is Apparel || clickedThing.HasComp&amp;lt;CompEquippable&amp;gt;())&lt;br /&gt;
        {&lt;br /&gt;
            return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(&amp;quot;Example_MendItem&amp;quot;.Translate(clickedThing.Label), () =&amp;gt;&lt;br /&gt;
            {&lt;br /&gt;
              // This is where the actual assignment of the job will take place.&lt;br /&gt;
            }), context.FirstSelectedPawn, clickedThing);&lt;br /&gt;
        }&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FloatMenuUtility.DecoratePrioritizedTask takes a FloatMenuOption, which will be provided an action, as well as the actor and targets. This method is how almost every &amp;quot;forced&amp;quot; task that players can tell pawns to do is created.&lt;br /&gt;
&lt;br /&gt;
Inside the delegate for the FloatMenuOption, we will add these two lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
Job job = JobMaker.MakeJob(Example_JobDefOf.Example_MendingJob, new LocalTargetInfo(clickedThing));&lt;br /&gt;
context.FirstSelectedPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line will create the Job using a specified JobDef and indicating the job is to be done on the clicked thing. '''Note: The missing reference to Example_JobDefOf.Example_MendingJob is explained in the next step.'''&lt;br /&gt;
The second line tells the currently selected pawn to take the newly created job.&lt;br /&gt;
&lt;br /&gt;
=== Assigning a Specific Job ===&lt;br /&gt;
&lt;br /&gt;
In the first line above, you'll notice we specify that our JobDef is Example_JobDefOf.Example_MendingJob. Included in that is the defName of a JobDef that we will now create:&lt;br /&gt;
&lt;br /&gt;
Defs/Example_JobDefs.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;Defs&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;JobDef&amp;gt;&lt;br /&gt;
        &amp;lt;defName&amp;gt;Example_MendingJob&amp;lt;/defName&amp;gt;&lt;br /&gt;
    &amp;lt;/JobDef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/Defs&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The other part of that line, Example_JobDefOf, is a DefOf. A DefOf is effectively a &amp;quot;promise&amp;quot;, wherein we create a class in C# and define a variable whose name and type match our xml - in this case, a JobDef called Example_MendingJob.&lt;br /&gt;
&lt;br /&gt;
In your project, create a new file with the following class and variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
using RimWorld;&lt;br /&gt;
using Verse;&lt;br /&gt;
&lt;br /&gt;
namespace ExampleMendingJob&lt;br /&gt;
{&lt;br /&gt;
    [DefOf]&lt;br /&gt;
    public class Example_JobDefOf&lt;br /&gt;
    {&lt;br /&gt;
        static Example_JobDefOf()&lt;br /&gt;
        {&lt;br /&gt;
            DefOfHelper.EnsureInitializedInCtor(typeof(Example_JobDefOf));&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        public static JobDef Example_MendingJob;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the following:&lt;br /&gt;
* The [DefOf] annotation on the class is RimWorld's way of specifying that the following class should be scanned after Defs have been loaded to provide each variable with a value, matching the name of the variable to the defName of a Def of that type from the xml.&lt;br /&gt;
* DefOf variables can reference Defs of any type from any mod or even from vanilla - not all of Ludeon's Defs are included in their own DefOf's, but you can simply make your own if you need to reference them.&lt;br /&gt;
* The constructor exists for a single purpose: to warn a developer in the event that a DefOf reference was used before all Defs have been loaded. If this happens, the reference will not have been filled yet, and will return null, which can cause errors. It is there to raise a warning, but it will not prevent errors itself.&lt;br /&gt;
* There are alternative ways of referencing xml Defs in C# code, such as the DefDatabase, if necessary/preferable, but each way has its own tradeoffs. This method is recommended for this tutorial.&lt;br /&gt;
&lt;br /&gt;
With this DefOf created, our FloatMenuOptionProvider should no longer be complaining about a missing reference because we promised that the JobDef truly does exist. If there is truly no Def with the right name, then the code will error at run-time with potentially catastrophic results, so make sure that your DefOf's are correctly matched to existing Defs!&lt;br /&gt;
&lt;br /&gt;
=== The JobDriver ===&lt;br /&gt;
&lt;br /&gt;
As mentioned in the overview, Jobs use JobDriver worker classes to handle how they operate. Let's add a few more details to our JobDef:&lt;br /&gt;
&lt;br /&gt;
Defs/Example_JobDefs.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;Defs&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;JobDef&amp;gt;&lt;br /&gt;
        &amp;lt;defName&amp;gt;Example_MendingJob&amp;lt;/defName&amp;gt;&lt;br /&gt;
        &amp;lt;driverClass&amp;gt;ExampleMendingJob.JobDriver_Mend&amp;lt;/driverClass&amp;gt;&lt;br /&gt;
        &amp;lt;reportString&amp;gt;mending TargetA.&amp;lt;/reportString&amp;gt;&lt;br /&gt;
        &amp;lt;suspendable&amp;gt;false&amp;lt;/suspendable&amp;gt;&lt;br /&gt;
    &amp;lt;/JobDef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/Defs&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We are about to create the JobDriver_Mend class, which will be the worker for the Job responsible for the Pawn completing it. We provide a reportString here as well - that is text that will be shown on the Pawn's inspect panel when they are doing the job to say what they're up to (TargetA will be automatically translated into the label of the Thing they are interacting with). Setting suspendable to false here means that our prioritized task shouldn't be interrupted randomly and will complete as we would expect it to.&lt;br /&gt;
&lt;br /&gt;
Create the JobDriver_Mend class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
using RimWorld;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using Verse;&lt;br /&gt;
using Verse.AI;&lt;br /&gt;
&lt;br /&gt;
namespace ExampleMendingJob&lt;br /&gt;
{&lt;br /&gt;
    public class JobDriver_Mend : JobDriver&lt;br /&gt;
    {&lt;br /&gt;
        public int ticksToNextMend = 0;&lt;br /&gt;
        public const int ticksBetweenMending = GenTicks.TicksPerRealSecond;&lt;br /&gt;
&lt;br /&gt;
        public override bool TryMakePreToilReservations(bool errorOnFailed)&lt;br /&gt;
        {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        protected override IEnumerable&amp;lt;Toil&amp;gt; MakeNewToils()&lt;br /&gt;
        {&lt;br /&gt;
            yield break;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All subclasses of JobDriver must override two methods, which we will handle separately. The two variables included will be used to make sure that mending is done roughly once every real second, which is 60 ticks.&lt;br /&gt;
&lt;br /&gt;
==== TryMakePreToilReservations ====&lt;br /&gt;
This method is responsible for reserving Things that are about to be worked on, and returns true if those Things were successfully reserved. If it returns false, then the Job is aborted before it begins, and oftentimes a warning will be provided that a Job was created but failed to start - this is a sign that something, like our FloatMenuOptionProvider, created the Job improperly.&lt;br /&gt;
&lt;br /&gt;
While it is possible to run arbitrary C# here, it is not a good idea to do so here, as the Job has not officially begun yet. This method is just responsible for setting up reservations and last-minute checks.&lt;br /&gt;
&lt;br /&gt;
In order to mend gear, we need to reserve the item that is going to be repaired:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
public override bool TryMakePreToilReservations(bool errorOnFailed)&lt;br /&gt;
{&lt;br /&gt;
  return pawn.Reserve(job.GetTarget(TargetIndex.A).Thing, job);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All JobDrivers keep the pawn doing the job as a local variable that we can access. Reserve will return true if the item is successfully reserved for the job, and because we only need to reserve a single item, we can return its boolean directly.&lt;br /&gt;
&lt;br /&gt;
==== MakeNewToils ====&lt;br /&gt;
&lt;br /&gt;
MakeNewToils is responsible for creating and returning the Toil(s) that form the composition of the Job. The completion of these Toils results in the Job's completion. What each of these Toils represents is up to the JobDriver to determine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override IEnumerable&amp;lt;Toil&amp;gt; MakeNewToils()&lt;br /&gt;
{&lt;br /&gt;
    // This Toil, from a utility class, handles all the details of the Pawn pathing to the specified Thing. We can assume that the Pawn is touching the Thing after the completion of this Toil if it succeeds.&lt;br /&gt;
    // If this Toil fails, such as if the target item were destroyed while pathing so it cannot actually reach it, then the Job is cancelled.&lt;br /&gt;
    yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch);&lt;br /&gt;
&lt;br /&gt;
    // There is no utility method for the mending Toil, so we will create our own.&lt;br /&gt;
    // A Toil is effectively just an empty task until it is told what it should do. The string below is just a debug name, and does not need to be translated.&lt;br /&gt;
    Toil mend = ToilMaker.MakeToil(&amp;quot;JobDriver_Mend_Toil&amp;quot;);&lt;br /&gt;
    // We can define an action that should happen only when this toil starts. We will use it to ensure the first mending occurs after a full second of the job passed.&lt;br /&gt;
    mend.initAction = () =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        ticksToNextMend = ticksBetweenMending;&lt;br /&gt;
    };&lt;br /&gt;
    // tickAction is called once per tick as it implies, and is where the bulk of the Toil happens. &lt;br /&gt;
    mend.tickAction = () =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // We want to keep the pawn facing toward the item, just in case they or the item is moved slightly.&lt;br /&gt;
        Pawn actor = mend.actor;&lt;br /&gt;
        actor.rotationTracker.FaceTarget(TargetThingA);&lt;br /&gt;
        // Reduce the timer to the next mending by one, and if it hit (or is below) zero, then do some mending and add onto the timer again.&lt;br /&gt;
        ticksToNextMend--;&lt;br /&gt;
        if (ticksToNextMend &amp;lt;= 0f)&lt;br /&gt;
        {&lt;br /&gt;
            ticksToNextMend += ticksBetweenMending;&lt;br /&gt;
            // If the thing is fully mended, we're done. End the job as a success and that's it.&lt;br /&gt;
            if (TargetThingA.HitPoints &amp;lt; TargetThingA.MaxHitPoints)&lt;br /&gt;
            {&lt;br /&gt;
                TargetThingA.HitPoints++;&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                actor.jobs.EndCurrentJob(JobCondition.Succeeded);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
    // The mending job should fail if the item is no longer touchable for whatever reason, should only complete when it says so, and handles its own rotation.&lt;br /&gt;
    mend.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);&lt;br /&gt;
    mend.defaultCompleteMode = ToilCompleteMode.Never;&lt;br /&gt;
    mend.handlingFacing = true;&lt;br /&gt;
    yield return mend;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example above explains each line as it can, but a few things should be noted:&lt;br /&gt;
* Toils are created and returned all at once, as soon as the Job is created and assigned. They are '''not''' created when it is time for that Toil to begin, which means that you should treat each Toil as independent of each other when writing them and use the appropriate methods when initializing variables they use.&lt;br /&gt;
* It is strongly recommended that you examine the JobDrivers of vanilla classes when you are making your own, as there are a lot of helpful utility classes and methods that you might otherwise miss.&lt;br /&gt;
* Our mend Toil handles completing the Job itself, but that is not how all Jobs end. Some end based on a delayed timer, and some may end simply when their Toils are all completed or when interrupted.&lt;br /&gt;
&lt;br /&gt;
=== Testing ===&lt;br /&gt;
&lt;br /&gt;
With the JobDriver created, you should now be able to test. Make sure to test that the FloatMenuOptionProvider is showing option as appropriate, but also not showing the option when it should be invalid, or else you may find yourself facing strange bugs!&lt;br /&gt;
&lt;br /&gt;
When debugging Jobs, it can be helpful to go from start to finish:&lt;br /&gt;
* Make sure that the FloatMenuOptionProvider (or whatever is providing the Job) is correctly identifying when it is legal to do the Job.&lt;br /&gt;
* Check that the correct Job is being created with the correct JobDef, which has the correct JobDriver listed in it and other details provided.&lt;br /&gt;
* If you're confident the right JobDriver is being used, then you can start sifting through your code to identify why individual Toils may be misbehaving.&lt;br /&gt;
&lt;br /&gt;
[[File:Example_Mending_JobInProgress.png|none|border]]&lt;br /&gt;
&lt;br /&gt;
=== Room for Improvement ===&lt;br /&gt;
&lt;br /&gt;
If you've done everything right, you've got a way to mend damaged apparel and weapons - but this is a very simple example with numerous ways to improve. From here, try experimenting with some of the following:&lt;br /&gt;
* Some things can be mended which probably shouldn't be, such as wood logs or beer, because they're weapons. How might you improve the FloatMenuOptionProvider to weed out these edge cases?&lt;br /&gt;
* The mend Toil currently spends an additional second at the end of the Job with the item fully repaired before the job is completed. How could the Toil's tickAction be rewritten to give pawns back those few precious ticks of productivity?&lt;br /&gt;
* The Job doesn't account for the Pawn doing the job at all. If the Pawn has no hands, they're not allowed to pick up a gun, but this code will allow them to mend that gun - what might be needed to make sure they're capable of doing the work?&lt;br /&gt;
* Many Jobs provide the Pawn doing it XP in a skill, and with a work speed that is based on their skills. Maybe mending should be affected by the crafting skill, or give XP in crafting - decompiling vanilla JobDrivers could point the way on having this affect skills and be affected by skills.&lt;br /&gt;
* Unlike most jobs, this JobDriver doesn't make any sound effects or visual effects while in progress. What effects make sense, and how do they tie in?&lt;br /&gt;
* Mending is currently free - but should it be? Perhaps MakeNewToils could be improved so that the gear will be brought by the Pawn somewhere or an item will be brought to the gear to pay to repair it. Alternatively, mending could affect the gear's quality, or even produce additional items as byproducts.&lt;br /&gt;
&lt;br /&gt;
If you get any errors, get stuck, or are looking for additional resources, be sure to check out the [[Modding_Tutorials/Troubleshooting|troubleshooting guide]] or join us on the '''#mod-development''' channel on the [https://discord.gg/rimworld RimWorld Discord server].&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding]]&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=File:Example_Mending_JobInProgress.png&amp;diff=175591</id>
		<title>File:Example Mending JobInProgress.png</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=File:Example_Mending_JobInProgress.png&amp;diff=175591"/>
		<updated>2026-02-20T00:19:53Z</updated>

		<summary type="html">&lt;p&gt;Killathon: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=File:Example_Mending_FloatMenuOptionProvider.png&amp;diff=175590</id>
		<title>File:Example Mending FloatMenuOptionProvider.png</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=File:Example_Mending_FloatMenuOptionProvider.png&amp;diff=175590"/>
		<updated>2026-02-20T00:19:11Z</updated>

		<summary type="html">&lt;p&gt;Killathon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Example of the FloatMenuOptionProvider showing the new mending option&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_FloatMenuOptionProvider&amp;diff=173013</id>
		<title>Modding Tutorials/Code FloatMenuOptionProvider</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_FloatMenuOptionProvider&amp;diff=173013"/>
		<updated>2025-12-11T22:38:39Z</updated>

		<summary type="html">&lt;p&gt;Killathon: There aren't really hidden float menu options - this was included mistakenly&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Example FloatMenuOptionProvider}}&lt;br /&gt;
{{BackToTutorials}}&lt;br /&gt;
&lt;br /&gt;
This is a basic RimWorld mod tutorial for creating a FloatMenuOptionProvider to run arbitrary C# code. &lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
In this tutorial you will:&lt;br /&gt;
&lt;br /&gt;
* Create a basic C# solution and compile it into an assembly&lt;br /&gt;
* Create a basic FloatMenuOptionProvider: A simple option to instantly kill a non-player pawn&lt;br /&gt;
* Learn how float menu options distinguish between disabled and enabled options&lt;br /&gt;
* Create a message to display text on screen to display at a glance who was selected and who was killed&lt;br /&gt;
* Learn how to use LanguageData to allow for translations of code used in the solution&lt;br /&gt;
&lt;br /&gt;
[[File:Example_FloatMenuOptionProvider.png|none|border]]&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
FloatMenuOptionProviders were added in 1.6 to permit for finer tuned control over assigning orders to player-controlled pawns. Prior to 1.6, many of these float menu options were handled by a monolithic method that made extending via mods difficult and liable to create conflicts. Some examples of vanilla cases in 1.6 include:&lt;br /&gt;
* Ordering player-controlled pawns to equip or drop weapons and apparel&lt;br /&gt;
* Ordering player-controlled pawns to arrest, rescue, pick up, romance, and otherwise interact with other pawns&lt;br /&gt;
* Ordering player-controlled pawns to interact with relics, terminals, and other quest objects&lt;br /&gt;
&lt;br /&gt;
== Recommended Reading ==&lt;br /&gt;
* [[Modding_Tutorials/Mod_Folder_Structure|Mod Folder Structure]]&lt;br /&gt;
* [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]]&lt;br /&gt;
* [[Modding_Tutorials/Decompiling_source_code|Decompiling Source Code]]&lt;br /&gt;
&lt;br /&gt;
== Sample Repository ==&lt;br /&gt;
A working implementation of this mod can be found [https://github.com/RWDevathon/ExampleFloatMenuOptionProvider in this GitHub repository]. You can use it to compare against your work or as a basis for modification! The repository contains comments explaining each part, if you prefer learning by seeing the larger picture. The comments in the repository will be explained in greater detail here.&lt;br /&gt;
&lt;br /&gt;
== Folder Setup ==&lt;br /&gt;
&lt;br /&gt;
First, you will want to create the files and folders necessary for this mod:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Mods&lt;br /&gt;
└ MyModFolder&lt;br /&gt;
  ├ About&lt;br /&gt;
  │ ├ About.xml&lt;br /&gt;
  │ └ Preview.png&lt;br /&gt;
  ├ Assemblies&lt;br /&gt;
  ├ Languages&lt;br /&gt;
  │ ├ English&lt;br /&gt;
  │   └ Keyed&lt;br /&gt;
  │     ├ FloatMenuOptions.xml&lt;br /&gt;
  │     └ Messages.xml&lt;br /&gt;
  └ Source&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check out the [[Modding_Tutorials/Mod_Folder_Structure|mod folder structure guide]] for more information about individual folders.&lt;br /&gt;
&lt;br /&gt;
=== About.xml ===&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;About.xml&amp;lt;/code&amp;gt; is used to identify your mod to RimWorld; please see [[Modding_Tutorials/About.xml|the About.xml reference page]] for more information. Be sure to replace &amp;quot;AuthorName&amp;quot; with your own name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;ModMetaData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is the internal identifier for your mod. --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- It is recommended that you make it unique to as to avoid potential collisions with other authors; --&amp;gt;&lt;br /&gt;
  &amp;lt;!--     if Rimworld detects multiple mods with the same packageId then it will refuse to load all of them. --&amp;gt;&lt;br /&gt;
  &amp;lt;packageId&amp;gt;AuthorName.ExampleFloatMenuOptionProvider&amp;lt;/packageId&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is both the displayed name of your mod as well as the name used for patch targeting. --&amp;gt;&lt;br /&gt;
  &amp;lt;name&amp;gt;Example Float Menu Option Provider&amp;lt;/name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Your name goes here. --&amp;gt;&lt;br /&gt;
  &amp;lt;author&amp;gt;AuthorName&amp;lt;/author&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- A version number for your own tracking --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- See wiki About.xml guide for concerns regarding this field for RimWorld versions prior to 1.4 --&amp;gt;&lt;br /&gt;
  &amp;lt;modVersion&amp;gt;1.0&amp;lt;/modVersion&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- These are the RimWorld game versions that your mod supports. --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- It is recommended that you only list versions that you have explicitly tested to ensure they work, --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- as even basic XML options can change between major versions of the game. --&amp;gt;&lt;br /&gt;
  &amp;lt;supportedVersions&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;1.6&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/supportedVersions&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is the description of your mod shown in both the vanilla mod manager as well as modded managers. --&amp;gt;&lt;br /&gt;
  &amp;lt;description&amp;gt;This is an example float menu option provider made for the RimWorld Wiki.&amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ModMetaData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
&lt;br /&gt;
=== Create your solution ===&lt;br /&gt;
&lt;br /&gt;
Our first step is to set up the C# workspace where we will create the FloatMenuOptionProvider. This tutorial assumes you have completed the [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]] tutorial and know how to initialize a solution. If you have not yet learned how to create a solution, please review that tutorial.&lt;br /&gt;
&lt;br /&gt;
Place a newly created solution in the Source folder with an appropriate name, and configure it to build to the Assemblies folder.&lt;br /&gt;
&lt;br /&gt;
=== Create the FloatMenuOptionProvider subclass ===&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptionProvider is an abstract class. Subclasses of it inherit numerous properties and methods that can be overridden in order to have a wide variety of outcomes, and all subclasses will be automatically identified by the game. We will create our own FloatMenuOptionProvider subclass to allow for execution of code that has access to a source and target pawn (this tutorial will refer to them as &amp;quot;selected&amp;quot; and &amp;quot;clicked,&amp;quot; respectively, as this aligns with how they are identified in C#).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
using RimWorld;&lt;br /&gt;
using Verse;&lt;br /&gt;
&lt;br /&gt;
namespace ExampleFloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    public class FloatMenuOptionProvider_Example : FloatMenuOptionProvider&lt;br /&gt;
    {&lt;br /&gt;
      // Pasted content omitted&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RimWorld automatically identifies all subclasses of FloatMenuOptionProvider and applies them - meaning we only have to define this one class to be able to have it usable in game.&lt;br /&gt;
&lt;br /&gt;
=== Make a FloatMenuOption Appear In-Game ===&lt;br /&gt;
&lt;br /&gt;
Our subclass inherits many properties and methods from its parent class. It is highly recommended that you [[Modding_Tutorials/Decompiling_source_code|decompile]] the &amp;lt;code&amp;gt;FloatMenuOptionProvider&amp;lt;/code&amp;gt; class so that you can learn all of the properties and methods that you can override. In this example, we are only overriding a small handful of them in order to compile and run the code.&lt;br /&gt;
&lt;br /&gt;
Before the solution can compile, we must override three properties from the parent class which are abstract (meaning that the parent class does not define a value for these properties and is expecting subclasses to define them):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
public class FloatMenuOptionProvider_Example : FloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    protected override bool Drafted =&amp;gt; true;&lt;br /&gt;
    protected override bool Undrafted =&amp;gt; true;&lt;br /&gt;
    protected override bool Multiselect =&amp;gt; false;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our float menu option will be provided only if a single player-controlled pawn is selected and we do not care if they are drafted or undrafted. If any of these conditions are not met for the selected pawn, then the float menu option will not appear at all. '''These are not the only properties and methods that control whether the option will appear.''' Please decompile FloatMenuOptionProvider to see an up-to-date comprehensive list of them all, and their default values. These three are the only properties which are abstract and have no default values set.&lt;br /&gt;
&lt;br /&gt;
==== Making the FloatMenuOption ====&lt;br /&gt;
Next, we will define what the FloatMenuOption we want to provide is. Because this example is focusing on killing a pawn, we will choose to override a method specific to targeting pawns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, null);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is all the code we need in order to compile and have a float menu option appear in game. Note that the string is the label for the option, and the &amp;quot;null&amp;quot; in the example above is the action that would happen if the option were to be selected. By leaving it null, the game will register this float menu option as disabled, and thus not selectable. We will provide an action in the following steps. Compile the code, make sure the assembly ends up in the correct place, and test whether the float menu appears in game.&lt;br /&gt;
&lt;br /&gt;
[[File:Example_FloatMenuOptionProvider_FirstOption.png|none|border]]&lt;br /&gt;
&lt;br /&gt;
Experiment with the provider to see situations and contexts in which the option will and will not appear.&lt;br /&gt;
&lt;br /&gt;
=== FloatMenuOption Actions ===&lt;br /&gt;
&lt;br /&gt;
In order for our provided FloatMenuOption to execute code, it needs to have an Action provided. The easiest way to define what the option will do is to provide the FloatMenuOption a lambda expression with the code that you want to have run inside of it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, () =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we are telling the FloatMenuOption to run the code inside the lambda expression - to kill the pawn that was clicked on - when the option is selected. Recompile the code and test it out. Selecting the option should now be possible and should instantly kill the pawn.&lt;br /&gt;
&lt;br /&gt;
You can run any arbitrary C# from within the expression, such as spawning explosions, changing the skills, traits, hediffs, or relationships of the clicked pawn, and more.&lt;br /&gt;
&lt;br /&gt;
==== Sending a Message ====&lt;br /&gt;
Next, we will add a message saying who was selected and who was killed, as a way to show some visual feedback for the action that the player just carried out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, () =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
        Messages.Message($&amp;quot;{context.FirstSelectedPawn} has killed {clickedPawn} with their mind&amp;quot;, MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FloatMenuContext instance passed in to the method contains a lot of useful information, such as who is currently selected. Messages are the small lines of text that appear in the top left corner of the screen, and are usually reserved for transitory information that is relevant to a player but not worthy of a full Letter. By passing &amp;lt;code&amp;gt;historical: false&amp;lt;/code&amp;gt; to the Message, we inform it that we do not want this Message to be logged in the History tab.&lt;br /&gt;
&lt;br /&gt;
Note: See the Referencing Defs from C# section of [[Modding_Tutorials/Defs|Defs]] for details on DefOf's like &amp;lt;code&amp;gt;MessageTypeDefOf.PositiveEvent&amp;lt;/code&amp;gt; which are not covered in this tutorial.&lt;br /&gt;
&lt;br /&gt;
If you recompile your code and run the game again, every time the float menu option is selected, the clicked pawn should now be killed and a message should appear with the names of both the selected and clicked pawns.&lt;br /&gt;
&lt;br /&gt;
=== Allowing for Translations ===&lt;br /&gt;
&lt;br /&gt;
If all has gone well, we have a fully functional FloatMenuOptionProvider. At the moment, though, the label for the option and the text in the Message are entirely contained in our solution and cannot be accessed externally, making it impossible to translate the strings to other languages or re-use effectively. RimWorld allows for setting up translations much like it does for setting up Defs. It's time to change our raw strings to translated strings accessible in XML using &amp;lt;code&amp;gt;Translate&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;Example_KillPawn&amp;quot;.Translate(clickedPawn), () =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
        Messages.Message(&amp;quot;Example_KilledWithTheirMind&amp;quot;.Translate(context.FirstSelectedPawn, clickedPawn), MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With these two key strings created, RimWorld will now look in the Languages folder for the player's language for a &amp;lt;code&amp;gt;Keyed&amp;lt;/code&amp;gt; folder for these key strings. The file structure for key strings inside the Keyed folder does not matter, but it can be helpful for translators and yourself to keep the key strings organized by where they are used, as there is no way to know in XML what they are used for in the C#.&lt;br /&gt;
&lt;br /&gt;
Fill in text for the key strings like below:&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Numbers represent the index of arguments passed to Translate. In this case, 0 is the Pawn that was clicked on. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KillPawn&amp;gt;Make {0} die&amp;lt;/Example_KillPawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Messages.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Numbers represent the index of arguments passed to Translate. In this case, 0 is the selected pawn and 1 is the Pawn that was clicked on. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KilledWithTheirMind&amp;gt;{0} has killed {1} with their mind&amp;lt;/Example_KilledWithTheirMind&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the key string must '''exactly''' match the key in the solution, or else you will see the key string name from the solution itself in-game (if you have dev-mode on, you will see something called zalgo text to help visualize that this probably was not intentional).&lt;br /&gt;
&lt;br /&gt;
Recompile the code after checking that the key strings in the solution and translation files match, and test. You can change the text or what arguments are provided to the Translate method if you would like.&lt;br /&gt;
&lt;br /&gt;
=== Final Touches ===&lt;br /&gt;
&lt;br /&gt;
At this point, you should have a working FloatMenuOptionProvider that allows for execution of arbitrary C# with visual feedback and that allows for all text to be properly translated! From here, you can start expanding what the provider does and allow for creating entirely custom orders to be assigned to pawns. The concepts in this tutorial are widely used in RimWorld to handle all sorts of vanilla interactions that the player can force, and so should help serve as a foundation for new interactions.&lt;br /&gt;
&lt;br /&gt;
This tutorial concludes with one additional - optional - change to the FloatMenuOptionProvider we created by preventing the player from instantly killing their own pawns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    if (clickedPawn.Faction != Faction.OfPlayer)&lt;br /&gt;
    {&lt;br /&gt;
        return new FloatMenuOption(&amp;quot;Example_KillPawn&amp;quot;.Translate(clickedPawn), () =&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            clickedPawn.Kill(null);&lt;br /&gt;
            Messages.Message(&amp;quot;Example_KilledWithTheirMind&amp;quot;.Translate(context.FirstSelectedPawn, clickedPawn), MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;Example_CannotKillPlayerPawns&amp;quot;.Translate(clickedPawn), null);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Languages/English/Keyed/FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- 0 is the first argument passed to translate, which is the Pawn clicked on in this case. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KillPawn&amp;gt;Make {0} die&amp;lt;/Example_KillPawn&amp;gt;&lt;br /&gt;
    &amp;lt;Example_CannotKillPlayerPawns&amp;gt;{0} is on your team, you can't kill them!&amp;lt;/Example_CannotKillPlayerPawns&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can set as many different FloatMenuOption outcomes as you like, based on all sorts of conditions. Note that you may also return null from this method, if you ultimately decide you don't want to have a float menu option appear at all. This can be useful if the validation for the selected pawn or the clicked pawn mistakenly returned true for something that should not receive an option, or if after validation occurred, something changed and an option should no longer be valid.&lt;br /&gt;
&lt;br /&gt;
Don't forget to keep your translation key strings in the xml synced whenever you change them in the solution!&lt;br /&gt;
&lt;br /&gt;
If you get any errors, be sure to check out the [[Modding_Tutorials/Troubleshooting|troubleshooting guide]] or join us on the '''#mod-development''' channel on the [https://discord.gg/rimworld RimWorld Discord server].&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding]]&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_FloatMenuOptionProvider&amp;diff=173007</id>
		<title>Modding Tutorials/Code FloatMenuOptionProvider</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_FloatMenuOptionProvider&amp;diff=173007"/>
		<updated>2025-12-11T18:59:30Z</updated>

		<summary type="html">&lt;p&gt;Killathon: Changed delegates to lambda functions, all references to colonists to instead refer to player-controlled pawns, and updated an image reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Example FloatMenuOptionProvider}}&lt;br /&gt;
{{BackToTutorials}}&lt;br /&gt;
&lt;br /&gt;
This is a basic RimWorld mod tutorial for creating a FloatMenuOptionProvider to run arbitrary C# code. &lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
In this tutorial you will:&lt;br /&gt;
&lt;br /&gt;
* Create a basic C# solution and compile it into an assembly&lt;br /&gt;
* Create a basic FloatMenuOptionProvider: A simple option to instantly kill a non-player pawn&lt;br /&gt;
* Learn how float menu options distinguish between hidden, disabled, and enabled options&lt;br /&gt;
* Create a message to display text on screen to display at a glance who was selected and who was killed&lt;br /&gt;
* Learn how to use LanguageData to allow for translations of code used in the solution&lt;br /&gt;
&lt;br /&gt;
[[File:Example_FloatMenuOptionProvider.png|none|border]]&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
FloatMenuOptionProviders were added in 1.6 to permit for finer tuned control over assigning orders to player-controlled pawns. Prior to 1.6, many of these float menu options were handled by a monolithic method that made extending via mods difficult and liable to create conflicts. Some examples of vanilla cases in 1.6 include:&lt;br /&gt;
* Ordering player-controlled pawns to equip or drop weapons and apparel&lt;br /&gt;
* Ordering player-controlled pawns to arrest, rescue, pick up, romance, and otherwise interact with other pawns&lt;br /&gt;
* Ordering player-controlled pawns to interact with relics, terminals, and other quest objects&lt;br /&gt;
&lt;br /&gt;
== Recommended Reading ==&lt;br /&gt;
* [[Modding_Tutorials/Mod_Folder_Structure|Mod Folder Structure]]&lt;br /&gt;
* [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]]&lt;br /&gt;
* [[Modding_Tutorials/Decompiling_source_code|Decompiling Source Code]]&lt;br /&gt;
&lt;br /&gt;
== Sample Repository ==&lt;br /&gt;
A working implementation of this mod can be found [https://github.com/RWDevathon/ExampleFloatMenuOptionProvider in this GitHub repository]. You can use it to compare against your work or as a basis for modification! The repository contains comments explaining each part, if you prefer learning by seeing the larger picture. The comments in the repository will be explained in greater detail here.&lt;br /&gt;
&lt;br /&gt;
== Folder Setup ==&lt;br /&gt;
&lt;br /&gt;
First, you will want to create the files and folders necessary for this mod:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Mods&lt;br /&gt;
└ MyModFolder&lt;br /&gt;
  ├ About&lt;br /&gt;
  │ ├ About.xml&lt;br /&gt;
  │ └ Preview.png&lt;br /&gt;
  ├ Assemblies&lt;br /&gt;
  ├ Languages&lt;br /&gt;
  │ ├ English&lt;br /&gt;
  │   └ Keyed&lt;br /&gt;
  │     ├ FloatMenuOptions.xml&lt;br /&gt;
  │     └ Messages.xml&lt;br /&gt;
  └ Source&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check out the [[Modding_Tutorials/Mod_Folder_Structure|mod folder structure guide]] for more information about individual folders.&lt;br /&gt;
&lt;br /&gt;
=== About.xml ===&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;About.xml&amp;lt;/code&amp;gt; is used to identify your mod to RimWorld; please see [[Modding_Tutorials/About.xml|the About.xml reference page]] for more information. Be sure to replace &amp;quot;AuthorName&amp;quot; with your own name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;ModMetaData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is the internal identifier for your mod. --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- It is recommended that you make it unique to as to avoid potential collisions with other authors; --&amp;gt;&lt;br /&gt;
  &amp;lt;!--     if Rimworld detects multiple mods with the same packageId then it will refuse to load all of them. --&amp;gt;&lt;br /&gt;
  &amp;lt;packageId&amp;gt;AuthorName.ExampleFloatMenuOptionProvider&amp;lt;/packageId&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is both the displayed name of your mod as well as the name used for patch targeting. --&amp;gt;&lt;br /&gt;
  &amp;lt;name&amp;gt;Example Float Menu Option Provider&amp;lt;/name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Your name goes here. --&amp;gt;&lt;br /&gt;
  &amp;lt;author&amp;gt;AuthorName&amp;lt;/author&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- A version number for your own tracking --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- See wiki About.xml guide for concerns regarding this field for RimWorld versions prior to 1.4 --&amp;gt;&lt;br /&gt;
  &amp;lt;modVersion&amp;gt;1.0&amp;lt;/modVersion&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- These are the RimWorld game versions that your mod supports. --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- It is recommended that you only list versions that you have explicitly tested to ensure they work, --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- as even basic XML options can change between major versions of the game. --&amp;gt;&lt;br /&gt;
  &amp;lt;supportedVersions&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;1.6&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/supportedVersions&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is the description of your mod shown in both the vanilla mod manager as well as modded managers. --&amp;gt;&lt;br /&gt;
  &amp;lt;description&amp;gt;This is an example float menu option provider made for the RimWorld Wiki.&amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ModMetaData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
&lt;br /&gt;
=== Create your solution ===&lt;br /&gt;
&lt;br /&gt;
Our first step is to set up the C# workspace where we will create the FloatMenuOptionProvider. This tutorial assumes you have completed the [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]] tutorial and know how to initialize a solution. If you have not yet learned how to create a solution, please review that tutorial.&lt;br /&gt;
&lt;br /&gt;
Place a newly created solution in the Source folder with an appropriate name, and configure it to build to the Assemblies folder.&lt;br /&gt;
&lt;br /&gt;
=== Create the FloatMenuOptionProvider subclass ===&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptionProvider is an abstract class. Subclasses of it inherit numerous properties and methods that can be overridden in order to have a wide variety of outcomes, and all subclasses will be automatically identified by the game. We will create our own FloatMenuOptionProvider subclass to allow for execution of code that has access to a source and target pawn (this tutorial will refer to them as &amp;quot;selected&amp;quot; and &amp;quot;clicked,&amp;quot; respectively, as this aligns with how they are identified in C#).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
using RimWorld;&lt;br /&gt;
using Verse;&lt;br /&gt;
&lt;br /&gt;
namespace ExampleFloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    public class FloatMenuOptionProvider_Example : FloatMenuOptionProvider&lt;br /&gt;
    {&lt;br /&gt;
      // Pasted content omitted&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RimWorld automatically identifies all subclasses of FloatMenuOptionProvider and applies them - meaning we only have to define this one class to be able to have it usable in game.&lt;br /&gt;
&lt;br /&gt;
=== Make a FloatMenuOption Appear In-Game ===&lt;br /&gt;
&lt;br /&gt;
Our subclass inherits many properties and methods from its parent class. It is highly recommended that you [[Modding_Tutorials/Decompiling_source_code|decompile]] the &amp;lt;code&amp;gt;FloatMenuOptionProvider&amp;lt;/code&amp;gt; class so that you can learn all of the properties and methods that you can override. In this example, we are only overriding a small handful of them in order to compile and run the code.&lt;br /&gt;
&lt;br /&gt;
Before the solution can compile, we must override three properties from the parent class which are abstract (meaning that the parent class does not define a value for these properties and is expecting subclasses to define them):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
public class FloatMenuOptionProvider_Example : FloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    protected override bool Drafted =&amp;gt; true;&lt;br /&gt;
    protected override bool Undrafted =&amp;gt; true;&lt;br /&gt;
    protected override bool Multiselect =&amp;gt; false;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our float menu option will be provided only if a single player-controlled pawn is selected and we do not care if they are drafted or undrafted. If any of these conditions are not met for the selected pawn, then the float menu option will not appear at all. '''These are not the only properties and methods that control whether the option will appear.''' Please decompile FloatMenuOptionProvider to see an up-to-date comprehensive list of them all, and their default values. These three are the only properties which are abstract and have no default values set.&lt;br /&gt;
&lt;br /&gt;
==== Making the FloatMenuOption ====&lt;br /&gt;
Next, we will define what the FloatMenuOption we want to provide is. Because this example is focusing on killing a pawn, we will choose to override a method specific to targeting pawns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, null);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is all the code we need in order to compile and have a float menu option appear in game. Note that the string is the label for the option, and the &amp;quot;null&amp;quot; in the example above is the action that would happen if the option were to be selected. By leaving it null, the game will register this float menu option as disabled, and thus not selectable. We will provide an action in the following steps. Compile the code, make sure the assembly ends up in the correct place, and test whether the float menu appears in game.&lt;br /&gt;
&lt;br /&gt;
[[File:Example_FloatMenuOptionProvider_FirstOption.png|none|border]]&lt;br /&gt;
&lt;br /&gt;
Experiment with the provider to see situations and contexts in which the option will and will not appear.&lt;br /&gt;
&lt;br /&gt;
=== FloatMenuOption Actions ===&lt;br /&gt;
&lt;br /&gt;
In order for our provided FloatMenuOption to execute code, it needs to have an Action provided. The easiest way to define what the option will do is to provide the FloatMenuOption a lambda expression with the code that you want to have run inside of it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, () =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we are telling the FloatMenuOption to run the code inside the lambda expression - to kill the pawn that was clicked on - when the option is selected. Recompile the code and test it out. Selecting the option should now be possible and should instantly kill the pawn.&lt;br /&gt;
&lt;br /&gt;
You can run any arbitrary C# from within the expression, such as spawning explosions, changing the skills, traits, hediffs, or relationships of the clicked pawn, and more.&lt;br /&gt;
&lt;br /&gt;
==== Sending a Message ====&lt;br /&gt;
Next, we will add a message saying who was selected and who was killed, as a way to show some visual feedback for the action that the player just carried out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, () =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
        Messages.Message($&amp;quot;{context.FirstSelectedPawn} has killed {clickedPawn} with their mind&amp;quot;, MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FloatMenuContext instance passed in to the method contains a lot of useful information, such as who is currently selected. Messages are the small lines of text that appear in the top left corner of the screen, and are usually reserved for transitory information that is relevant to a player but not worthy of a full Letter. By passing &amp;lt;code&amp;gt;historical: false&amp;lt;/code&amp;gt; to the Message, we inform it that we do not want this Message to be logged in the History tab.&lt;br /&gt;
&lt;br /&gt;
Note: See the Referencing Defs from C# section of [[Modding_Tutorials/Defs|Defs]] for details on DefOf's like &amp;lt;code&amp;gt;MessageTypeDefOf.PositiveEvent&amp;lt;/code&amp;gt; which are not covered in this tutorial.&lt;br /&gt;
&lt;br /&gt;
If you recompile your code and run the game again, every time the float menu option is selected, the clicked pawn should now be killed and a message should appear with the names of both the selected and clicked pawns.&lt;br /&gt;
&lt;br /&gt;
=== Allowing for Translations ===&lt;br /&gt;
&lt;br /&gt;
If all has gone well, we have a fully functional FloatMenuOptionProvider. At the moment, though, the label for the option and the text in the Message are entirely contained in our solution and cannot be accessed externally, making it impossible to translate the strings to other languages or re-use effectively. RimWorld allows for setting up translations much like it does for setting up Defs. It's time to change our raw strings to translated strings accessible in XML using &amp;lt;code&amp;gt;Translate&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;Example_KillPawn&amp;quot;.Translate(clickedPawn), () =&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
        Messages.Message(&amp;quot;Example_KilledWithTheirMind&amp;quot;.Translate(context.FirstSelectedPawn, clickedPawn), MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With these two key strings created, RimWorld will now look in the Languages folder for the player's language for a &amp;lt;code&amp;gt;Keyed&amp;lt;/code&amp;gt; folder for these key strings. The file structure for key strings inside the Keyed folder does not matter, but it can be helpful for translators and yourself to keep the key strings organized by where they are used, as there is no way to know in XML what they are used for in the C#.&lt;br /&gt;
&lt;br /&gt;
Fill in text for the key strings like below:&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Numbers represent the index of arguments passed to Translate. In this case, 0 is the Pawn that was clicked on. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KillPawn&amp;gt;Make {0} die&amp;lt;/Example_KillPawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Messages.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Numbers represent the index of arguments passed to Translate. In this case, 0 is the selected pawn and 1 is the Pawn that was clicked on. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KilledWithTheirMind&amp;gt;{0} has killed {1} with their mind&amp;lt;/Example_KilledWithTheirMind&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the key string must '''exactly''' match the key in the solution, or else you will see the key string name from the solution itself in-game (if you have dev-mode on, you will see something called zalgo text to help visualize that this probably was not intentional).&lt;br /&gt;
&lt;br /&gt;
Recompile the code after checking that the key strings in the solution and translation files match, and test. You can change the text or what arguments are provided to the Translate method if you would like.&lt;br /&gt;
&lt;br /&gt;
=== Final Touches ===&lt;br /&gt;
&lt;br /&gt;
At this point, you should have a working FloatMenuOptionProvider that allows for execution of arbitrary C# with visual feedback and that allows for all text to be properly translated! From here, you can start expanding what the provider does and allow for creating entirely custom orders to be assigned to pawns. The concepts in this tutorial are widely used in RimWorld to handle all sorts of vanilla interactions that the player can force, and so should help serve as a foundation for new interactions.&lt;br /&gt;
&lt;br /&gt;
This tutorial concludes with one additional - optional - change to the FloatMenuOptionProvider we created by preventing the player from instantly killing their own pawns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    if (clickedPawn.Faction != Faction.OfPlayer)&lt;br /&gt;
    {&lt;br /&gt;
        return new FloatMenuOption(&amp;quot;Example_KillPawn&amp;quot;.Translate(clickedPawn), () =&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            clickedPawn.Kill(null);&lt;br /&gt;
            Messages.Message(&amp;quot;Example_KilledWithTheirMind&amp;quot;.Translate(context.FirstSelectedPawn, clickedPawn), MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;Example_CannotKillPlayerPawns&amp;quot;.Translate(clickedPawn), null);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Languages/English/Keyed/FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- 0 is the first argument passed to translate, which is the Pawn clicked on in this case. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KillPawn&amp;gt;Make {0} die&amp;lt;/Example_KillPawn&amp;gt;&lt;br /&gt;
    &amp;lt;Example_CannotKillPlayerPawns&amp;gt;{0} is on your team, you can't kill them!&amp;lt;/Example_CannotKillPlayerPawns&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can set as many different FloatMenuOption outcomes as you like, based on all sorts of conditions. Note that you may also return null from this method, if you ultimately decide you don't want to have a float menu option appear at all. This can be useful if the validation for the selected pawn or the clicked pawn mistakenly returned true for something that should not receive an option, or if after validation occurred, something changed and an option should no longer be valid.&lt;br /&gt;
&lt;br /&gt;
Don't forget to keep your translation key strings in the xml synced whenever you change them in the solution!&lt;br /&gt;
&lt;br /&gt;
If you get any errors, be sure to check out the [[Modding_Tutorials/Troubleshooting|troubleshooting guide]] or join us on the '''#mod-development''' channel on the [https://discord.gg/rimworld RimWorld Discord server].&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding]]&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=File:Example_FloatMenuOptionProvider_FirstOption.png&amp;diff=172946</id>
		<title>File:Example FloatMenuOptionProvider FirstOption.png</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=File:Example_FloatMenuOptionProvider_FirstOption.png&amp;diff=172946"/>
		<updated>2025-12-09T22:00:19Z</updated>

		<summary type="html">&lt;p&gt;Killathon: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=File:Example_FloatMenuOptionProvider.png&amp;diff=172945</id>
		<title>File:Example FloatMenuOptionProvider.png</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=File:Example_FloatMenuOptionProvider.png&amp;diff=172945"/>
		<updated>2025-12-09T22:00:19Z</updated>

		<summary type="html">&lt;p&gt;Killathon: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_FloatMenuOptionProvider&amp;diff=172944</id>
		<title>Modding Tutorials/Code FloatMenuOptionProvider</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_FloatMenuOptionProvider&amp;diff=172944"/>
		<updated>2025-12-09T22:02:09Z</updated>

		<summary type="html">&lt;p&gt;Killathon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Example FloatMenuOptionProvider}}&lt;br /&gt;
{{BackToTutorials}}&lt;br /&gt;
&lt;br /&gt;
This is a basic RimWorld mod tutorial for creating a FloatMenuOptionProvider to run arbitrary C# code. &lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
In this tutorial you will:&lt;br /&gt;
&lt;br /&gt;
* Create a basic C# solution and compile it into an assembly&lt;br /&gt;
* Create a basic FloatMenuOptionProvider: A simple option to instantly kill a non-player pawn&lt;br /&gt;
* Learn how float menu options distinguish between hidden, disabled, and enabled options&lt;br /&gt;
* Create a message to display text on screen to display at a glance who was selected and who was killed&lt;br /&gt;
* Learn how to use LanguageData to allow for translations of code used in the solution&lt;br /&gt;
&lt;br /&gt;
[[File:Example_FloatMenuOptionProvider.png|none|border]]&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
FloatMenuOptionProviders were added in 1.6 to permit for finer tuned control over assigning orders to colonists. Prior to 1.6, many of these float menu options were handled by a monolithic method that made extending via mods difficult and liable to create conflicts. Some examples of vanilla cases in 1.6 include:&lt;br /&gt;
* Telling colonists to equip or drop weapons and apparel&lt;br /&gt;
* Telling colonists to arrest, rescue, pick up, romance, and otherwise interact with other pawns&lt;br /&gt;
* Telling colonists to interact with relics, terminals, and other quest objects&lt;br /&gt;
&lt;br /&gt;
== Recommended Reading ==&lt;br /&gt;
* [[Modding_Tutorials/Mod_Folder_Structure|Mod Folder Structure]]&lt;br /&gt;
* [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]]&lt;br /&gt;
* [[Modding_Tutorials/Decompiling_source_code|Decompiling Source Code]]&lt;br /&gt;
&lt;br /&gt;
== Sample Repository ==&lt;br /&gt;
A working implementation of this mod can be found [https://github.com/RWDevathon/ExampleFloatMenuOptionProvider in this GitHub repository]. You can use it to compare against your work or as a basis for modification! The repository contains comments explaining each part, if you prefer learning by seeing the larger picture. The comments in the repository will be explained in greater detail here.&lt;br /&gt;
&lt;br /&gt;
== Folder Setup ==&lt;br /&gt;
&lt;br /&gt;
First, you will want to create the files and folders necessary for this mod:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Mods&lt;br /&gt;
└ MyModFolder&lt;br /&gt;
  ├ About&lt;br /&gt;
  │ ├ About.xml&lt;br /&gt;
  │ └ Preview.png&lt;br /&gt;
  ├ Assemblies&lt;br /&gt;
  ├ Languages&lt;br /&gt;
  │ ├ English&lt;br /&gt;
  │   └ Keyed&lt;br /&gt;
  │     ├ FloatMenuOptions.xml&lt;br /&gt;
  │     └ Messages.xml&lt;br /&gt;
  └ Source&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check out the [[Modding_Tutorials/Mod_Folder_Structure|mod folder structure guide]] for more information about individual folders.&lt;br /&gt;
&lt;br /&gt;
=== About.xml ===&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;About.xml&amp;lt;/code&amp;gt; is used to identify your mod to RimWorld; please see [[Modding_Tutorials/About.xml|the About.xml reference page]] for more information. Be sure to replace &amp;quot;AuthorName&amp;quot; with your own name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;ModMetaData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is the internal identifier for your mod. --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- It is recommended that you make it unique to as to avoid potential collisions with other authors; --&amp;gt;&lt;br /&gt;
  &amp;lt;!--     if Rimworld detects multiple mods with the same packageId then it will refuse to load all of them. --&amp;gt;&lt;br /&gt;
  &amp;lt;packageId&amp;gt;AuthorName.ExampleFloatMenuOptionProvider&amp;lt;/packageId&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is both the displayed name of your mod as well as the name used for patch targeting. --&amp;gt;&lt;br /&gt;
  &amp;lt;name&amp;gt;Example Float Menu Option Provider&amp;lt;/name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Your name goes here. --&amp;gt;&lt;br /&gt;
  &amp;lt;author&amp;gt;AuthorName&amp;lt;/author&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- A version number for your own tracking --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- See wiki About.xml guide for concerns regarding this field for RimWorld versions prior to 1.4 --&amp;gt;&lt;br /&gt;
  &amp;lt;modVersion&amp;gt;1.0&amp;lt;/modVersion&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- These are the RimWorld game versions that your mod supports. --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- It is recommended that you only list versions that you have explicitly tested to ensure they work, --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- as even basic XML options can change between major versions of the game. --&amp;gt;&lt;br /&gt;
  &amp;lt;supportedVersions&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;1.6&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/supportedVersions&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is the description of your mod shown in both the vanilla mod manager as well as modded managers. --&amp;gt;&lt;br /&gt;
  &amp;lt;description&amp;gt;This is an example float menu option provider made for the RimWorld Wiki.&amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ModMetaData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
&lt;br /&gt;
=== Create your solution ===&lt;br /&gt;
&lt;br /&gt;
Our first step is to set up the C# workspace where we will create the FloatMenuOptionProvider. This tutorial assumes you have completed the [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]] tutorial and know how to initialize a solution. If you have not yet learned how to create a solution, please review that tutorial.&lt;br /&gt;
&lt;br /&gt;
Place a newly created solution in the Source folder with an appropriate name, and configure it to build to the Assemblies folder.&lt;br /&gt;
&lt;br /&gt;
=== Create the FloatMenuOptionProvider subclass ===&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptionProvider is an abstract class. Subclasses of it inherit numerous properties and methods that can be overridden in order to have a wide variety of outcomes, and all subclasses will be automatically identified by the game. We will create our own FloatMenuOptionProvider subclass to allow for execution of code that has access to a source and target pawn (this tutorial will refer to them as &amp;quot;selected&amp;quot; and &amp;quot;clicked,&amp;quot; respectively, as this aligns with how they are identified in C#).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
using RimWorld;&lt;br /&gt;
using Verse;&lt;br /&gt;
&lt;br /&gt;
namespace ExampleFloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    public class FloatMenuOptionProvider_Example : FloatMenuOptionProvider&lt;br /&gt;
    {&lt;br /&gt;
      // Pasted content omitted&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RimWorld automatically identifies all subclasses of FloatMenuOptionProvider and applies them - meaning we only have to define this one class to be able to have it usable in game.&lt;br /&gt;
&lt;br /&gt;
=== Make a FloatMenuOption Appear In-Game ===&lt;br /&gt;
&lt;br /&gt;
Our subclass inherits many properties and methods from its parent class. It is highly recommended that you [[Modding_Tutorials/Decompiling_source_code|decompile]] the &amp;lt;code&amp;gt;FloatMenuOptionProvider&amp;lt;/code&amp;gt; class so that you can learn all of the properties and methods that you can override. In this example, we are only overriding a small handful of them in order to compile and run the code.&lt;br /&gt;
&lt;br /&gt;
Before the solution can compile, we must override three properties from the parent class which are abstract (meaning that the parent class does not define a value for these properties and is expecting subclasses to define them):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
public class FloatMenuOptionProvider_Example : FloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    protected override bool Drafted =&amp;gt; true;&lt;br /&gt;
    protected override bool Undrafted =&amp;gt; true;&lt;br /&gt;
    protected override bool Multiselect =&amp;gt; false;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our float menu option will be provided only if a single colonist is selected and we do not care if they are drafted or undrafted. If any of these conditions are not met for the selected colonist, then the float menu option will not appear at all. '''These are not the only properties and methods that control whether the option will appear.''' Please decompile FloatMenuOptionProvider to see an up-to-date comprehensive list of them all, and their default values. These three are the only properties which are abstract and have no default values set.&lt;br /&gt;
&lt;br /&gt;
==== Making the FloatMenuOption ====&lt;br /&gt;
Next, we will define what the FloatMenuOption we want to provide is. Because this example is focusing on killing a pawn, we will choose to override a method specific to targeting pawns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, null);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is all the code we need in order to compile and have a float menu option appear in game. Note that the string is the label for the option, and the &amp;quot;null&amp;quot; in the example above is the action that would happen if the option were to be selected. By leaving it null, the game will register this float menu option as disabled, and thus not selectable. We will provide an action in the following steps. Compile the code, make sure the assembly ends up in the correct place, and test whether the float menu appears in game.&lt;br /&gt;
&lt;br /&gt;
[[File:Example_FloatMenuOptionProvider.png|none|border]]&lt;br /&gt;
&lt;br /&gt;
Experiment with the provider to see situations and contexts in which the option will and will not appear.&lt;br /&gt;
&lt;br /&gt;
=== FloatMenuOption Actions ===&lt;br /&gt;
&lt;br /&gt;
In order for our provided FloatMenuOption to execute code, it needs to have an Action provided. The easiest way to define what the option will do is to provide the FloatMenuOption a delegate with the code that you want to have run inside of it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, delegate&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we are telling the FloatMenuOption to run the code inside the delegate - to kill the pawn that was clicked on - when the option is selected. Recompile the code and test it out. Selecting the option should now be possible and should instantly kill the pawn.&lt;br /&gt;
&lt;br /&gt;
You can run any arbitrary C# from within the delegate, such as spawning explosions, changing the skills, traits, hediffs, or relationships of the clicked pawn, and more.&lt;br /&gt;
&lt;br /&gt;
==== Sending a Message ====&lt;br /&gt;
Next, we will add a message saying who was selected and who was killed, as a way to show some visual feedback for the action that the player just carried out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, delegate&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
        Messages.Message($&amp;quot;{context.FirstSelectedPawn} has killed {clickedPawn} with their mind&amp;quot;, MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FloatMenuContext instance passed in to the method contains a lot of useful information, such as who is currently selected. Messages are the small lines of text that appear in the top left corner of the screen, and are usually reserved for transitory information that is relevant to a player but not worthy of a full Letter. By passing &amp;lt;code&amp;gt;historical: false&amp;lt;/code&amp;gt; to the Message, we inform it that we do not want this Message to be logged in the History tab.&lt;br /&gt;
&lt;br /&gt;
Note: See the Referencing Defs from C# section of [[Modding_Tutorials/Defs|Defs]] for details on DefOf's like &amp;lt;code&amp;gt;MessageTypeDefOf.PositiveEvent&amp;lt;/code&amp;gt; which are not covered in this tutorial.&lt;br /&gt;
&lt;br /&gt;
If you recompile your code and run the game again, every time the float menu option is selected, the clicked pawn should now be killed and a message should appear with the names of both the selected and clicked pawns.&lt;br /&gt;
&lt;br /&gt;
=== Allowing for Translations ===&lt;br /&gt;
&lt;br /&gt;
If all has gone well, we have a fully functional FloatMenuOptionProvider. At the moment, though, the label for the option and the text in the Message are entirely contained in our solution and cannot be accessed externally, making it impossible to translate the strings to other languages or re-use effectively. RimWorld allows for setting up translations much like it does for setting up Defs. It's time to change our raw strings to translated strings accessible in XML using &amp;lt;code&amp;gt;Translate&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;Example_KillPawn&amp;quot;.Translate(clickedPawn), delegate&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
        Messages.Message(&amp;quot;Example_KilledWithTheirMind&amp;quot;.Translate(context.FirstSelectedPawn, clickedPawn), MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With these two key strings created, RimWorld will now look in the Languages folder for the player's language for a &amp;lt;code&amp;gt;Keyed&amp;lt;/code&amp;gt; folder for these key strings. The file structure for key strings inside the Keyed folder does not matter, but it can be helpful for translators and yourself to keep the key strings organized by where they are used, as there is no way to know in XML what they are used for in the C#.&lt;br /&gt;
&lt;br /&gt;
Fill in text for the key strings like below:&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Numbers represent the index of arguments passed to Translate. In this case, 0 is the Pawn that was clicked on. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KillPawn&amp;gt;Make {0} die&amp;lt;/Example_KillPawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Messages.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Numbers represent the index of arguments passed to Translate. In this case, 0 is the selected pawn and 1 is the Pawn that was clicked on. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KilledWithTheirMind&amp;gt;{0} has killed {1} with their mind&amp;lt;/Example_KilledWithTheirMind&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the key string must '''exactly''' match the key in the solution, or else you will see the key string name from the solution itself in-game (if you have dev-mode on, you will see something called zalgo text to help visualize that this probably was not intentional).&lt;br /&gt;
&lt;br /&gt;
Recompile the code after checking that the key strings in the solution and translation files match, and test. You can change the text or what arguments are provided to the Translate method if you would like.&lt;br /&gt;
&lt;br /&gt;
=== Final Touches ===&lt;br /&gt;
&lt;br /&gt;
At this point, you should have a working FloatMenuOptionProvider that allows for execution of arbitrary C# with visual feedback and that allows for all text to be properly translated! From here, you can start expanding what the provider does and allow for creating entirely custom orders to be assigned to pawns. The concepts in this tutorial are widely used in RimWorld to handle all sorts of vanilla interactions that the player can force, and so should help serve as a foundation for new interactions.&lt;br /&gt;
&lt;br /&gt;
This tutorial concludes with one additional - optional - change to the FloatMenuOptionProvider we created by preventing the player from instantly killing their own pawns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    if (clickedPawn.Faction != Faction.OfPlayer)&lt;br /&gt;
    {&lt;br /&gt;
        return new FloatMenuOption(&amp;quot;Example_KillPawn&amp;quot;.Translate(clickedPawn), delegate&lt;br /&gt;
        {&lt;br /&gt;
            clickedPawn.Kill(null);&lt;br /&gt;
            Messages.Message(&amp;quot;Example_KilledWithTheirMind&amp;quot;.Translate(context.FirstSelectedPawn, clickedPawn), MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;Example_CannotKillPlayerPawns&amp;quot;.Translate(clickedPawn), null);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Languages/English/Keyed/FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- 0 is the first argument passed to translate, which is the Pawn clicked on in this case. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KillPawn&amp;gt;Make {0} die&amp;lt;/Example_KillPawn&amp;gt;&lt;br /&gt;
    &amp;lt;Example_CannotKillPlayerPawns&amp;gt;{0} is on your team, you can't kill them!&amp;lt;/Example_CannotKillPlayerPawns&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can set as many different FloatMenuOption outcomes as you like, based on all sorts of conditions. Note that you may also return null from this method, if you ultimately decide you don't want to have a float menu option appear at all. This can be useful if the validation for the selected colonist or the clicked pawn mistakenly returned true for something that should not receive an option, or if after validation occurred, something changed and an option should no longer be valid.&lt;br /&gt;
&lt;br /&gt;
Don't forget to keep your translation key strings in the xml synced whenever you change them in the solution!&lt;br /&gt;
&lt;br /&gt;
If you get any errors, be sure to check out the [[Modding_Tutorials/Troubleshooting|troubleshooting guide]] or join us on the '''#mod-development''' channel on the [https://discord.gg/rimworld RimWorld Discord server].&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding]]&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
	<entry>
		<id>https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_FloatMenuOptionProvider&amp;diff=172900</id>
		<title>Modding Tutorials/Code FloatMenuOptionProvider</title>
		<link rel="alternate" type="text/html" href="https://rimworldwiki.com/index.php?title=Modding_Tutorials/Code_FloatMenuOptionProvider&amp;diff=172900"/>
		<updated>2025-12-08T22:55:23Z</updated>

		<summary type="html">&lt;p&gt;Killathon: Created page with &amp;quot;{{DISPLAYTITLE:Example FloatMenuOptionProvider}} {{BackToTutorials}}  This is a basic RimWorld mod tutorial for creating a FloatMenuOptionProvider to run arbitrary C# code....&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Example FloatMenuOptionProvider}}&lt;br /&gt;
{{BackToTutorials}}&lt;br /&gt;
&lt;br /&gt;
This is a basic RimWorld mod tutorial for creating a FloatMenuOptionProvider to run arbitrary C# code. &lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
In this tutorial you will:&lt;br /&gt;
&lt;br /&gt;
* Create a basic C# solution and compile it into an assembly&lt;br /&gt;
* Create a basic FloatMenuOptionProvider: A simple option to instantly kill a non-player pawn&lt;br /&gt;
* Learn how float menu options distinguish between hidden, disabled, and enabled options&lt;br /&gt;
* Create a message to display text on screen to display at a glance who was selected and who was killed&lt;br /&gt;
* Learn how to use LanguageData to allow for translations of code used in the solution&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
FloatMenuOptionProviders were added in 1.6 to permit for finer tuned control over assigning orders to colonists. Prior to 1.6, many of these float menu options were handled by a monolithic method that made extending via mods difficult and liable to create conflicts. Some examples of vanilla cases in 1.6 include:&lt;br /&gt;
* Telling colonists to equip or drop weapons and apparel&lt;br /&gt;
* Telling colonists to arrest, rescue, pick up, romance, and otherwise interact with other pawns&lt;br /&gt;
* Telling colonists to interact with relics, terminals, and other quest objects&lt;br /&gt;
&lt;br /&gt;
== Recommended Reading ==&lt;br /&gt;
* [[Modding_Tutorials/Mod_Folder_Structure|Mod Folder Structure]]&lt;br /&gt;
* [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]]&lt;br /&gt;
* [[Modding_Tutorials/Decompiling_source_code|Decompiling Source Code]]&lt;br /&gt;
&lt;br /&gt;
== Sample Repository ==&lt;br /&gt;
A working implementation of this mod can be found [https://github.com/RWDevathon/ExampleFloatMenuOptionProvider in this GitHub repository]. You can use it to compare against your work or as a basis for modification! The repository contains comments explaining each part, if you prefer learning by seeing the larger picture. The comments in the repository will be explained in greater detail here.&lt;br /&gt;
&lt;br /&gt;
== Folder Setup ==&lt;br /&gt;
&lt;br /&gt;
First, you will want to create the files and folders necessary for this mod:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Mods&lt;br /&gt;
└ MyModFolder&lt;br /&gt;
  ├ About&lt;br /&gt;
  │ ├ About.xml&lt;br /&gt;
  │ └ Preview.png&lt;br /&gt;
  ├ Assemblies&lt;br /&gt;
  ├ Languages&lt;br /&gt;
  │ ├ English&lt;br /&gt;
  │   └ Keyed&lt;br /&gt;
  │     ├ FloatMenuOptions.xml&lt;br /&gt;
  │     └ Messages.xml&lt;br /&gt;
  └ Source&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check out the [[Modding_Tutorials/Mod_Folder_Structure|mod folder structure guide]] for more information about individual folders.&lt;br /&gt;
&lt;br /&gt;
=== About.xml ===&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;About.xml&amp;lt;/code&amp;gt; is used to identify your mod to RimWorld; please see [[Modding_Tutorials/About.xml|the About.xml reference page]] for more information. Be sure to replace &amp;quot;AuthorName&amp;quot; with your own name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;ModMetaData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is the internal identifier for your mod. --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- It is recommended that you make it unique to as to avoid potential collisions with other authors; --&amp;gt;&lt;br /&gt;
  &amp;lt;!--     if Rimworld detects multiple mods with the same packageId then it will refuse to load all of them. --&amp;gt;&lt;br /&gt;
  &amp;lt;packageId&amp;gt;AuthorName.ExampleFloatMenuOptionProvider&amp;lt;/packageId&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is both the displayed name of your mod as well as the name used for patch targeting. --&amp;gt;&lt;br /&gt;
  &amp;lt;name&amp;gt;Example Float Menu Option Provider&amp;lt;/name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Your name goes here. --&amp;gt;&lt;br /&gt;
  &amp;lt;author&amp;gt;AuthorName&amp;lt;/author&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- A version number for your own tracking --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- See wiki About.xml guide for concerns regarding this field for RimWorld versions prior to 1.4 --&amp;gt;&lt;br /&gt;
  &amp;lt;modVersion&amp;gt;1.0&amp;lt;/modVersion&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- These are the RimWorld game versions that your mod supports. --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- It is recommended that you only list versions that you have explicitly tested to ensure they work, --&amp;gt;&lt;br /&gt;
  &amp;lt;!-- as even basic XML options can change between major versions of the game. --&amp;gt;&lt;br /&gt;
  &amp;lt;supportedVersions&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;1.6&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/supportedVersions&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is the description of your mod shown in both the vanilla mod manager as well as modded managers. --&amp;gt;&lt;br /&gt;
  &amp;lt;description&amp;gt;This is an example float menu option provider made for the RimWorld Wiki.&amp;lt;/description&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ModMetaData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
&lt;br /&gt;
=== Create your solution ===&lt;br /&gt;
&lt;br /&gt;
Our first step is to set up the C# workspace where we will create the FloatMenuOptionProvider. This tutorial assumes you have completed the [[Modding_Tutorials/Setting_up_a_solution|Setting Up a Solution]] tutorial and know how to initialize a solution. If you have not yet learned how to create a solution, please review that tutorial.&lt;br /&gt;
&lt;br /&gt;
Place a newly created solution in the Source folder with an appropriate name, and configure it to build to the Assemblies folder.&lt;br /&gt;
&lt;br /&gt;
=== Create the FloatMenuOptionProvider subclass ===&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptionProvider is an abstract class. Subclasses of it inherit numerous properties and methods that can be overridden in order to have a wide variety of outcomes, and all subclasses will be automatically identified by the game. We will create our own FloatMenuOptionProvider subclass to allow for execution of code that has access to a source and target pawn (this tutorial will refer to them as &amp;quot;selected&amp;quot; and &amp;quot;clicked,&amp;quot; respectively, as this aligns with how they are identified in C#).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
using RimWorld;&lt;br /&gt;
using Verse;&lt;br /&gt;
&lt;br /&gt;
namespace ExampleFloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    public class FloatMenuOptionProvider_Example : FloatMenuOptionProvider&lt;br /&gt;
    {&lt;br /&gt;
      // Pasted content omitted&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RimWorld automatically identifies all subclasses of FloatMenuOptionProvider and applies them - meaning we only have to define this one class to be able to have it usable in game.&lt;br /&gt;
&lt;br /&gt;
=== Make a FloatMenuOption Appear In-Game ===&lt;br /&gt;
&lt;br /&gt;
Our subclass inherits many properties and methods from its parent class. It is highly recommended that you [[Modding_Tutorials/Decompiling_source_code|decompile]] the &amp;lt;code&amp;gt;FloatMenuOptionProvider&amp;lt;/code&amp;gt; class so that you can learn all of the properties and methods that you can override. In this example, we are only overriding a small handful of them in order to compile and run the code.&lt;br /&gt;
&lt;br /&gt;
Before the solution can compile, we must override three properties from the parent class which are abstract (meaning that the parent class does not define a value for these properties and is expecting subclasses to define them):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
public class FloatMenuOptionProvider_Example : FloatMenuOptionProvider&lt;br /&gt;
{&lt;br /&gt;
    protected override bool Drafted =&amp;gt; true;&lt;br /&gt;
    protected override bool Undrafted =&amp;gt; true;&lt;br /&gt;
    protected override bool Multiselect =&amp;gt; false;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our float menu option will be provided only if a single colonist is selected and we do not care if they are drafted or undrafted. If any of these conditions are not met for the selected colonist, then the float menu option will not appear at all. '''These are not the only properties and methods that control whether the option will appear.''' Please decompile FloatMenuOptionProvider to see an up-to-date comprehensive list of them all, and their default values. These three are the only properties which are abstract and have no default values set.&lt;br /&gt;
&lt;br /&gt;
==== Making the FloatMenuOption ====&lt;br /&gt;
Next, we will define what the FloatMenuOption we want to provide is. Because this example is focusing on killing a pawn, we will choose to override a method specific to targeting pawns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, null);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is all the code we need in order to compile and have a float menu option appear in game. Note that the string is the label for the option, and the &amp;quot;null&amp;quot; in the example above is the action that would happen if the option were to be selected. By leaving it null, the game will register this float menu option as disabled, and thus not selectable. We will provide an action in the following steps. Compile the code, make sure the assembly ends up in the correct place, and test whether the float menu appears in game.&lt;br /&gt;
&lt;br /&gt;
Experiment with the provider to see situations and contexts in which the option will and will not appear.&lt;br /&gt;
&lt;br /&gt;
=== FloatMenuOption Actions ===&lt;br /&gt;
&lt;br /&gt;
In order for our provided FloatMenuOption to execute code, it needs to have an Action provided. The easiest way to define what the option will do is to provide the FloatMenuOption a delegate with the code that you want to have run inside of it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, delegate&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, we are telling the FloatMenuOption to run the code inside the delegate - to kill the pawn that was clicked on - when the option is selected. Recompile the code and test it out. Selecting the option should now be possible and should instantly kill the pawn.&lt;br /&gt;
&lt;br /&gt;
You can run any arbitrary C# from within the delegate, such as spawning explosions, changing the skills, traits, hediffs, or relationships of the clicked pawn, and more.&lt;br /&gt;
&lt;br /&gt;
==== Sending a Message ====&lt;br /&gt;
Next, we will add a message saying who was selected and who was killed, as a way to show some visual feedback for the action that the player just carried out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;This is a Float Menu Option&amp;quot;, delegate&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
        Messages.Message($&amp;quot;{context.FirstSelectedPawn} has killed {clickedPawn} with their mind&amp;quot;, MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FloatMenuContext instance passed in to the method contains a lot of useful information, such as who is currently selected. Messages are the small lines of text that appear in the top left corner of the screen, and are usually reserved for transitory information that is relevant to a player but not worthy of a full Letter. By passing &amp;lt;code&amp;gt;historical: false&amp;lt;/code&amp;gt; to the Message, we inform it that we do not want this Message to be logged in the History tab.&lt;br /&gt;
&lt;br /&gt;
Note: See the Referencing Defs from C# section of [[Modding_Tutorials/Defs|Defs]] for details on DefOf's like &amp;lt;code&amp;gt;MessageTypeDefOf.PositiveEvent&amp;lt;/code&amp;gt; which are not covered in this tutorial.&lt;br /&gt;
&lt;br /&gt;
If you recompile your code and run the game again, every time the float menu option is selected, the clicked pawn should now be killed and a message should appear with the names of both the selected and clicked pawns.&lt;br /&gt;
&lt;br /&gt;
=== Allowing for Translations ===&lt;br /&gt;
&lt;br /&gt;
If all has gone well, we have a fully functional FloatMenuOptionProvider. At the moment, though, the label for the option and the text in the Message are entirely contained in our solution and cannot be accessed externally, making it impossible to translate the strings to other languages or re-use effectively. RimWorld allows for setting up translations much like it does for setting up Defs. It's time to change our raw strings to translated strings accessible in XML using &amp;lt;code&amp;gt;Translate&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;Example_KillPawn&amp;quot;.Translate(clickedPawn), delegate&lt;br /&gt;
    {&lt;br /&gt;
        clickedPawn.Kill(null);&lt;br /&gt;
        Messages.Message(&amp;quot;Example_KilledWithTheirMind&amp;quot;.Translate(context.FirstSelectedPawn, clickedPawn), MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With these two key strings created, RimWorld will now look in the Languages folder for the player's language for a &amp;lt;code&amp;gt;Keyed&amp;lt;/code&amp;gt; folder for these key strings. The file structure for key strings inside the Keyed folder does not matter, but it can be helpful for translators and yourself to keep the key strings organized by where they are used, as there is no way to know in XML what they are used for in the C#.&lt;br /&gt;
&lt;br /&gt;
Fill in text for the key strings like below:&lt;br /&gt;
&lt;br /&gt;
FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Numbers represent the index of arguments passed to Translate. In this case, 0 is the Pawn that was clicked on. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KillPawn&amp;gt;Make {0} die&amp;lt;/Example_KillPawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Messages.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Numbers represent the index of arguments passed to Translate. In this case, 0 is the selected pawn and 1 is the Pawn that was clicked on. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KilledWithTheirMind&amp;gt;{0} has killed {1} with their mind&amp;lt;/Example_KilledWithTheirMind&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the key string must '''exactly''' match the key in the solution, or else you will see the key string name from the solution itself in-game (if you have dev-mode on, you will see something called zalgo text to help visualize that this probably was not intentional).&lt;br /&gt;
&lt;br /&gt;
Recompile the code after checking that the key strings in the solution and translation files match, and test. You can change the text or what arguments are provided to the Translate method if you would like.&lt;br /&gt;
&lt;br /&gt;
=== Final Touches ===&lt;br /&gt;
&lt;br /&gt;
At this point, you should have a working FloatMenuOptionProvider that allows for execution of arbitrary C# with visual feedback and that allows for all text to be properly translated! From here, you can start expanding what the provider does and allow for creating entirely custom orders to be assigned to pawns. The concepts in this tutorial are widely used in RimWorld to handle all sorts of vanilla interactions that the player can force, and so should help serve as a foundation for new interactions.&lt;br /&gt;
&lt;br /&gt;
This tutorial concludes with one additional - optional - change to the FloatMenuOptionProvider we created by preventing the player from instantly killing their own pawns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cs&amp;quot;&amp;gt;&lt;br /&gt;
protected override FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)&lt;br /&gt;
{&lt;br /&gt;
    if (clickedPawn.Faction != Faction.OfPlayer)&lt;br /&gt;
    {&lt;br /&gt;
        return new FloatMenuOption(&amp;quot;Example_KillPawn&amp;quot;.Translate(clickedPawn), delegate&lt;br /&gt;
        {&lt;br /&gt;
            clickedPawn.Kill(null);&lt;br /&gt;
            Messages.Message(&amp;quot;Example_KilledWithTheirMind&amp;quot;.Translate(context.FirstSelectedPawn, clickedPawn), MessageTypeDefOf.PositiveEvent, historical: false);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return new FloatMenuOption(&amp;quot;Example_CannotKillPlayerPawns&amp;quot;.Translate(clickedPawn), null);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Languages/English/Keyed/FloatMenuOptions.xml:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;LanguageData&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- 0 is the first argument passed to translate, which is the Pawn clicked on in this case. --&amp;gt;&lt;br /&gt;
    &amp;lt;Example_KillPawn&amp;gt;Make {0} die&amp;lt;/Example_KillPawn&amp;gt;&lt;br /&gt;
    &amp;lt;Example_CannotKillPlayerPawns&amp;gt;{0} is on your team, you can't kill them!&amp;lt;/Example_CannotKillPlayerPawns&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/LanguageData&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can set as many different FloatMenuOption outcomes as you like, based on all sorts of conditions. Note that you may also return null from this method, if you ultimately decide you don't want to have a float menu option appear at all. This can be useful if the validation for the selected colonist or the clicked pawn mistakenly returned true for something that should not receive an option, or if after validation occurred, something changed and an option should no longer be valid.&lt;br /&gt;
&lt;br /&gt;
Don't forget to keep your translation key strings in the xml synced whenever you change them in the solution!&lt;br /&gt;
&lt;br /&gt;
If you get any errors, be sure to check out the [[Modding_Tutorials/Troubleshooting|troubleshooting guide]] or join us on the '''#mod-development''' channel on the [https://discord.gg/rimworld RimWorld Discord server].&lt;br /&gt;
&lt;br /&gt;
[[Category:Modding]]&lt;br /&gt;
[[Category:Modding tutorials]]&lt;/div&gt;</summary>
		<author><name>Killathon</name></author>
	</entry>
</feed>