Ludeon Forums

RimWorld => Mods => Help => Topic started by: Danetta on January 18, 2017, 08:17:09 PM

Title: Custom definition
Post by: Danetta on January 18, 2017, 08:17:09 PM
Hello.

I have created a new class for my object and now I need to create a new definition inside one of XML files.

I did this:
  public class NewThing: ThingDef
    {
        public string newdef;
    }


Then I added <newdef> to XML, but how to make it loaded from XML into C# code?
Title: Re: Custom definition
Post by: RawCode on January 18, 2017, 08:39:46 PM
please provide your xml
Title: Re: Custom definition
Post by: Danetta on January 18, 2017, 09:09:15 PM
There is nothing to see in it.

It's like a original barrel:
  <ThingDef ParentName="BuildingBase">
    <defName>FermentingBarrel</defName>
    <label>fermenting barrel</label>
    <thingClass>Rimmod.Building_FermentingBarrel</thingClass>
    <graphicData>
      <texPath>Things/Building/Production/FermentingBarrel</texPath>
      <graphicClass>Graphic_Multi</graphicClass>
      <damageData>
        <rect>(0.05,0.1,0.9,0.9)</rect>
      </damageData>
    </graphicData>
    <minifiedDef>MinifiedFurniture</minifiedDef>
    <altitudeLayer>Building</altitudeLayer>
    <passability>PassThroughOnly</passability>
    <fillPercent>0.45</fillPercent>
    <pathCost>60</pathCost>
    <statBases>
      <WorkToBuild>600</WorkToBuild>
      <Mass>10</Mass>
      <MaxHitPoints>100</MaxHitPoints>
      <Flammability>1.0</Flammability>
    </statBases>
    <description>A barrel for fermenting raw wort into beer.</description>
    <costList>
      <Steel>10</Steel>
      <WoodLog>30</WoodLog>
    </costList>
<comps>
<li Class="CompProperties_TemperatureRuinable">
<minSafeTemperature>-1</minSafeTemperature>
<maxSafeTemperature>32</maxSafeTemperature>
<progressPerDegreePerTick>0.00001</progressPerDegreePerTick>
</li>
</comps>
    <tickerType>Rare</tickerType>
    <rotatable>true</rotatable>
    <designationCategory>Production</designationCategory>
    <constructEffect>ConstructWood</constructEffect>
    <researchPrerequisites><li>Brewing</li></researchPrerequisites>
  </ThingDef>


I want it to have an additional field like <newdef>somevalue</newdef> so I will be able to retrieve this value and use it in my C# class.
Title: Re: Custom definition
Post by: RawCode on January 18, 2017, 09:49:19 PM
instead of ThingDef you should define your own type NewThing (don't forget to put it into proper folder (NewThings) and you will have your field available.
Title: Re: Custom definition
Post by: Danetta on January 18, 2017, 09:59:06 PM
Well, I don't understand what you are trying to say. It's like creating new XML structure in different folder, but I am okay with existing strcuture. I am not creating a new object, I am adding functional to existing object. Why can't it be a child of an existing one, but with additional field?

Total lack of documentation blowing my mind. PS1 romhacking, disassembling and modding was much easier that this.
Title: Re: Custom definition
Post by: RawCode on January 19, 2017, 01:30:28 AM
use your own head, modding is part of "game play", i hope you are not asking someone to complete difficult fight or complicated puzzle for you and actually try again and again self?
Title: Re: Custom definition
Post by: Danetta on January 19, 2017, 02:36:53 AM
Quote from: RawCode on January 19, 2017, 01:30:28 AM
use your own head, modding is part of "game play", i hope you are not asking someone to complete difficult fight or complicated puzzle for you and actually try again and again self?
It's not the same thing. I have completed a lot of "complicated puzzles" via modding because, as I said, I am PS1 mod-maker.
Modding in Rimworld is opposite thing, I cфme here to create content (so others and myself might enjoy it), not to solve puzzles again (doesn't mean I don't want to learn — I do want to learn). So, yes, hindering myself from creating content simply because "I need to learn this myself instead of reading documentation" is pretty stupid.

Also, saying "figure it out by yourself" in Help-section of the forum is kinda... you know.

Again, back in the time when I did a lot of rom-hacking — those puzzles made a lot of sense, because there was almost no one who can answer my question. It was only way to do anything — solve puzzles. Even developers of some of the projects were lost and forgotten by the time I did touch their products. You should not solve puzzled with Rimworld. Well, you can if you want so, but it's like trying to explore The Great Pyramids and their assignment when all the builders sitting right infront of you.

Rimworld is not dead and it's not some old game from 1998. All the stuff going here can be easily structured and documented. It's right here and right now, it's alive. Why would you talk like that?
Title: Re: Custom definition
Post by: skullywag on January 19, 2017, 04:26:11 AM
<ThingDef>

should be

<Namespace.CustomClass>

then if you have a field in your class it will be available with the same name in xml. Hope that helps.
Title: Re: Custom definition
Post by: Danetta on January 19, 2017, 04:27:58 AM
Quote from: skullywag on January 19, 2017, 04:26:11 AM
<ThingDef>

should be

<Namespace.CustomClass>

then if you have a field in your class it will be available with the same name in xml. Hope that helps.
So, it will be mirrored automatically?
Title: Re: Custom definition
Post by: skullywag on January 19, 2017, 04:30:45 AM
yes so if you have:

float myFloat; in c# the def (matching the namespace.classname) will now accept an xml node of <myFloat>1f</myFloat>
Title: Re: Custom definition
Post by: Danetta on January 19, 2017, 05:22:43 AM
I am still misunderstooding something.

XML:

<ThingDef ParentName="BuildingBase">
<defName>FermentingBarrel</defName>
<label>fermenting barrel</label>
<thingClass>Rimmod.Building_FermentingBarrel</thingClass>
<defaultAlcohol>Beer</defaultAlcohol>
...
</ThingDef>


C#
namespace Rimmod
{
public class Building_FermentingBarrel : Building
    {
        string defaultAlcohol;
        ......
    }
}


Everything works except the new field and I got a console pop-up with no log.
Title: Re: Custom definition
Post by: skullywag on January 19, 2017, 05:52:14 AM
<ThingDef ParentName="BuildingBase"> should be:

<Rimmod.Building_FermentingBarrel  ParentName="BuildingBase">

and the closing tag obv. I did state this a few posts up.
Title: Re: Custom definition
Post by: Danetta on January 19, 2017, 06:01:15 AM
If it is no longer a "ThingDef", how can it be derived from "BuildingBase", which is "ThingDef"?
Apparently, my object just dissapeared after this change.
Title: Re: Custom definition
Post by: Haplo on January 19, 2017, 06:18:41 AM
You need a ThingDef variant:

namespace Rimmod
{
  public class ThingDef_FermentingBarrel: ThingDef
    {
        public string defaultAlcohol;
    }
}


Change the XML ThingDef:

Old: <ThingDef ParentName="BuildingBase">
New: <Rimmod.ThingDef_FermentingBarrel  ParentName="BuildingBase">


And then you can access it in your building by using this:

baseAlcohol = (def as ThingDef_FermentingBarrel).defaultAlcohol;


This should work if I didn't do any errors (not at my computer right now)
Title: Re: Custom definition
Post by: skullywag on January 19, 2017, 06:23:10 AM
Ah yes i missed that you had building there. Needs to be ThingDef as above. Good spot Haplo.
Title: Re: Custom definition
Post by: Danetta on January 19, 2017, 07:15:00 AM
Now it works, thanks everyone.
Title: Re: Custom definition
Post by: Danetta on January 19, 2017, 08:59:43 AM
Got another question about these custom defs.
This is part of the code I am using:
foreach (ThingDef_Alcohol alcoDef in from def in DefDatabase<ThingDef_Alcohol>.AllDefs
                                          where def.category == ThingCategory.Item
                                          select def)
            {
                if (sel.TrueForAll((IAlcoToFermentSettable x) => GenAlco.CanFermAlco(alcoDef, x)))
                {
                    yield return alcoDef;
                }
            }


I adjusted code from Growing Zones to work with barrels and it works. Filtering items by tags also works (we also only finding ThingDef_Alcohol ones), but I also need to filter them by Fermentation Zones in case of diffrent kind of barrels.

Obviously when I do "Thing thing = obj as Thing;" on "CanFermAlco(alcoDef, x)", I can't use my fields as thing.def.alcoholTag, while they are declared as:
    public class ThingDef_FermentingBarrel : ThingDef
    {
        public ThingDef defaultAlcohol;
        public string alcoholTag;
    }


I thought about something like adding derived class "Thing_FermentingBarrel : Thing" and add it's "ThingDef_FermentingBarrel" as a field, but Building_FermentingBarrel already derived from building, while building derived from thing.

So.. well, how to cast an obj so I will be able to use new fields via "thing.def.newfield"?
Currently "IAlcoToFermentSettable" interface used only by "Building_FermentingBarrel", so casting it to "Thing" is kinda pointless.

If I do something like "Building_FermentingBarrel thing = obj as Building_FermentingBarrel;", I still can't access my fields directly and I also can't do anything like "this.alcoholTag = (def as ThingDef_FermentingBarrel).alcoholTag;" in this scope. Maybe I should do that in constructor and then access it's member variable to get the value of field?

I see a lot of workarounds, but I want to do that in a right way, that is why I need help.