public static Func <int, int> GetBuildingResourcesLeaveCalculator(Thing diedThing, DestroyMode mode) { if (!GenLeaving.CanBuildingLeaveResources(diedThing, mode)) { return((int count) => 0); } switch (mode) { case DestroyMode.Vanish: return((int count) => 0); case DestroyMode.KillFinalize: return((int count) => GenMath.RoundRandom((float)((float)count * 0.5))); case DestroyMode.Deconstruct: return((int count) => GenMath.RoundRandom(Mathf.Min((float)count * diedThing.def.resourcesFractionWhenDeconstructed, (float)(count - 1)))); case DestroyMode.Cancel: return((int count) => GenMath.RoundRandom((float)((float)count * 1.0))); case DestroyMode.FailConstruction: return((int count) => GenMath.RoundRandom((float)((float)count * 0.5))); case DestroyMode.Refund: return((int count) => count); default: throw new ArgumentException("Unknown destroy mode " + mode); } }
public override void Destroy(DestroyMode mode = DestroyMode.Vanish) { bool spawned = base.Spawned; Map map = base.Map; base.Destroy(mode); if (InnerThing == null) { return; } InstallBlueprintUtility.CancelBlueprintsFor(this); if (spawned) { switch (mode) { case DestroyMode.Deconstruct: SoundDefOf.Building_Deconstructed.PlayOneShot(new TargetInfo(base.Position, map)); GenLeaving.DoLeavingsFor(InnerThing, map, mode, this.OccupiedRect()); break; case DestroyMode.KillFinalize: GenLeaving.DoLeavingsFor(InnerThing, map, mode, this.OccupiedRect()); break; } } if (InnerThing is MonumentMarker) { InnerThing.Destroy(); } }
public override void Destroy(DestroyMode mode = DestroyMode.Vanish) { bool spawned = base.Spawned; Map map = base.Map; base.Destroy(mode); if (this.InnerThing != null) { InstallBlueprintUtility.CancelBlueprintsFor(this); if (mode == DestroyMode.Deconstruct && spawned) { SoundDef.Named("BuildingDeconstructed").PlayOneShot(new TargetInfo(base.Position, map, false)); GenLeaving.DoLeavingsFor(this.InnerThing, map, mode, this.OccupiedRect()); } } }
private static Func <int, int> GetBuildingResourcesLeaveCalculator(Thing destroyedThing, DestroyMode mode) { if (!GenLeaving.CanBuildingLeaveResources(destroyedThing, mode)) { return((int count) => 0); } if (mode == DestroyMode.Deconstruct && typeof(Frame).IsAssignableFrom(destroyedThing.GetType())) { mode = DestroyMode.Cancel; } switch (mode) { case DestroyMode.Vanish: return((int count) => 0); case DestroyMode.WillReplace: return((int count) => 0); case DestroyMode.KillFinalize: return((int count) => GenMath.RoundRandom((float)count * 0.5f)); case DestroyMode.Deconstruct: return((int count) => GenMath.RoundRandom(Mathf.Min((float)count * destroyedThing.def.resourcesFractionWhenDeconstructed, (float)(count - 1)))); case DestroyMode.FailConstruction: return((int count) => GenMath.RoundRandom((float)count * 0.5f)); case DestroyMode.Cancel: return((int count) => GenMath.RoundRandom((float)count * 1f)); case DestroyMode.Refund: return((int count) => count); default: throw new ArgumentException("Unknown destroy mode " + mode); } }
public static void DoLeavingsFor(Thing diedThing, Map map, DestroyMode mode, CellRect leavingsRect, Predicate <IntVec3> nearPlaceValidator = null) { if ((Current.ProgramState != ProgramState.Playing && mode != DestroyMode.Refund) || mode == DestroyMode.Vanish) { return; } if (mode == DestroyMode.KillFinalize && diedThing.def.filthLeaving != null) { for (int i = leavingsRect.minZ; i <= leavingsRect.maxZ; i++) { for (int j = leavingsRect.minX; j <= leavingsRect.maxX; j++) { IntVec3 c = new IntVec3(j, 0, i); FilthMaker.MakeFilth(c, map, diedThing.def.filthLeaving, Rand.RangeInclusive(1, 3)); } } } ThingOwner <Thing> thingOwner = new ThingOwner <Thing>(); if (mode == DestroyMode.KillFinalize && diedThing.def.killedLeavings != null) { for (int k = 0; k < diedThing.def.killedLeavings.Count; k++) { Thing thing = ThingMaker.MakeThing(diedThing.def.killedLeavings[k].thingDef, null); thing.stackCount = diedThing.def.killedLeavings[k].count; thingOwner.TryAdd(thing, true); } } if (GenLeaving.CanBuildingLeaveResources(diedThing, mode)) { Frame frame = diedThing as Frame; if (frame != null) { for (int l = frame.resourceContainer.Count - 1; l >= 0; l--) { int num = GenLeaving.GetBuildingResourcesLeaveCalculator(diedThing, mode)(frame.resourceContainer[l].stackCount); if (num > 0) { frame.resourceContainer.TryTransferToContainer(frame.resourceContainer[l], thingOwner, num, true); } } frame.resourceContainer.ClearAndDestroyContents(DestroyMode.Vanish); } else { List <ThingDefCountClass> list = diedThing.CostListAdjusted(); for (int m = 0; m < list.Count; m++) { ThingDefCountClass thingDefCountClass = list[m]; int num2 = GenLeaving.GetBuildingResourcesLeaveCalculator(diedThing, mode)(thingDefCountClass.count); if (num2 > 0 && mode == DestroyMode.KillFinalize && thingDefCountClass.thingDef.slagDef != null) { int count = thingDefCountClass.thingDef.slagDef.smeltProducts.First((ThingDefCountClass pro) => pro.thingDef == ThingDefOf.Steel).count; int num3 = num2 / 2 / 8; for (int n = 0; n < num3; n++) { thingOwner.TryAdd(ThingMaker.MakeThing(thingDefCountClass.thingDef.slagDef, null), true); } num2 -= num3 * count; } if (num2 > 0) { Thing thing2 = ThingMaker.MakeThing(thingDefCountClass.thingDef, null); thing2.stackCount = num2; thingOwner.TryAdd(thing2, true); } } } } List <IntVec3> list2 = leavingsRect.Cells.InRandomOrder(null).ToList <IntVec3>(); int num4 = 0; while (thingOwner.Count > 0) { if (mode == DestroyMode.KillFinalize && !map.areaManager.Home[list2[num4]]) { thingOwner[0].SetForbidden(true, false); } ThingOwner <Thing> thingOwner2 = thingOwner; Thing thing3 = thingOwner[0]; IntVec3 dropLoc = list2[num4]; ThingPlaceMode mode2 = ThingPlaceMode.Near; Thing thing4; ref Thing lastResultingThing = ref thing4; if (!thingOwner2.TryDrop(thing3, dropLoc, map, mode2, out lastResultingThing, null, nearPlaceValidator)) { Log.Warning(string.Concat(new object[] { "Failed to place all leavings for destroyed thing ", diedThing, " at ", leavingsRect.CenterCell }), false); return; } num4++; if (num4 >= list2.Count) { num4 = 0; } }
public static void DoLeavingsFor(Thing diedThing, Map map, DestroyMode mode) { GenLeaving.DoLeavingsFor(diedThing, map, mode, diedThing.OccupiedRect(), null); }
public static void DoLeavingsFor(Thing diedThing, Map map, DestroyMode mode, CellRect leavingsRect) { if (Current.ProgramState != ProgramState.Playing && mode != DestroyMode.Refund) { return; } switch (mode) { case DestroyMode.Vanish: return; case DestroyMode.KillFinalize: if (diedThing.def.filthLeaving != null) { for (int i = leavingsRect.minZ; i <= leavingsRect.maxZ; i++) { for (int j = leavingsRect.minX; j <= leavingsRect.maxX; j++) { IntVec3 c = new IntVec3(j, 0, i); FilthMaker.MakeFilth(c, map, diedThing.def.filthLeaving, Rand.RangeInclusive(1, 3)); } } } break; } ThingOwner <Thing> thingOwner = new ThingOwner <Thing>(); if (mode == DestroyMode.KillFinalize && diedThing.def.killedLeavings != null) { for (int k = 0; k < diedThing.def.killedLeavings.Count; k++) { Thing thing = ThingMaker.MakeThing(diedThing.def.killedLeavings[k].thingDef, null); thing.stackCount = diedThing.def.killedLeavings[k].count; thingOwner.TryAdd(thing, true); } } if (GenLeaving.CanBuildingLeaveResources(diedThing, mode)) { Frame frame = diedThing as Frame; if (frame != null) { for (int num = frame.resourceContainer.Count - 1; num >= 0; num--) { int num2 = GenLeaving.GetBuildingResourcesLeaveCalculator(diedThing, mode)(frame.resourceContainer[num].stackCount); if (num2 > 0) { frame.resourceContainer.TryTransferToContainer(frame.resourceContainer[num], thingOwner, num2, true); } } frame.resourceContainer.ClearAndDestroyContents(DestroyMode.Vanish); } else { List <ThingCountClass> list = diedThing.CostListAdjusted(); for (int l = 0; l < list.Count; l++) { ThingCountClass thingCountClass = list[l]; int num3 = GenLeaving.GetBuildingResourcesLeaveCalculator(diedThing, mode)(thingCountClass.count); if (num3 > 0 && mode == DestroyMode.KillFinalize && thingCountClass.thingDef.slagDef != null) { int count = thingCountClass.thingDef.slagDef.smeltProducts.First((ThingCountClass pro) => pro.thingDef == ThingDefOf.Steel).count; int num4 = num3 / 2 / 8; for (int m = 0; m < num4; m++) { thingOwner.TryAdd(ThingMaker.MakeThing(thingCountClass.thingDef.slagDef, null), true); } num3 -= num4 * count; } if (num3 > 0) { Thing thing2 = ThingMaker.MakeThing(thingCountClass.thingDef, null); thing2.stackCount = num3; thingOwner.TryAdd(thing2, true); } } } } List <IntVec3> list2 = leavingsRect.Cells.InRandomOrder(null).ToList(); int num5 = 0; while (true) { if (thingOwner.Count > 0) { if (mode == DestroyMode.KillFinalize && !((Area)map.areaManager.Home)[list2[num5]]) { thingOwner[0].SetForbidden(true, false); } Thing thing3 = default(Thing); if (thingOwner.TryDrop(thingOwner[0], list2[num5], map, ThingPlaceMode.Near, out thing3, (Action <Thing, int>)null)) { num5++; if (num5 >= list2.Count) { num5 = 0; } continue; } break; } return; } Log.Warning("Failed to place all leavings for destroyed thing " + diedThing + " at " + leavingsRect.CenterCell); }
private static void CacheAccessibleThings(int nearTile) { if (nearTile == cachedAccessibleThingsForTile && RealTime.frameCount == cachedAccessibleThingsForFrame) { return; } cachedAccessibleThings.Clear(); cachedPossiblyAccessibleThings.Clear(); cachedMakeableItemDefs.Clear(); WorldGrid worldGrid = Find.WorldGrid; List <Map> maps = Find.Maps; for (int i = 0; i < maps.Count; i++) { if (!(worldGrid.ApproxDistanceInTiles(nearTile, maps[i].Tile) > 5f)) { ThingOwnerUtility.GetAllThingsRecursively(maps[i], tmpThings, allowUnreal: false); cachedAccessibleThings.AddRange(tmpThings); } } List <Caravan> caravans = Find.WorldObjects.Caravans; for (int j = 0; j < caravans.Count; j++) { if (caravans[j].IsPlayerControlled && !(worldGrid.ApproxDistanceInTiles(nearTile, caravans[j].Tile) > 5f)) { ThingOwnerUtility.GetAllThingsRecursively(caravans[j], tmpThings, allowUnreal: false); cachedAccessibleThings.AddRange(tmpThings); } } for (int k = 0; k < cachedAccessibleThings.Count; k++) { Thing thing = cachedAccessibleThings[k]; cachedPossiblyAccessibleThings.Add(new ThingDefCount(thing.def, thing.stackCount)); if (GenLeaving.CanBuildingLeaveResources(thing, DestroyMode.Deconstruct)) { List <ThingDefCountClass> list = thing.CostListAdjusted(); for (int l = 0; l < list.Count; l++) { int num = Mathf.RoundToInt((float)list[l].count * thing.def.resourcesFractionWhenDeconstructed); if (num > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(list[l].thingDef, num)); cachedMakeableItemDefs.Add(list[l].thingDef); } } } Plant plant = thing as Plant; if (plant != null && (plant.HarvestableNow || plant.HarvestableSoon)) { int num2 = Mathf.RoundToInt(plant.def.plant.harvestYield * Find.Storyteller.difficultyValues.cropYieldFactor); if (num2 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(plant.def.plant.harvestedThingDef, num2)); cachedMakeableItemDefs.Add(plant.def.plant.harvestedThingDef); } } if (!thing.def.butcherProducts.NullOrEmpty()) { for (int m = 0; m < thing.def.butcherProducts.Count; m++) { cachedPossiblyAccessibleThings.Add(thing.def.butcherProducts[m]); cachedMakeableItemDefs.Add(thing.def.butcherProducts[m].thingDef); } } Pawn pawn = thing as Pawn; if (pawn != null) { if (pawn.RaceProps.meatDef != null) { int num3 = Mathf.RoundToInt(pawn.GetStatValue(StatDefOf.MeatAmount)); if (num3 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(pawn.RaceProps.meatDef, num3)); cachedMakeableItemDefs.Add(pawn.RaceProps.meatDef); } } if (pawn.RaceProps.leatherDef != null) { int num4 = GenMath.RoundRandom(pawn.GetStatValue(StatDefOf.LeatherAmount)); if (num4 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(pawn.RaceProps.leatherDef, num4)); cachedMakeableItemDefs.Add(pawn.RaceProps.leatherDef); } } if (!pawn.RaceProps.Humanlike) { PawnKindLifeStage curKindLifeStage = pawn.ageTracker.CurKindLifeStage; if (curKindLifeStage.butcherBodyPart != null) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(curKindLifeStage.butcherBodyPart.thing, 1)); cachedMakeableItemDefs.Add(curKindLifeStage.butcherBodyPart.thing); } } } if (thing.def.smeltable) { List <ThingDefCountClass> list2 = thing.CostListAdjusted(); for (int n = 0; n < list2.Count; n++) { if (!list2[n].thingDef.intricate) { int num5 = Mathf.RoundToInt((float)list2[n].count * 0.25f); if (num5 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(list2[n].thingDef, num5)); cachedMakeableItemDefs.Add(list2[n].thingDef); } } } } if (thing.def.smeltable && !thing.def.smeltProducts.NullOrEmpty()) { for (int num6 = 0; num6 < thing.def.smeltProducts.Count; num6++) { cachedPossiblyAccessibleThings.Add(thing.def.smeltProducts[num6]); cachedMakeableItemDefs.Add(thing.def.smeltProducts[num6].thingDef); } } } int num7 = 0; for (int num8 = 0; num8 < cachedAccessibleThings.Count; num8++) { Pawn pawn2 = cachedAccessibleThings[num8] as Pawn; if (pawn2 != null && pawn2.IsFreeColonist && !pawn2.Dead && !pawn2.Downed && pawn2.workSettings.WorkIsActive(WorkTypeDefOf.Crafting)) { num7++; } } if (num7 > 0) { tmpWorkTables.Clear(); for (int num9 = 0; num9 < cachedAccessibleThings.Count; num9++) { Building_WorkTable building_WorkTable = cachedAccessibleThings[num9] as Building_WorkTable; if (building_WorkTable == null || !building_WorkTable.Spawned || !tmpWorkTables.Add(building_WorkTable.def)) { continue; } List <RecipeDef> allRecipes = building_WorkTable.def.AllRecipes; for (int num10 = 0; num10 < allRecipes.Count; num10++) { if (!allRecipes[num10].AvailableNow || !allRecipes[num10].AvailableOnNow(building_WorkTable) || !allRecipes[num10].products.Any() || allRecipes[num10].PotentiallyMissingIngredients(null, building_WorkTable.Map).Any()) { continue; } ThingDef stuffDef = (allRecipes[num10].products[0].thingDef.MadeFromStuff ? GenStuff.DefaultStuffFor(allRecipes[num10].products[0].thingDef) : null); float num11 = allRecipes[num10].WorkAmountTotal(stuffDef); if (num11 <= 0f) { continue; } int num12 = Mathf.FloorToInt((float)(num7 * 60000 * 5) * 0.09f / num11); if (num12 > 0) { for (int num13 = 0; num13 < allRecipes[num10].products.Count; num13++) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(allRecipes[num10].products[num13].thingDef, allRecipes[num10].products[num13].count * num12)); cachedMakeableItemDefs.Add(allRecipes[num10].products[num13].thingDef); } } } } } cachedAccessibleThingsForTile = nearTile; cachedAccessibleThingsForFrame = RealTime.frameCount; }
private static void CacheAccessibleThings(int nearTile) { if (nearTile != PlayerItemAccessibilityUtility.cachedAccessibleThingsForTile || RealTime.frameCount != PlayerItemAccessibilityUtility.cachedAccessibleThingsForFrame) { PlayerItemAccessibilityUtility.cachedAccessibleThings.Clear(); PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Clear(); WorldGrid worldGrid = Find.WorldGrid; List <Map> maps = Find.Maps; for (int i = 0; i < maps.Count; i++) { float num = worldGrid.ApproxDistanceInTiles(nearTile, maps[i].Tile); if (num <= 5f) { ThingOwnerUtility.GetAllThingsRecursively(maps[i], PlayerItemAccessibilityUtility.tmpThings, false, null); PlayerItemAccessibilityUtility.cachedAccessibleThings.AddRange(PlayerItemAccessibilityUtility.tmpThings); } } List <Caravan> caravans = Find.WorldObjects.Caravans; for (int j = 0; j < caravans.Count; j++) { if (caravans[j].IsPlayerControlled) { float num2 = worldGrid.ApproxDistanceInTiles(nearTile, caravans[j].Tile); if (num2 <= 5f) { ThingOwnerUtility.GetAllThingsRecursively(caravans[j], PlayerItemAccessibilityUtility.tmpThings, false, null); PlayerItemAccessibilityUtility.cachedAccessibleThings.AddRange(PlayerItemAccessibilityUtility.tmpThings); } } } for (int k = 0; k < PlayerItemAccessibilityUtility.cachedAccessibleThings.Count; k++) { Thing thing = PlayerItemAccessibilityUtility.cachedAccessibleThings[k]; PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(new ThingDefCount(thing.def, thing.stackCount)); if (GenLeaving.CanBuildingLeaveResources(thing, DestroyMode.Deconstruct)) { List <ThingDefCountClass> list = thing.CostListAdjusted(); for (int l = 0; l < list.Count; l++) { int num3 = Mathf.RoundToInt((float)list[l].count * thing.def.resourcesFractionWhenDeconstructed); if (num3 > 0) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(new ThingDefCount(list[l].thingDef, num3)); } } } Plant plant = thing as Plant; if (plant != null) { if (plant.HarvestableNow || plant.HarvestableSoon) { int num4 = Mathf.RoundToInt(plant.def.plant.harvestYield * Find.Storyteller.difficulty.cropYieldFactor); if (num4 > 0) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(new ThingDefCount(plant.def.plant.harvestedThingDef, num4)); } } } if (!thing.def.butcherProducts.NullOrEmpty <ThingDefCountClass>()) { for (int m = 0; m < thing.def.butcherProducts.Count; m++) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(thing.def.butcherProducts[m]); } } Pawn pawn = thing as Pawn; if (pawn != null) { if (pawn.RaceProps.meatDef != null) { int num5 = Mathf.RoundToInt(pawn.GetStatValue(StatDefOf.MeatAmount, true)); if (num5 > 0) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(new ThingDefCount(pawn.RaceProps.meatDef, num5)); } } if (pawn.RaceProps.leatherDef != null) { int num6 = GenMath.RoundRandom(pawn.GetStatValue(StatDefOf.LeatherAmount, true)); if (num6 > 0) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(new ThingDefCount(pawn.RaceProps.leatherDef, num6)); } } if (!pawn.RaceProps.Humanlike) { PawnKindLifeStage curKindLifeStage = pawn.ageTracker.CurKindLifeStage; if (curKindLifeStage.butcherBodyPart != null) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(new ThingDefCount(curKindLifeStage.butcherBodyPart.thing, 1)); } } } if (thing.def.smeltable) { List <ThingDefCountClass> list2 = thing.CostListAdjusted(); for (int n = 0; n < list2.Count; n++) { if (!list2[n].thingDef.intricate) { int num7 = Mathf.RoundToInt((float)list2[n].count * 0.25f); if (num7 > 0) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(new ThingDefCount(list2[n].thingDef, num7)); } } } } if (thing.def.smeltable && !thing.def.smeltProducts.NullOrEmpty <ThingDefCountClass>()) { for (int num8 = 0; num8 < thing.def.smeltProducts.Count; num8++) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(thing.def.smeltProducts[num8]); } } } int num9 = 0; for (int num10 = 0; num10 < PlayerItemAccessibilityUtility.cachedAccessibleThings.Count; num10++) { Pawn pawn2 = PlayerItemAccessibilityUtility.cachedAccessibleThings[num10] as Pawn; if (pawn2 != null && pawn2.IsFreeColonist && !pawn2.Dead && !pawn2.Downed && pawn2.workSettings.WorkIsActive(WorkTypeDefOf.Crafting)) { num9++; } } if (num9 > 0) { PlayerItemAccessibilityUtility.tmpWorkTables.Clear(); for (int num11 = 0; num11 < PlayerItemAccessibilityUtility.cachedAccessibleThings.Count; num11++) { Building_WorkTable building_WorkTable = PlayerItemAccessibilityUtility.cachedAccessibleThings[num11] as Building_WorkTable; if (building_WorkTable != null && building_WorkTable.Spawned && PlayerItemAccessibilityUtility.tmpWorkTables.Add(building_WorkTable.def)) { List <RecipeDef> allRecipes = building_WorkTable.def.AllRecipes; for (int num12 = 0; num12 < allRecipes.Count; num12++) { if (allRecipes[num12].AvailableNow) { if (allRecipes[num12].products.Any <ThingDefCountClass>()) { if (!allRecipes[num12].PotentiallyMissingIngredients(null, building_WorkTable.Map).Any <ThingDef>()) { ThingDef stuffDef = (!allRecipes[num12].products[0].thingDef.MadeFromStuff) ? null : GenStuff.DefaultStuffFor(allRecipes[num12].products[0].thingDef); float num13 = allRecipes[num12].WorkAmountTotal(stuffDef); if (num13 > 0f) { int num14 = Mathf.FloorToInt((float)(num9 * 60000 * 5) * 0.09f / num13); if (num14 > 0) { for (int num15 = 0; num15 < allRecipes[num12].products.Count; num15++) { PlayerItemAccessibilityUtility.cachedPossiblyAccessibleThings.Add(new ThingDefCount(allRecipes[num12].products[num15].thingDef, allRecipes[num12].products[num15].count * num14)); } } } } } } } } } } PlayerItemAccessibilityUtility.cachedAccessibleThingsForTile = nearTile; PlayerItemAccessibilityUtility.cachedAccessibleThingsForFrame = RealTime.frameCount; } }