private float GetMass(Thing thing) { if (thing == null) { return(0f); } float num = thing.GetStatValue(StatDefOf.Mass, true); if (thing is Pawn pawn) { if (InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignorePawnInventoryMass)) { num -= MassUtility.InventoryMass(pawn); } } else if (ignoreSpawnedCorpseGearAndInventoryMass) { if (thing is Corpse corpse && corpse.Spawned) { num -= MassUtility.GearAndInventoryMass(corpse.InnerPawn); } } return(num); }
public static void PushEffect(Thing caster, Thing target, float damageAbsorbedPercent, HediffCompProperties_Knockback props) { if (target is Pawn pawn && pawn.Spawned && !pawn.Downed && !pawn.Dead && pawn.MapHeld != null) { var origDistance = props.knockDistance.RandomInRange; if (origDistance == 0) { return; } var distanceAbsorbedFactor = props.knockDistanceAbsorbedPercentCurve.Evaluate(damageAbsorbedPercent); var pawnMass = pawn.GetStatValue(StatDefOf.Mass); var inventoryMass = MassUtility.InventoryMass(pawn); var distanceMassFactor = props.knockDistanceMassCurve.Evaluate(pawnMass - inventoryMass); var distance = origDistance * distanceAbsorbedFactor * distanceMassFactor; DebugMessage($"PushEffect(caster: {caster}, target: {target}, damageAbsorbedPercent: {damageAbsorbedPercent}): " + $"distanceAbsorbedFactor = absorbedPercentCurve({damageAbsorbedPercent}) = {distanceAbsorbedFactor}; " + $"distanceMassFactor = massCurve({pawnMass}-{inventoryMass}={pawnMass - inventoryMass}) = {distanceMassFactor}; " + $"distance = ({props.knockDistance} => {origDistance}) * {distanceAbsorbedFactor} * {distanceMassFactor} = {distance}"); var destLoc = PushResult(caster, target, distance, out var actualDistance, out var collision); if (props.knockbackThought != null && (collision || actualDistance > 0f) && pawn.RaceProps.Humanlike) { pawn.needs.mood.thoughts.memories.TryGainMemory(props.knockbackThought); } DamageInfo?impactDinfo = null; // Always calculate impactDinfo if we need a FlyingObject, in case something exists at destination // by the time the FlyingObject arrives at it. if (collision || actualDistance > 0f) { var distancePercent = actualDistance / distance; var origImpactDamage = props.knockImpactDamage.RandomInRange; var impactDamageFactor = props.knockImpactDamageDistancePercentCurve.Evaluate(distancePercent); var impactDamage = origImpactDamage * impactDamageFactor; DebugMessage($"PushEffect(caster: {caster}, target: {target}, damageAbsorbedPercent: {damageAbsorbedPercent}): " + $"impactDamageFactor = distanceCurve({actualDistance}/{distance}={distancePercent}) = {impactDamageFactor}; " + $"impactDamage = ({props.knockImpactDamage} => {origImpactDamage}) * {impactDamageFactor} = {impactDamage}"); if (impactDamage > 0f) { impactDinfo = new DamageInfo(props.knockImpactDamageType, impactDamage); } } if (actualDistance > 0f) { var flyingObject = (FlyingObject)GenSpawn.Spawn(MiscDefOf.JT_FlyingObject, target.PositionHeld, target.MapHeld); flyingObject.Props.speed = props.knockbackSpeed; flyingObject.Launch(caster, destLoc.ToIntVec3(), target, impactDinfo); DebugMessage($"PushEffect(caster: {caster}, target: {target}, damageAbsorbedPercent: {damageAbsorbedPercent}): " + $"flyingObject = {flyingObject}"); } else if (impactDinfo is DamageInfo immediateImpactDinfo) { DebugMessage($"PushEffect(caster: {caster}, target: {target}, damageAbsorbedPercent: {damageAbsorbedPercent}): " + $"immediateImpactDinfo = {immediateImpactDinfo}"); target.TakeDamage(immediateImpactDinfo); } } }
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 IEnumerable<Gizmo> LaunchAndBombGizmosPassthrough(IEnumerable<Gizmo> __result, Caravan __instance) { IEnumerator<Gizmo> enumerator = __result.GetEnumerator(); while (enumerator.MoveNext()) { var element = enumerator.Current; yield return element; if ((element as Command_Action)?.defaultLabel == "CommandSettle".Translate() && __instance.PawnsListForReading.Any(x => x.inventory.innerContainer.Any(y => y.TryGetComp<CompLaunchableSRTS>() != null))) { float massUsage = 0f; Thing srts = null; foreach (Pawn p in __instance.PawnsListForReading) { foreach (Thing t in p.inventory?.innerContainer) { if (t.TryGetComp<CompLaunchableSRTS>() != null) srts = t; else { massUsage += t.GetStatValue(StatDefOf.Mass, true) * t.stackCount; } } massUsage += p.GetStatValue(StatDefOf.Mass, true); massUsage -= MassUtility.InventoryMass(p) * p.stackCount; } yield return new Command_Action { defaultLabel = "CommandLaunchGroup".Translate(), defaultDesc = "CommandLaunchGroupDesc".Translate(), icon = Tex2D.LaunchSRTS, alsoClickIfOtherInGroupClicked = false, action = delegate () { if (massUsage > SRTSMod.GetStatFor<float>(srts.def.defName, StatName.massCapacity)) Messages.Message("TooBigTransportersMassUsage".Translate(), MessageTypeDefOf.RejectInput, false); else srts.TryGetComp<CompLaunchableSRTS>().WorldStartChoosingDestination(__instance); } }; /* Not Yet Implemented */ /*yield return new Command_Action { defaultLabel = "BombTarget".Translate(), defaultDesc = "BombTargetDesc".Translate(), icon = TexCommand.Attack, action = delegate () { if(SRTSMod.mod.settings.passengerLimits) { if(__instance.PawnsListForReading.Count < SRTSMod.GetStatFor<int>(srts.def.defName, StatName.minPassengers)) { Messages.Message("NotEnoughPilots".Translate(), MessageTypeDefOf.RejectInput, false); return; } else if(__instance.PawnsListForReading.Count > SRTSMod.GetStatFor<int>(srts.def.defName, StatName.maxPassengers)) { Messages.Message("TooManyPilots".Translate(), MessageTypeDefOf.RejectInput, false); return; } } FloatMenuOption carpetBombing = new FloatMenuOption("CarpetBombing".Translate(), delegate () { srts.TryGetComp<CompBombFlyer>().bombType = BombingType.carpet; srts.TryGetComp<CompBombFlyer>().StartChoosingWorldDestinationBomb(__instance); }); FloatMenuOption preciseBombing = new FloatMenuOption("PreciseBombing".Translate(), delegate () { srts.TryGetComp<CompBombFlyer>().bombType = BombingType.precise; srts.TryGetComp<CompBombFlyer>().StartChoosingWorldDestinationBomb(__instance); }); Find.WindowStack.Add(new FloatMenuGizmo(new List<FloatMenuOption>() { carpetBombing, preciseBombing }, srts, srts.LabelCap, UI.MouseMapPosition())); } };*/ Command_Action RefuelSRTS = new Command_Action() { defaultLabel = "CommandAddFuelSRTS".Translate(srts.TryGetComp<CompRefuelable>().parent.Label), defaultDesc = "CommandAddFuelDescSRTS".Translate(), icon = Tex2D.FuelSRTS, alsoClickIfOtherInGroupClicked = false, action = delegate () { bool flag = false; int count = 0; List<Thing> thingList = CaravanInventoryUtility.AllInventoryItems(__instance); for (int index = 0; index < thingList.Count; ++index) { if (thingList[index].def == ThingDefOf.Chemfuel) { count = thingList[index].stackCount; Pawn ownerOf = CaravanInventoryUtility.GetOwnerOf(__instance, thingList[index]); float num = srts.TryGetComp<CompRefuelable>().Props.fuelCapacity - srts.TryGetComp<CompRefuelable>().Fuel; if ((double)num < 1.0 && (double)num > 0.0) count = 1; if ((double)count * 1.0 >= (double)num) count = (int)num; if ((double)thingList[index].stackCount * 1.0 <= (double)count) { thingList[index].stackCount -= count; Thing thing = thingList[index]; ownerOf.inventory.innerContainer.Remove(thing); thing.Destroy(DestroyMode.Vanish); } else if ((uint)count > 0U) thingList[index].SplitOff(count).Destroy(DestroyMode.Vanish); srts.TryGetComp<CompRefuelable>().GetType().GetField("fuel", BindingFlags.Instance | BindingFlags.NonPublic).SetValue((object)srts.TryGetComp<CompRefuelable>(), (object)(float)((double)srts.TryGetComp<CompRefuelable>().Fuel + (double)count)); flag = true; break; } } if (flag) Messages.Message("AddFuelSRTSCaravan".Translate(count, srts.LabelCap), MessageTypeDefOf.PositiveEvent, false); else Messages.Message("NoFuelSRTSCaravan".Translate(), MessageTypeDefOf.RejectInput, false); } }; if (srts.TryGetComp<CompRefuelable>().IsFull) RefuelSRTS.Disable(); yield return RefuelSRTS; yield return new Gizmo_MapRefuelableFuelStatus { nowFuel = srts.TryGetComp<CompRefuelable>().Fuel, maxFuel = srts.TryGetComp<CompRefuelable>().Props.fuelCapacity, compLabel = srts.TryGetComp<CompRefuelable>().Props.FuelGizmoLabel }; } } }