Difference between revisions of "Modding Tutorials/Custom Comp Classes"
Jump to navigation
Jump to search
(→Accessing your Comps: Stupid formatting with no documentation :p) |
|||
Line 70: | Line 70: | ||
==== Accessing CompProperty directly ==== | ==== Accessing CompProperty directly ==== | ||
This is the "hard" way, but doable if you want: | This is the "hard" way, but doable if you want: | ||
− | < | + | <source lang="C#"> |
− | int importantProperty = ((MyCompProperties)((ThingWithComps)myObject).GetComp<MyLinkedCompThing>().props).mySecondCompProp; | + | int importantProperty = ((MyCompProperties)((ThingWithComps)myObject) |
− | // The "(ThingWithComps) cast may or may not be needed | + | .GetComp<MyLinkedCompThing>().props).mySecondCompProp; |
− | </ | + | // The "(ThingWithComps)" cast may or may not be needed |
+ | </source> | ||
==== Use the "get" method we created ==== | ==== Use the "get" method we created ==== | ||
− | < | + | <source lang="C#"> |
// real world example: | // real world example: | ||
SlotGroup slotGroup = GetSlotGroupInEarlierCode(); | SlotGroup slotGroup = GetSlotGroupInEarlierCode(); | ||
Line 84: | Line 85: | ||
int x = otherObject.GetComp<MyLinkedCompThing>().mySecondCompProp; // be sure it exists, etc | int x = otherObject.GetComp<MyLinkedCompThing>().mySecondCompProp; // be sure it exists, etc | ||
} else { /* not a thing with my comp, etc */ } | } else { /* not a thing with my comp, etc */ } | ||
− | </ | + | </source> |
=== Cautions, traps, etc === | === Cautions, traps, etc === |
Revision as of 03:36, 6 January 2019
Creating a custom comp class is a convenient way to add new functionality to RimWorld.
Prerequisites
- You need to have set up your editor and environment
- You need to know how to write custom code
- You should probably understand Defs at least somewhat.
def (xml) and C# structure
Setup, Defs, and Classes
You will have some custom def and it will have something like this:
Defs (xml)
<ThingDef ...> ... ... <comps> <li Class="MyNamespace.MyCompProperties"> <myCustomCompProperty>some value</myCustomCompProperty> <mySecondCompProp>4</mySecondCompProp> </li> <li> <!-- this is kind of like <tag>MN.MyCustomTag</tag>:--> <compClass>MyNamespace.MyCustomThingComp</compClass> </li> </comps> </ThingDef>
C#
namespace MyNamespace // For example, LWM.ModName - by using your // handle/name/etc, you almost certainly guarantee uniqueness { //////////// <li Class="MyNamespace.MyCompProperties"> //////////// public class MyCompProperties : CompProperties // Name this as you wish, of course { public Properties() { this.compClass = typeof(MyNamespace.MyLinkedCompThing); // rename as appropriate } public string myCustomCompProperty; // Name matches def, of course public int mySecondCompProp = 1; // Can set default values } // this ThingComp is used to actually access the comp property defined above // this is not "<compClass>MyNamespace.MyCustomThingComp</compClass>" public class MyLinkedCompThing : ThingComp { public string myCustomCompProperty { get { return ((MyCompProperties)this.props).myCustomCompProperty; } } public int mySecondCompProperty // Have to get all the names right { get { return ((MyCompProperties)this.props).mySecondCompProperty; } } //etc } //////////// <compClass>MyNamespace.MyCustomThingComp</compClass> //////////// public class MyCustomThingComp : ThingComp { public override void CompTick() { // do stuff } public override void CompTickRare() //etc public override ... // Check out Verse/ThingComp.cs for more ideas } } // end MyNamespace
Accessing your Comps
Just setting up your custom comps doesn't do you a lot of good if you can't access them!
Accessing CompProperty directly
This is the "hard" way, but doable if you want:
int importantProperty = ((MyCompProperties)((ThingWithComps)myObject) .GetComp<MyLinkedCompThing>().props).mySecondCompProp; // The "(ThingWithComps)" cast may or may not be needed
Use the "get" method we created
// real world example: SlotGroup slotGroup = GetSlotGroupInEarlierCode(); MyLinkedCompThing comp = ((ThingWithComps)slotGroup.parent).GetComp<MyLinkedCompThing>(); if (comp != null) { string s = comp.myCustomCompProperty; int x = otherObject.GetComp<MyLinkedCompThing>().mySecondCompProp; // be sure it exists, etc } else { /* not a thing with my comp, etc */ }
Cautions, traps, etc
If you have the same comp in an abstract (XML) def and attempt to redefine it in a (XML) child def, it will get counted twice. It's possible to get around this in the code, if you want to have default comps:
<ThingDef Name=ParentWithDefault ... Abstract=true> ... <comps> <li Class="MyCompPropertiesWithDefault"> <myValue>3</myValue> </li> </comps> </ThingDef> <ThingDef ParentName="ParentWihtDefault"> ... <comps> <li Class="MyCompPropertiesWithDefault"> <myValue>5</myValue> </li> </comps> </ThingDef>
public class MyLinkedCompThing : ThingComp { public string myCustomCompProperty //etc public override void Initialize (CompProperties props) { base.Initialize(props); // Remove duplicate entries and ensure the last entry is the only one left // This allows a default abstract def with the comp // and child def to change the comp value: MyCompProprtiesWithDefault[] list = this.parent.GetComps<MyCompPropertiesWithDefault>().ToArray(); // Remove everything but the last entry; harmless if only one entry: for (var i = 0; i < list.Length-1; i++) { this.parent.AllComps.Remove(list[i]); } } ///etc }