[Solved] Changing designationCategory of ThingDef

Started by 1000101, April 19, 2015, 09:39:43 PM

Previous topic - Next topic

1000101

After directing Famous Shoes to look into DefDatabase.AddAllInMods(), I thought I would take a look at it to see if I could resolve the issue I was having here with this problem.  Well, I found the solution.

It's a mere three lines of code and you can change what designationCategory a ThingDef uses.  In my case, I shall be using it to unlock buildings and tables based on more than one research tech.

Code to do this (so simple, really) provided in a nice neat function:public static void ChangeThingDefDesignationCategoryDefOfTo( ThingDef t, string d )
{
// Set the designation category on the thing
t.designationCategory = d;
t.menuHidden = ( d == "None" );

// Resolve all designation category defs
DefDatabase< DesignationCategoryDef >.ResolveAllReferences();
}


That's it.  Hope some other intrepid modders can make use of this tid-bit.




OP:

So, akin to the unlockable recipes by multiple research, I am attempting to be able to unlock buildings by multiple research.

The code is basically the same as the recipe code with the exception that instead of messing with a buildings recipes, the code is messing with its designationCategory.  Everything works in that respect except the build doesn't return to it's category after research.  The building is removed properly at first but not returned after research.

Now, one might ask if I am storing the old designations, well, of course I am otherwise I wouldn't know where to return it to.  The code is the same each way.

Remove:// Designator unlock on buildings
if( Advanced.originalBuildingDesignations == null )
Advanced.originalBuildingDesignations = new List< buildingDesignationPair >();

// Store the building designator
DesignationCategoryDef bDesignation = DefDatabase< DesignationCategoryDef >.GetNamed( building.designationCategory );
if( bDesignation == null ){
Log.Message( "Advanced Research :: buildingDefName( " + buildingDefName +" ).designationCategory( " + building.designationCategory + " ) resolved to null in AdvancedResearchDef( " + Advanced.defName + " )" );
return;
}
Advanced.originalBuildingDesignations.Add( new buildingDesignationPair( buildingDefName, building.designationCategory ) );

// Hide the building
building.designationCategory = "None";

// Rebuild the references
bDesignation.ResolveReferences();
Log.Message( "Advanced Research :: ThingDef( " + buildingDefName + " ).designationCategory = '" + building.designationCategory + "'" );


Re-addition:// Designator unlock on buildings
foreach( buildingDesignationPair bdPair in Advanced.originalBuildingDesignations ){
ThingDef building = DefDatabase< ThingDef >.GetNamed( bdPair.building );

// Set the designation category
building.designationCategory = bdPair.designationCategory;

// Rebuild the references
DesignationCategoryDef bDesignation = DefDatabase< DesignationCategoryDef >.GetNamed( bdPair.designationCategory );
bDesignation.ResolveReferences();

Log.Message( "Advanced Research :: ThingDef( " + building.defName + " ).designationCategory = '" + building.designationCategory + "'" );
}


The code reports the removal and re-addition of the building from the designation category but only the removal works.

Stumped here.  ���


Edit:

Trying to ResolveReferences() on the build too yields no results (which is to be expected since all derived methods are null functions).


Edit:

After spending days on end trying to figure this out, I am just going to have to pass this up for now.  The DesignationManager was a dead end, I can't decompile (and disassembly would be fugly) the main game executable so see how it's resolving research with table designators.

After exhaustive testing and huge log dumps describing all fields and members of the classes involved, it all points to one thing - The list of cached designators in a DesignatonCategoryDef is being updated and the list is valid.  I've looked at every decompilable reference to DesignationCategoryDef but nothing leads me to a usable result.

DesignationCategoryDef.ResolveReferences() properly rebuilds the list of Designators, the game just ignores it and continues not showing the menu option.

I am leaving this problem unresolved and thus not a possible feature in my mod.  I will just move on to something else unless someone can provide insights.
(2*b)||!(2*b) - That is the question.
There are 10 kinds of people in this world - those that understand binary and those that don't.

Powered By

Tynan

I believe the DesignatorManager caches all its designator listings when the mods are loaded. That's where DesignationCategory gets used, IIRC.

You could decompile the DesignatorManager to see what it's doing.
Tynan Sylvester - @TynanSylvester - Tynan's Blog

1000101

Wow, I wasn't actually expecting a reply from you.  I'll look into that and thanks for the pointer.  :)
(2*b)||!(2*b) - That is the question.
There are 10 kinds of people in this world - those that understand binary and those that don't.

Powered By

OpalMonkey

Hi E,

Thought I'd leave my two cents on your unresolved issue, in case it helps at all. Plus I guess I need to make my first post on these forums at some point  :D

I'm in the process of making my own RimWorld mod and found this thread when searching for info on how to do similar things. Now, the way I ended up getting this to work isn't actually the same thing, so depending on how you want things to work this may or may not work. I did make my own attempts to get your method working, to no avail.

Rather than removing buildings from the menu by changing the designationCategory I decided to try using research to hide/unhide them. By changing the researchPrerequisite you can get a similar result. They'll all still show up when in God Mode, but that shouldn't really be a serious problem.

I also noticed research projects can basically be locked permanently by setting themselves as a prerequisite. So I created a permalocked research that never even shows up in game, like so:

<ResearchProjectDef>
<defName>Permalocked</defName>
<label>permalocked</label>
<totalCost>99999</totalCost>
<prerequisites>
<li>Permalocked</li>
</prerequisites>
</ResearchProjectDef>


And wrote an extension method for ThingDef that acts on one ThingDef (the one to remove) and takes another ThingDef (the one to add):

public static class Extensions
{
public static string lockedResearch = "Permalocked";
public static void ReplaceInMenu(this ThingDef pOld, ThingDef pNew, ResearchProjectDef pResearchToHideWith = null)
{
pOld.researchPrerequisite = (pResearchToHideWith == null ? ResearchProjectDef.Named(lockedResearch) : pResearchToHideWith);
pNew.researchPrerequisite = (ResearchProjectDef)null;
}
}


A call to it would look like so:
ThingDef.Named("ThingToLock").ReplaceInMenu(ThingDef.Named("ThingToUnlock"));

Now this is just a stripped down version of what I'm using, to illustrate what I'm doing. Since I'm swapping one item for another when completing research, this works nicely. But of course could be changed to work for other situations.

Hope this helps in some way! I know it's not quite what you were after, but does mimic the result for the most part. And if I've done anything horribly wrong or undesirable, please let me know. This mod is my first time using C# and most of my coding experience before this point has been with scripting languages.


PS: Loving the game, Tynan! This is the first game that's truly inspired me to make a full-fledged mod, learning C# in the process. I look forward to seeing what RimWorld will become over time.

Tynan

If you're just learning C# I'd say you're off to a great start :)
Tynan Sylvester - @TynanSylvester - Tynan's Blog

1000101

#5
Actually, I resolved this quite a while ago but it's interesting to see how you did it.  There's many ways to skin a cat.

I had heard that research couldn't prereq itself although I never tested it.  If that actually works, then it opens a few doors.
(2*b)||!(2*b) - That is the question.
There are 10 kinds of people in this world - those that understand binary and those that don't.

Powered By

OpalMonkey

@E:
Ah, I was wondering if that might have been the case. Glad you still found this interesting. Many ways indeed. If you don't mind my asking, how did you go about getting it working?

And yes, from my tests so far having research require itself as a prerequisite seems to work. I honestly hadn't expected it to but tried on a whim anyways. That said, nothing in my mod is tested under actual gameplay conditions yet. I've just been using dev mode to test everything quickly. So there could be some issue I haven't noticed yet.

@Tynan:
Thanks! It's been an interesting three weeks making this mod and hope to release it before too long. Just need to finish adding some content, but I think the technical issues are pretty much done with. Then I can finally get back to actually playing RimWorld rather than just launching it 50 times a day to test things. Haven't even played Alpha 10 properly yet  :o

1000101

Quote from: OpalMonkeyIf you don't mind my asking, how did you go about getting it working?

Everything to do it is in the first code block of the first post.

Quote from: OpalMonkeyHaven't even played Alpha 10 properly yet  :o

haha, I know that feeling.  XD
(2*b)||!(2*b) - That is the question.
There are 10 kinds of people in this world - those that understand binary and those that don't.

Powered By

OpalMonkey

Quote from: 1000101 on May 21, 2015, 01:32:00 PM
Quote from: OpalMonkeyIf you don't mind my asking, how did you go about getting it working?

Everything to do it is in the first code block of the first post.

Heh... I uhh, misunderstood the structure of the first post. Derp.

Are you referring to the ChangeThingDefDesignationCategoryDefOfTo method? I had to try it again to be sure, but that isn't working for me. Maybe it's conflicting with something else in my mod, but it actually causes some weird issues. No errors, but it messes with the menu hotkeys and some other things. Maybe that's why I misunderstood the post.

Just tried it out in a fresh project with no new ThingDefs, just a single extra research and a copy of the sandbags def that removes the designationCategory.

class ResearchModsSpecial
{
public static void ChangeThingDefDesignationCategoryDefOfTo(ThingDef t, string d)
{
// Set the designation category on the thing
t.designationCategory = d;
t.menuHidden = (d == "None");
// Resolve all designation category defs
DefDatabase<DesignationCategoryDef>.ResolveAllReferences();
}

public static void Test()
{
ChangeThingDefDesignationCategoryDefOfTo(ThingDef.Named("TurretGun"), "None");
ChangeThingDefDesignationCategoryDefOfTo(ThingDef.Named("Sandbags"), "Security");
}
}


When I finish the research the turret is gone and the sandbags are back, as the are supposed to be. Problem is, the normal and EMP mortars also disappear from the menu (leaving the incendiary mortar) and all the hotkeys (except for things like deconstruct and cancel) are removed. No errors.

Guess getting this result is what confused me about your original post and drove me to the conclusion that this was never resolved. Sorry for the misunderstanding.

Since I've got it working another way I'll just leave it be. Maybe it's just something I'm not understanding properly.

1000101

I haven't encountered that but, I haven't tested it exaustively either.  The situation which I am using it - hiding production tables and furntiture until multiple research techs are completed - it works.  I have setup motars in my personal mod to hide behind multiple techs but I haven't actually tested them specifically.  Also, my test cases are usually with only the core and EdB mods enabled plus my own mod.  There may be some other mod interaction so, please consult your doctor before trying MyPotentiallyFaultyCode (tm).  :P
(2*b)||!(2*b) - That is the question.
There are 10 kinds of people in this world - those that understand binary and those that don't.

Powered By