public static void FindColumnCount(ushort blockID, ref int columnCount) { if (blockID > 0) { columnCount = Mathf.Max(columnCount, ZoneBlockDetour.GetColumnCount(ref ZoneManager.instance.m_blocks.m_buffer[blockID])); } }
private static void CheckZoning(ref Building _this, ItemClass.Zone zone1, ItemClass.Zone zone2, ref uint validCells, ref bool secondary, ref ZoneBlock block) { BuildingInfo.ZoningMode zoningMode = _this.Info.m_zoningMode; int width = _this.Width; int length = _this.Length; Vector3 vector3_1 = new Vector3(Mathf.Cos(_this.m_angle), 0.0f, Mathf.Sin(_this.m_angle)) * 8f; Vector3 vector3_2 = new Vector3(vector3_1.z, 0.0f, -vector3_1.x); int rowCount = block.RowCount; int columnCount = ZoneBlockDetour.GetColumnCount(ref block); // modified Vector3 vector3_3 = new Vector3(Mathf.Cos(block.m_angle), 0.0f, Mathf.Sin(block.m_angle)) * 8f; Vector3 vector3_4 = new Vector3(vector3_3.z, 0.0f, -vector3_3.x); Vector3 vector3_5 = block.m_position - _this.m_position + vector3_1 * (float)((double)width * 0.5 - 0.5) + vector3_2 * (float)((double)length * 0.5 - 0.5); for (int z = 0; z < rowCount; ++z) { Vector3 vector3_6 = ((float)z - 3.5f) * vector3_4; for (int x = 0; (long)x < columnCount; ++x) // modified { if (((long)block.m_valid & ~(long)block.m_shared & 1L << (z << 3 | x)) != 0L) { ItemClass.Zone zone = block.GetZone(x, z); bool flag1 = zone == zone1; if (zone == zone2 && zone2 != ItemClass.Zone.None) { flag1 = true; secondary = true; } if (flag1) { Vector3 vector3_7 = ((float)x - 3.5f) * vector3_3; Vector3 vector3_8 = vector3_5 + vector3_7 + vector3_6; float num1 = (float)((double)vector3_1.x * (double)vector3_8.x + (double)vector3_1.z * (double)vector3_8.z); float num2 = (float)((double)vector3_2.x * (double)vector3_8.x + (double)vector3_2.z * (double)vector3_8.z); int num3 = Mathf.RoundToInt(num1 / 64f); int num4 = Mathf.RoundToInt(num2 / 64f); bool flag2 = false; if (zoningMode == BuildingInfo.ZoningMode.Straight) { flag2 = num4 == 0; } else if (zoningMode == BuildingInfo.ZoningMode.CornerLeft) { flag2 = num4 == 0 && num3 >= width - 2 || num4 <= 1 && num3 == width - 1; } else if (zoningMode == BuildingInfo.ZoningMode.CornerRight) { flag2 = num4 == 0 && num3 <= 1 || num4 <= 1 && num3 == 0; } if ((!flag2 || x == 0) && (num3 >= 0 && num4 >= 0) && (num3 < width && num4 < length)) { validCells = validCells | (uint)(1 << (num4 << 3) + num3); } } } } } }
private static void CalculateFillBuffer(ZoneTool _this, Vector3 position, Vector3 direction, float angle, ushort blockIndex, ref ZoneBlock block, ItemClass.Zone requiredZone, bool occupied1, bool occupied2) { float f1 = Mathf.Abs(block.m_angle - angle) * 0.6366197f; float num1 = f1 - Mathf.Floor(f1); if ((double)num1 >= 0.00999999977648258 && (double)num1 <= 0.990000009536743) { return; } int rowCount = block.RowCount; int columnCount = ZoneBlockDetour.GetColumnCount(ref block); // modified Vector3 vector3_1 = new Vector3(Mathf.Cos(block.m_angle), 0.0f, Mathf.Sin(block.m_angle)) * 8f; Vector3 vector3_2 = new Vector3(vector3_1.z, 0.0f, -vector3_1.x); var m_fillBuffer1 = GetFillBuffer(_this); // modified var blockID = ZoneBlockDetour.FindBlockId(ref block); // modified for (int z = 0; z < rowCount; ++z) { Vector3 vector3_3 = ((float)z - 3.5f) * vector3_2; for (int x = 0; x < columnCount; ++x) // modifed { if (((long)block.m_valid & 1L << (z << 3 | x)) != 0L && ZoneBlockDetour.GetZoneDeep(ref block, blockID, x, z) == requiredZone) { if (occupied1) { if (requiredZone == ItemClass.Zone.Unzoned && ((long)block.m_occupied1 & 1L << (z << 3 | x)) == 0L) { continue; } } else if (occupied2) { if (requiredZone == ItemClass.Zone.Unzoned && ((long)block.m_occupied2 & 1L << (z << 3 | x)) == 0L) { continue; } } else if ((((long)block.m_occupied1 | (long)block.m_occupied2) & 1L << (z << 3 | x)) != 0L) { continue; } Vector3 vector3_4 = ((float)x - 3.5f) * vector3_1; Vector3 vector3_5 = block.m_position + vector3_4 + vector3_3 - position; float f2 = (float)(((double)vector3_5.x * (double)direction.x + (double)vector3_5.z * (double)direction.z) * 0.125 + 32.0); float f3 = (float)(((double)vector3_5.x * (double)direction.z - (double)vector3_5.z * (double)direction.x) * 0.125 + 32.0); int num2 = Mathf.RoundToInt(f2); int index = Mathf.RoundToInt(f3); if (num2 >= 0 && num2 < 64 && (index >= 0 && index < 64) && ((double)Mathf.Abs(f2 - (float)num2) < 0.0125000001862645 && (double)Mathf.Abs(f3 - (float)index) < 0.0125000001862645)) { m_fillBuffer1[index] |= (ulong)(1L << num2); } } } } }
private static bool ApplyZoning(ZoneTool _this, ushort blockIndex, ref ZoneBlock data, Quad2 quad2) { int rowCount = data.RowCount; int columnCount = ZoneBlockDetour.GetColumnCount(ref data); // modified Vector2 vector2_1 = new Vector2(Mathf.Cos(data.m_angle), Mathf.Sin(data.m_angle)) * 8f; Vector2 vector2_2 = new Vector2(vector2_1.y, -vector2_1.x); Vector2 vector2_3 = VectorUtils.XZ(data.m_position); if (!new Quad2() { a = (vector2_3 - 4f * vector2_1 - 4f * vector2_2), b = (vector2_3 + 4f * vector2_1 - 4f * vector2_2), c = (vector2_3 + 4f * vector2_1 + (float)(rowCount - 4) * vector2_2), d = (vector2_3 - 4f * vector2_1 + (float)(rowCount - 4) * vector2_2) }.Intersect(quad2)) { return(false); } bool flag = false; var m_zoning = IsZoningEnabled(_this); // custom var m_dezoning = IsDezoningEnabled(_this); // custom var blockID = ZoneBlockDetour.FindBlockId(ref data); // modified for (int z = 0; z < rowCount; ++z) { Vector2 vector2_4 = ((float)z - 3.5f) * vector2_2; for (int x = 0; x < columnCount; ++x) // custom { Vector2 vector2_5 = ((float)x - 3.5f) * vector2_1; Vector2 p = vector2_3 + vector2_5 + vector2_4; if (quad2.Intersect(p)) { if (m_zoning) { if ((_this.m_zone == ItemClass.Zone.Unzoned || ZoneBlockDetour.GetZoneDeep(ref data, blockID, x, z) == ItemClass.Zone.Unzoned) && ZoneBlockDetour.SetZoneDeep(ref data, blockID, x, z, _this.m_zone)) { flag = true; } } else if (m_dezoning && ZoneBlockDetour.SetZoneDeep(ref data, blockID, x, z, ItemClass.Zone.Unzoned)) { flag = true; } } } } if (!flag) { return(false); } data.RefreshZoning(blockIndex); return(true); }
private static void ApplyBrush(ZoneTool _this, ushort blockIndex, ref ZoneBlock data, Vector3 position, float brushRadius) { Vector3 vector3_1 = data.m_position - position; if ((double)Mathf.Abs(vector3_1.x) > 46.0 + (double)brushRadius || (double)Mathf.Abs(vector3_1.z) > 46.0 + (double)brushRadius) { return; } int num = (int)((data.m_flags & 65280U) >> 8); int columnCount = ZoneBlockDetour.GetColumnCount(ref data); // modified Vector3 vector3_2 = new Vector3(Mathf.Cos(data.m_angle), 0.0f, Mathf.Sin(data.m_angle)) * 8f; Vector3 vector3_3 = new Vector3(vector3_2.z, 0.0f, -vector3_2.x); bool flag = false; var m_zoning = IsZoningEnabled(_this); // custom var m_dezoning = IsDezoningEnabled(_this); // custom var blockID = ZoneBlockDetour.FindBlockId(ref data); // modified for (int z = 0; z < num; ++z) { Vector3 vector3_4 = ((float)z - 3.5f) * vector3_3; for (int x = 0; x < columnCount; ++x) // modified { Vector3 vector3_5 = ((float)x - 3.5f) * vector3_2; Vector3 vector3_6 = vector3_1 + vector3_5 + vector3_4; if ((double)vector3_6.x * (double)vector3_6.x + (double)vector3_6.z * (double)vector3_6.z <= (double)brushRadius * (double)brushRadius) { if (m_zoning) { if ((_this.m_zone == ItemClass.Zone.Unzoned || ZoneBlockDetour.GetZoneDeep(ref data, blockID, x, z) == ItemClass.Zone.Unzoned) && ZoneBlockDetour.SetZoneDeep(ref data, blockID, x, z, _this.m_zone)) { flag = true; } } else if (m_dezoning && ZoneBlockDetour.SetZoneDeep(ref data, blockID, x, z, ItemClass.Zone.Unzoned)) { flag = true; } } } } if (!flag) { return; } data.RefreshZoning(blockIndex); if (!m_zoning) { return; } UsedZone(_this, _this.m_zone); }
private static void CheckDataIntegrity(ulong[] zoneMask, int minDepth) { for (ushort blockID = 1; blockID < zoneMask.Length; blockID++) { { if (ZoneBlockDetour.GetColumnCount(ref ZoneManager.instance.m_blocks.m_buffer[blockID]) < minDepth && (zoneMask[blockID] != 0UL)) { zoneMask[blockID] = 0UL; } } } }
private static void FindClosestZone(BuildingTool _this, BuildingInfo info, ushort block, Vector3 refPos, ref float minD, ref float min2, ref Vector3 minPos, ref float minAngle) { if ((int)block == 0) { return; } ZoneBlock zoneBlock = Singleton <ZoneManager> .instance.m_blocks.m_buffer[(int)block]; if ((double)Mathf.Abs(zoneBlock.m_position.x - refPos.x) >= 52.0 || (double)Mathf.Abs(zoneBlock.m_position.z - refPos.z) >= 52.0) { return; } int rowCount = zoneBlock.RowCount; int columnCount = ZoneBlockDetour.GetColumnCount(ref zoneBlock); // modified Vector3 lhs = new Vector3(Mathf.Cos(zoneBlock.m_angle), 0.0f, Mathf.Sin(zoneBlock.m_angle)) * 8f; Vector3 vector3_1 = new Vector3(lhs.z, 0.0f, -lhs.x); for (int row = 0; row < rowCount; ++row) { Vector3 vector3_2 = ((float)row - 3.5f) * vector3_1; for (int column = 0; (long)column < columnCount; ++column) // modified { if (((long)zoneBlock.m_valid & 1L << (row << 3 | column)) != 0L) { Vector3 vector3_3 = ((float)column - 3.5f) * lhs; Vector3 vector3_4 = zoneBlock.m_position + vector3_3 + vector3_2; float num1 = Mathf.Sqrt((float)(((double)vector3_4.x - (double)refPos.x) * ((double)vector3_4.x - (double)refPos.x) + ((double)vector3_4.z - (double)refPos.z) * ((double)vector3_4.z - (double)refPos.z))); float num2 = Vector3.Dot(lhs, refPos - zoneBlock.m_position); if ((double)num1 <= (double)minD - 0.200000002980232 || (double)num1 < (double)minD + 0.200000002980232 && (double)num2 < (double)min2) { minD = num1; min2 = num2; if ((info.m_cellWidth & 1) == 0) { Vector3 vector3_5 = vector3_4 + vector3_1 * 0.5f; Vector3 vector3_6 = vector3_4 - vector3_1 * 0.5f; minPos = ((double)vector3_5.x - (double)refPos.x) * ((double)vector3_5.x - (double)refPos.x) + ((double)vector3_5.z - (double)refPos.z) * ((double)vector3_5.z - (double)refPos.z) >= ((double)vector3_6.x - (double)refPos.x) * ((double)vector3_6.x - (double)refPos.x) + ((double)vector3_6.z - (double)refPos.z) * ((double)vector3_6.z - (double)refPos.z) ? zoneBlock.m_position + (float)((double)info.m_cellLength * 0.5 - 4.0) * lhs + ((float)row - 4f) * vector3_1 : zoneBlock.m_position + (float)((double)info.m_cellLength * 0.5 - 4.0) * lhs + ((float)row - 3f) * vector3_1; } else { minPos = zoneBlock.m_position + (float)((double)info.m_cellLength * 0.5 - 4.0) * lhs + ((float)row - 3.5f) * vector3_1; } minPos.y = refPos.y; minAngle = zoneBlock.m_angle + 1.570796f; } } } } }
[RedirectMethod(true)] // Detour Reason: Deeper zones data storage, custom depth public static bool CreateBlock(ZoneManager _this, out ushort block, ref Randomizer randomizer, Vector3 position, float angle, int rows, uint buildIndex) { bool result; var columns = NetManagerDetour.newBlockColumnCount; if (columns == 0) // create no blocks if desired zone depth is 0 { block = 0; result = false; } else { // Call original method CreateBlockRedirector.Revert(); result = _this.CreateBlock(out block, ref randomizer, position, angle, rows, buildIndex); CreateBlockRedirector.Apply(); if (result) { // --- support for larger zones --- if (DataExtension.zones3 != null) { DataExtension.zones3[block] = 0UL; } if (DataExtension.zones4 != null) { DataExtension.zones4[block] = 0UL; } // --- dynamic column count --- // TODO should only affect new roads, not ones replaced or splitted by the game (see Network Skins source code) ZoneBlockDetour.SetColumnCount(ref _this.m_blocks.m_buffer[(int)block], columns); } } return(result); }
public override void OnCreated(ILoading loading) { base.OnCreated(loading); Debugger.Initialize(); Debugger.Log("ON_CREATED"); Debugger.Log("Building Themes: Initializing Mod..."); try { PolicyPanelEnabler.Register(); BuildingThemesManager.instance.Reset(); BuildingVariationManager.instance.Reset(); UpdateConfig(); try { Redirector <BuildingManagerDetour> .Deploy(); Debugger.Log("Building Themes: BuildingManager Methods detoured!"); } catch (Exception e) { Debugger.LogException(e); } try { Redirector <DistrictManagerDetour> .Deploy(); Debugger.Log("Building Themes: DistrictManager Methods detoured!"); } catch (Exception e) { Debugger.LogException(e); } try { Redirector <ZoneBlockDetour> .Deploy(); Debugger.Log("Building Themes: ZoneBlock Methods detoured!"); ZoneBlockDetour.SetUp(); } catch (Exception e) { Debugger.LogException(e); } try { Detour.ImmaterialResourceManagerDetour.Deploy(); } catch (Exception e) { Debugger.LogException(e); } try { Detour.PrivateBuildingAIDetour <ResidentialBuildingAI> .Deploy(); } catch (Exception e) { Debugger.LogException(e); } try { Detour.PrivateBuildingAIDetour <CommercialBuildingAI> .Deploy(); } catch (Exception e) { Debugger.LogException(e); } try { Detour.PrivateBuildingAIDetour <IndustrialBuildingAI> .Deploy(); } catch (Exception e) { Debugger.LogException(e); } try { Detour.PrivateBuildingAIDetour <OfficeBuildingAI> .Deploy(); } catch (Exception e) { Debugger.LogException(e); } try { Detour.PoliciesPanelDetour.Deploy(); } catch (Exception e) { Debugger.LogException(e); } try { Redirector <DistrictWorldInfoPanelDetour> .Deploy(); Debugger.Log("Building Themes: DistrictWorldInfoPanel Methods detoured!"); } catch (Exception e) { Debugger.LogException(e); } Debugger.Log("Building Themes: Mod successfully intialized."); } catch (Exception e) { Debugger.LogException(e); } }
private static bool ApplyFillBuffer(ZoneTool _this, Vector3 position, Vector3 direction, float angle, ushort blockIndex, ref ZoneBlock block) { var m_zoning = IsZoningEnabled(_this); // custom var m_dezoning = IsDezoningEnabled(_this); // custom var blockID = ZoneBlockDetour.FindBlockId(ref block); // modified int rowCount = block.RowCount; int columnCount = ZoneBlockDetour.GetColumnCount(ref block); // modified Vector3 vector3_1 = new Vector3(Mathf.Cos(block.m_angle), 0.0f, Mathf.Sin(block.m_angle)) * 8f; Vector3 vector3_2 = new Vector3(vector3_1.z, 0.0f, -vector3_1.x); bool flag1 = false; for (int z = 0; z < rowCount; ++z) { Vector3 vector3_3 = ((float)z - 3.5f) * vector3_2; for (int x = 0; x < columnCount; ++x) // custom { Vector3 vector3_4 = ((float)x - 3.5f) * vector3_1; Vector3 vector3_5 = block.m_position + vector3_4 + vector3_3 - position; float f1 = (float)(((double)vector3_5.x * (double)direction.x + (double)vector3_5.z * (double)direction.z) * 0.125 + 32.0); float f2 = (float)(((double)vector3_5.x * (double)direction.z - (double)vector3_5.z * (double)direction.x) * 0.125 + 32.0); int num1 = Mathf.Clamp(Mathf.RoundToInt(f1), 0, 63); int num2 = Mathf.Clamp(Mathf.RoundToInt(f2), 0, 63); bool flag2 = false; var m_fillBuffer1 = GetFillBuffer(_this); // modified for (int index1 = -1; index1 <= 1 && !flag2; ++index1) { for (int index2 = -1; index2 <= 1 && !flag2; ++index2) { int num3 = num1 + index2; int index3 = num2 + index1; if (num3 >= 0 && num3 < 64 && (index3 >= 0 && index3 < 64) && (((double)f1 - (double)num3) * ((double)f1 - (double)num3) + ((double)f2 - (double)index3) * ((double)f2 - (double)index3) < 9.0 / 16.0 && ((long)m_fillBuffer1[index3] & 1L << num3) != 0L)) { if (m_zoning) { if ((_this.m_zone == ItemClass.Zone.Unzoned || ZoneBlockDetour.GetZoneDeep(ref block, blockID, x, z) == ItemClass.Zone.Unzoned) && ZoneBlockDetour.SetZoneDeep(ref block, blockID, x, z, _this.m_zone)) { flag1 = true; } } else if (m_dezoning && ZoneBlockDetour.SetZoneDeep(ref block, blockID, x, z, ItemClass.Zone.Unzoned)) { flag1 = true; } flag2 = true; } } } } } if (!flag1) { return(false); } block.RefreshZoning(blockIndex); return(true); }
public static void CheckSpace(ZoneManager _this, ushort block, Vector3 position, float angle, int width, int length, ref ulong space1, ref ulong space2, ref ulong space3, ref ulong space4) { ZoneBlock zoneBlock = _this.m_blocks.m_buffer[(int)block]; // difference of 2 radian angles (360 deg = 2*PI * 0.6366197f = 4f) // that means an angle difference of 90 deg would result in 1f float angleDiff = Mathf.Abs(zoneBlock.m_angle - angle) * 0.6366197f; float rightAngleDiff = angleDiff - Mathf.Floor(angleDiff); // check if the input angle and the zone block are in right angle (0 90 180 270 deg), otherwise return if ((double)rightAngleDiff >= 0.0199999995529652 && (double)rightAngleDiff <= 0.980000019073486) { return; } float searchRadius = Mathf.Min(72f, (float)(width + length) * 4f) + 6f; float minX = position.x - searchRadius; float minZ = position.z - searchRadius; float maxX = position.x + searchRadius; float maxZ = position.z + searchRadius; // check if the zone block is in the area of interest, otherwise return if ((double)zoneBlock.m_position.x + 46.0 < (double)minX || (double)zoneBlock.m_position.x - 46.0 > (double)maxX || ((double)zoneBlock.m_position.z + 46.0 < (double)minZ || (double)zoneBlock.m_position.z - 46.0 > (double)maxZ)) { return; } // width of the zone block int rowCount = zoneBlock.RowCount; int columnCount = ZoneBlockDetour.GetColumnCount(ref zoneBlock); // modified // orientation of the zone block Vector3 columnDirection = new Vector3(Mathf.Cos(zoneBlock.m_angle), 0.0f, Mathf.Sin(zoneBlock.m_angle)) * 8f; Vector3 rowDirection = new Vector3(columnDirection.z, 0.0f, -columnDirection.x); // direction vectors for the given angle Vector3 angleParallelDirection = new Vector3(Mathf.Cos(angle), 0.0f, Mathf.Sin(angle)) * 8f; Vector3 angleOrthogonalDirection = new Vector3(angleParallelDirection.z, 0.0f, -angleParallelDirection.x); for (int row = 0; row < rowCount; ++row) { Vector3 rowMiddleLength = ((float)row - 3.5f) * rowDirection; for (int column = 0; (long)column < columnCount; ++column) { // check if the current cell is valid (not shared, not occupied) if (((long)zoneBlock.m_valid & ~(long)zoneBlock.m_shared & ~((long)zoneBlock.m_occupied1 | (long)zoneBlock.m_occupied2) & 1L << (row << 3 | column)) != 0L) { Vector3 columnMiddleLength = ((float)column - 3.5f) * columnDirection; // absolute position of the zone block cell Vector3 cellPosition = zoneBlock.m_position + columnMiddleLength + rowMiddleLength; // check if the cell is in search radius if ((double)Mathf.Abs(position.x - cellPosition.x) < (double)searchRadius && (double)Mathf.Abs(position.z - cellPosition.z) < (double)searchRadius) { // cycle through every cell of the building plot // find the cell that is in the same position as the zone block cell bool cellsMatch = false; for (int plotColumn = 0; plotColumn < length && !cellsMatch; ++plotColumn) { Vector3 plotColumnMiddleLength = (float)((double)plotColumn - (double)length * 0.5 + 0.5) * angleOrthogonalDirection; for (int plotRow = 0; plotRow < width && !cellsMatch; ++plotRow) { Vector3 plotRowMiddleLength = (float)((double)plotRow - (double)width * 0.5 + 0.5) * angleParallelDirection; // absolute position of the building plot cell Vector3 plotCellPosition = position + plotRowMiddleLength + plotColumnMiddleLength; // check if zone block cell and building plot cell positions match if ((double)Mathf.Abs(plotCellPosition.x - cellPosition.x) < 0.200000002980232 && (double)Mathf.Abs(plotCellPosition.z - cellPosition.z) < 0.200000002980232) { cellsMatch = true; // depending on column, use one of the 4 masks to report that a cell was found if (plotColumn < 4) { space1 = space1 | (ulong)(1L << (plotColumn << 4 | plotRow)); } else if (plotColumn < 8) { space2 = space2 | (ulong)(1L << (plotColumn - 4 << 4 | plotRow)); } else if (plotColumn < 12) { space3 = space3 | (ulong)(1L << (plotColumn - 8 << 4 | plotRow)); } else { space4 = space4 | (ulong)(1L << (plotColumn - 12 << 4 | plotRow)); } } } } } } } } }