[Resolved] makeImmuneTo Tag & FoodPoisoning [harmony help request]

Started by jetharius, June 16, 2019, 02:19:12 AM

Previous topic - Next topic

jetharius

Does the <makeImmuneTo> tag in the HediffDef class not prevent the FoodPoisoning hediff? 

Code is below for the implant, it gives the proper tooltip in game "Prevents Infection: Food Poisoning" however, the pawn is still capable of contracting it.  Is this some symptom of the uniqueness of the food poisoning hediff or is there something I'm doing wrong?

   <HediffDef ParentName="AddedBodyPartBase">
      <defName>EvolvedStomach</defName>
      <label>evolved stomach</label>
      <labelNoun>an evolved stomach</labelNoun>
      <spawnThingOnRemoved>EvolvedStomach</spawnThingOnRemoved>
      <addedPartProps>
         <solid>true</solid>
         <partEfficiency>2.0</partEfficiency>
      </addedPartProps>
      <stages>
         <li>
                 <makeImmuneTo>
                                         <li>FoodPoisoning</li>
                                </makeImmuneTo>
            <hungerRateFactor>0.75</hungerRateFactor>
         </li>
      </stages>
   </HediffDef>

jetharius

So even with adding the Immunizable property to the FoodPoisoning HediffDef in xml, the code doesn't seem to ever evaluate it before running the hediffgiver.  I think the only way to fix this is with a assembly to add an evaluation like :
         if (pawn.health.immunity.GetImmunity(HediffDefOf.FoodPoisoning) > 0f)
         {
            return;
         }


LWM

Sounds like a very simple Harmony Prefix for FoodUtility's AddFoodPoisoningHediff!  Seriously, as far as Harmony black magic goes, this is almost as easy as it gets...

Are you familiar with C# and RimWorld?

--LWM

jetharius

I am but exclusively, I just dived into the source of the game yesterday.  I have more experience with Java than C# but they are relatively similar.  I'm going to be investigating the harmony framework as I understand that is the best way to inject C# assemblies.

As far as my experience with Rimworld, about 1000 hours played, about 200 hours tinkering with basic XML modding.

jetharius

Jeez reading the Harmony Transpiler Tutorial is a bit intimidating.  Just executing a prefix to the hediffgiver method to evaluate the Immunizable DefOf FoodPoisoning of the pawn being considered for the hediff and exiting the method if the evaluation returns anything greater than zero i think will be the direction I go.  I'm open to suggestions if there is another way.

jetharius

Heres my first attempt at the harmony patch.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using Harmony;
using RimWorld;
using Verse;

namespace EvolvedOrgans
{
    [StaticConstructorOnStartup]
    static class HarmonyPatches
    {
        static HarmonyPatches()
        {
            HarmonyInstance harmony = HarmonyInstance.Create("rimworld.evolvedorgans");

            MethodInfo targetmethod = AccessTools.Method(typeof(RimWorld.FoodUtility), "AddFoodPoisoningHediff");

            HarmonyMethod prefixmethod = new HarmonyMethod(typeof(EvolvedOrgans.HarmonyPatches).GetMethod("AddFoodPoisoningHediff_Prefix"));

            harmony.Patch(targetmethod, prefixmethod, null);
        }

        public static void AddFoodPoisoningHediff_Prefix(Pawn pawn)
        {
            if (pawn.health.immunity.GetImmunity(HediffDefOf.FoodPoisoning) > 0f)
            {
                return;
            }
        }
    }
}

Feedback appreciated.

LWM

I mean.  Does it compile?  Does it work?

It looks good, but I almost exclusively use annotations (because I usually have more than one).

Oh, wait:


        public static bool AddFoodPoisoningHediff_Prefix(Pawn pawn)
        {
            if (pawn.health.immunity.GetImmunity(HediffDefOf.FoodPoisoning) > 0f)
            {
                return false;  // do not run original if immune to food poisoning
            }
            return true;
        }


--LWM

(modified to correct tabbing :p )

jetharius

#7
Finally home and got a chance to compile and test it.  It compiled and it throws a plethora of Harmony typeload errors on startup, I did some research online and there are some archaic posts about it being a .NET framework conflict but that doesn't seem relevant as the 0Harmony.dll im using is compiled for .NET F472

Heres the log:

ReflectionTypeLoadException getting types in assembly 0Harmony: System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
  at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
  at System.Reflection.Assembly.GetTypes () [0x00000] in <filename unknown>:0
  at Verse.ModAssemblyHandler.AssemblyIsUsable (System.Reflection.Assembly asm) [0x00000] in <filename unknown>:0

Loader exceptions:
   => System.TypeLoadException: Could not load type 'Harmony.Traverse' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.CodeTranspiler+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.CodeTranspiler+<ConvertToOurInstructions>d__7' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.Patches+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonyInstance+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonyMethod+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonyMethod+<>c__DisplayClass13_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonyMethod+<>c__DisplayClass13_1' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonyMethod+<>c__DisplayClass14_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonyMethodExtensions+<>c__DisplayClass0_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonyMethodExtensions+<>c__DisplayClass2_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonyMethodExtensions+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.HarmonySharedState+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.MethodPatcher+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.PatchFunctions+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.PatchProcessor+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.AccessTools+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.AccessTools+<>c__DisplayClass21_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.AccessTools+<>c__DisplayClass22_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.AccessTools+<>c__DisplayClass23_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.AccessTools+<>c__DisplayClass24_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.AccessTools+<>c__DisplayClass36_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.GeneralExtensions+<>c__DisplayClass0_0`1[T]' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.GeneralExtensions+<>c__0`1[T]' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.GeneralExtensions+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.PatchTools+<>c__2`1[T]' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.Tools.SelfPatching+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.ILCopying.Emitter+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type 'Harmony.ILCopying.MethodBodyReader+<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type '<>c' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type '<>c__DisplayClass36_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type '<>c__DisplayClass37_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type '<>c__DisplayClass38_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type '<>c__DisplayClass39_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type '<>c__DisplayClass40_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
   => System.TypeLoadException: Could not load type '<>c__DisplayClass41_0' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.

Verse.Log:Error(String, Boolean)
Verse.ModAssemblyHandler:AssemblyIsUsable(Assembly)
Verse.ModAssemblyHandler:ReloadAll()
Verse.ModContentPack:ReloadContent()
Verse.LoadedModManager:LoadModContent()
Verse.LoadedModManager:LoadAllActiveMods()
Verse.PlayDataLoader:DoPlayLoad()
Verse.PlayDataLoader:LoadAllPlayData(Boolean)
Verse.Root:<Start>m__1()
Verse.LongEventHandler:RunEventFromAnotherThread(Action)
Verse.LongEventHandler:<UpdateCurrentAsynchronousEvent>m__1()


Which leads me to believe its something borked in my namespace.

jetharius

Resolved, it turns out the .net framework has to be set to 3.5 and you will have to reload your harmony package for it to compile properly.

LWM

Hehe, that's a super helpful log isn't it.   ::)

Good job figuring it out - RW is 3.5 framework, and that is just another detail you have to catch ><

Congrats on the stomach!

--LWM