Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - BukTaki

#16
Help / Re: Help with Harmony
December 16, 2018, 07:35:18 PM
THANK YOU!!!! that was the missing link just ran it now it works perfect added logic for equipping the shield from the inventory.


using System;
using Verse;
using RimWorld;
using Harmony;

namespace Shield
{
    [StaticConstructorOnStartup]
    class Harmonypatches
    {
        private static readonly Type shieldPatchType = typeof(Harmonypatches);
       
        static Harmonypatches()
        {
            HarmonyInstance h = HarmonyInstance.Create("ShieldHarmony");

            h.Patch(AccessTools.Method(typeof(Pawn_EquipmentTracker), nameof(Pawn_EquipmentTracker.AddEquipment)),
            postfix: new HarmonyMethod(shieldPatchType, nameof(ShieldPatchAddEquipment)));

            h.Patch(AccessTools.Method(typeof(Pawn_ApparelTracker), nameof(Pawn_ApparelTracker.Wear)),
           postfix: new HarmonyMethod(shieldPatchType, nameof(ShieldPatchWearApparel)));           
        }

        public static void ShieldPatchAddEquipment(Pawn_EquipmentTracker __instance, ThingWithComps newEq)
        {
            Pawn owner = __instance.pawn;         

            // must have picked up a weapon
            if (PawnHasShieldEquiped(owner) || PawnHasShieldInInvnetory(owner))
            {
                if (newEq.def.IsWeapon)
                {
                    if (PawnHasValidEquiped(owner) && PawnHasShieldInInvnetory(owner))
                    {
                        for (int i = 0; i < owner.inventory.innerContainer.Count; i++)
                        {
                            foreach (ThingCategoryDef tgd in owner.inventory.innerContainer[i].def.thingCategories)
                            {
                                if (tgd.defName == "Shield")
                                {
                                    Thing whocares;
                                    __instance.pawn.inventory.innerContainer.TryDrop(owner.inventory.innerContainer[i], ThingPlaceMode.Direct, out whocares, null, null);
                                    owner.apparel.Wear(whocares as Apparel);
                                }
                            }
                        }
                    }
                    else
                    {
                        if (PawnHasShieldEquiped(owner) && !PawnHasValidEquiped(owner))
                        {
                            Apparel shield = null;
                            // do we have a shield equipped

                            for(int i = 0; i < owner.inventory.innerContainer.Count; i++)
                            {
                                foreach (ThingCategoryDef tgd in owner.inventory.innerContainer[i].def.thingCategories)
                                {
                                    if (tgd.defName == "Shield")
                                    {
                                        Thing whocares;
                                        __instance.pawn.inventory.innerContainer.TryDrop(owner.inventory.innerContainer[i], ThingPlaceMode.Direct, out whocares, null, null);
                                    }
                                }
                            }

                            for (int i = 0; i < owner.apparel.WornApparelCount; i++)
                            {
                                foreach (ThingCategoryDef tgd in owner.apparel.WornApparel[i].def.thingCategories)
                                {
                                    if (tgd.defName == "Shield")
                                    {
                                        shield = owner.apparel.WornApparel[i];
                                    }
                                }
                            }
                           
                            // we have a shield equipped
                            if (shield != null)
                            {
                                owner.apparel.Remove(shield);
                                owner.inventory.innerContainer.TryAddOrTransfer(shield, false);
                            }
                        }

                    }
                }
            }
        }

        public static void ShieldPatchWearApparel(Pawn_EquipmentTracker __instance, Apparel newApparel)
        {
            bool shield = false;

            foreach (ThingCategoryDef tgd in newApparel.def.thingCategories)
            {
                // we have a shield in the inventory
                if (tgd.defName == "Shield")
                {
                    shield = true;
                }
            }

            if (!shield)
            {
                return;
            }

            Pawn owner = __instance.pawn;

            // must have picked up a weapon
            if (PawnHasShieldInInvnetory(owner))
            {                         
                // do we have a shield equipped
               
                for (int i = 0; i < owner.inventory.innerContainer.Count; i++)
                {
                    foreach (ThingCategoryDef tgd in owner.inventory.innerContainer[i].def.thingCategories)
                    {
                        if (tgd.defName == "Shield")
                        {
                            Thing whocares;
                            __instance.pawn.inventory.innerContainer.TryDrop(owner.inventory.innerContainer[i], ThingPlaceMode.Direct, out whocares, null, null);
                        }
                    }
                }
                Apparel wornshield = null;

                for (int i = 0; i < owner.apparel.WornApparelCount; i++)
                {
                    foreach (ThingCategoryDef tgd in owner.apparel.WornApparel[i].def.thingCategories)
                    {
                        if (tgd.defName == "Shield")
                        {
                            wornshield = owner.apparel.WornApparel[i];
                        }
                    }
                }

                // we have a shield equipped
                if (wornshield != null)
                {
                    owner.apparel.Remove(wornshield);
                    owner.inventory.innerContainer.TryAddOrTransfer(wornshield, false);
                }
            }
            else
            {
                if (!PawnHasValidEquiped(owner))
                {
                    Apparel wornshield = null;

                    for (int i = 0; i < owner.apparel.WornApparelCount; i++)
                    {
                        foreach (ThingCategoryDef tgd in owner.apparel.WornApparel[i].def.thingCategories)
                        {
                            if (tgd.defName == "Shield")
                            {
                                wornshield = owner.apparel.WornApparel[i];
                            }
                        }
                    }

                    // we have a shield equipped
                    if (wornshield != null)
                    {
                        owner.apparel.Remove(wornshield);
                        owner.inventory.innerContainer.TryAddOrTransfer(wornshield, false);
                    }
                }
            }
        }

       // check if a pawn has a shield equipped
        public static bool PawnHasShieldEquiped(Pawn pawn)
        {
            bool revalue = false;

            Apparel shield = null;
            // do we have a shield equipped
            foreach (Apparel a in pawn.apparel.WornApparel)
            {
                foreach (ThingCategoryDef tgd in a.def.thingCategories)
                {
                    if (tgd.defName == "Shield")
                    {
                        shield = a;
                    }
                }
            }
            // we have a shield equipped
            if (shield != null)
            {
                revalue = true;
            }

            return revalue;
        }

        // check if a pawn has a shield in inventory
        public static bool PawnHasShieldInInvnetory(Pawn pawn)
        {
            bool revalue = false;

            foreach (Thing a in pawn.inventory.innerContainer)
            {
                foreach (ThingCategoryDef tgd in a.def.thingCategories)
                {
                    // we have a shield in the inventory
                    if (tgd.defName == "Shield")
                    {
                        revalue = true;
                    }
                }
            }
            return revalue;
        }

        // check if the pawn picked up a shield
        public static bool PawnPickedUpAShield(ThingWithComps newEquipment)
        {
            bool reValue = false;

            foreach (ThingCategoryDef tgd in newEquipment.def.thingCategories)
            {
                if (tgd.defName == "Shield")
                {
                    reValue = true;
                }
            }
            return reValue;
        }
       
        // check if equiped weapon can be used with shield
        public static bool PawnHasValidEquiped(Pawn pawn)
        {                       
            if (pawn.equipment.Primary.def.IsMeleeWeapon)
            {
                // add logic for the two handed weaopns
                return true;
            }
            if (pawn.equipment.Primary.def.defName.Equals("Gun_Pistol"))
            {
                return true;
            }
            if (pawn.equipment.Primary.def.defName.Equals("Gun_PDW"))
            {
                return true;
            }
            if (pawn.equipment.Primary.def.defName.Equals("Gun_HeavySMG"))
            {
                return true;
            }           
            if (pawn.equipment.Primary.def.defName.Equals("Pila"))
            {
                return true;
            }
            if (pawn.equipment.Primary.def.weaponTags.Contains("MedievalShields_ValidSidearm"))
            {
                return true;
            }

            return false;
        }
               
    }
}



That error was causing all the problems that was making me think about trying jobs.

Once again thank you so much. Now all i have to do clean up the shield class.
#17
Help / Re: Help with Harmony
December 15, 2018, 07:42:50 PM
Ho to properly drop an item from the inventory

So i abandoned the Job Idea when i realized the problem i was having with script was that I needed to patch to Pawn_ApparelTracker.Wear because the shield is apparel. along with the Pawn_EquipmentTracker.AddEquipmet.

now the problem i am having is i need to drop the shield from Inventory properly.



foreach (Thing a in owner.inventory.innerContainer)
                    {
                        foreach (ThingCategoryDef tgd in a.def.thingCategories)
                        {
                            // we have a shield in the inventory
                            if (tgd.defName == "Shield")
                            {
                                // drop the shield in inventory transfer the one we just picked up.
                                Thing whocares;
                                owner.inventory.innerContainer.TryDrop(a, ThingPlaceMode.Direct, out whocares, null, null);
                            }
                        }
                    }
                    owner.inventory.innerContainer.TryAddOrTransfer(newApparel as Thing);



This line works fine when picking up a shield with a ranged weapon equipped it slides the shield to the inventory. but if there is already one in the inventory get an error.


JobDriver threw exception in initAction for pawn Satrasen driver=JobDriver_Wear (toilIndex=2) driver.job=(Wear (Job_66637) A=Thing_AncientWooden_ShieldLarge81348) lastJobGiver=Verse.AI.ThinkNode_QueuedJob
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.Generic.List`1/Enumerator<Verse.Thing>.VerifyState () <0x00128>
at System.Collections.Generic.List`1/Enumerator<Verse.Thing>.MoveNext () <0x0003f>
at Shield.Harmonypatches.patchAddApparrel (RimWorld.Pawn_ApparelTracker,RimWorld.Apparel) <0x00347>
at (wrapper dynamic-method) RimWorld.Pawn_ApparelTracker.Wear_Patch1 (object,RimWorld.Apparel,bool) <0x0052e>
at RimWorld.JobDriver_Wear/<MakeNewToils>c__Iterator0.<>m__1 () <0x00053>
at Verse.AI.JobDriver.TryActuallyStartNextToil () <0x0071f>

Verse.Log:Error(String, Boolean)
Verse.AI.JobUtility:TryStartErrorRecoverJob(Pawn, String, Exception, JobDriver)
Verse.AI.JobDriver:TryActuallyStartNextToil()
Verse.AI.JobDriver:ReadyForNextToil()
Verse.AI.JobDriver:DriverTick()
Verse.AI.Pawn_JobTracker:JobTrackerTick()
Verse.Pawn:Tick()
Verse.TickList:Tick()
Verse.TickManager:DoSingleTick()
Verse.TickManager:TickManagerUpdate()
Verse.Game:UpdatePlay()
Verse.Root_Play:Update()


I'm thinking I cant call both those functions in the same function what i tried to do was patch ThingOwner.AddOrTransfer() but i got an error so i dont think i can patch that.
#18
Help / Re: Help with Harmony
December 13, 2018, 09:50:17 AM
Good stuff

When i complete the Job definition I'll post it.
#19
Help / Re: Help with Harmony
December 10, 2018, 09:37:18 PM
Thank you again I know have two problems the first is I have a Function that works fine for the most part problem is i can't get it called at the right time.



public static void JobEquip_Start(Pawn_EquipmentTracker __instance, ThingWithComps newEq)
        {
            Pawn owner = __instance.pawn;
                                 
            if (PawnPickedUpAShield(newEq))
            {
                // picked up a shield
                if (PawnHasShieldEquiped(owner) || PawnHasShieldInInvnetory(owner))
                {
                    // has a shield already
                    if (PawnHasShieldEquiped(owner))
                    {
                        // rimworlds apparel system takes care of this we just exit
                        // return;
                    }
                    if (PawnHasShieldInInvnetory(owner))
                    {
                        foreach (Thing a in owner.inventory.innerContainer)
                        {
                            foreach (ThingCategoryDef tgd in a.def.thingCategories)
                            {
                                // we have a shield in the inventory
                                if (tgd.defName == "Shield")
                                {
                                    // drop the shield in inventory transfer the one we just picked up.
                                    owner.inventory.innerContainer.TryDrop(a,ThingPlaceMode.Direct,out Thing thing, null,null);
                                    owner.inventory.innerContainer.TryAddOrTransfer(newEq as Thing);
                                }
                            }
                        }
                    }
                }
            }
           
            // must have picked up a weapon
            if (PawnHasShieldEquiped(owner) || PawnHasShieldInInvnetory(owner))
            {
                if (newEq.def.IsWeapon)
                {
                    if(newEq.def.IsMeleeWeapon && PawnHasShieldInInvnetory(owner))
                    {
                        foreach (Thing a in owner.inventory.innerContainer)
                        {
                            foreach (ThingCategoryDef tgd in a.def.thingCategories)
                            {
                                if (tgd.defName == "Shield")
                                {
                                    // owner.apparel.Wear(owner.inventory.innerContainer. as Apparel, true);
                                    owner.inventory.innerContainer.TryDrop(a, ThingPlaceMode.Direct, out Thing thing, null, null);

                                }
                            }
                        }
                    }
                    else
                    {
                        if (PawnHasShieldEquiped(owner) && !newEq.def.IsMeleeWeapon)
                        {
                            Apparel shield = null;
                            // do we have a shield equipped
                            foreach (Apparel a in owner.apparel.WornApparel)
                            {
                                foreach (ThingCategoryDef tgd in a.def.thingCategories)
                                {
                                    if (tgd.defName == "Shield")
                                    {
                                        shield = a;
                                    }
                                }
                            }
                            // we have a shield equipped
                            if (shield != null)
                            {
                                owner.inventory.innerContainer.TryAddOrTransfer(shield, false);
                            }
                        }
                    }
                }
            }
        }       



There are a couple of Helper functions that work fine. I tired calling it



    h.Patch(AccessTools.Method(typeof(Pawn_EquipmentTracker), nameof(Pawn_EquipmentTracker.AddEquipment)),
            postfix: new HarmonyMethod(shieldPatchType, nameof(JobEquip_Start)));



lol I just got done trying to do a Parallel co-routine with no dice. l

But i actually want to call JobEquip_Start after Jobdrive_equip has finished and i am not sure how to do it. i was thinking of Queuing a Job after equip, or maybe Injecting a toil at the end of the driver. I can't Figure out what always gets called at the end of the Job that's why i tried the lambda earlier.

Im stuck in the mud.

 
#20
Help / Re: Help with Harmony
December 08, 2018, 11:41:37 AM
The ultimate goal simplest way to coordinate the equipping of a shield based on what weapons a pawn equips or picks up. that way its compatible with mods like simple side arms and can also be ran by its self too.


if pawn picks up shield
    then check if there is already a shield in inventory if there is swap it.


Since its apparel rimworld will handle if one is equipped


if a pawn has a shield either equipped or inventory
    and if the pawn picks up a weapon

    Check if its melee
            if it is and the shield is not worn we move the shield from the inventory to the worn apparel

     if its not melee
            we check if there is a shield worn and move it to the inventory.



when the shield is in the inventory it does not provide the bonus. I originally had the logic in the Shield.apparel class. It works getting the shield to the inventory but once the shield is in the inventory you cant get it out from the shield.apparel class so i had been looking at the source for both Simple Side arms and Survival tools that's when i came across harmony.

#21
Help / Re: Help with Harmony thank you
December 07, 2018, 10:51:00 PM
Ok i have been trying different implementations now i need advice here is what i tried. First


static Harmonypatches()
        {
            HarmonyInstance h = HarmonyInstance.Create("ShieldHarmony");

            h.Patch(AccessTools.Method(typeof(Pawn_EquipmentTracker), nameof(Pawn_EquipmentTracker.AddEquipment)),
                postfix: new HarmonyMethod(shieldPatchType, nameof(JobEquip_Start)));
          }


with a function



public static void JobEquip_Start(Pawn_EquipmentTracker __instance, ThingWithComps newEq)
        {
            Pawn owner = __instance.pawn;
            if (newEq.def.IsWeapon)
            {
                // check we already have a shield

                // pick best shield

                // equip best shield

                // drop other

                if (!newEq.def.IsMeleeWeapon || !owner.equipment.Primary.def.IsMeleeWeapon)
                {
                    Apparel shield = null;

                    foreach (Apparel a in owner.apparel.WornApparel)
                    {
                        foreach (ThingCategoryDef tgd in a.def.thingCategories)
                        {
                            if (tgd.defName == "Shield")
                            {
                                shield = a;
                            }
                        }
                    }
                    // we have a shield equipped we drop it
                    if (shield != null)
                    {
                        owner.apparel.TryDrop(shield);
                        shield.SetForbidden(false);
                    }
                }
                else
                {
                    // check we already have a shield

                    // pick best shield

                    // equip best shield

                    // drop other



                    /* foreach (Thing a in owner.inventory.innerContainer)
                     {
                         foreach (ThingCategoryDef tgd in a.def.thingCategories)
                         {
                             if (tgd.defName == "Shield")
                             {
                                 owner.inventory.innerContainer.Remove(a);
                             }
                         }
                     }*/
                    // We are good to equip a Shield
                    // if we have a shield equiped we have to move it the inventory

                }
            }
            else
            {
                if (newEq.def.weaponTags.Contains("Shield"))
                {
                    // check we already have a shield

                    // pick best shield

                    // equip best shield

                    // drop other
                    throw new Exception("We picked up a shield");

                    if (!owner.equipment.Primary.def.IsMeleeWeapon)
                    {
                        owner.inventory.innerContainer.TryAddOrTransfer(newEq as Thing, false);
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }
        }       



There is only one problem if the pawn picks up a shield there is no way to check because the AddEquipment method must instance the the JobDriver_Equip function;

So i tried a Lambda with the job driver


static Harmonypatches()
        {
            HarmonyInstance h = HarmonyInstance.Create("ShieldHarmony");

            h.Patch(AccessTools.Method(typeof(JobDriver_Equip), nameof(JobDriver_Equip.Notify_Starting)),
                prefix: new HarmonyMethod(shieldPatchType, nameof(JobDriverEquip_Start)));
        }


i tried post fix too with



public static void JobDriverEquip_Start(JobDriver_Equip __instance)
        {
            if(__instance == null)
            {
                return;
            }
            if (__instance.job.targetA.HasThing)
            {
                if(__instance.job.targetA.Thing.def.IsWeapon || __instance.job.targetA.Thing.def.weaponTags.Contains("Shield"))
                {
                    Action action = () =>
                    {
                        Pawn owner = __instance.pawn;

                        if (!owner.equipment.Primary.def.IsMeleeWeapon)
                        {
                            Apparel shield = null;

                            foreach (Apparel a in owner.apparel.WornApparel)
                            {
                                foreach (ThingCategoryDef tgd in a.def.thingCategories)
                                {
                                    if (tgd.defName == "Shield")
                                    {
                                        shield = a;
                                    }
                                }
                            }
                            // we have a shield equipped we drop it
                            if (shield != null)
                            {
                                owner.inventory.innerContainer.TryAddOrTransfer(shield as Thing, false);
                                // owner.apparel.TryDrop(shield);
                                // shield.SetForbidden(false);
                            }
                        }
                        else
                        {
                            {

                                foreach (Thing tgd in owner.inventory.innerContainer)
                                {
                                    if (tgd.def.weaponTags.Contains("Shield"))
                                    {
                                        ThingWithComps twc = tgd as ThingWithComps;
                                        owner.equipment.AddEquipment(twc);
                                        // owner.inventory.innerContainer.Remove(tgd);
                                    }
                                }
                            }
                        }
                    };
                    __instance.AddFinishAction(action);
                }
                else
                {
                    return;
                }
            }
            else
            {
                return;
            }           
        }



the problem was ever time went to get anything there was an error
so the new idea i wanna try is to create a shield toil or job.
but i dont understand what a toil is i looked at Declaration but i dont get it.

The question is about toils. if a pawn is on the other side of a wall and i left click a piece on another side and force wear when will the JobDriver_Equip be declared? Is the movement to the object considered a new toil or is that a different job.
currently i am reading

https://github.com/roxxploxx/RimWorldModGuide/wiki/SHORTTUTORIAL:-How-Pawns-Think

as soon as i figure this it out i think i'll be fine.
thank you, thank you

i honestly cant say that enough Mehni thank you for your help. Your awesome.
#22
Help / Re: Help with Harmony
December 07, 2018, 11:30:29 AM
LOL i forgot to put the 0Harmony.dll in the assemblies folder. thank you so much.
#23
Help / Re: Help with Harmony
December 06, 2018, 10:03:07 PM
So i got it to Drop currently shield and Melee weapon but after cleaning the class i now have wicked error

Could not execute post-long-event action. Exception: System.TypeInitializationException: An exception was thrown by the type initializer for Shield.ShieldHarmony ---> System.TypeLoadException: Could not load type 'Harmony.HarmonyInstance' from assembly '0Harmony, Version=1.2.0.1, Culture=neutral, PublicKeyToken=null'.
  --- End of inner exception stack trace ---
  at (wrapper managed-to-native) System.Runtime.CompilerServices.RuntimeHelpers:RunClassConstructor (intptr)
  at System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (RuntimeTypeHandle type) [0x00000] in <filename unknown>:0
  at Verse.StaticConstructorOnStartupUtility.CallAll () [0x00000] in <filename unknown>:0
  at Verse.PlayDataLoader.<DoPlayLoad>m__2 () [0x00000] in <filename unknown>:0
  at Verse.LongEventHandler.ExecuteToExecuteWhenFinished () [0x00000] in <filename unknown>:0
Verse.Log:Error(String, Boolean)
Verse.LongEventHandler:ExecuteToExecuteWhenFinished()
Verse.LongEventHandler:UpdateCurrentAsynchronousEvent()
Verse.LongEventHandler:LongEventsUpdate(Boolean&)
Verse.Root:Update()
Verse.Root_Entry:Update()



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

namespace Shield
{
    [StaticConstructorOnStartup]
    class ShieldHarmony
    {
        private static readonly Type shieldPatchType = typeof(ShieldHarmony);

        static ShieldHarmony()
        {
            HarmonyInstance h = HarmonyInstance.Create("ShieldHarmony");

            h.Patch(AccessTools.Method(typeof(Pawn_EquipmentTracker), nameof(Pawn_EquipmentTracker.AddEquipment)),
            new HarmonyMethod(shieldPatchType, nameof(JobEquip_Start)));

        }

        public static void JobEquip_Start(Pawn_EquipmentTracker __instance, ThingWithComps newEq)
        {
            Pawn owner = __instance.pawn;

            if (!newEq.def.IsMeleeWeapon || !owner.equipment.Primary.def.IsMeleeWeapon)
            {
                Apparel shield = null;

                foreach (Apparel a in owner.apparel.WornApparel)
                {
                    foreach (ThingCategoryDef tgd in a.def.thingCategories)
                    {
                        if (tgd.defName == "Shield")
                        {
                            shield = a;
                        }
                    }
                } 
                // we have a shield equipped we drop it
                if (shield != null)
                {
                    owner.apparel.TryDrop(shield);
                    shield.SetForbidden(false);
                }
            }
            else
            {
               
               /* foreach (Thing a in owner.inventory.innerContainer)
                {
                    foreach (ThingCategoryDef tgd in a.def.thingCategories)
                    {
                        if (tgd.defName == "Shield")
                        {
                            owner.inventory.innerContainer.Remove(a);
                        }
                    }
                }*/
                // We are good to equip a Shield
                // if we have a shield equiped we have to move it the inventory

            }
        }       
    }   
}



It compiles fine but when i add the .dll  i get error when i activate the mod.

#24
Help / Re: Help with Harmony
December 06, 2018, 02:26:21 PM
and again your awesome thank you i'll let you know how it goes.
#25
Help / Re: Help with Harmony
December 06, 2018, 12:05:14 PM
and your awesome thank you the errors are gone but there is no measurable result. I think i am implementing it wrong i think the get for primaryEq rarely gets called i tried adding the patch to the Jobdriver_Equip


            h.Patch(AccessTools.Property(typeof(JobDriver_Equip), nameof(JobDriver_Equip.OnLastToil)).GetGetMethod(),
            new HarmonyMethod(shieldPatchType, nameof(JobEquip_Start)));


but i don't think it gets called a lot either cause when the pawn picks up a shield or weapon the shield is never moved to or from inventory.

Any Idea were the best place to Patch would be?

What i want to have happen is every time a pawn equips a weapon the jobequip_function is called. 
#26
Help / Help with Harmony
December 05, 2018, 08:12:20 PM
I am trying to get harmony to with my shield script and its pretty mind Bending. I keep getting errors with and i Dont think i am using the tool right.


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

namespace Shield
{
    [StaticConstructorOnStartup]
    class ShieldHarmony
    {
        private static readonly Type shieldPatchType = typeof(ShieldHarmony);

        static ShieldHarmony()
        {
            HarmonyInstance h = HarmonyInstance.Create("ShieldHarmony");

            h.Patch(AccessTools.Property(typeof(Pawn_InventoryTracker), nameof(Pawn_EquipmentTracker.PrimaryEq)).GetGetMethod(),
                new HarmonyMethod(shieldPatchType, nameof(JobEquip_Start)));         
        }

        public static void JobEquip_Start(Pawn_EquipmentTracker _instance, ref CompEquippable _referance)
        {
            if (_referance != null)
            {
                Pawn owner = _instance.pawn;
                bool canepuipshield = false;
                bool hasShieldEquiped = false;
                bool hasShieldinInventory = false;
                Def defShieldequiped = null;
                Def defshieldininventory = null;
                Apparel e = null;
                Apparel i = null;
                foreach (Apparel a in owner.apparel.WornApparel)
                {
                    if (a.def.apparel.tags.Contains("shield"))
                    {
                        hasShieldEquiped = true;
                        defShieldequiped = a.def;
                        e = a;

                    }
                }

                foreach (Thing t in owner.inventory.innerContainer)
                {
                    Apparel a = t as Apparel;
                    if (a.def.apparel.tags.Contains("shield"))
                    {
                        hasShieldinInventory = true;
                        defshieldininventory = a.def;
                        i = a;

                    }
                }

                if (!hasShieldEquiped && !hasShieldinInventory)
                {
                    return;
                }

                if (owner.equipment.Primary != null && hasShieldinInventory && !hasShieldEquiped)
                {
                    if (owner.equipment.Primary.def.IsMeleeWeapon)
                    {
                        canepuipshield = true;
                    }
                    if (owner.equipment.Primary.def.defName.Equals("Gun_Pistol"))
                    {
                        canepuipshield = true;
                    }
                    if (owner.equipment.Primary.def.defName.Equals("Gun_PDW"))
                    {
                        canepuipshield = true;
                    }
                    if (owner.equipment.Primary.def.defName.Equals("Gun_HeavySMG"))
                    {
                        canepuipshield = true;
                    }
                    if (owner.equipment.Primary.def.defName.Equals("Gun_HeavySMG"))
                    {
                        canepuipshield = true;
                    }
                    if (owner.equipment.Primary.def.weaponTags.Contains("MedievalShields_ValidSidearm"))
                    {
                        canepuipshield = true;
                    }
                    canepuipshield = false;
                }


                if (canepuipshield && hasShieldinInventory && i != null)
                {
                    owner.apparel.Wear(i);
                }

                if (hasShieldEquiped && !canepuipshield && e != null)
                {
                    owner.inventory.innerContainer.TryAddOrTransfer(e as Thing, false);
                }

                return;
            }
        }
    }
}



the error i get is
Could not execute post-long-event action. Exception: System.TypeInitializationException: An exception was thrown by the type initializer for Shield.ShieldHarmony ---> System.NullReferenceException: Object reference not set to an instance of an object
  at Shield.ShieldHarmony..cctor () [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at (wrapper managed-to-native) System.Runtime.CompilerServices.RuntimeHelpers:RunClassConstructor (intptr)
  at System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (RuntimeTypeHandle type) [0x00000] in <filename unknown>:0
  at Verse.StaticConstructorOnStartupUtility.CallAll () [0x00000] in <filename unknown>:0
  at Verse.PlayDataLoader.<DoPlayLoad>m__2 () [0x00000] in <filename unknown>:0
  at Verse.LongEventHandler.ExecuteToExecuteWhenFinished () [0x00000] in <filename unknown>:0
Verse.Log:Error(String, Boolean)
Verse.LongEventHandler:ExecuteToExecuteWhenFinished()
Verse.LongEventHandler:UpdateCurrentAsynchronousEvent()
Verse.LongEventHandler:LongEventsUpdate(Boolean&)
Verse.Root:Update_Patch1(Object)
Verse.Root_Entry:Update()

Any help would be greatly appreciated.

The ultimate end goal is to have an action or function "JobEquip_Start" called using harmony or some other event. I tried using the sidearms and survival tools source to try to figure it out. But no dice.

#27
Help / Item and equipment swapping
November 01, 2018, 06:33:26 PM
I need help with my shield mod as of right now i can add shields to the Pawns inventory using the


this.Wearer.inventory.innerContainer.TryAddOrTransfer(this as Thing, false);


the problem is i cant retrieve it when the pawn switches weapons. Is there a delegate or function that is called when when a pawn switches its primary weapon? I can listen for. any ideas would be greatly appreciated.

#28
Help / Re: Tips for making textures
October 31, 2018, 12:19:08 PM
Oh snap i got you in the xml in graphics data


    <graphicData>
      <texPath>Things/Building/Furniture/Bed/SleepSpot</texPath>
      <graphicClass>Graphic_Multi</graphicClass>
      <drawSize>(3,4)</drawSize>
    </graphicData


then when set up textures you would do Sleepspot_n for north _e for east facing or something like that.
#29
Help / Re: Adding Custom Values to a Def
October 31, 2018, 11:40:52 AM
I am trying to add a boolean Value called <coloredByMaterials> </coloredByMaterials> to the xml then having the Shield.Apparel_Shield class recognize it some how.
#30
Help / Adding Custom Values to a Def
October 27, 2018, 05:07:19 PM
I have a def

<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef ParentName="Buckler_Shield">
    <defName>Test_Buckler</defName>
<colorable>False</colorable>
<thingClass>Shield.Apparel_Shield</thingClass>
<label>Test Buckler</label>
    <description>This Is a Test</description>
    <graphicData>
      <texPath>Things/Item/Equipment/Apparel/Accessory/Shield/Buckler/buckler</texPath>
      <graphicClass>Graphic_Single</graphicClass>
</graphicData>
    <costList>
<WoodLog>20</WoodLog>
<Steel>5</Steel>
    </costList>
<recipeMaker>
<recipeUsers>
<li>CraftingSpot</li>
</recipeUsers>
</recipeMaker>
    <statBases>
  <WorkToMake>500</WorkToMake>
  <Mass>10</Mass>
  <MaxHitPoints>100</MaxHitPoints>
      <Flammability>1.0</Flammability>
      <DeteriorationRate>1</DeteriorationRate>
  <ArmorRating_Blunt>0.2</ArmorRating_Blunt>
      <ArmorRating_Sharp>0.2</ArmorRating_Sharp>
    </statBases>
    <useHitPoints>True</useHitPoints>
<smeltable>True</smeltable>
</ThingDef>

</Defs>


i want to add a variable to Shield.Apparel_Shield that can be set in the xml and i cant find any info on it.