public static bool Prefix(Pawn pawn, Thing thing, WorkGiver_HaulToInventory __instance, bool forced, ref bool __result) { #region PickUpAndHaul code //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(false); } if (!WorkGiver_HaulToInventory.GoodThingToHaul(thing, pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(false); } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); bool foundCell = StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true); #endregion if (!foundCell) { __result = false; } else { SlotGroup slotGroup = pawn.Map.haulDestinationManager.SlotGroupAt(storeCell); __result = !(slotGroup != null && Limits.HasLimit(slotGroup.Settings) && Limits.GetLimit(slotGroup.Settings) >= slotGroup.TotalPrecalculatedItemsStack()); } return(false); }
static void Postfix(ref Pawn p, ref float __result) { ExtendedDataStorage store = GiddyUpCore.Base.Instance.GetExtendedDataStorage(); if (store == null)//this check is needed because some mods call this function on world load { return; } ExtendedPawnData pawnData = store.GetExtendedDataFor(p); if (pawnData == null || pawnData.caravanRider == null) { return; } else { //new solution A - more forgiving //float riderTotalMass = pawnData.caravanRider.GetStatValue(StatDefOf.Mass); //float riderGearInvMass = MassUtility.GearAndInventoryMass(pawnData.caravanRider); //float riderBodyMass = riderTotalMass - riderGearInvMass; //__result -= riderBodyMass; //__result = Math.Max(__result, 0f); //new solution B - more restrictive float riderTotalMass = pawnData.caravanRider.GetStatValue(StatDefOf.Mass); float riderGearInvMass = MassUtility.GearAndInventoryMass(pawnData.caravanRider); float riderBodyMass = riderTotalMass - riderGearInvMass; float riderCapacity = MassUtility.Capacity(pawnData.caravanRider); float riderGrossMass = riderBodyMass + riderCapacity; __result -= riderGrossMass; __result = Math.Max(__result, 0f); } }
public static bool CheckCanCarryGift(List <Tradeable> tradeables, ITrader trader) { Pawn pawn = trader as Pawn; if (pawn == null) { return(true); } float num = 0f; float num2 = 0f; Lord lord = pawn.GetLord(); if (lord != null) { for (int i = 0; i < lord.ownedPawns.Count; i++) { Pawn pawn2 = lord.ownedPawns[i]; TraderCaravanRole traderCaravanRole = pawn2.GetTraderCaravanRole(); if ((pawn2.RaceProps.Humanlike && traderCaravanRole != TraderCaravanRole.Guard) || traderCaravanRole == TraderCaravanRole.Carrier) { num += MassUtility.Capacity(pawn2); num2 += MassUtility.GearAndInventoryMass(pawn2); } } } else { num = MassUtility.Capacity(pawn); num2 = MassUtility.GearAndInventoryMass(pawn); } float num3 = 0f; for (int j = 0; j < tradeables.Count; j++) { if (tradeables[j].ActionToDo == TradeAction.PlayerSells) { int num4 = Mathf.Min(tradeables[j].CountToTransferToDestination, tradeables[j].CountHeldBy(Transactor.Colony)); if (num4 > 0) { num3 += tradeables[j].AnyThing.GetStatValue(StatDefOf.Mass) * (float)num4; } } } if (num2 + num3 <= num) { return(true); } float num5 = num - num2; if (num5 <= 0f) { Messages.Message("MessageCantGiveGiftBecauseCantCarryEncumbered".Translate(), MessageTypeDefOf.RejectInput, historical: false); } else { Messages.Message("MessageCantGiveGiftBecauseCantCarry".Translate(num3.ToStringMass(), num5.ToStringMass()), MessageTypeDefOf.RejectInput, historical: false); } return(false); }
public static bool DrawThingRow(object tab, ref float y, ref float width, Thing thing, bool inventory) { if (!Settings.gui_manual_unload) { return(true); } Pawn SelPawn = (Pawn)ITab_Pawn_Gear_Utility.LSelPawnForGear.GetValue(tab); bool CanControl = (bool)ITab_Pawn_Gear_Utility.LCanControl.GetValue(tab); Color hColor = new Color(1f, 0.8f, 0.8f, 1f); //Log.Message($"CanControl={CanControl}, pc={SelPawn.IsColonistPlayerControlled}, spawned={SelPawn.Spawned}, pcHome={SelPawn.Map.IsPlayerHome}, bcoded={IsBiocodedOrLinked(SelPawn, thing, inventory)}, locked={IsLocked(SelPawn, thing)}"); Rect rect = new Rect(0f, y, width, 28f); if ((thing is ThingWithComps) && CanControl && (inventory || SelPawn.IsColonistPlayerControlled || SelPawn.Spawned && !SelPawn.Map.IsPlayerHome) && !IsBiocodedOrLinked(SelPawn, thing, inventory) && !IsLocked(SelPawn, thing)) { Rect rect2 = new Rect(rect.width - 24f, y, 24f, 24f); CompUnloadChecker c = CompUnloadChecker.GetChecker(thing, false, true); if (c.ShouldUnload) { TooltipHandler.TipRegion(rect2, "UnloadThingCancel".Translate()); var cl = GUI.color; if (Widgets.ButtonImage(rect2, ContentFinder <Texture2D> .Get("UI/Icons/Unload_Thing_Cancel"), hColor)) { SoundDefOf.Tick_High.PlayOneShotOnCamera(null); c.ShouldUnload = false; if (MassUtility.Capacity(SelPawn, null) < MassUtility.GearAndInventoryMass(SelPawn) && thing.stackCount * thing.GetStatValue(StatDefOf.Mass, true) > 0 && !thing.def.destroyOnDrop) { ITab_Pawn_Gear_Utility.LInterfaceDrop.Invoke(tab, new object[] { thing }); } } GUI.color = cl; } else { TooltipHandler.TipRegion(rect2, "UnloadThing".Translate()); var cl = GUI.color; if (Widgets.ButtonImage(rect2, ContentFinder <Texture2D> .Get("UI/Icons/Unload_Thing"), Color.white)) { SoundDefOf.Tick_High.PlayOneShotOnCamera(null); c.ShouldUnload = true; } } width -= 24f; } return(true); }
public static bool Prefix(ITab_Pawn_Gear __instance, ref float y, ref float width, Thing thing, bool inventory) { if (!Settings.gui_manual_unload) { return(true); } bool CanControl = Traverse.Create(__instance).Property("CanControl").GetValue <bool>(); Pawn SelPawnForGear = Traverse.Create(__instance).Property("SelPawnForGear").GetValue <Pawn>(); Rect rect = new Rect(0f, y, width, 28f); if (CanControl && (SelPawnForGear.IsColonistPlayerControlled || SelPawnForGear.Spawned && !SelPawnForGear.Map.IsPlayerHome) && (thing is ThingWithComps) && !IsBiocodedOrLinked(SelPawnForGear, thing, inventory) && !IsLocked(SelPawnForGear, thing)) { Rect rect2 = new Rect(rect.width - 24f, y, 24f, 24f); CompUnloadChecker c = CompUnloadChecker.GetChecker(thing, false, true); if (c.ShouldUnload) { TooltipHandler.TipRegion(rect2, "UnloadThingCancel".Translate()); //weird shenanigans with colors var cl = GUI.color; if (Widgets.ButtonImage(rect2, ContentFinder <Texture2D> .Get("UI/Icons/Unload_Thing_Cancel"), hColor)) { SoundDefOf.Tick_High.PlayOneShotOnCamera(null); c.ShouldUnload = false; if (MassUtility.Capacity(SelPawnForGear, null) < MassUtility.GearAndInventoryMass(SelPawnForGear) && thing.stackCount * thing.GetStatValue(StatDefOf.Mass, true) > 0 && !thing.def.destroyOnDrop) { Thing t; SelPawnForGear.inventory.innerContainer.TryDrop(thing, SelPawnForGear.Position, SelPawnForGear.Map, ThingPlaceMode.Near, out t, null, null); } } GUI.color = cl; } else { TooltipHandler.TipRegion(rect2, "UnloadThing".Translate()); if (Widgets.ButtonImage(rect2, ContentFinder <Texture2D> .Get("UI/Icons/Unload_Thing"))) { SoundDefOf.Tick_High.PlayOneShotOnCamera(null); c.ShouldUnload = true; } } width -= 24f; } return(true); }
//pick up stuff until you can't anymore, //while you're up and about, pick up something and haul it //before you go out, empty your pockets public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) { CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>(); if (takenToInventory == null) { return(null); } if (thing is Corpse) { return(null); } if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(null); } if (thing.IsForbidden(pawn) || StoreUtility.IsInValidBestStorage(thing)) { return(null); } //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(null); } StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing); if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true)) { //since we've gone through all the effort of getting the loc, might as well use it. //Don't multi-haul food to hoppers. if (thing.def.IsNutritionGivingIngestible) { if (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty) { List <Thing> thingList = storeCell.GetThingList(thing.Map); for (int i = 0; i < thingList.Count; i++) { Thing thingAtCell = thingList[i]; if (thingAtCell.def == ThingDefOf.Hopper) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } } } } }
private void TryDrawMassInfo(ref float curY, float width) { if (this.SelPawnForCargo.GetComp <CompShips>().beached) { return; } Rect rect = new Rect(0f, curY, width, 22f); float num = MassUtility.GearAndInventoryMass(this.SelPawnForCargo); float num2 = MassUtility.Capacity(this.SelPawnForCargo, null); Widgets.Label(rect, "MassCarried".Translate(num.ToString("0.##"), num2.ToString("0.##"))); curY += 22f; }
private void TryDrawMassInfo(ref float curY, float width) { if (this.SelPawnForGear.Dead || !this.ShouldShowInventory(this.SelPawnForGear)) { return; } Rect rect = new Rect(0f, curY, width, 22f); float num = MassUtility.GearAndInventoryMass(this.SelPawnForGear); float num2 = MassUtility.Capacity(this.SelPawnForGear, null); Widgets.Label(rect, "MassCarried".Translate(num.ToString("0.##"), num2.ToString("0.##"))); curY += 22f; }
public static void TryDrawMassInfo(Pawn pawn, ref float curY, float width) { if (pawn.Dead || !ShouldShowInventory(pawn)) { return; } Rect rect = new Rect(0f, curY, width, 22f); float num = MassUtility.GearAndInventoryMass(pawn); float num2 = MassUtility.Capacity(pawn, null); Widgets.Label(rect, "MassCarried".Translate(num.ToString("0.##"), num2.ToString("0.##"))); curY += 22f; }
//pick up stuff until you can't anymore, //while you're up and about, pick up something and haul it //before you go out, empty your pockets public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) { //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(null); } DesignationDef haulUrgentlyDesignation = DefDatabase <DesignationDef> .GetNamed("HaulUrgentlyDesignation", false); // Misc. Robots compatibility // See https://github.com/catgirlfighter/RimWorld_CommonSense/blob/master/Source/CommonSense11/CommonSense/OpportunisticTasks.cs#L129-L140 if (pawn.TryGetComp <CompHauledToInventory>() == null) { return(null); } //This WorkGiver gets hijacked by AllowTool and expects us to urgently haul corpses. if (ModCompatibilityCheck.AllowToolIsActive && thing is Corpse && pawn.Map.designationManager.DesignationOn(thing)?.def == haulUrgentlyDesignation && HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } if (!GoodThingToHaul(thing, pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(null); } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true)) { //since we've gone through all the effort of getting the loc, might as well use it. //Don't multi-haul food to hoppers. if (thing.def.IsNutritionGivingIngestible) { if (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty) { List <Thing> thingList = storeCell.GetThingList(thing.Map); foreach (Thing t in thingList) { if (t.def == ThingDefOf.Hopper) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } } } } }
private void TryDrawMassInfo1(Rect rect) { if (this.SelPawnForGear.Dead || !this.ShouldShowInventory(this.SelPawnForGear)) { return; } Rect rect1 = new Rect(rect.x, rect.y, 24f, 24f); GUI.DrawTexture(rect1, ContentFinder <Texture2D> .Get("UI/Icons/Sandy_MassCarried_Icon", true)); TooltipHandler.TipRegion(rect1, "SandyMassCarried".Translate()); float num = MassUtility.GearAndInventoryMass(this.SelPawnForGear); float num2 = MassUtility.Capacity(this.SelPawnForGear, null); Rect rect2 = new Rect(rect.x + 30f, rect.y + 2f, 104f, 24f); Widgets.Label(rect2, "SandyMassValue".Translate(num.ToString("0.##"), num2.ToString("0.##"))); }
public override bool HasJobOnThing(Pawn pawn, Thing thing, bool forced = false) { //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(false); } if (!GoodThingToHaul(thing, pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(false); } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); return(StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 _)); }
private void DrawMassInfo(Vector2 topLeft) { if (SelPawnForGear.Dead || !ShouldShowInventory(SelPawnForGear)) { return; } Rect iconRect = new Rect(topLeft.x, topLeft.y, SmallIconSize, SmallIconSize); GUI.DrawTexture(iconRect, ContentFinder <Texture2D> .Get("UI/Icons/Sandy_MassCarried_Icon", true)); TooltipHandler.TipRegion(iconRect, "SandyMassCarried".Translate()); float mass = MassUtility.GearAndInventoryMass(SelPawnForGear); float capacity = MassUtility.Capacity(SelPawnForGear, null); Rect textRect = new Rect(topLeft.x + SmallIconSize + MediumMargin, topLeft.y + SmallIconMargin, statBoxWidth - SmallIconSize, SmallIconSize); Widgets.Label(textRect, "SandyMassValue".Translate(mass.ToString("0.##"), capacity.ToString("0.##"))); }
//pick up stuff until you can't anymore, //while you're up and about, pick up something and haul it //before you go out, empty your pockets public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) { //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(null); } DesignationDef HaulUrgentlyDesignation = DefDatabase <DesignationDef> .GetNamed("HaulUrgentlyDesignation", false); //This WorkGiver gets hijacked by AllowTool and expects us to urgently haul corpses. if (ModCompatibilityCheck.AllowToolIsActive && thing is Corpse && pawn.Map.designationManager.DesignationOn(thing)?.def == HaulUrgentlyDesignation && HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } if (!GoodThingToHaul(thing, pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(null); } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true)) { //since we've gone through all the effort of getting the loc, might as well use it. //Don't multi-haul food to hoppers. if (thing.def.IsNutritionGivingIngestible) { if (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty) { List <Thing> thingList = storeCell.GetThingList(thing.Map); for (int i = 0; i < thingList.Count; i++) { if (thingList[i].def == ThingDefOf.Hopper) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } } } } }
/// <summary> /// Carry capacity with Vehicles when using MassCalculator /// </summary> /// <param name="thingCounts"></param> /// <param name="__result"></param> /// <param name="explanation"></param> public static bool CapacityWithVehicle(List <ThingCount> thingCounts, ref float __result, StringBuilder explanation = null) { if (thingCounts.NotNullAndAny(x => x.Thing is VehiclePawn)) { float num = 0f; foreach (ThingCount tc in thingCounts) { if (tc.Count > 0) { if (tc.Thing is VehiclePawn) { num += MassUtility.Capacity(tc.Thing as Pawn, explanation) * (float)tc.Count; } } } __result = Mathf.Max(num, 0f); return(false); } return(true); }
private void TryDrawMassInfo(ref float curY, float width) { if (SelPawnForCargo.beached) { return; } Rect rect = new Rect(0f, curY, width, StandardLineHeight); float cannonsNum = 0f; if (SelPawnForCargo.TryGetComp <CompCannons>() != null) { foreach (VehicleTurret cannon in SelPawnForCargo.CompCannons.Cannons) { cannonsNum += cannon.loadedAmmo is null ? 0f : cannon.loadedAmmo.BaseMass * cannon.shellCount; } } float num = MassUtility.GearAndInventoryMass(SelPawnForCargo) + cannonsNum; float num2 = MassUtility.Capacity(SelPawnForCargo, null); Widgets.Label(rect, "MassCarried".Translate(num.ToString("0.##"), num2.ToString("0.##"))); curY += StandardLineHeight; }
public void DrawStatistics(Rect rect) { var viewRect = new Rect(rect.x, rect.y, rect.width - 16f, statsHeight); //Widgets.DrawBoxSolid(rect, Color.green); var height = 0f; Widgets.BeginScrollView(rect, ref statsScroll, viewRect); ModGUIUtility.ListSeperator(ref viewRect, "LoadoutStatistics"); viewRect.AdjVertBy(GenUI.GapTiny); var loadoutItems = selectedUnit.loadout.AllItems.ToList(); ModGUIUtility.BarWithOverlay( viewRect.PopTopPartPixels(ModGUIUtility.SPACED_HEIGHT), Utility.HypotheticalEncumberancePercent(pawn, loadoutItems), Utility.HypotheticalUnboundedEncumberancePercent(pawn, loadoutItems) > 1f ? Textures.ValvetTex as Texture2D : Textures.RWPrimaryTex as Texture2D, "Weight".Translate(), Utility.HypotheticalGearAndInventoryMass(pawn, loadoutItems).ToString("0.#") + "/" + MassUtility.Capacity(pawn).ToStringMass(), "WeightOverCapacity".Translate()); height += GenUI.GapTiny + ModGUIUtility.SPACED_HEIGHT; // var statBonuses = new Dictionary<StatDef, List<Item>>(); // var wornApparel = selectedUnit.loadout.HypotheticalWornApparel(pawn.RaceProps.body).ToList(); // var heldItems = loadoutItems.Where(item => !item.Def.IsApparel).ToList(); // // foreach (var potentialStatBoost in wornApparel.Union(heldItems)) // { // if (!potentialStatBoost.Def?.equippedStatOffsets?.Any() ?? true) continue; // // foreach (var mod in potentialStatBoost.Def.equippedStatOffsets.Select(m => m.stat)) { // if (!statBonuses.TryGetValue(mod, out var list)) { // statBonuses.Add(mod, new List<Item> { potentialStatBoost }); // continue; // } // list.Add(potentialStatBoost); // } // } // // var apparelBonuses = new List<StatDef> { // StatDefOf.SharpDamageMultiplier, StatDefOf.ArmorRating_Blunt, StatDefOf.ArmorRating_Heat, // StatDefOf.Insulation_Cold, StatDefOf.Insulation_Heat // }; // // foreach (var stat in apparelBonuses) { // statBonuses.Add(stat, wornApparel); // } // // foreach (var statBonus in statBonuses) { // TryDrawSpoofStatCalculations(ref viewRect, statBonus.Key, statBonus.Value); // height += GUIUtility.SPACED_HEIGHT; // } Widgets.EndScrollView(); statsHeight = height; }
//[HarmonyPostfix] public static void TicksPerMove(bool diagonal, Pawn __instance, ref int __result) { if (_carrymodifier == 0f) { return; } if (!MassUtility.CanEverCarryAnything(__instance)) { __result = Mathf.Clamp(Mathf.RoundToInt(__result / _modifier), 1, 450); return; } var c = (float)__result; var pawnMass = __instance.GetStatValue(StatDefOf.Mass); var ignoredMass = pawnMass * (__instance.RaceProps.packAnimal ? 0.5f : 0.2f); if (Compatibility_GiddyUp.GetMount(__instance) is Pawn mount) { __result = diagonal ? mount.TicksPerMoveDiagonal : mount.TicksPerMoveCardinal; return; } // add our own modifiers var mass = ignoredMass - MassUtility.GearAndInventoryMass(__instance); if (Compatibility_GiddyUp.GetRider(__instance) is Pawn rider) { mass += MassUtility.GearAndInventoryMass(rider); mass += rider.GetStatValue(StatDefOf.Mass, true); var riderCarriedThing = rider.carryTracker.CarriedThing; if (riderCarriedThing != null) { mass += riderCarriedThing.stackCount * riderCarriedThing.GetStatValue(StatDefOf.Mass); if (riderCarriedThing is Pawn p) { mass += MassUtility.GearAndInventoryMass(p); // undo carry pawn modifier c /= 1.666f; } } } var capacity = MassUtility.Capacity(__instance, null); var pawnCarriedThing = __instance.carryTracker.CarriedThing; if (pawnCarriedThing != null) { mass += pawnCarriedThing.stackCount * pawnCarriedThing.GetStatValue(StatDefOf.Mass); if (pawnCarriedThing is Pawn p) { mass += MassUtility.GearAndInventoryMass(p); // undo carry pawn modifier c /= 1.666f; } } var encumbrance = Mathf.Clamp(mass / capacity, 0f, 1f); var modifier = 1 + (encumbrance * _carrymodifier); c *= modifier; __result = Mathf.Clamp(Mathf.RoundToInt(c / _modifier), 1, 450); }
public static float HypotheticalUnboundedEncumberancePercent(Pawn p, List <Item> items) { return(HypotheticalGearAndInventoryMass(p, items) / MassUtility.Capacity(p)); }
private void DrawMass(Rect rect, TransferableOneWay trad, float availableMass) { if (!trad.HasAnyThing) { return; } Thing anyThing = trad.AnyThing; Pawn pawn = anyThing as Pawn; if (pawn != null && !includePawnsMassInMassUsage && !MassUtility.CanEverCarryAnything(pawn)) { return; } Widgets.DrawHighlightIfMouseover(rect); if (pawn == null || includePawnsMassInMassUsage) { float mass = GetMass(anyThing); if (Mouse.IsOver(rect)) { if (pawn != null) { float gearMass = 0f; float invMass = 0f; gearMass = MassUtility.GearMass(pawn); if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignorePawnInventoryMass)) { invMass = MassUtility.InventoryMass(pawn); } TooltipHandler.TipRegion(rect, () => GetPawnMassTip(trad, 0f, mass - gearMass - invMass, gearMass, invMass), trad.GetHashCode() * 59); } else { TooltipHandler.TipRegion(rect, "ItemWeightTip".Translate()); } } if (mass > availableMass) { GUI.color = ColoredText.RedReadable; } else { GUI.color = TransferableOneWayWidget.ItemMassColor; } Widgets.Label(rect, mass.ToStringMass()); } else { float cap = MassUtility.Capacity(pawn, null); float gearMass = MassUtility.GearMass(pawn); float invMass = InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignorePawnInventoryMass) ? 0f : MassUtility.InventoryMass(pawn); float num = cap - gearMass - invMass; if (num > 0f) { GUI.color = Color.green; } else if (num < 0f) { GUI.color = ColoredText.RedReadable; } else { GUI.color = Color.gray; } Widgets.Label(rect, num.ToStringMassOffset()); if (Mouse.IsOver(rect)) { TooltipHandler.TipRegion(rect, () => GetPawnMassTip(trad, cap, 0f, gearMass, invMass), trad.GetHashCode() * 59); } } GUI.color = Color.white; }
public static bool canCarrySidearmType(ThingDefStuffDefPair sidearm, Pawn pawn, out string errString) { float maxCapacity = MassUtility.Capacity(pawn); float freeCapacity = MassUtility.FreeSpace(pawn); float sidearmWeight = sidearm.thing.GetStatValueAbstract(StatDefOf.Mass, sidearm.stuff); if (((pawn.CombinedDisabledWorkTags & WorkTags.Violent) != 0) && (!sidearm.isTool())) { errString = "SidearmPickupFail_NotAToolForPacifist".Translate(pawn.LabelShort); return(false); } //this is duplicated in the switches later but Id rather not risk accidentaly deleting a case that might come up if (!isValidSidearm(sidearm, out errString)) { return(false); } if (sidearmWeight >= freeCapacity) { errString = "SidearmPickupFail_NoFreeSpace".Translate(); return(false); } if (!SimpleSidearms.SeparateModes) { switch (SimpleSidearms.LimitModeSingle.Value) { case LimitModeSingleSidearm.None: break; case LimitModeSingleSidearm.AbsoluteWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingle_Absolute.Value) { errString = "SidearmPickupFail_TooHeavyForSidearm".Translate(); return(false); } break; case LimitModeSingleSidearm.RelativeWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingle_Relative.Value * maxCapacity) { errString = "SidearmPickupFail_TooHeavyForSidearm".Translate(); return(false); } break; case LimitModeSingleSidearm.Selection: if (!SimpleSidearms.LimitModeSingle_Selection.Value.InnerList.Contains <ThingDef>(sidearm.thing)) { errString = "SidearmPickupFail_NotASidearm".Translate(); return(false); } break; } switch (SimpleSidearms.LimitModeAmount.Value) { case LimitModeAmountOfSidearms.MaximumCarryWeightOnly: break; case LimitModeAmountOfSidearms.AbsoluteWeight: if (sidearmWeight >= (SimpleSidearms.LimitModeAmount_Absolute.Value - weightForLimitType(pawn, WeaponSearchType.Both))) { errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate(); return(false); } break; case LimitModeAmountOfSidearms.RelativeWeight: if (sidearmWeight >= ((SimpleSidearms.LimitModeAmount_Relative.Value * maxCapacity) - weightForLimitType(pawn, WeaponSearchType.Both))) { errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate(); return(false); } break; case LimitModeAmountOfSidearms.Slots: if (SimpleSidearms.LimitModeAmount_Slots.Value <= countForLimitType(pawn, WeaponSearchType.Both)) { errString = "SidearmPickupFail_AllSlotsFull".Translate(); return(false); } break; } } else { switch (SimpleSidearms.LimitModeAmountTotal.Value) { case LimitModeAmountOfSidearms.MaximumCarryWeightOnly: break; case LimitModeAmountOfSidearms.AbsoluteWeight: if (sidearmWeight >= (SimpleSidearms.LimitModeAmountTotal_Absolute.Value - weightForLimitType(pawn, WeaponSearchType.Both))) { errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate(); return(false); } break; case LimitModeAmountOfSidearms.RelativeWeight: if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountTotal_Relative.Value * maxCapacity) - weightForLimitType(pawn, WeaponSearchType.Both))) { errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate(); return(false); } break; case LimitModeAmountOfSidearms.Slots: if (SimpleSidearms.LimitModeAmountTotal_Slots.Value <= countForLimitType(pawn, WeaponSearchType.Both)) { errString = "SidearmPickupFail_AllSlotsFull".Translate(); return(false); } break; } if (sidearm.thing.IsMeleeWeapon) { switch (SimpleSidearms.LimitModeSingleMelee.Value) { case LimitModeSingleSidearm.None: break; case LimitModeSingleSidearm.AbsoluteWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingleMelee_Absolute.Value) { errString = "SidearmPickupFail_TooHeavyForSidearmMelee".Translate(); return(false); } break; case LimitModeSingleSidearm.RelativeWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingleMelee_Relative.Value * maxCapacity) { errString = "SidearmPickupFail_TooHeavyForSidearmMelee".Translate(); return(false); } break; case LimitModeSingleSidearm.Selection: if (!SimpleSidearms.LimitModeSingleMelee_Selection.Value.InnerList.Contains <ThingDef>(sidearm.thing)) { errString = "SidearmPickupFail_NotASidearmMelee".Translate(); return(false); } break; } switch (SimpleSidearms.LimitModeAmountMelee.Value) { case LimitModeAmountOfSidearms.MaximumCarryWeightOnly: break; case LimitModeAmountOfSidearms.AbsoluteWeight: if (sidearmWeight >= (SimpleSidearms.LimitModeAmountMelee_Absolute.Value - weightForLimitType(pawn, WeaponSearchType.Melee))) { errString = "SidearmPickupFail_SidearmsTooHeavyMelee".Translate(); return(false); } break; case LimitModeAmountOfSidearms.RelativeWeight: if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountMelee_Relative.Value * maxCapacity) - weightForLimitType(pawn, WeaponSearchType.Melee))) { errString = "SidearmPickupFail_SidearmsTooHeavyMelee".Translate(); return(false); } break; case LimitModeAmountOfSidearms.Slots: if (SimpleSidearms.LimitModeAmountMelee_Slots.Value <= countForLimitType(pawn, WeaponSearchType.Melee)) { errString = "SidearmPickupFail_MeleeSlotsFull".Translate(); return(false); } break; } } else if (sidearm.thing.IsRangedWeapon) { switch (SimpleSidearms.LimitModeSingleRanged.Value) { case LimitModeSingleSidearm.None: break; case LimitModeSingleSidearm.AbsoluteWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingleRanged_Absolute.Value) { errString = "SidearmPickupFail_TooHeavyForSidearmRanged".Translate(); return(false); } break; case LimitModeSingleSidearm.RelativeWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingleRanged_Relative.Value * maxCapacity) { errString = "SidearmPickupFail_TooHeavyForSidearmRanged".Translate(); return(false); } break; case LimitModeSingleSidearm.Selection: if (!SimpleSidearms.LimitModeSingleRanged_Selection.Value.InnerList.Contains <ThingDef>(sidearm.thing)) { errString = "SidearmPickupFail_NotASidearmRanged".Translate(); return(false); } break; } switch (SimpleSidearms.LimitModeAmountRanged.Value) { case LimitModeAmountOfSidearms.MaximumCarryWeightOnly: break; case LimitModeAmountOfSidearms.AbsoluteWeight: if (sidearmWeight >= (SimpleSidearms.LimitModeAmountRanged_Absolute.Value - weightForLimitType(pawn, WeaponSearchType.Ranged))) { errString = "SidearmPickupFail_SidearmsTooHeavyRanged".Translate(); return(false); } break; case LimitModeAmountOfSidearms.RelativeWeight: if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountRanged_Relative.Value * maxCapacity) - weightForLimitType(pawn, WeaponSearchType.Ranged))) { errString = "SidearmPickupFail_SidearmsTooHeavyRanged".Translate(); return(false); } break; case LimitModeAmountOfSidearms.Slots: if (SimpleSidearms.LimitModeAmountRanged_Slots.Value <= countForLimitType(pawn, WeaponSearchType.Ranged)) { errString = "SidearmPickupFail_RangedSlotsFull".Translate(); return(false); } break; } } } errString = "SidearmPickupPass".Translate(); return(true); }
internal static bool canCarrySidearm(ThingDef sidearm, Pawn pawn, out string errString) { float maxCapacity = MassUtility.Capacity(pawn); float freeCapacity = MassUtility.FreeSpace(pawn); float sidearmWeight = sidearm.GetStatValueAbstract(StatDefOf.Mass); //ThingStuffPair sidearmAsThingStuffPair = new ThingStuffPair(sidearm.def, sidearm.Stuff); if (sidearmWeight >= freeCapacity) { errString = "SidearmPickupFail_NoFreeSpace".Translate(); return(false); } if (!SimpleSidearms.SeparateModes) { switch (SimpleSidearms.LimitModeSingle.Value) { case LimitModeSingleSidearm.None: break; case LimitModeSingleSidearm.AbsoluteWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingle_Absolute.Value) { errString = "SidearmPickupFail_TooHeavyForSidearm".Translate(); return(false); } break; case LimitModeSingleSidearm.RelativeWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingle_Relative.Value * maxCapacity) { errString = "SidearmPickupFail_TooHeavyForSidearm".Translate(); return(false); } break; case LimitModeSingleSidearm.Selection: if (!SimpleSidearms.LimitModeSingle_Selection.Value.InnerList.Contains <string>(sidearm.defName)) { errString = "SidearmPickupFail_NotASidearm".Translate(); return(false); } break; } switch (SimpleSidearms.LimitModeAmount.Value) { case LimitModeAmountOfSidearms.MaximumCarryWeightOnly: break; case LimitModeAmountOfSidearms.AbsoluteWeight: if (sidearmWeight >= (SimpleSidearms.LimitModeAmount_Absolute.Value - weightForType(pawn, WeaponSearchType.Both))) { errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate(); return(false); } break; case LimitModeAmountOfSidearms.RelativeWeight: if (sidearmWeight >= ((SimpleSidearms.LimitModeAmount_Relative.Value * maxCapacity) - weightForType(pawn, WeaponSearchType.Both))) { errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate(); return(false); } break; case LimitModeAmountOfSidearms.Slots: if (SimpleSidearms.LimitModeAmount_Slots.Value <= countForType(pawn, WeaponSearchType.Both)) { errString = "SidearmPickupFail_AllSlotsFull".Translate(); return(false); } break; } } else { switch (SimpleSidearms.LimitModeAmountTotal.Value) { case LimitModeAmountOfSidearms.MaximumCarryWeightOnly: break; case LimitModeAmountOfSidearms.AbsoluteWeight: if (sidearmWeight >= (SimpleSidearms.LimitModeAmountTotal_Absolute.Value - weightForType(pawn, WeaponSearchType.Both))) { errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate(); return(false); } break; case LimitModeAmountOfSidearms.RelativeWeight: if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountTotal_Relative.Value * maxCapacity) - weightForType(pawn, WeaponSearchType.Both))) { errString = "SidearmPickupFail_SidearmsTooHeavyInTotal".Translate(); return(false); } break; case LimitModeAmountOfSidearms.Slots: if (SimpleSidearms.LimitModeAmountTotal_Slots.Value <= countForType(pawn, WeaponSearchType.Both)) { errString = "SidearmPickupFail_AllSlotsFull".Translate(); return(false); } break; } if (!sidearm.IsRangedWeapon) { switch (SimpleSidearms.LimitModeSingleMelee.Value) { case LimitModeSingleSidearm.None: break; case LimitModeSingleSidearm.AbsoluteWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingleMelee_Absolute.Value) { errString = "SidearmPickupFail_TooHeavyForSidearmMelee".Translate(); return(false); } break; case LimitModeSingleSidearm.RelativeWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingleMelee_Relative.Value * maxCapacity) { errString = "SidearmPickupFail_TooHeavyForSidearmMelee".Translate(); return(false); } break; case LimitModeSingleSidearm.Selection: if (!SimpleSidearms.LimitModeSingleMelee_Selection.Value.InnerList.Contains <string>(sidearm.defName)) { errString = "SidearmPickupFail_NotASidearmMelee".Translate(); return(false); } break; } switch (SimpleSidearms.LimitModeAmountMelee.Value) { case LimitModeAmountOfSidearms.MaximumCarryWeightOnly: break; case LimitModeAmountOfSidearms.AbsoluteWeight: if (sidearmWeight >= (SimpleSidearms.LimitModeAmountMelee_Absolute.Value - weightForType(pawn, WeaponSearchType.Melee))) { errString = "SidearmPickupFail_SidearmsTooHeavyMelee".Translate(); return(false); } break; case LimitModeAmountOfSidearms.RelativeWeight: if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountMelee_Relative.Value * maxCapacity) - weightForType(pawn, WeaponSearchType.Melee))) { errString = "SidearmPickupFail_SidearmsTooHeavyMelee".Translate(); return(false); } break; case LimitModeAmountOfSidearms.Slots: if (SimpleSidearms.LimitModeAmountMelee_Slots.Value <= countForType(pawn, WeaponSearchType.Melee)) { errString = "SidearmPickupFail_MeleeSlotsFull".Translate(); return(false); } break; } } else { switch (SimpleSidearms.LimitModeSingleRanged.Value) { case LimitModeSingleSidearm.None: break; case LimitModeSingleSidearm.AbsoluteWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingleRanged_Absolute.Value) { errString = "SidearmPickupFail_TooHeavyForSidearmRanged".Translate(); return(false); } break; case LimitModeSingleSidearm.RelativeWeight: if (sidearmWeight >= SimpleSidearms.LimitModeSingleRanged_Relative.Value * maxCapacity) { errString = "SidearmPickupFail_TooHeavyForSidearmRanged".Translate(); return(false); } break; case LimitModeSingleSidearm.Selection: if (!SimpleSidearms.LimitModeSingleRanged_Selection.Value.InnerList.Contains <string>(sidearm.defName)) { errString = "SidearmPickupFail_NotASidearmRanged".Translate(); return(false); } break; } switch (SimpleSidearms.LimitModeAmountRanged.Value) { case LimitModeAmountOfSidearms.MaximumCarryWeightOnly: break; case LimitModeAmountOfSidearms.AbsoluteWeight: if (sidearmWeight >= (SimpleSidearms.LimitModeAmountRanged_Absolute.Value - weightForType(pawn, WeaponSearchType.Ranged))) { errString = "SidearmPickupFail_SidearmsTooHeavyRanged".Translate(); return(false); } break; case LimitModeAmountOfSidearms.RelativeWeight: if (sidearmWeight >= ((SimpleSidearms.LimitModeAmountRanged_Relative.Value * maxCapacity) - weightForType(pawn, WeaponSearchType.Ranged))) { errString = "SidearmPickupFail_SidearmsTooHeavyRanged".Translate(); return(false); } break; case LimitModeAmountOfSidearms.Slots: if (SimpleSidearms.LimitModeAmountRanged_Slots.Value <= countForType(pawn, WeaponSearchType.Ranged)) { errString = "SidearmPickupFail_RangedSlotsFull".Translate(); return(false); } break; } } } errString = "SidearmPickupPass".Translate(); return(true); }
public static bool DrawThingRow(Pawn SelPawn, bool CanControl, ref float y, ref float width, Thing thing, bool inventory) { Color hColor = new Color(1f, 0.8f, 0.8f, 1f); bool IsBiocodedOrLinked(Pawn pawn, Thing athing, bool ainventory) { if (pawn.IsQuestLodger()) { if (ainventory) { return(true); } else { CompBiocodable compBiocodable = athing.TryGetComp <CompBiocodable>(); if (compBiocodable != null && compBiocodable.Biocoded) { return(true); } else { CompBladelinkWeapon compBladelinkWeapon = athing.TryGetComp <CompBladelinkWeapon>(); return(compBladelinkWeapon != null && compBladelinkWeapon.bondedPawn == pawn); } } } else { return(false); } } bool IsLocked(Pawn pawn, Thing athing) { Apparel apparel; return((apparel = (athing as Apparel)) != null && pawn.apparel != null && pawn.apparel.IsLocked(apparel)); } if (!Settings.gui_manual_unload) { return(true); } Rect rect = new Rect(0f, y, width, 28f); if (CanControl && (SelPawn.IsColonistPlayerControlled || SelPawn.Spawned && !SelPawn.Map.IsPlayerHome) && (thing is ThingWithComps) && !IsBiocodedOrLinked(SelPawn, thing, inventory) && !IsLocked(SelPawn, thing)) { Rect rect2 = new Rect(rect.width - 24f, y, 24f, 24f); CompUnloadChecker c = CompUnloadChecker.GetChecker(thing, false, true); if (c.ShouldUnload) { TooltipHandler.TipRegion(rect2, "UnloadThingCancel".Translate()); //weird shenanigans with colors var cl = GUI.color; if (Widgets.ButtonImage(rect2, ContentFinder <Texture2D> .Get("UI/Icons/Unload_Thing_Cancel"), hColor)) { SoundDefOf.Tick_High.PlayOneShotOnCamera(null); c.ShouldUnload = false; if (MassUtility.Capacity(SelPawn, null) < MassUtility.GearAndInventoryMass(SelPawn) && thing.stackCount * thing.GetStatValue(StatDefOf.Mass, true) > 0 && !thing.def.destroyOnDrop) { Thing t; SelPawn.inventory.innerContainer.TryDrop(thing, SelPawn.Position, SelPawn.Map, ThingPlaceMode.Near, out t, null, null); } } GUI.color = cl; } else { TooltipHandler.TipRegion(rect2, "UnloadThing".Translate()); if (Widgets.ButtonImage(rect2, ContentFinder <Texture2D> .Get("UI/Icons/Unload_Thing"))) { SoundDefOf.Tick_High.PlayOneShotOnCamera(null); c.ShouldUnload = true; } } width -= 24f; } return(true); }
private static bool Prefix(PawnGroupMakerParms parms, PawnGroupMaker groupMaker, Pawn trader, List <Thing> wares, List <Pawn> outPawns) { Func <Thing, float> massTotaler = t => t.stackCount * t.GetStatValue(StatDefOf.Mass, true); List <Thing> list = wares.Where(t => !(t is Pawn)).ToList(); list.SortByDescending(massTotaler); float ttlMassThings = list.Sum(massTotaler); float ttlCapacity = 0f; float ttlBodySize = 0f; int numCarriers = 0; IEnumerable <PawnGenOption> carrierKinds = groupMaker.carriers.Where(p => { if (parms.tile != -1) { return(Find.WorldGrid[parms.tile].biome.IsPackAnimalAllowed(p.kind.race)); } return(true); }); PawnKindDef kind = carrierKinds.RandomElementByWeight(x => x.selectionWeight).kind; // No slow or small juveniles Predicate <Pawn> validator = (p => p.ageTracker.CurLifeStage.bodySizeFactor >= 1 && p.GetStatValue(StatDefOf.MoveSpeed, true) >= p.kindDef.race.GetStatValueAbstract(StatDefOf.MoveSpeed) ); // 50/50 chance of uniform carriers (like vanilla) or mixed carriers bool mixedCarriers = Rand.RangeInclusive(0, 1) == 1; // Generate all of the carrier pawns (empty). Either we spawn as many pawns as we need to cover // 120% of the weight of the items, or enough pawns before it seems "unreasonable" based on body // size. for (; ttlCapacity < ttlMassThings * 1.2 && ttlBodySize < 20; numCarriers++) { PawnGenerationRequest request = new PawnGenerationRequest( kind: kind, faction: parms.faction, tile: parms.tile, inhabitant: parms.inhabitants, validatorPreGear: validator ); Pawn pawn = PawnGenerator.GeneratePawn(request); outPawns.Add(pawn); ttlCapacity += MassUtility.Capacity(pawn); // Still can't have 100 chickenmuffalos. That might slow down some PCs. ttlBodySize += Mathf.Max(pawn.BodySize, 0.5f); if (mixedCarriers) { kind = carrierKinds.RandomElementByWeight(x => x.selectionWeight).kind; } } // Add items (in descending order of weight) to randomly chosen pack animals. This isn't the most // efficient routine, as we're trying to be a bit random. If I was trying to be efficient, I would // use something like SortByDescending(p.Capacity) against the existing thing list. foreach (Thing thing in list) { List <Pawn> validPawns = outPawns.FindAll(p => !MassUtility.WillBeOverEncumberedAfterPickingUp(p, thing, thing.stackCount)); if (validPawns.Count() != 0) { validPawns.RandomElement().inventory.innerContainer.TryAdd(thing, true); } else if (thing.stackCount > 1) { // No carrier can handle the full stack; split it up int countLeft = thing.stackCount; int c = 0; // safety counter (while loops can be dangerous) while (countLeft > 0) { validPawns = outPawns.FindAll(p => MassUtility.CountToPickUpUntilOverEncumbered(p, thing) >= 1); if (validPawns.Count() != 0 && c < thing.stackCount) { Pawn pawn = validPawns.RandomElement(); int countToAdd = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(pawn, thing), countLeft); countLeft -= pawn.inventory.innerContainer.TryAdd(thing, countToAdd, true); } else { // Either no carrier can handle a single item, or we're just in some bad while loop breakout. In // any case, force it in, evenly split among all carriers. int splitCount = Mathf.FloorToInt(countLeft / outPawns.Count()); if (splitCount > 0) { outPawns.ForEach(p => p.inventory.innerContainer.TryAdd(thing, splitCount, true)); countLeft -= splitCount * outPawns.Count(); } // Give the remainer to the ones with space (one at a time) while (countLeft > 0) { validPawns = new List <Pawn>(outPawns); validPawns.SortByDescending(p => MassUtility.FreeSpace(p)); validPawns.First().inventory.innerContainer.TryAdd(thing, 1, true); countLeft--; } break; } c++; } } else { // No way to split it; force it in validPawns = new List <Pawn>(outPawns); validPawns.SortByDescending(p => MassUtility.FreeSpace(p)); validPawns.First().inventory.innerContainer.TryAdd(thing, true); } } // Always skip the original method return(false); }