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 - Robostove

#1
It's strange starting as the dwarves and only being able to build/craft elven and hobbit stuff. Those mods really need research as well.
#2
Looks like a lot of great changes, especially glad to see how many of the QoL mods seem to have been integrated into the base game. Thanks Tynan!
#3
Help / Re: Problems detouring an internal class method
December 07, 2016, 12:03:08 AM
Thanks 0x45, your comment on the extension method parameter made me think "hey wait, I'm detouring a static class why do I have that parameter?". I forgot that originally I was detouring MainTabWindow_Inspect, and then changed it to InspectGizmoGrid (a static class). Aaaand I left that parameter in the declaration.  :P What I thought was a complicated error due to detouring an internal was just a stupid oversight on my part. It works fine now.
#4
Help / Re: Problems detouring an internal class method
December 05, 2016, 09:07:35 PM
Well turns out there's nothing to enumerate through, selectedObjects.Count is 0. I think I'm not getting the correct parameter. selectedObjects should be a List<IEnumerable>, not a WindowStack. Trying to call AddRange on a WindowStack must be giving the access violation. This is my first time detouring a method with parameters so I suppose I need to do something special to deal with that.

I'll figure it out with a non-internal class first  ;).
#5
Help / Problems detouring an internal class method
December 04, 2016, 09:04:00 PM
Here's my detour. The reflections are being found, selectedObjects is correctly being set to a Verse.WindowStack.
I'm getting a crash when objList tries to AddRange selectedObjects due to an access violation. This seems odd to me as before that line I have already interacted with both objList and selectedObjects. I guess the actual contents of selectedObjects are the problem? Is it actually possible to interact with an internal class or is this fruitless? Thanks.


    static class Detours_InspectGizmoGrid
    {
        //Reflect MainTabWindow_Inspect class (it is internal static)
        static Type _InspectGizmoGrid = Type.GetType("RimWorld.InspectGizmoGrid, Assembly-CSharp, Version=0.15.6089.4186, Culture=neutral, PublicKeyToken=null");//version determined using .NET IL Dissasembler

        //Reflect required fields from reflected class
        static List<object> objList =
            (List<object>)_InspectGizmoGrid
                .GetField("objList", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);

        static List<Gizmo> gizmoList =
            (List<Gizmo>)_InspectGizmoGrid
                .GetField("gizmoList", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);


        private static void DrawInspectGizmoGridFor(this MainTabWindow_Inspect _this, IEnumerable<object> selectedObjects)
        {

            if (_InspectGizmoGrid == null)
            {
                Log.Error("Reflected InspectGizmoGrid not found.");
                return;
            }
            if (objList == null)
            {
                Log.Error("Reflected objList not found.");
                return;
            }
            if (gizmoList == null)
            {
                Log.Error("Reflected gizmoList not found.");
                return;
            }

            try
            {
                Log.Message("Enter Draw Inspect");
                Log.Message($"{selectedObjects.ToString()}");
                if (selectedObjects == null)
                {
                    Log.Message("selectedObjects is null");
                }
                Log.Message("parameter accessed!");
                objList.Clear();
                Log.Message("objList cleared");
                objList.AddRange(selectedObjects); //CRASH here. Access violation due to read/write without permission.
                Log.Message("objList added selectedObjects");
                gizmoList.Clear();
                Log.Message("Start selectable");
                //...


Injecting this detour with RawCode's TryDetourFromTo:

    [StaticConstructorOnStartup]
    internal static class DetourInjector
    {
        static DetourInjector()
        {
            LongEventHandler.QueueLongEvent(Inject, "LibraryStartup", false, null);
        }

        public static void Inject()
        {
            if (InjectDetours()) Log.Message("Detour Core injected.");
            else Log.Error("Detour Core failed to get injected.");
        }

        public static bool InjectDetours()
        {
            if (!Detours.TryDetourFromTo(Detours_InspectGizmoGrid._InspectGizmoGrid.GetMethod("DrawInspectGizmoGridFor", BindingFlags.Static | BindingFlags.Public),
                typeof(Detours_InspectGizmoGrid).GetMethod("DrawInspectGizmoGridFor", BindingFlags.Static | BindingFlags.NonPublic)))
                return false;
           
            return true;
        }
    }

#6
Help / Re: Changing weight of silver?
December 04, 2016, 02:08:28 PM
Are you using CombatRealism? It adds Weight and Bulk to items. You can set the value for these in a ThingDef, silver is in ThingDefs_Items/Items_Resource_Stuff.xml.

If it's another mod that's adding weight to the game check out the specific xml for that mod.
#7
Help / Re: Multiple instances of RimWorld and mods
December 03, 2016, 08:55:50 PM
For Windows:
I made a copy of the whole game folder and then in the shortcut to the copy .exe, go to Properties->Shortcut and in the Target field put:

RimWorldWin.exe -savedatafolder=C:\Path\To\Where\You\Want

in front of what is already there (make sure you put a space between the new save path and the existing "C:\..." path).

That way it'll give you a copy with unique saves and mods. If you just make a copy without specifying -savedatafolder they will both use the default save path and you can't keep different mods activated.
#8
Alright, figured it out. The base game doesn't expect primary equipment (i.e. weapons) to have attached gizmos, so it doesn't check for them.

I detoured Pawn_EquipmentTracker.GetGizmos() to get all the gizmos attached to ThingComps on equipped items.


        internal static IEnumerable<Gizmo> Detour_GetGizmos(this Pawn_EquipmentTracker _this)
        {
            //reflect required methods
            MethodInfo ShouldUseSquadAttackGizmo = typeof(Pawn_EquipmentTracker).GetMethod("ShouldUseSquadAttackGizmo", BindingFlags.Instance | BindingFlags.NonPublic);
            MethodInfo GetSquadAttackGizmo = typeof(Pawn_EquipmentTracker).GetMethod("GetSquadAttackGizmo", BindingFlags.Instance | BindingFlags.NonPublic);

            //From here until the next comment is just the original GetGizmos updated to use reflected methods
            bool flag = false;

            if ((bool)ShouldUseSquadAttackGizmo.Invoke(_this, null))
            {
                yield return (Gizmo)GetSquadAttackGizmo.Invoke(_this, null);
            }
            int num = 0;
            IEnumerator<ThingWithComps> enumerator = _this.AllEquipment.GetEnumerator();
            while (enumerator.MoveNext())
            {
                ThingWithComps current = enumerator.Current;

                //Here's the meat of it. This returns ThingComp gizmos for all equipment
                IEnumerator<Gizmo> compGizmosEnumerator = current.GetGizmos().GetEnumerator();
                while (compGizmosEnumerator.MoveNext())
                {
                    yield return compGizmosEnumerator.Current;
                }

                //... (original method code)
            }
        }


Edit: Also has the side effect of having the forbid item gizmo show up when equipped, since CompForbiddable is one of the comps it is grabbing gizmos from.
#9
I implemented this by looking at Combat Realism's source for their ammo gizmo and making some modifications.

My override of GizmoOnGui:
[StaticConstructorOnStartup]
    public class GizmoChargeStatus : Command
    {
        //...
        public override GizmoResult GizmoOnGUI(Vector2 topLeft)
        {
            if (!initialized)
                InitializeTextures();

            Rect overRect = new Rect(topLeft.x, topLeft.y, Width, Height);
            Widgets.DrawBox(overRect);
            GUI.DrawTexture(overRect, BGTex);

            Rect inRect = overRect.ContractedBy(6);

            Rect textRect = inRect;
            textRect.height = overRect.height / 2;
            Text.Font = GameFont.Tiny;
            Widgets.Label(textRect, "Charges Remaining");

            // Bar
            Rect barRect = inRect;
            barRect.yMin = overRect.y + overRect.height / 2f;
            float ePct = (float)compCharge.curCharge / compCharge.Props.chargeCount;
            Widgets.FillableBar(barRect, ePct);
            Text.Font = GameFont.Small;
            Text.Anchor = TextAnchor.MiddleCenter;
            Widgets.Label(barRect, compCharge.curCharge + " / " + compCharge.Props.chargeCount);
            Text.Anchor = TextAnchor.UpperLeft;

            return new GizmoResult(GizmoState.Clear);
        }
        //...


My override of CompGetGizmosExtra:

    public class CompChargeUser : ThingComp
    {
        //...
        public override IEnumerable<Command> CompGetGizmosExtra()
        {
            GizmoChargeStatus chargeStatusGizmo = new GizmoChargeStatus { compCharge = this };
            yield return chargeStatusGizmo;
        }
        //...
    }


That handles the 'how' and 'where' of rendering the button, but I haven't figured out the 'when'. I noticed PersonalShield has an override called GetWornGizmos, but that's apparel specific.

Do I have to override Tick for this and manually call GizmoOnGui?
#10
I've created a ThingComp that overrides CompGetGizmosExtra() to add a "charges remaining" gizmo to a weapon. The gizmo is displayed when I select the item on the ground, but it doesn't display when the item is equipped by a drafted pawn.

How do I get it to show up?
#11
Help / Re: Resurrecting Pawns?
November 29, 2016, 02:18:08 PM
Thanks for the tip RawCode, I can't believe how simple that was - reflection is amazing.
#12
Mods / Re: Necromancer Requests
November 23, 2016, 08:04:24 PM
Just a small update here, since it has been longer than the few days I hinted at.

I'm working on a mod that adds a magic system to the game. One of the spells is "Animate Dead" which revives corpses (human or animal) that can be used like an animal trained with Release. They continue to rot while reanimated though, and eventually will fall permanently dead once they are down to a skeleton.

There are some technical issues that are keeping me from releasing yet. I'm still working on it and making progress though.
#13
Help / Re: Resurrecting Pawns?
November 23, 2016, 07:42:26 PM
Resurrecting pawns is easy enough. Use that innerPawn in the corpse, assign it new instances of stances, needs and mindState (these were destroyed when the pawn was killed).

You also need to change the healthState of the pawn from PawnHealthState.Dead to PawnHealthState.Mobile. An easy way to accomplish this is simply calling innerPawn.health.Reset(), although this has the unfortunate side effect of clearing all hediffs (injuries, missing limbs, whatever) that were on the pawn. Great if you want the pawn totally restored, not so great if you just want a living version of the existing pawn.

The problem with trying to maintain existing injuries is that health.healthState is private -- you can't just flip it to PawnHealthState.Mobile. I've tried doing a deepcopy of the existing hediffs before calling health.Reset(), but always get a game crash due to access violations.

Does anyone know a method to force change a field that is private?
#14
First off, I'd just like to say excellent work on Combat Realism. The depth of gameplay here is amazing.

I'm trying to incorporate a "charges remaining" mechanic into certain weapons in my mod, using a display like your GizmoAmmoStatus. I've managed to get the display showing on weapons while they are on the ground, but I can't seem to figure out how to show it once the weapon is equipped.

Could you possibly point me towards a solution, or refer me to where in your source this is accomplished?

Thank you, and keep up the good work!
#15
Mods / Re: Necromancer Requests
November 17, 2016, 02:30:15 PM
Keep your eye on the releases section in the next few days.  ;)