// Detours public static void SimulationStep(ref ZoneBlock zoneBlock, ushort blockID) { // This is the decompiled ZoneBlock.SimulationStep() method // Segments which were changed are marked with "begin mod" and "end mod" if (Debugger.Enabled && debugCount < 10) { debugCount++; Debugger.LogFormat("Building Themes: Detoured ZoneBlock.SimulationStep was called. blockID: {0}, position: {1}.", blockID, zoneBlock.m_position); } ZoneManager zoneManager = Singleton <ZoneManager> .instance; int rowCount = zoneBlock.RowCount; float m_angle = zoneBlock.m_angle; Vector2 xDirection = new Vector2(Mathf.Cos(m_angle), Mathf.Sin(m_angle)) * 8f; Vector2 zDirection = new Vector2(xDirection.y, -xDirection.x); ulong num = zoneBlock.m_valid & ~(zoneBlock.m_occupied1 | zoneBlock.m_occupied2); int spawnpointRow = 0; ItemClass.Zone zone = ItemClass.Zone.Unzoned; int num3 = 0; while (num3 < 4 && zone == ItemClass.Zone.Unzoned) { spawnpointRow = Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)rowCount); if ((num & 1uL << (spawnpointRow << 3)) != 0uL) { zone = zoneBlock.GetZone(0, spawnpointRow); } num3++; } DistrictManager instance2 = Singleton <DistrictManager> .instance; Vector3 m_position = (Vector3)zoneBlock.m_position; byte district = instance2.GetDistrict(m_position); int num4; switch (zone) { case ItemClass.Zone.ResidentialLow: num4 = zoneManager.m_actualResidentialDemand; num4 += instance2.m_districts.m_buffer[(int)district].CalculateResidentialLowDemandOffset(); break; case ItemClass.Zone.ResidentialHigh: num4 = zoneManager.m_actualResidentialDemand; num4 += instance2.m_districts.m_buffer[(int)district].CalculateResidentialHighDemandOffset(); break; case ItemClass.Zone.CommercialLow: num4 = zoneManager.m_actualCommercialDemand; num4 += instance2.m_districts.m_buffer[(int)district].CalculateCommercialLowDemandOffset(); break; case ItemClass.Zone.CommercialHigh: num4 = zoneManager.m_actualCommercialDemand; num4 += instance2.m_districts.m_buffer[(int)district].CalculateCommercialHighDemandOffset(); break; case ItemClass.Zone.Industrial: num4 = zoneManager.m_actualWorkplaceDemand; num4 += instance2.m_districts.m_buffer[(int)district].CalculateIndustrialDemandOffset(); break; case ItemClass.Zone.Office: num4 = zoneManager.m_actualWorkplaceDemand; num4 += instance2.m_districts.m_buffer[(int)district].CalculateOfficeDemandOffset(); break; default: return; } Vector2 a = VectorUtils.XZ(m_position); Vector2 vector3 = a - 3.5f * xDirection + ((float)spawnpointRow - 3.5f) * zDirection; int[] tmpXBuffer = zoneManager.m_tmpXBuffer; for (int i = 0; i < 13; i++) { tmpXBuffer[i] = 0; } Quad2 quad = default(Quad2); quad.a = a - 4f * xDirection + ((float)spawnpointRow - 10f) * zDirection; quad.b = a + 3f * xDirection + ((float)spawnpointRow - 10f) * zDirection; quad.c = a + 3f * xDirection + ((float)spawnpointRow + 2f) * zDirection; quad.d = a - 4f * xDirection + ((float)spawnpointRow + 2f) * zDirection; Vector2 vector4 = quad.Min(); Vector2 vector5 = quad.Max(); //begin mod int num5 = Mathf.Max((int)((vector4.x - 46f) / 64f + _zoneGridHalfResolution), 0); int num6 = Mathf.Max((int)((vector4.y - 46f) / 64f + _zoneGridHalfResolution), 0); int num7 = Mathf.Min((int)((vector5.x + 46f) / 64f + _zoneGridHalfResolution), _zoneGridResolution - 1); int num8 = Mathf.Min((int)((vector5.y + 46f) / 64f + _zoneGridHalfResolution), _zoneGridResolution - 1); //end mod for (int j = num6; j <= num8; j++) { for (int k = num5; k <= num7; k++) { //begin mod ushort num9 = zoneManager.m_zoneGrid[j * _zoneGridResolution + k]; //end mod int num10 = 0; while (num9 != 0) { Vector3 positionVar = zoneManager.m_blocks.m_buffer[(int)num9].m_position; float num11 = Mathf.Max(Mathf.Max(vector4.x - 46f - positionVar.x, vector4.y - 46f - positionVar.z), Mathf.Max(positionVar.x - vector5.x - 46f, positionVar.z - vector5.y - 46f)); if (num11 < 0f) { _CheckBlock.Invoke(zoneBlock, new object[] { zoneManager.m_blocks.m_buffer[(int)num9], tmpXBuffer, zone, vector3, xDirection, zDirection, quad }); } num9 = zoneManager.m_blocks.m_buffer[(int)num9].m_nextGridBlock; if (++num10 >= 49152) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } for (int l = 0; l < 13; l++) { uint num12 = (uint)tmpXBuffer[l]; int num13 = 0; bool flag = (num12 & 196608u) == 196608u; bool flag2 = false; while ((num12 & 1u) != 0u) { num13++; flag2 = ((num12 & 65536u) != 0u); num12 >>= 1; } if (num13 == 5 || num13 == 6) { if (flag2) { num13 -= Singleton <SimulationManager> .instance.m_randomizer.Int32(2u) + 2; } else { num13 = 4; } num13 |= 131072; } else if (num13 == 7) { num13 = 4; num13 |= 131072; } if (flag) { num13 |= 65536; } tmpXBuffer[l] = num13; } int num14 = tmpXBuffer[6] & 65535; if (num14 == 0) { return; } bool flag3 = (bool)_IsGoodPlace.Invoke(zoneBlock, new object[] { vector3 }); if (Singleton <SimulationManager> .instance.m_randomizer.Int32(100u) >= num4) { if (flag3) { zoneManager.m_goodAreaFound[(int)zone] = 1024; } return; } if (!flag3 && zoneManager.m_goodAreaFound[(int)zone] > -1024) { if (zoneManager.m_goodAreaFound[(int)zone] == 0) { zoneManager.m_goodAreaFound[(int)zone] = -1; } return; } int num15 = 6; int num16 = 6; bool flag4 = true; while (true) { if (flag4) { while (num15 != 0) { if ((tmpXBuffer[num15 - 1] & 65535) != num14) { break; } num15--; } while (num16 != 12) { if ((tmpXBuffer[num16 + 1] & 65535) != num14) { break; } num16++; } } else { while (num15 != 0) { if ((tmpXBuffer[num15 - 1] & 65535) < num14) { break; } num15--; } while (num16 != 12) { if ((tmpXBuffer[num16 + 1] & 65535) < num14) { break; } num16++; } } int num17 = num15; int num18 = num16; while (num17 != 0) { if ((tmpXBuffer[num17 - 1] & 65535) < 2) { break; } num17--; } while (num18 != 12) { if ((tmpXBuffer[num18 + 1] & 65535) < 2) { break; } num18++; } bool flag5 = num17 != 0 && num17 == num15 - 1; bool flag6 = num18 != 12 && num18 == num16 + 1; if (flag5 && flag6) { if (num16 - num15 > 2) { break; } if (num14 <= 2) { if (!flag4) { goto Block_34; } } else { num14--; } } else if (flag5) { if (num16 - num15 > 1) { goto Block_36; } if (num14 <= 2) { if (!flag4) { goto Block_38; } } else { num14--; } } else if (flag6) { if (num16 - num15 > 1) { goto Block_40; } if (num14 <= 2) { if (!flag4) { goto Block_42; } } else { num14--; } } else { if (num15 != num16) { goto IL_884; } if (num14 <= 2) { if (!flag4) { goto Block_45; } } else { num14--; } } flag4 = false; } num15++; num16--; Block_34: goto IL_891; Block_36: num15++; Block_38: goto IL_891; Block_40: num16--; Block_42: Block_45: IL_884: IL_891: int num19; int num20; if (num14 == 1 && num16 - num15 >= 1) { num15 += Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)(num16 - num15)); num16 = num15 + 1; num19 = num15 + Singleton <SimulationManager> .instance.m_randomizer.Int32(2u); num20 = num19; } else { do { num19 = num15; num20 = num16; if (num16 - num15 == 2) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2u) == 0) { num20--; } else { num19++; } } else if (num16 - num15 == 3) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2u) == 0) { num20 -= 2; } else { num19 += 2; } } else if (num16 - num15 == 4) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2u) == 0) { num16 -= 2; num20 -= 3; } else { num15 += 2; num19 += 3; } } else if (num16 - num15 == 5) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2u) == 0) { num16 -= 3; num20 -= 2; } else { num15 += 3; num19 += 2; } } else if (num16 - num15 >= 6) { if (num15 == 0 || num16 == 12) { if (num15 == 0) { num15 = 3; num19 = 2; } if (num16 == 12) { num16 = 9; num20 = 10; } } else if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2u) == 0) { num16 = num15 + 3; num20 = num19 + 2; } else { num15 = num16 - 3; num19 = num20 - 2; } } }while (num16 - num15 > 3 || num20 - num19 > 3); } int depth_A = 4; int width_A = num16 - num15 + 1; BuildingInfo.ZoningMode zoningMode = BuildingInfo.ZoningMode.Straight; bool flag7 = true; for (int m = num15; m <= num16; m++) { depth_A = Mathf.Min(depth_A, tmpXBuffer[m] & 65535); if ((tmpXBuffer[m] & 131072) == 0) { flag7 = false; } } if (num16 > num15) { if ((tmpXBuffer[num15] & 65536) != 0) { zoningMode = BuildingInfo.ZoningMode.CornerLeft; num20 = num15 + num20 - num19; num19 = num15; } if ((tmpXBuffer[num16] & 65536) != 0 && (zoningMode != BuildingInfo.ZoningMode.CornerLeft || Singleton <SimulationManager> .instance.m_randomizer.Int32(2u) == 0)) { zoningMode = BuildingInfo.ZoningMode.CornerRight; num19 = num16 + num19 - num20; num20 = num16; } } int depth_B = 4; int width_B = num20 - num19 + 1; BuildingInfo.ZoningMode zoningMode2 = BuildingInfo.ZoningMode.Straight; bool flag8 = true; for (int n = num19; n <= num20; n++) { depth_B = Mathf.Min(depth_B, tmpXBuffer[n] & 65535); if ((tmpXBuffer[n] & 131072) == 0) { flag8 = false; } } if (num20 > num19) { if ((tmpXBuffer[num19] & 65536) != 0) { zoningMode2 = BuildingInfo.ZoningMode.CornerLeft; } if ((tmpXBuffer[num20] & 65536) != 0 && (zoningMode2 != BuildingInfo.ZoningMode.CornerLeft || Singleton <SimulationManager> .instance.m_randomizer.Int32(2u) == 0)) { zoningMode2 = BuildingInfo.ZoningMode.CornerRight; } } ItemClass.SubService subService = ItemClass.SubService.None; ItemClass.Level level = ItemClass.Level.Level1; ItemClass.Service service; switch (zone) { case ItemClass.Zone.ResidentialLow: service = ItemClass.Service.Residential; subService = ItemClass.SubService.ResidentialLow; break; case ItemClass.Zone.ResidentialHigh: service = ItemClass.Service.Residential; subService = ItemClass.SubService.ResidentialHigh; break; case ItemClass.Zone.CommercialLow: service = ItemClass.Service.Commercial; subService = ItemClass.SubService.CommercialLow; break; case ItemClass.Zone.CommercialHigh: service = ItemClass.Service.Commercial; subService = ItemClass.SubService.CommercialHigh; break; case ItemClass.Zone.Industrial: service = ItemClass.Service.Industrial; break; case ItemClass.Zone.Office: service = ItemClass.Service.Office; subService = ItemClass.SubService.None; break; default: return; } BuildingInfo buildingInfo = null; Vector3 vector6 = Vector3.zero; int num25_row = 0; int length = 0; int width = 0; BuildingInfo.ZoningMode zoningMode3 = BuildingInfo.ZoningMode.Straight; int num28 = 0; // begin mod int depth_alt = Mathf.Min(depth_A, 4); int width_alt = width_A; // end mod while (num28 < 8) // while (num28 < 6) { switch (num28) { // Corner cases case 0: if (zoningMode != BuildingInfo.ZoningMode.Straight) { num25_row = num15 + num16 + 1; length = depth_A; width = width_A; zoningMode3 = zoningMode; goto IL_D6A; } break; case 1: if (zoningMode2 != BuildingInfo.ZoningMode.Straight) { num25_row = num19 + num20 + 1; length = depth_B; width = width_B; zoningMode3 = zoningMode2; goto IL_D6A; } break; case 2: if (zoningMode != BuildingInfo.ZoningMode.Straight) { if (depth_A >= 4) { num25_row = num15 + num16 + 1; length = ((!flag7) ? 2 : 3); width = width_A; zoningMode3 = zoningMode; goto IL_D6A; } } break; case 3: if (zoningMode2 != BuildingInfo.ZoningMode.Straight) { if (depth_B >= 4) { num25_row = num19 + num20 + 1; length = ((!flag8) ? 2 : 3); width = width_B; zoningMode3 = zoningMode2; goto IL_D6A; } } break; // begin mod case 4: if (zoningMode != BuildingInfo.ZoningMode.Straight) { if (width_alt > 1) { width_alt--; } else if (depth_alt > 1) { depth_alt--; width_alt = width_A; } else { break; } if (width_alt == width_A) { num25_row = num15 + num16 + 1; } else { if (zoningMode == BuildingInfo.ZoningMode.CornerLeft) { num25_row = num15 + num16 + 1 - (width_A - width_alt); } else { num25_row = num15 + num16 + 1 + (width_A - width_alt); } } length = depth_alt; width = width_alt; zoningMode3 = zoningMode; num28--; goto IL_D6A; } break; // end mod // Straight cases case 5: num25_row = num15 + num16 + 1; length = depth_A; width = width_A; zoningMode3 = BuildingInfo.ZoningMode.Straight; goto IL_D6A; case 6: // begin mod // reset variables depth_alt = Mathf.Min(depth_A, 4); width_alt = width_A; // end mod //int width_B = num20 - num19 + 1; num25_row = num19 + num20 + 1; length = depth_B; width = width_B; zoningMode3 = BuildingInfo.ZoningMode.Straight; goto IL_D6A; // begin mod case 7: if (width_alt > 1) { width_alt--; } else { break; } if (width_alt == width_A) { num25_row = num15 + num16 + 1; } else if (width_A % 2 != width_alt % 2) { num25_row = num15 + num16; } else { num25_row = num15 + num16 + 1; } length = depth_alt; width = width_alt; zoningMode3 = BuildingInfo.ZoningMode.Straight; num28--; goto IL_D6A; // end mod default: goto IL_D6A; } IL_DF0: num28++; continue; IL_D6A: vector6 = m_position + VectorUtils.X_Y(((float)length * 0.5f - 4f) * xDirection + ((float)num25_row * 0.5f + (float)spawnpointRow - 10f) * zDirection); if (zone == ItemClass.Zone.Industrial) { ZoneBlock.GetIndustryType(vector6, out subService, out level); } else if (zone == ItemClass.Zone.CommercialLow || zone == ItemClass.Zone.CommercialHigh) { ZoneBlock.GetCommercialType(vector6, zone, width, length, out subService, out level); } byte district2 = instance2.GetDistrict(vector6); ushort style = instance2.m_districts.m_buffer[(int)district2].m_Style; // begin mod // Here we are calling a custom getRandomBuildingInfo method buildingInfo = BuildingManagerDetour.GetRandomBuildingInfo_Spawn(vector6, ref Singleton <SimulationManager> .instance.m_randomizer, service, subService, level, width, length, zoningMode3, style); // end mod if (buildingInfo != null) { // begin mod // If the depth of the found prefab is smaller than the one we were looking for, recalculate the size // This is done by checking the position of every prop // Plots only get shrinked when no assets are placed on the extra space // This is needed for themes which only contain small buildings (e.g. 1x2) // because those buildings would occupy more space than needed! if (buildingInfo.GetWidth() == width && buildingInfo.GetLength() != length) { // Calculate the z position of the furthest away prop float biggestPropPosZ = 0; if (buildingInfo.m_props != null) { foreach (var prop in buildingInfo.m_props) { if (prop == null) { continue; } biggestPropPosZ = Mathf.Max(biggestPropPosZ, buildingInfo.m_expandFrontYard ? prop.m_position.z : -prop.m_position.z); } } // Check if the furthest away prop is outside of the bounds of the prefab float occupiedExtraSpace = biggestPropPosZ - buildingInfo.GetLength() * 4; if (occupiedExtraSpace <= 0) { // No? Then shrink the plot to the prefab length so no space is wasted! length = buildingInfo.GetLength(); } else { // Yes? Shrink the plot so all props are in the bounds int newLength = buildingInfo.GetLength() + Mathf.CeilToInt(occupiedExtraSpace / 8); length = Mathf.Min(length, newLength); } vector6 = m_position + VectorUtils.X_Y(((float)length * 0.5f - 4f) * xDirection + ((float)num25_row * 0.5f + (float)spawnpointRow - 10f) * zDirection); } // This block handles Corner buildings. We always shrink them else if (buildingInfo.GetLength() == width && buildingInfo.GetWidth() != length) { length = buildingInfo.GetWidth(); vector6 = m_position + VectorUtils.X_Y(((float)length * 0.5f - 4f) * xDirection + ((float)num25_row * 0.5f + (float)spawnpointRow - 10f) * zDirection); } // end mod if (Debugger.Enabled) { Debugger.LogFormat("Found prefab: {5} - {0}, {1}, {2}, {3} x {4}", service, subService, level, width, length, buildingInfo.name); } break; } if (Debugger.Enabled) { } goto IL_DF0; } if (buildingInfo == null) { if (Debugger.Enabled) { Debugger.LogFormat("No prefab found: {0}, {1}, {2}, {3} x {4}", service, subService, level, width, length); } return; } float num29 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(vector6)); if (num29 > vector6.y) { return; } float num30 = m_angle + 1.57079637f; if (zoningMode3 == BuildingInfo.ZoningMode.CornerLeft && buildingInfo.m_zoningMode == BuildingInfo.ZoningMode.CornerRight) { num30 -= 1.57079637f; length = width; } else if (zoningMode3 == BuildingInfo.ZoningMode.CornerRight && buildingInfo.m_zoningMode == BuildingInfo.ZoningMode.CornerLeft) { num30 += 1.57079637f; length = width; } ushort num31; if (Singleton <BuildingManager> .instance.CreateBuilding(out num31, ref Singleton <SimulationManager> .instance.m_randomizer, buildingInfo, vector6, num30, length, Singleton <SimulationManager> .instance.m_currentBuildIndex)) { Singleton <SimulationManager> .instance.m_currentBuildIndex += 1u; switch (service) { case ItemClass.Service.Residential: zoneManager.m_actualResidentialDemand = Mathf.Max(0, zoneManager.m_actualResidentialDemand - 5); break; case ItemClass.Service.Commercial: zoneManager.m_actualCommercialDemand = Mathf.Max(0, zoneManager.m_actualCommercialDemand - 5); break; case ItemClass.Service.Industrial: zoneManager.m_actualWorkplaceDemand = Mathf.Max(0, zoneManager.m_actualWorkplaceDemand - 5); break; case ItemClass.Service.Office: zoneManager.m_actualWorkplaceDemand = Mathf.Max(0, zoneManager.m_actualWorkplaceDemand - 5); break; } switch (zone) { case ItemClass.Zone.ResidentialHigh: case ItemClass.Zone.CommercialHigh: { Building[] expr_FD7_cp_0 = Singleton <BuildingManager> .instance.m_buildings.m_buffer; ushort expr_FD7_cp_1 = num31; expr_FD7_cp_0[(int)expr_FD7_cp_1].m_flags = (expr_FD7_cp_0[(int)expr_FD7_cp_1].m_flags | Building.Flags.HighDensity); break; } } } zoneManager.m_goodAreaFound[(int)zone] = 1024; }
public override void SimulationStep(ushort buildingID, ref Building buildingData, ref Building.Frame frameData) { base.SimulationStep(buildingID, ref buildingData, ref frameData); if (Singleton <SimulationManager> .instance.m_randomizer.Int32(10U) == 0) { DistrictManager instance = Singleton <DistrictManager> .instance; byte district = instance.GetDistrict(buildingData.m_position); ushort num = instance.m_districts.m_buffer[(int)district].m_Style; if ((int)num > 0 && (int)num - 1 < instance.m_Styles.Length) { DistrictStyle districtStyle = instance.m_Styles[(int)num - 1]; if (districtStyle != null && (UnityEngine.Object) this.m_info.m_class != (UnityEngine.Object)null && (districtStyle.AffectsService(this.m_info.GetService(), this.m_info.GetSubService(), this.m_info.m_class.m_level) && !districtStyle.Contains(this.m_info)) && (int)Singleton <ZoneManager> .instance.m_lastBuildIndex == (int)Singleton <SimulationManager> .instance.m_currentBuildIndex) { buildingData.m_flags |= Building.Flags.Demolishing; ++Singleton <SimulationManager> .instance.m_currentBuildIndex; } } } if ((buildingData.m_flags & Building.Flags.ZonesUpdated) != Building.Flags.None) { SimulationManager instance = Singleton <SimulationManager> .instance; if ((int)buildingData.m_fireIntensity != 0 || instance.m_randomizer.Int32(10U) != 0 || (int)Singleton <ZoneManager> .instance.m_lastBuildIndex != (int)instance.m_currentBuildIndex) { return; } buildingData.m_flags &= ~Building.Flags.ZonesUpdated; if (buildingData.CheckZoning(this.m_info.m_class.GetZone(), this.m_info.m_class.GetSecondaryZone())) { return; } buildingData.m_flags |= Building.Flags.Demolishing; PrivateBuildingAIDetour.CheckNearbyBuildingZones(buildingData.m_position); ++instance.m_currentBuildIndex; } else { if ((buildingData.m_flags & (Building.Flags.Abandoned | Building.Flags.Downgrading)) == Building.Flags.None || (int)buildingData.m_majorProblemTimer != (int)byte.MaxValue && (buildingData.m_flags & Building.Flags.Abandoned) != Building.Flags.None) { return; } SimulationManager instance1 = Singleton <SimulationManager> .instance; ZoneManager instance2 = Singleton <ZoneManager> .instance; int num1; switch (this.m_info.m_class.m_service) { case ItemClass.Service.Residential: num1 = instance2.m_actualResidentialDemand; break; case ItemClass.Service.Commercial: num1 = instance2.m_actualCommercialDemand; break; case ItemClass.Service.Industrial: num1 = instance2.m_actualWorkplaceDemand; break; case ItemClass.Service.Office: num1 = instance2.m_actualWorkplaceDemand; break; default: num1 = 0; break; } if (instance1.m_randomizer.Int32(100U) >= num1 || (int)instance2.m_lastBuildIndex != (int)instance1.m_currentBuildIndex || (double)Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(buildingData.m_position)) > (double)buildingData.m_position.y) { return; } ItemClass.SubService subService = this.m_info.m_class.m_subService; ItemClass.Level level = ItemClass.Level.Level1; int width = buildingData.Width; int num2 = buildingData.Length; if (this.m_info.m_class.m_service == ItemClass.Service.Industrial) { ZoneBlock.GetIndustryType(buildingData.m_position, out subService, out level); } else if (this.m_info.m_class.m_service == ItemClass.Service.Commercial) { ZoneBlock.GetCommercialType(buildingData.m_position, this.m_info.m_class.GetZone(), width, num2, out subService, out level); } DistrictManager instance3 = Singleton <DistrictManager> .instance; byte district = instance3.GetDistrict(buildingData.m_position); ushort num3 = instance3.m_districts.m_buffer[(int)district].m_Style; BuildingInfo randomBuildingInfo = Singleton <BuildingManager> .instance.GetRandomBuildingInfo(ref Singleton <SimulationManager> .instance.m_randomizer, this.m_info.m_class.m_service, subService, level, width, num2, this.m_info.m_zoningMode, (int)num3); if (randomBuildingInfo == null) { return; } buildingData.m_flags |= Building.Flags.Demolishing; float num4 = buildingData.m_angle + 1.570796f; float num5; if (this.m_info.m_zoningMode == BuildingInfo.ZoningMode.CornerLeft && randomBuildingInfo.m_zoningMode == BuildingInfo.ZoningMode.CornerRight) { num5 = num4 - 1.570796f; num2 = width; } else if (this.m_info.m_zoningMode == BuildingInfo.ZoningMode.CornerRight && randomBuildingInfo.m_zoningMode == BuildingInfo.ZoningMode.CornerLeft) { num5 = num4 + 1.570796f; num2 = width; } ushort building; if (Singleton <BuildingManager> .instance.CreateBuilding(out building, ref Singleton <SimulationManager> .instance.m_randomizer, randomBuildingInfo, buildingData.m_position, buildingData.m_angle, num2, Singleton <SimulationManager> .instance.m_currentBuildIndex)) { ++Singleton <SimulationManager> .instance.m_currentBuildIndex; switch (this.m_info.m_class.m_service) { case ItemClass.Service.Residential: instance2.m_actualResidentialDemand = Mathf.Max(0, instance2.m_actualResidentialDemand - 5); break; case ItemClass.Service.Commercial: instance2.m_actualCommercialDemand = Mathf.Max(0, instance2.m_actualCommercialDemand - 5); break; case ItemClass.Service.Industrial: instance2.m_actualWorkplaceDemand = Mathf.Max(0, instance2.m_actualWorkplaceDemand - 5); break; case ItemClass.Service.Office: instance2.m_actualWorkplaceDemand = Mathf.Max(0, instance2.m_actualWorkplaceDemand - 5); break; } } ++instance1.m_currentBuildIndex; } }
public static void SimulationStep(ref ZoneBlock block, ushort blockID) { ZoneManager instance1 = Singleton <ZoneManager> .instance; int rowCount = block.RowCount; Vector2 xDir = new Vector2(Mathf.Cos(block.m_angle), Mathf.Sin(block.m_angle)) * 8f; Vector2 zDir = new Vector2(xDir.y, -xDir.x); ulong num1 = block.m_valid & (ulong)~((long)block.m_occupied1 | (long)block.m_occupied2); int z = 0; ItemClass.Zone zone = ItemClass.Zone.Unzoned; for (int index = 0; index < 4 && zone == ItemClass.Zone.Unzoned; ++index) { z = Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)rowCount); if (((long)num1 & 1L << (z << 3)) != 0L) { zone = block.GetZone(0, z); } } DistrictManager instance2 = Singleton <DistrictManager> .instance; byte district1 = instance2.GetDistrict(block.m_position); int num2; switch (zone) { case ItemClass.Zone.ResidentialLow: num2 = instance1.m_actualResidentialDemand + instance2.m_districts.m_buffer[(int)district1].CalculateResidentialLowDemandOffset(); break; case ItemClass.Zone.ResidentialHigh: num2 = instance1.m_actualResidentialDemand + instance2.m_districts.m_buffer[(int)district1].CalculateResidentialHighDemandOffset(); break; case ItemClass.Zone.CommercialLow: num2 = instance1.m_actualCommercialDemand + instance2.m_districts.m_buffer[(int)district1].CalculateCommercialLowDemandOffset(); break; case ItemClass.Zone.CommercialHigh: num2 = instance1.m_actualCommercialDemand + instance2.m_districts.m_buffer[(int)district1].CalculateCommercialHighDemandOffset(); break; case ItemClass.Zone.Industrial: num2 = instance1.m_actualWorkplaceDemand + instance2.m_districts.m_buffer[(int)district1].CalculateIndustrialDemandOffset(); break; case ItemClass.Zone.Office: num2 = instance1.m_actualWorkplaceDemand + instance2.m_districts.m_buffer[(int)district1].CalculateOfficeDemandOffset(); break; default: return; } Vector2 vector2_1 = VectorUtils.XZ(block.m_position); Vector2 vector2_2 = vector2_1 - 3.5f * xDir + ((float)z - 3.5f) * zDir; int[] xBuffer = instance1.m_tmpXBuffer; for (int index = 0; index < 13; ++index) { xBuffer[index] = 0; } Quad2 quad = new Quad2(); quad.a = vector2_1 - 4f * xDir + ((float)z - 10f) * zDir; quad.b = vector2_1 + 3f * xDir + ((float)z - 10f) * zDir; quad.c = vector2_1 + 3f * xDir + ((float)z + 2f) * zDir; quad.d = vector2_1 - 4f * xDir + ((float)z + 2f) * zDir; Vector2 vector2_3 = quad.Min(); Vector2 vector2_4 = quad.Max(); //begin mod int num3 = Mathf.Max((int)(((double)vector2_3.x - 46.0) / 64.0 + FakeZoneManager.HALFGRID), 0); int num4 = Mathf.Max((int)(((double)vector2_3.y - 46.0) / 64.0 + FakeZoneManager.HALFGRID), 0); int num5 = Mathf.Min((int)(((double)vector2_4.x + 46.0) / 64.0 + FakeZoneManager.HALFGRID), FakeZoneManager.GRIDSIZE - 1); int num6 = Mathf.Min((int)(((double)vector2_4.y + 46.0) / 64.0 + FakeZoneManager.HALFGRID), FakeZoneManager.GRIDSIZE - 1); //end mod for (int index1 = num4; index1 <= num6; ++index1) { for (int index2 = num3; index2 <= num5; ++index2) { //begin mod ushort num7 = instance1.m_zoneGrid[index1 * FakeZoneManager.GRIDSIZE + index2]; //end mod int num8 = 0; while ((int)num7 != 0) { Vector3 vector3 = instance1.m_blocks.m_buffer[(int)num7].m_position; if ((double)Mathf.Max(Mathf.Max(vector2_3.x - 46f - vector3.x, vector2_3.y - 46f - vector3.z), Mathf.Max((float)((double)vector3.x - (double)vector2_4.x - 46.0), (float)((double)vector3.z - (double)vector2_4.y - 46.0))) < 0.0) { //begin mod CheckBlock(ref block, ref instance1.m_blocks.m_buffer[(int)num7], xBuffer, zone, vector2_2, xDir, zDir, quad); } //end mod num7 = instance1.m_blocks.m_buffer[(int)num7].m_nextGridBlock; if (++num8 >= 49152) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace); break; } } } } for (int index = 0; index < 13; ++index) { uint num7 = (uint)xBuffer[index]; int num8 = 0; bool flag1 = ((int)num7 & 196608) == 196608; bool flag2 = false; while (((int)num7 & 1) != 0) { ++num8; flag2 = ((int)num7 & 65536) != 0; num7 >>= 1; } if (num8 == 5 || num8 == 6) { num8 = (!flag2 ? 4 : num8 - (Singleton <SimulationManager> .instance.m_randomizer.Int32(2U) + 2)) | 131072; } else if (num8 == 7) { num8 = 4 | 131072; } if (flag1) { num8 |= 65536; } xBuffer[index] = num8; } int num9 = xBuffer[6] & (int)ushort.MaxValue; if (num9 == 0) { return; } //begin mod bool flag3 = IsGoodPlace(ref block, vector2_2); //end mod if (Singleton <SimulationManager> .instance.m_randomizer.Int32(100U) >= num2) { if (!flag3) { return; } instance1.m_goodAreaFound[(int)zone] = (short)1024; } else if (!flag3 && (int)instance1.m_goodAreaFound[(int)zone] > -1024) { if ((int)instance1.m_goodAreaFound[(int)zone] != 0) { return; } instance1.m_goodAreaFound[(int)zone] = (short)-1; } else { int index1 = 6; int index2 = 6; bool flag1 = true; while (true) { if (flag1) { while (index1 != 0 && (xBuffer[index1 - 1] & (int)ushort.MaxValue) == num9) { --index1; } while (index2 != 12 && (xBuffer[index2 + 1] & (int)ushort.MaxValue) == num9) { ++index2; } } else { while (index1 != 0 && (xBuffer[index1 - 1] & (int)ushort.MaxValue) >= num9) { --index1; } while (index2 != 12 && (xBuffer[index2 + 1] & (int)ushort.MaxValue) >= num9) { ++index2; } } int num7 = index1; int num8 = index2; while (num7 != 0 && (xBuffer[num7 - 1] & (int)ushort.MaxValue) >= 2) { --num7; } while (num8 != 12 && (xBuffer[num8 + 1] & (int)ushort.MaxValue) >= 2) { ++num8; } bool flag2 = num7 != 0 && num7 == index1 - 1; bool flag4 = num8 != 12 && num8 == index2 + 1; if (flag2 && flag4) { if (index2 - index1 <= 2) { if (num9 <= 2) { if (!flag1) { goto label_88; } } else { --num9; } } else { break; } } else if (flag2) { if (index2 - index1 <= 1) { if (num9 <= 2) { if (!flag1) { goto label_88; } } else { --num9; } } else { goto label_73; } } else if (flag4) { if (index2 - index1 <= 1) { if (num9 <= 2) { if (!flag1) { goto label_88; } } else { --num9; } } else { goto label_79; } } else if (index1 == index2) { if (num9 <= 2) { if (!flag1) { goto label_88; } } else { --num9; } } else { goto label_88; } flag1 = false; } ++index1; --index2; goto label_88; label_73: ++index1; goto label_88; label_79: --index2; label_88: int index3; int index4; if (num9 == 1 && index2 - index1 >= 1) { index1 += Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)(index2 - index1)); index2 = index1 + 1; index3 = index1 + Singleton <SimulationManager> .instance.m_randomizer.Int32(2U); index4 = index3; } else { do { index3 = index1; index4 = index2; if (index2 - index1 == 2) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2U) == 0) { --index4; } else { ++index3; } } else if (index2 - index1 == 3) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2U) == 0) { index4 -= 2; } else { index3 += 2; } } else if (index2 - index1 == 4) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2U) == 0) { index2 -= 2; index4 -= 3; } else { index1 += 2; index3 += 3; } } else if (index2 - index1 == 5) { if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2U) == 0) { index2 -= 3; index4 -= 2; } else { index1 += 3; index3 += 2; } } else if (index2 - index1 >= 6) { if (index1 == 0 || index2 == 12) { if (index1 == 0) { index1 = 3; index3 = 2; } if (index2 == 12) { index2 = 9; index4 = 10; } } else if (Singleton <SimulationManager> .instance.m_randomizer.Int32(2U) == 0) { index2 = index1 + 3; index4 = index3 + 2; } else { index1 = index2 - 3; index3 = index4 - 2; } } }while (index2 - index1 > 3 || index4 - index3 > 3); } int a1 = 4; int num10 = index2 - index1 + 1; BuildingInfo.ZoningMode zoningMode1 = BuildingInfo.ZoningMode.Straight; bool flag5 = true; for (int index5 = index1; index5 <= index2; ++index5) { a1 = Mathf.Min(a1, xBuffer[index5] & (int)ushort.MaxValue); if ((xBuffer[index5] & 131072) == 0) { flag5 = false; } } if (index2 > index1) { if ((xBuffer[index1] & 65536) != 0) { zoningMode1 = BuildingInfo.ZoningMode.CornerLeft; index4 = index1 + index4 - index3; index3 = index1; } if ((xBuffer[index2] & 65536) != 0 && (zoningMode1 != BuildingInfo.ZoningMode.CornerLeft || Singleton <SimulationManager> .instance.m_randomizer.Int32(2U) == 0)) { zoningMode1 = BuildingInfo.ZoningMode.CornerRight; index3 = index2 + index3 - index4; index4 = index2; } } int a2 = 4; int num11 = index4 - index3 + 1; BuildingInfo.ZoningMode zoningMode2 = BuildingInfo.ZoningMode.Straight; bool flag6 = true; for (int index5 = index3; index5 <= index4; ++index5) { a2 = Mathf.Min(a2, xBuffer[index5] & (int)ushort.MaxValue); if ((xBuffer[index5] & 131072) == 0) { flag6 = false; } } if (index4 > index3) { if ((xBuffer[index3] & 65536) != 0) { zoningMode2 = BuildingInfo.ZoningMode.CornerLeft; } if ((xBuffer[index4] & 65536) != 0 && (zoningMode2 != BuildingInfo.ZoningMode.CornerLeft || Singleton <SimulationManager> .instance.m_randomizer.Int32(2U) == 0)) { zoningMode2 = BuildingInfo.ZoningMode.CornerRight; } } ItemClass.SubService subService = ItemClass.SubService.None; ItemClass.Level level = ItemClass.Level.Level1; ItemClass.Service service; switch (zone) { case ItemClass.Zone.ResidentialLow: service = ItemClass.Service.Residential; subService = ItemClass.SubService.ResidentialLow; break; case ItemClass.Zone.ResidentialHigh: service = ItemClass.Service.Residential; subService = ItemClass.SubService.ResidentialHigh; break; case ItemClass.Zone.CommercialLow: service = ItemClass.Service.Commercial; subService = ItemClass.SubService.CommercialLow; break; case ItemClass.Zone.CommercialHigh: service = ItemClass.Service.Commercial; subService = ItemClass.SubService.CommercialHigh; break; case ItemClass.Zone.Industrial: service = ItemClass.Service.Industrial; break; case ItemClass.Zone.Office: service = ItemClass.Service.Office; break; default: return; } BuildingInfo info = (BuildingInfo)null; Vector3 vector3 = Vector3.zero; int num12 = 0; int num13 = 0; int width = 0; BuildingInfo.ZoningMode zoningMode3 = BuildingInfo.ZoningMode.Straight; for (int index5 = 0; index5 < 6; ++index5) { switch (index5) { case 0: if (zoningMode1 != BuildingInfo.ZoningMode.Straight) { num12 = index1 + index2 + 1; num13 = a1; width = num10; zoningMode3 = zoningMode1; goto default; } else { break; } case 1: if (zoningMode2 != BuildingInfo.ZoningMode.Straight) { num12 = index3 + index4 + 1; num13 = a2; width = num11; zoningMode3 = zoningMode2; goto default; } else { break; } case 2: if (zoningMode1 != BuildingInfo.ZoningMode.Straight && a1 >= 4) { num12 = index1 + index2 + 1; num13 = !flag5 ? 2 : 3; width = num10; zoningMode3 = zoningMode1; goto default; } else { break; } case 3: if (zoningMode2 != BuildingInfo.ZoningMode.Straight && a2 >= 4) { num12 = index3 + index4 + 1; num13 = !flag6 ? 2 : 3; width = num11; zoningMode3 = zoningMode2; goto default; } else { break; } case 4: num12 = index1 + index2 + 1; num13 = a1; width = num10; zoningMode3 = BuildingInfo.ZoningMode.Straight; goto default; case 5: num12 = index3 + index4 + 1; num13 = a2; width = num11; zoningMode3 = BuildingInfo.ZoningMode.Straight; goto default; default: vector3 = block.m_position + VectorUtils.X_Y((float)((double)num13 * 0.5 - 4.0) * xDir + (float)((double)num12 * 0.5 + (double)z - 10.0) * zDir); if (zone == ItemClass.Zone.Industrial) { ZoneBlock.GetIndustryType(vector3, out subService, out level); } else if (zone == ItemClass.Zone.CommercialLow || zone == ItemClass.Zone.CommercialHigh) { ZoneBlock.GetCommercialType(vector3, zone, width, num13, out subService, out level); } else if (zone == ItemClass.Zone.ResidentialLow || zone == ItemClass.Zone.ResidentialHigh) { ZoneBlock.GetResidentialType(vector3, zone, width, num13, out subService, out level); } else if (zone == ItemClass.Zone.Office) { ZoneBlock.GetOfficeType(vector3, zone, width, num13, out subService, out level); } byte district2 = instance2.GetDistrict(vector3); ushort style = instance2.m_districts.m_buffer[(int)district2].m_Style; if (Singleton <BuildingManager> .instance.m_BuildingWrapper != null) { Singleton <BuildingManager> .instance.m_BuildingWrapper.OnCalculateSpawn(vector3, ref service, ref subService, ref level, ref style); } info = Singleton <BuildingManager> .instance.GetRandomBuildingInfo(ref Singleton <SimulationManager> .instance.m_randomizer, service, subService, level, width, num13, zoningMode3, (int)style); if (info == null) { break; } goto label_169; } } label_169: if (info == null || (double)Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(vector3)) > (double)vector3.y || Singleton <DisasterManager> .instance.IsEvacuating(vector3)) { return; } float angle = block.m_angle + 1.570796f; if (zoningMode3 == BuildingInfo.ZoningMode.CornerLeft && info.m_zoningMode == BuildingInfo.ZoningMode.CornerRight) { angle -= 1.570796f; num13 = width; } else if (zoningMode3 == BuildingInfo.ZoningMode.CornerRight && info.m_zoningMode == BuildingInfo.ZoningMode.CornerLeft) { angle += 1.570796f; num13 = width; } ushort building; if (Singleton <BuildingManager> .instance.CreateBuilding(out building, ref Singleton <SimulationManager> .instance.m_randomizer, info, vector3, angle, num13, Singleton <SimulationManager> .instance.m_currentBuildIndex)) { ++Singleton <SimulationManager> .instance.m_currentBuildIndex; switch (service) { case ItemClass.Service.Residential: instance1.m_actualResidentialDemand = Mathf.Max(0, instance1.m_actualResidentialDemand - 5); break; case ItemClass.Service.Commercial: instance1.m_actualCommercialDemand = Mathf.Max(0, instance1.m_actualCommercialDemand - 5); break; case ItemClass.Service.Industrial: instance1.m_actualWorkplaceDemand = Mathf.Max(0, instance1.m_actualWorkplaceDemand - 5); break; case ItemClass.Service.Office: instance1.m_actualWorkplaceDemand = Mathf.Max(0, instance1.m_actualWorkplaceDemand - 5); break; } switch (zone) { case ItemClass.Zone.ResidentialHigh: case ItemClass.Zone.CommercialHigh: Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)building].m_flags |= Building.Flags.HighDensity; break; } } instance1.m_goodAreaFound[(int)zone] = (short)1024; } }