Beispiel #1
0
 public static void InterfaceDrop(ITab_Pawn_Gear __instance, Thing t)
 {
     if (t.def.IsMeleeWeapon || t.def.IsRangedWeapon)
     {
         ThingWithComps thingWithComps = t as ThingWithComps;
         ThingOwner     thingOwner     = thingWithComps.holdingOwner;
         IThingHolder   actualOwner    = thingOwner.Owner;
         if (actualOwner is Pawn_InventoryTracker)
         {
             CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn((actualOwner as Pawn_InventoryTracker).pawn);
             if (pawnMemory == null)
             {
                 return;
             }
             pawnMemory.InformOfDroppedSidearm(thingWithComps, true);
         }
         else if (actualOwner is Pawn_EquipmentTracker)
         {
             CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn((actualOwner as Pawn_EquipmentTracker).ParentHolder as Pawn);
             if (pawnMemory == null)
             {
                 return;
             }
             pawnMemory.InformOfDroppedSidearm(thingWithComps, true);
         }
     }
 }
Beispiel #2
0
        public static bool trySwapToMoreAccurateRangedWeapon(Pawn pawn, LocalTargetInfo target, bool dropCurrent, bool skipManualUse, bool skipDangerous = true, bool skipEMP = true)
        {
            CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);

            if (pawn == null || pawn.Dead || pawnMemory == null || pawn.equipment == null || pawn.inventory == null)
            {
                return(false);
            }

            if (pawnMemory.IsCurrentWeaponForced(false))
            {
                return(false);
            }

            (ThingWithComps weapon, float dps, float averageSpeed)bestWeapon = GettersFilters.findBestRangedWeapon(pawn, target, skipManualUse, skipDangerous, skipEMP, true);

            if (bestWeapon.weapon == null)
            {
                return(false);
            }

            CellRect cellRect   = (!target.HasThing) ? CellRect.SingleCell(target.Cell) : target.Thing.OccupiedRect();
            float    range      = cellRect.ClosestDistSquaredTo(pawn.Position);
            float    currentDPS = StatCalculator.RangedDPS(pawn.equipment.Primary, Settings.SpeedSelectionBiasRanged, bestWeapon.averageSpeed, range);

            if (bestWeapon.dps < currentDPS + MiscUtils.ANTI_OSCILLATION_FACTOR)
            {
                return(false);
            }

            equipSpecificWeaponFromInventory(pawn, bestWeapon.weapon, dropCurrent, false);
            return(true);
        }
Beispiel #3
0
        public static void ClearWeaponMemory(Pawn p)
        {
            CompSidearmMemory csm = p.TryGetComp <CompSidearmMemory>();

            if (csm != null && csm.rememberedWeapons != null && csm.RememberedWeapons.Count > 0 && p.equipment != null)
            {
                while (csm.RememberedWeapons.Count > 0)
                {
                    csm.ForgetSidearmMemory(csm.RememberedWeapons[0]);
                }
                csm.generateRememberedWeaponsFromEquipped();
            }
        }
        public IEnumerable <Pawn> AffectedPawns()
        {
            if (!Settings.ShowAlertsMissingSidearm)
            {
                yield break;
            }
            else
            {
                HashSet <Pawn> pawns = new HashSet <Pawn>();
                if (PawnsFinder.AllMaps_FreeColonistsSpawned != null)
                {
                    foreach (Pawn pawn in PawnsFinder.AllMaps_FreeColonistsSpawned)
                    {
                        if (!pawn.IsValidSidearmsCarrier())
                        {
                            continue;
                        }
                        else
                        {
                            if (pawn.health != null && pawn.Downed)
                            {
                                continue;
                            }
                            if (pawn.drafter != null && pawn.Drafted)
                            {
                                continue;
                            }
                            if (pawn.CurJob != null && pawn.CurJob.def != null && (pawn.CurJob.def == SidearmsDefOf.EquipSecondary))
                            {
                                continue;
                            }

                            CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                            if (pawnMemory != null)
                            {
                                foreach (ThingDefStuffDefPair weaponMemory in pawnMemory.RememberedWeapons)
                                {
                                    if (!pawn.hasWeaponType(weaponMemory))
                                    {
                                        if (pawns.Add(pawn))
                                        {
                                            yield return(pawn);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #5
0
        public static void HuntersWithoutRangedWeapon(Alert_HunterLacksRangedWeapon __instance, ref List <Pawn> __result)
        {
            List <Pawn> editedList = new List <Pawn>();

            foreach (Pawn pawn in __result)
            {
                CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                if (pawnMemory != null && pawn.IsValidSidearmsCarrier() && pawnMemory.IsUsingAutotool(true, true))
                {
                    continue;
                }
                //if I implement default-melee ranged hunting, the check goes here
                editedList.Add(pawn);
            }
            __result = editedList;
        }
Beispiel #6
0
 public static void AddEquipment_Postfix(Pawn_EquipmentTracker __instance, ThingWithComps newEq)
 {
     if (!addEquipmentSourcedBySimpleSidearms)
     {
         Pawn pawn = __instance.pawn;
         if (!pawn.IsValidSidearmsCarrier())
         {
             return;
         }
         CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
         if (pawnMemory == null)
         {
             return;
         }
         pawnMemory.InformOfAddedPrimary(newEq);
     }
 }
Beispiel #7
0
 public static void CarryWeaponOpenly(ref PawnRenderer __instance, ref Pawn ___pawn, ref bool __result)
 {
     if (!___pawn.IsValidSidearmsCarrier())
     {
         return;
     }
     if (__result == true)
     {
         return;
     }
     else
     {
         CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(___pawn);
         if (pawnMemory != null && pawnMemory.autotoolToil != null)
         {
             __result = true;
         }
     }
 }
Beispiel #8
0
        public static void dropSidearm(Pawn pawn, Thing weapon, bool intentionalDrop)
        {
            if (weapon == null)
            {
                return;
            }
            if (pawn.IsQuestLodger() && intentionalDrop)
            {
                return;
            }

            if (!intentionalDrop)
            {
                DoFumbleMote(pawn);
            }

            if (pawn.equipment.Primary == weapon)
            {
                Pawn_EquipmentTracker_TryDropEquipment.dropEquipmentSourcedBySimpleSidearms = true;
                pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out _, pawn.Position, false);
                Pawn_EquipmentTracker_TryDropEquipment.dropEquipmentSourcedBySimpleSidearms = false;
            }
            else
            {
                if (weapon.stackCount > 1)
                {
                    var toDrop = weapon.SplitOff(1);
                    GenDrop.TryDropSpawn(toDrop, pawn.Position, pawn.Map, ThingPlaceMode.Near, out _);
                }
                else
                {
                    pawn.inventory.innerContainer.TryDrop(weapon, pawn.Position, pawn.Map, ThingPlaceMode.Near, out _, null);
                }
            }

            CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);

            if (pawnMemory == null)
            {
                return;
            }
            pawnMemory.InformOfDroppedSidearm(weapon, intentionalDrop);
        }
Beispiel #9
0
        public static void TryDropEquipment_Postfix(Pawn_EquipmentTracker __instance, bool __result, ThingWithComps resultingEq)
        {
            if (__result == true && resultingEq != null)
            {
                Pawn pawn = __instance.pawn;
                if (!pawn.IsValidSidearmsCarrier())
                {
                    return;
                }

                if (!(Pawn_HealthTracker_MakeDowned.beingDowned || dropEquipmentSourcedBySimpleSidearms))
                {
                    CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                    if (pawnMemory != null)
                    {
                        pawnMemory.ForgetSidearmMemory(resultingEq.toThingDefStuffDefPair());
                    }
                }
            }
        }
        //public static void GetGizmos(Pawn __instance, ref IEnumerable<Gizmo> __result)
        public static IEnumerable <Gizmo> Postfix(IEnumerable <Gizmo> __result, Pawn __instance)
        {
            //This postfix inserts the SimpleSidearms gizmo before all other gizmos
            if (__instance.IsValidSidearmsCarrier() && (__instance.IsColonistPlayerControlled ||
                                                        DebugSettings.godMode) && __instance.equipment != null && __instance.inventory != null
                )
            {
                IEnumerable <ThingWithComps> carriedWeapons = __instance.getCarriedWeapons(includeTools: true);

                CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(__instance);
                if (pawnMemory != null)
                {
                    List <ThingDefStuffDefPair> rangedWeaponMemories = new List <ThingDefStuffDefPair>();
                    List <ThingDefStuffDefPair> meleeWeaponMemories  = new List <ThingDefStuffDefPair>();

                    foreach (ThingDefStuffDefPair weapon in pawnMemory.RememberedWeapons)
                    {
                        if (weapon.thing.IsMeleeWeapon)
                        {
                            meleeWeaponMemories.Add(weapon);
                        }
                        else if (weapon.thing.IsRangedWeapon)
                        {
                            rangedWeaponMemories.Add(weapon);
                        }
                    }

                    yield return(new Gizmo_SidearmsList(__instance, carriedWeapons, pawnMemory.RememberedWeapons));

                    if (DebugSettings.godMode)
                    {
                        yield return(new Gizmo_Brainscope(__instance));
                    }
                }
            }

            foreach (var aGizmo in __result)
            {
                yield return(aGizmo);
            }
        }
Beispiel #11
0
        public static void DraftedSetter(Pawn_DraftController __instance)
        {
            //Log.Message("undraft intercept: " + __instance.Drafted);
            if (!__instance.Drafted)
            {
                Pawn pawn = __instance.pawn;
                if (!pawn.IsValidSidearmsCarrier())
                {
                    return;
                }
                if (pawn.IsColonist)
                {
                    CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                    if (pawnMemory == null)
                    {
                        return;
                    }

                    pawnMemory.InformOfUndraft();
                }
            }
        }
Beispiel #12
0
        public static bool equipBestWeaponFromInventoryByStatModifiers(Pawn pawn, List <StatDef> stats)
        {
            //Log.Message("looking for a stat booster for stats " + String.Join(",", stats.Select(s => s.label))); ;

            if (!pawn.IsValidSidearmsCarrier() || stats.Count == 0 || pawn.Drafted)
            {
                return(false);
            }

            CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);

            if (pawnMemory == null)
            {
                return(false);
            }

            ThingWithComps bestBooster = pawn.getCarriedWeapons(includeTools: true).Where(t =>
            {
                _ = t.toThingDefStuffDefPair().getBestStatBoost(stats, out bool found); return(found);
            }).OrderBy(t =>
            {
                return(t.toThingDefStuffDefPair().getBestStatBoost(stats, out _));
            }).FirstOrDefault();

            if (bestBooster == default(ThingWithComps))
            {
                return(false);
            }

            if (bestBooster == pawn.equipment.Primary)
            {
                return(true);
            }

            bool success = equipSpecificWeaponFromInventory(pawn, bestBooster, false, false);

            return(success);
        }
Beispiel #13
0
        public static bool tryCQCWeaponSwapToMelee(Pawn pawn, Pawn target, DroppingModeEnum dropMode)
        {
            if (!pawn.IsValidSidearmsCarrier())
            {
                return(false);
            }

            CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);

            if (pawnMemory == null)
            {
                return(false);
            }

            if (!pawn.RaceProps.Humanlike)
            {
                return(false);
            }

            if (pawn.equipment.Primary != null)
            {
                if (pawn.equipment.Primary.def.destroyOnDrop)
                {
                    return(false);
                }
            }

            if (pawnMemory.IsCurrentWeaponForced(false))
            {
                return(false);
            }

            var current = pawn.equipment.Primary;

            equipBestWeaponFromInventoryByPreference(pawn, dropMode, PrimaryWeaponMode.Melee, target: target);
            return(current != pawn.equipment.Primary);
        }
Beispiel #14
0
        public static void _ctor(Toil __instance)
        {
            if (SimpleSidearms.ToolAutoSwitch == true)
            {
                Toil toil = __instance;
                if (toil == null)
                {
                    return;
                }

                toil.AddPreInitAction(delegate
                {
                    Pawn pawn = toil.GetActor();
                    if (pawn == null || !pawn.IsValidSidearmsCarrier())
                    {
                        return;
                    }

                    CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                    if (pawnMemory == null)
                    {
                        return;
                    }
                    pawnMemory.CheckIfStillOnAutotoolJob();

                    StatDef activeStat = pawn.CurJob?.RecipeDef?.workSpeedStat;

                    SkillDef activeSkill = null;
                    if (toil.activeSkill != null && toil.activeSkill() != null)
                    {
                        activeSkill = toil.activeSkill();
                    }
                    else
                    {
                        activeSkill = pawn.CurJob?.RecipeDef?.workSkill;
                    }

                    List <StatDef> possiblyActiveStats = new List <StatDef>();
                    if (activeStat != null)
                    {
                        possiblyActiveStats.Add(activeStat);
                    }
                    else if (activeSkill != null && SkillStatMap.Map.ContainsKey(activeSkill))
                    {
                        possiblyActiveStats.AddRange(SkillStatMap.Map[activeSkill]);
                    }

                    bool usingAppropriateTool = WeaponAssingment.equipBestWeaponFromInventoryByStatModifiers(toil.GetActor(), possiblyActiveStats);
                    if (usingAppropriateTool)
                    {
                        if (pawnMemory != null)
                        {
                            pawnMemory.autotoolToil = toil;
                            pawnMemory.autotoolJob  = pawn.CurJobDef;
                        }
                    }
                });
                toil.AddFinishAction(delegate
                {
                    Pawn pawn = toil.GetActor();
                    if (!pawn.IsValidSidearmsCarrier())
                    {
                        return;
                    }
                    CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                    if (pawnMemory != null)
                    {
                        if (pawnMemory.autotoolToil == toil)
                        {
                            pawnMemory.delayIdleSwitchTimestamp = Find.TickManager.TicksGame;
                        }
                        else
                        {
                            pawnMemory.autotoolToil = null;
                        }
                    }
                });
            }
        }
        public static List <Thing> RemoveRememberedWeaponsFromThingList(List <Thing> carvanInventory, IEnumerable <Pawn> pawns)
        {
            // get remembered weapons for all pawns
            var rememberedNonEquippedCount = new Dictionary <ThingDefStuffDefPair, int>();

            foreach (var pawn in pawns)
            {
                // check if the pawn is a colonist
                if (!pawn.IsColonist)
                {
                    continue;
                }

                // retrieve siderarm memory
                var memory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                if (memory == null)
                {
                    continue;
                }

                // iterate over every remembered weapon
                foreach (var weapon in memory.RememberedWeapons)
                {
                    // ignore equipped remembered weapons
                    if (pawn.equipment?.Primary?.matchesThingDefStuffDefPair(weapon) == true)
                    {
                        continue;
                    }

                    // count remembered weapons which are not equipped
                    if (rememberedNonEquippedCount.ContainsKey(weapon))
                    {
                        rememberedNonEquippedCount[weapon]++;
                    }
                    else
                    {
                        rememberedNonEquippedCount.Add(weapon, 1);
                    }
                }
            }

            // sort items by quality so the highest quality items will be reserved for pawns
            carvanInventory.SortByDescending((thing) =>
            {
                QualityUtility.TryGetQuality(thing, out QualityCategory qc);
                return((int)qc); // NOTE: what about high quality weapons with low hitpoints?
            });

            // check for biocoded weapons and remove them from the list if the biocoded pawns are part of the caravan and remembers them
            for (int i = 0; i < carvanInventory.Count;)
            {
                var thing = carvanInventory[i];
                // check if thing is biocodable, is biocoded and if the pawn whom it is biocoded to is part of the caravan
                if (thing.TryGetComp <CompBiocodable>() is CompBiocodable biocode &&
                    biocode.Biocoded &&
                    biocode.CodedPawn is Pawn pawn &&
                    pawn.IsColonist &&
                    pawns.Contains(pawn))
                {
                    // if the pawn whom this weapon is biocoded to remembers this weapon, remove it from the output
                    var pair   = thing.toThingDefStuffDefPair();
                    var memory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                    if (memory != null && memory.RememberedWeapons.Contains(pair))
                    {
                        //Log.Message($"'{thing}' is biocoded and remembered by caravan member '{pawn}', removing from output");

                        // remove thing from output
                        carvanInventory.Remove(thing);
                        rememberedNonEquippedCount[pair]--;
                        continue;
                    }
                }
                i++;
            }

            // iterate over quality-sorted list of things in caravan inventory
            for (int i = 0; i < carvanInventory.Count;)
            {
                // if thing is a remembered weapon, skip it; this removes it from the output
                var thing = carvanInventory[i];
                var pair  = thing.toThingDefStuffDefPair();
                if (pair != null &&
                    rememberedNonEquippedCount.ContainsKey(pair) &&
                    rememberedNonEquippedCount[pair] > 0)
                {
                    //Log.Message($"'{thing}' is remembered by caravan member, removing from output");

                    // remove thing from output
                    carvanInventory.Remove(thing);
                    rememberedNonEquippedCount[pair]--;
                    continue;
                }
                i++;
            }

            // return output
            return(carvanInventory);
        }
Beispiel #16
0
        public static bool equipSpecificWeapon(Pawn pawn, ThingWithComps weapon, bool dropCurrent, bool intentionalDrop)
        {
            if (!pawn.IsValidSidearmsCarrier())
            {
                return(false);
            }

            CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);

            if (pawnMemory == null)
            {
                return(false);
            }

            if (weapon == pawn.equipment.Primary) //attepmpting to equip already-equipped weapon
            {
                Log.Warning("attepmpting to equip already-equipped weapon");
                return(false);
            }

            if (!Settings.AllowBlockedWeaponUse && !StatCalculator.canUseSidearmInstance(weapon, pawn, out string reason))
            {
                Log.Warning($"blocked equip of {weapon.Label} at equip-time because of: {reason}");
                return(false);
            }

            var currentPrimary = pawn.equipment.Primary;

            //drop current on the ground
            if (dropCurrent && pawn.equipment.Primary != null)
            {
                if (!intentionalDrop)
                {
                    DoFumbleMote(pawn);
                }
                pawnMemory.InformOfDroppedSidearm(weapon, intentionalDrop);
                Pawn_EquipmentTracker_TryDropEquipment.dropEquipmentSourcedBySimpleSidearms = true;
                pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out ThingWithComps droppedItem, pawn.Position, false);
                Pawn_EquipmentTracker_TryDropEquipment.dropEquipmentSourcedBySimpleSidearms = false;
            }
            //or put it in inventory
            else if (pawn.equipment.Primary != null)
            {
                ThingWithComps oldPrimary       = pawn.equipment.Primary;
                bool           addedToInventory = pawn.inventory.innerContainer.TryAddOrTransfer(oldPrimary, true);
                //pawn.equipment.Remove(oldPrimary);
                //bool addedToInventory = pawn.inventory.innerContainer.TryAdd(oldPrimary, true);
                if (!addedToInventory)
                {
                    Log.Warning(String.Format("Failed to place primary equipment {0} (initially was {1}) into inventory when swapping to {2} on pawn {3} (colonist: {4}) (dropping: {5}, current drop mode: {6}). Aborting swap. Please report this!",
                                              pawn.equipment.Primary != null ? pawn.equipment.Primary.LabelCap : "NULL",
                                              currentPrimary != null ? currentPrimary.LabelCap : "NULL",
                                              weapon != null ? weapon.LabelCap : "NULL",
                                              pawn?.LabelCap,
                                              pawn?.IsColonist,
                                              dropCurrent,
                                              Settings.FumbleMode
                                              ));
                }
            }

            if (pawn.equipment.Primary != null)
            {
                Log.Warning(String.Format("Failed to remove current primary equipment {0} (initially was {1}) when swapping to {2} on pawn {3} (colonist: {4}) (dropping: {5}, current drop mode: {6}). Aborting swap. Please report this!",
                                          pawn.equipment.Primary != null ? pawn.equipment.Primary.LabelCap : "NULL",
                                          currentPrimary != null ? currentPrimary.LabelCap : "NULL",
                                          weapon != null ? weapon.LabelCap : "NULL",
                                          pawn?.LabelCap,
                                          pawn?.IsColonist,
                                          dropCurrent,
                                          Settings.FumbleMode
                                          ));
                return(false);
            }

            if (weapon == null)
            {
            }
            else
            {
                if (weapon.stackCount > 1)
                {
                    weapon = weapon.SplitOff(1) as ThingWithComps; //if this cast doesnt work the world has gone mad
                }
                if (weapon.holdingOwner != null)
                {
                    weapon.holdingOwner.Remove(weapon);
                }
                Pawn_EquipmentTracker_AddEquipment.addEquipmentSourcedBySimpleSidearms = true;
                pawn.equipment.AddEquipment(weapon as ThingWithComps);
                Pawn_EquipmentTracker_AddEquipment.addEquipmentSourcedBySimpleSidearms = false;

                if (weapon.def.soundInteract != null)
                {
                    weapon.def.soundInteract.PlayOneShot(new TargetInfo(pawn.Position, pawn.Map, false));
                }
            }

            //avoid hunting stackoverflowexception
            if (pawn.jobs != null && pawn.jobs.curJob != null && pawn.jobs.curJob.def == JobDefOf.Hunt)
            {
                pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, true);
            }

            return(true);
        }
Beispiel #17
0
        public static void equipBestWeaponFromInventoryByPreference(Pawn pawn, DroppingModeEnum dropMode, PrimaryWeaponMode?modeOverride = null, Pawn target = null)
        {
            if (!pawn.IsValidSidearmsCarrier())
            {
                return;
            }
            CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);

            if (pawnMemory == null)
            {
                return;
            }

            PrimaryWeaponMode mode = modeOverride == null ? pawnMemory.primaryWeaponMode : modeOverride.Value;

            if ((pawn.CombinedDisabledWorkTags & WorkTags.Violent) != 0)
            {
                if (pawn.equipment.Primary != null)
                {
                    bool success = equipSpecificWeapon(pawn, null, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                    if (success)
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }

            if (pawn.Drafted &&
                (pawnMemory.ForcedUnarmedWhileDrafted || pawnMemory.ForcedUnarmed && pawnMemory.ForcedWeaponWhileDrafted == null))
            {
                if (pawn.equipment.Primary != null)
                {
                    bool success = equipSpecificWeapon(pawn, null, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                    if (success)
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }
            if (pawn.Drafted && pawnMemory.ForcedWeaponWhileDrafted != null)
            {
                if (pawn.equipment.Primary == null || pawn.equipment.Primary.toThingDefStuffDefPair() != pawnMemory.ForcedWeaponWhileDrafted.Value)
                {
                    var requiredWeapon = pawnMemory.ForcedWeaponWhileDrafted.Value;
                    if (!Settings.AllowBlockedWeaponUse && StatCalculator.canCarrySidearmType(requiredWeapon, pawn, out _))
                    {
                        //clear invalid
                        pawnMemory.ForcedWeaponWhileDrafted = null;
                        return;
                    }
                    bool success = equipSpecificWeaponTypeFromInventory(pawn, requiredWeapon, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                    if (success)
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }
            if (pawnMemory.ForcedUnarmed)
            {
                if (pawn.equipment.Primary != null)
                {
                    bool success = equipSpecificWeapon(pawn, null, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                    if (success)
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }
            if (pawnMemory.ForcedWeapon != null)
            {
                if (pawn.equipment.Primary == null || pawn.equipment.Primary.toThingDefStuffDefPair() != pawnMemory.ForcedWeapon.Value)
                {
                    var requiredWeapon = pawnMemory.ForcedWeapon.Value;
                    if (!Settings.AllowBlockedWeaponUse && StatCalculator.canCarrySidearmType(requiredWeapon, pawn, out _))
                    {
                        //clear invalid
                        pawnMemory.ForcedWeapon = null;
                        return;
                    }
                    bool success = equipSpecificWeaponTypeFromInventory(pawn, requiredWeapon, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                    if (success)
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }

            if (mode == PrimaryWeaponMode.Ranged ||
                ((mode == PrimaryWeaponMode.BySkill) && (pawn.getSkillWeaponPreference() == PrimaryWeaponMode.Ranged)))
            {
                if (pawnMemory.DefaultRangedWeapon != null && pawn.hasWeaponType(pawnMemory.DefaultRangedWeapon.Value))
                {
                    if (pawn.equipment.Primary == null || pawn.equipment.Primary.toThingDefStuffDefPair() != pawnMemory.DefaultRangedWeapon.Value)
                    {
                        var requiredWeapon = pawnMemory.DefaultRangedWeapon.Value;
                        if (!Settings.AllowBlockedWeaponUse && StatCalculator.canCarrySidearmType(requiredWeapon, pawn, out _))
                        {
                            //clear invalid
                            pawnMemory.DefaultRangedWeapon = null;
                            return;
                        }
                        bool success = equipSpecificWeaponTypeFromInventory(pawn, requiredWeapon, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                        if (success)
                        {
                            return;
                        }
                    }
                    else
                    {
                        return;
                    }
                }

                else
                {
                    bool skipManualUse = true;
                    bool skipDangerous = pawn.IsColonistPlayerControlled && Settings.SkipDangerousWeapons;
                    bool skipEMP       = true;
                    (ThingWithComps weapon, float dps, float averageSpeed)bestWeapon = GettersFilters.findBestRangedWeapon(pawn, null, skipManualUse, skipDangerous, skipEMP);
                    if (bestWeapon.weapon != null)
                    {
                        if (pawn.equipment.Primary != bestWeapon.weapon)
                        {
                            bool success = equipSpecificWeaponFromInventory(pawn, bestWeapon.weapon, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                            if (success)
                            {
                                return;
                            }
                        }
                        else
                        {
                            return;
                        }
                    }
                }
            }

            //all that's left is either melee preference or no ranged weapon found - so in either case, we want to equip a melee weapon.

            /*if (mode == GoldfishModule.PrimaryWeaponMode.Melee ||
             *  ((mode == GoldfishModule.PrimaryWeaponMode.BySkill) && (pawn.getSkillWeaponPreference() == GoldfishModule.PrimaryWeaponMode.Melee)))*/
            {
                //Log.Message("melee mode");
                //prefers melee
                if (pawnMemory.PreferredUnarmed)
                {
                    if (pawn.equipment.Primary != null)
                    {
                        bool success = equipSpecificWeapon(pawn, null, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                        if (success)
                        {
                            return;
                        }
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    if (pawnMemory.PreferredMeleeWeapon != null && pawn.hasWeaponType(pawnMemory.PreferredMeleeWeapon.Value))
                    {
                        if (pawn.equipment.Primary == null || pawn.equipment.Primary.toThingDefStuffDefPair() != pawnMemory.PreferredMeleeWeapon.Value)
                        {
                            var requiredWeapon = pawnMemory.PreferredMeleeWeapon.Value;
                            if (!Settings.AllowBlockedWeaponUse && StatCalculator.canCarrySidearmType(requiredWeapon, pawn, out _))
                            {
                                //clear invalid
                                pawnMemory.PreferredMeleeWeapon = null;
                                return;
                            }
                            bool success = equipSpecificWeaponTypeFromInventory(pawn, requiredWeapon, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                            if (success)
                            {
                                return;
                            }
                        }
                        else
                        {
                            return;
                        }
                    }
                    else
                    {
                        ThingWithComps result;
                        bool           foundAlternative = GettersFilters.findBestMeleeWeapon(pawn, out result, includeRangedWithBash: false);
                        if (foundAlternative)
                        {
                            if (pawn.equipment.Primary != result)
                            {
                                bool success = equipSpecificWeaponFromInventory(pawn, result, MiscUtils.shouldDrop(pawn, dropMode, false), false);
                                if (success)
                                {
                                    return;
                                }
                            }
                            else
                            {
                                return;
                            }
                        }
                    }
                }
            }
            return;
        }
Beispiel #18
0
        public static void GetGizmos(Pawn __instance, ref IEnumerable <Gizmo> __result)
        {
            if (!__instance.IsValidSidearmsCarrier())
            {
                return;
            }
            try
            {
                if ((__instance.IsColonistPlayerControlled) ||
                    DebugSettings.godMode)
                {
                    if (__instance.equipment != null && __instance.inventory != null)
                    {
                        IEnumerable <ThingWithComps> carriedWeapons = __instance.getCarriedWeapons(includeTools: true);

                        CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(__instance);
                        if (pawnMemory == null)
                        {
                            return;
                        }

                        //if (carriedWeapons.Count() > 0 || (pawnMemory != null && pawnMemory.RememberedWeapons.Count > 0))
                        {
                            List <ThingDefStuffDefPair> rangedWeaponMemories = new List <ThingDefStuffDefPair>();
                            List <ThingDefStuffDefPair> meleeWeaponMemories  = new List <ThingDefStuffDefPair>();

                            if (pawnMemory != null)
                            {
                                foreach (ThingDefStuffDefPair weapon in pawnMemory.RememberedWeapons)
                                {
                                    if (weapon.thing.IsMeleeWeapon)
                                    {
                                        meleeWeaponMemories.Add(weapon);
                                    }
                                    else if (weapon.thing.IsRangedWeapon)
                                    {
                                        rangedWeaponMemories.Add(weapon);
                                    }
                                }
                            }

                            Gizmo_SidearmsList advanced = new Gizmo_SidearmsList(__instance, carriedWeapons, pawnMemory.RememberedWeapons);

                            List <Gizmo> results = new List <Gizmo>();
                            results.Add(advanced);
                            if (DebugSettings.godMode)
                            {
                                Gizmo_Brainscope brainscope = new Gizmo_Brainscope(__instance);
                                results.Add(brainscope);
                            }
                            foreach (Gizmo gizmo in __result)
                            {
                                results.Add(gizmo);
                            }
                            ;
                            __result = results;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("Exception during SimpleSidearms gizmo intercept. Cancelling intercept. Exception: " + e.ToString());
            }
        }
        public static void TransferWeaponsToCorrectInventory(List <Pawn> pawns)
        {
            if (!(pawns?.Count > 0))
            {
                return;
            }

            var missingWeaponsForPawn   = new Dictionary <Pawn, List <ThingDefStuffDefPair> >();
            var availableThings         = new List <ThingWithComps>();
            var availableBiocodedThings = new Dictionary <Pawn, List <ThingWithComps> >();

            foreach (var pawn in pawns)
            {
                var pawnThings = new List <ThingWithComps>();

                // add equipped weapon to list
                if (pawn.equipment?.Primary != null)
                {
                    pawnThings.Add(pawn.equipment.Primary);
                }

                // add all weapons in inventory to list
                var inventory = pawn.inventory?.innerContainer;
                if (inventory != null)
                {
                    // filter out all weapons in inventory
                    foreach (var thing in inventory)
                    {
                        if ((thing.def.IsMeleeWeapon || thing.def.IsRangedWeapon) &&
                            thing is ThingWithComps thingWithComps)
                        {
                            pawnThings.Add(thingWithComps);
                        }
                    }
                }

                // check if we are looking at a colonist with an inventory
                if (pawn?.IsColonist == true)
                {
                    var pawnWeapons = new List <ThingDefStuffDefPair>(CompSidearmMemory.GetMemoryCompForPawn(pawn)?.RememberedWeapons);

                    // first remove things biocoded to this pawn; no-one else can use them anyway
                    for (int i = 0; i < pawnThings.Count;)
                    {
                        var thing = pawnThings[i];

                        // check if thing is biocoded to this pawn
                        var biocode = thing.TryGetComp <CompBiocodable>();
                        if (biocode?.Biocoded == true)
                        {
                            if (biocode.CodedPawn == pawn)
                            {
                                // remove from remembered weapon list
                                var weaponMemory = thing.toThingDefStuffDefPair();
                                if (weaponMemory != null)
                                {
                                    pawnWeapons.Remove(weaponMemory);
                                }
                            }
                            else
                            {
                                // add biocoded thing to their own list
                                var codedPawn = biocode.CodedPawn;
                                if (!availableBiocodedThings.ContainsKey(codedPawn))
                                {
                                    availableBiocodedThings.Add(codedPawn, new List <ThingWithComps>());
                                }
                                availableBiocodedThings[codedPawn].Add(thing);
                            }

                            // remove from thing list
                            pawnThings.Remove(thing);
                            continue;
                        }
                        i++;
                    }

                    // then remove things that fit the remembered weapons found on the pawn
                    if (pawnWeapons.Count > 0)
                    {
                        for (int i = 0; i < pawnThings.Count;)
                        {
                            var thing = pawnThings[i];

                            // check if thing is remembered
                            var weaponMemory = thing.toThingDefStuffDefPair();
                            if (weaponMemory != null && pawnWeapons.Contains(weaponMemory))
                            {
                                // remove remembered weapon and the thing that fits it
                                pawnWeapons.Remove(weaponMemory);
                                pawnThings.Remove(thing);
                                continue;
                            }
                            i++;
                        }
                    }

                    // finally all weapons still in the pawn's remembered weapons list are missing; we will look for them on other pawns
                    if (pawnWeapons.Count > 0 && !missingWeaponsForPawn.ContainsKey(pawn))
                    {
                        missingWeaponsForPawn.Add(pawn, new List <ThingDefStuffDefPair>());
                    }
                    foreach (var weapon in pawnWeapons)
                    {
                        missingWeaponsForPawn[pawn].Add(weapon);
                    }
                }

                // all things in the pawn's thing list are not remembered weapons for this pawn; they can be used by other pawns
                foreach (var thing in pawnThings)
                {
                    availableThings.Add(thing);
                }
            }

            // sort by quality; this way we should give every pawn the best weapon, unless they got a biocoded one
            availableThings.SortByDescending((thing) =>
            {
                QualityUtility.TryGetQuality(thing, out QualityCategory qc);
                return((int)qc);
            });

            // transfer unassigned weapons to pawns missing sidearms
            foreach (var entry in missingWeaponsForPawn)
            {
                var pawn           = entry.Key;
                var missingWeapons = entry.Value;

                List <ThingWithComps> biocodedToThisPawn = null;
                if (availableBiocodedThings.ContainsKey(pawn))
                {
                    biocodedToThisPawn = availableBiocodedThings[pawn];
                }

                // iterate over every missing weapon
                for (int i = 0; i < missingWeapons.Count;)
                {
                    var weaponMemory = missingWeapons[i];

                    // check available biocoded weapons first
                    if (biocodedToThisPawn != null)
                    {
                        // iterate over biocoded items
                        for (int j = 0; biocodedToThisPawn.Count > j;)
                        {
                            // get ThingDefStuffDefPair for thing
                            var thing       = biocodedToThisPawn[j];
                            var thingMemory = thing.toThingDefStuffDefPair();

                            // check if thing fits weapon memory
                            if (weaponMemory.Equals(thingMemory))
                            {
                                //Log.Message($"Transferring '{thing}' from '{ThingOwnerUtility.GetAnyParent<Pawn>(thing)}' ({thing.ParentHolder}) to '{pawn}' [biocoded]");
                                // transfer weapon
                                if (thing.holdingOwner.TryTransferToContainer(thing, pawn.inventory.innerContainer, 1) == 1)
                                {
                                    // remove weapon from missing weapons list and thing from unassigned things list
                                    missingWeapons.Remove(weaponMemory);
                                    biocodedToThisPawn.Remove(thing);
                                    goto CONTINUE;
                                }

                                // if it gets here, tranferring the weapon failed; this should obviously not happen
                                Log.Error($"Failed to transfer '{thing}' from '{ThingOwnerUtility.GetAnyParent<Pawn>(thing)}' ({thing.ParentHolder}) to '{pawn}'! [biocoded]");
                            }
                            j++;
                        }
                    }

                    // for each missing weapon, we check all things to find it
                    for (int j = 0; j < availableThings.Count;)
                    {
                        // get ThingDefStuffDefPair for thing
                        var thing       = availableThings[j];
                        var thingMemory = thing.toThingDefStuffDefPair();

                        // all things in this list should have a ThingDefStuffDefPair, remove it if it does not
                        if (thingMemory == null)
                        {
                            Log.Warning($"'{thing}' had null ThingDefStuffDefPair; removing from unassigned things");
                            availableThings.Remove(thing);
                            continue;
                        }

                        // check if thing fits weapon memory
                        if (weaponMemory.Equals(thingMemory))
                        {
                            //Log.Message($"Transferring '{thing}' from '{ThingOwnerUtility.GetAnyParent<Pawn>(thing)}' ({thing.ParentHolder}) to '{pawn}' [standard]");
                            // transfer weapon
                            if (thing.holdingOwner.TryTransferToContainer(thing, pawn.inventory.innerContainer, 1) == 1)
                            {
                                // remove weapon from missing weapons list and thing from unassigned things list
                                missingWeapons.Remove(weaponMemory);
                                availableThings.Remove(thing);
                                goto CONTINUE;
                            }

                            // if it gets here, tranferring the weapon failed; this should obviously not happen
                            Log.Error($"Failed to transfer '{thing}' from '{ThingOwnerUtility.GetAnyParent<Pawn>(thing)}' ({thing.ParentHolder}) to '{pawn}'! [standard]");
                        }
                        j++;
                    }
                    i++;

                    // if missing weapon was found go here without increasing the index
                    CONTINUE :;
                }
            }
        }