Showing a ThingComp gizmo when it's equipped by a drafted pawn

Started by Robostove, November 29, 2016, 11:30:19 PM

Previous topic - Next topic

Robostove

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?

RawCode

your code?
it won't display on it's own, you must define when, how and where to render new button and what information to use.

skullywag

Look at the vanilla personal shields code. All you need is in there.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Robostove

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?

Robostove

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.