private static bool CalculateFillBuffer(ZoneTool z, Vector3 position, Vector3 direction, ItemClass.Zone requiredZone, bool occupied1, bool occupied2) { var m_fillBuffer1 = (ulong[])typeof(ZoneTool).GetField("m_fillBuffer1", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(z); for (int index = 0; index < 64; ++index) { m_fillBuffer1[index] = 0UL; } if (!occupied2) { float angle = Mathf.Atan2(-direction.x, direction.z); float num1 = position.x - 256f; float num2 = position.z - 256f; float num3 = position.x + 256f; float num4 = position.z + 256f; int num5 = Mathf.Max((int)((num1 - 46f) / 64f + FakeZoneManager.HALFGRID), 0); int num6 = Mathf.Max((int)((num2 - 46f) / 64f + FakeZoneManager.HALFGRID), 0); int num7 = Mathf.Min((int)((num3 + 46f) / 64f + FakeZoneManager.HALFGRID), FakeZoneManager.GRIDSIZE - 1); int num8 = Mathf.Min((int)((num4 + 46f) / 64f + FakeZoneManager.HALFGRID), FakeZoneManager.GRIDSIZE - 1); ZoneManager instance = Singleton <ZoneManager> .instance; for (int index1 = num6; index1 <= num8; ++index1) { for (int index2 = num5; index2 <= num7; ++index2) { ushort blockIndex = instance.m_zoneGrid[index1 * FakeZoneManager.GRIDSIZE + index2]; int num9 = 0; while ((int)blockIndex != 0) { Vector3 vector3 = instance.m_blocks.m_buffer[(int)blockIndex].m_position; if ((double)Mathf.Max(Mathf.Max(num1 - 46f - vector3.x, num2 - 46f - vector3.z), Mathf.Max((float)((double)vector3.x - (double)num3 - 46.0), (float)((double)vector3.z - (double)num4 - 46.0))) < 0.0) { CalculateFillBuffer(z, position, direction, angle, blockIndex, ref instance.m_blocks.m_buffer[(int)blockIndex], requiredZone, occupied1, occupied2); } blockIndex = instance.m_blocks.m_buffer[(int)blockIndex].m_nextGridBlock; if (++num9 >= ZoneManager.MAX_BLOCK_COUNT) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace); break; } } } } } if (((long)m_fillBuffer1[32] & 4294967296L) != 0L) { m_fillPositions.Clear(); int num1 = 0; int num2 = 32; int num3 = 32; int num4 = 32; int num5 = 32; FillPos fillPos1; fillPos1.m_x = (byte)32; fillPos1.m_z = (byte)32; m_fillPositions.Add(fillPos1); m_fillBuffer1[32] &= 18446744069414584319UL; while (num1 < m_fillPositions.m_size) { FillPos fillPos2 = m_fillPositions.m_buffer[num1++]; if ((int)fillPos2.m_z > 0) { FillPos fillPos3 = fillPos2; --fillPos3.m_z; if (((long)m_fillBuffer1[(int)fillPos3.m_z] & 1L << (int)fillPos3.m_x) != 0L) { m_fillPositions.Add(fillPos3); m_fillBuffer1[(int)fillPos3.m_z] &= (ulong)~(1L << (int)fillPos3.m_x); if ((int)fillPos3.m_z < num3) { num3 = (int)fillPos3.m_z; } } } if ((int)fillPos2.m_x > 0) { FillPos fillPos3 = fillPos2; --fillPos3.m_x; if (((long)m_fillBuffer1[(int)fillPos3.m_z] & 1L << (int)fillPos3.m_x) != 0L) { m_fillPositions.Add(fillPos3); m_fillBuffer1[(int)fillPos3.m_z] &= (ulong)~(1L << (int)fillPos3.m_x); if ((int)fillPos3.m_x < num2) { num2 = (int)fillPos3.m_x; } } } if ((int)fillPos2.m_x < 63) { FillPos fillPos3 = fillPos2; ++fillPos3.m_x; if (((long)m_fillBuffer1[(int)fillPos3.m_z] & 1L << (int)fillPos3.m_x) != 0L) { m_fillPositions.Add(fillPos3); m_fillBuffer1[(int)fillPos3.m_z] &= (ulong)~(1L << (int)fillPos3.m_x); if ((int)fillPos3.m_x > num4) { num4 = (int)fillPos3.m_x; } } } if ((int)fillPos2.m_z < 63) { FillPos fillPos3 = fillPos2; ++fillPos3.m_z; if (((long)m_fillBuffer1[(int)fillPos3.m_z] & 1L << (int)fillPos3.m_x) != 0L) { m_fillPositions.Add(fillPos3); m_fillBuffer1[(int)fillPos3.m_z] &= (ulong)~(1L << (int)fillPos3.m_x); if ((int)fillPos3.m_z > num5) { num5 = (int)fillPos3.m_z; } } } } for (int index = 0; index < 64; ++index) { m_fillBuffer1[index] = 0UL; } for (int index = 0; index < m_fillPositions.m_size; ++index) { FillPos fillPos2 = m_fillPositions.m_buffer[index]; m_fillBuffer1[(int)fillPos2.m_z] |= (ulong)(1L << (int)fillPos2.m_x); } return(true); } for (int index = 0; index < 64; ++index) { m_fillBuffer1[index] = 0UL; } return(false); }
protected void EnsureCitizenUnits(ushort buildingID, ref Building data, int homeCount, int workCount, int visitCount, int studentCount) { int totalWorkCount = (workCount + 4) / 5; int totalVisitCount = (visitCount + 4) / 5; int totalHomeCount = homeCount; int[] workersRequired = new int[] { 0, 0, 0, 0 }; if ((data.m_flags & (Building.Flags.Abandoned | Building.Flags.BurnedDown)) == Building.Flags.None) { Citizen.Wealth wealthLevel = Citizen.GetWealthLevel(this.m_info.m_class.m_level); uint num = 0u; uint num2 = data.m_citizenUnits; int num3 = 0; while (num2 != 0u) { CitizenUnit.Flags flags = citizenUnitArray[(int)((UIntPtr)num2)].m_flags; if ((ushort)(flags & CitizenUnit.Flags.Home) != 0) { citizenUnitArray[(int)((UIntPtr)num2)].SetWealthLevel(wealthLevel); homeCount--; } if ((ushort)(flags & CitizenUnit.Flags.Work) != 0) { workCount -= 5; for (int i = 0; i < 5; i++) { uint citizen = citizenUnitArray[(int)((UIntPtr)num2)].GetCitizen(i); if (citizen != 0u) { // Tick off education to see what is there workersRequired[(int)citizenArray[(int)((UIntPtr)citizen)].EducationLevel]--; } } } if ((ushort)(flags & CitizenUnit.Flags.Visit) != 0) { visitCount -= 5; } if ((ushort)(flags & CitizenUnit.Flags.Student) != 0) { studentCount -= 5; } num = num2; num2 = citizenUnitArray[(int)((UIntPtr)num2)].m_nextUnit; if (++num3 > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } // end while /* * homeCount = Mathf.Max(0, homeCount); * workCount = Mathf.Max(0, workCount); */ visitCount = Mathf.Max(0, visitCount); studentCount = Mathf.Max(0, studentCount); if (homeCount > 0 || workCount > 0 || visitCount > 0 || studentCount > 0) { uint num4 = 0u; if (citizenManager.CreateUnits(out num4, ref Singleton <SimulationManager> .instance.m_randomizer, buildingID, 0, homeCount, workCount, visitCount, 0, studentCount)) { if (num != 0u) { citizenUnitArray[(int)((UIntPtr)num)].m_nextUnit = num4; } else { data.m_citizenUnits = num4; } } } if (DataStore.strictCapacity) { // This is done to have the count in numbers of citizen units and only if the building is of a privateBuilding (Res, Com, Ind, Office) // There also appears to be an issue that without allowRemovalOfCitizens flag, the population will dip, then shoot up. if (DataStore.allowRemovalOfCitizens && (data.Info.GetAI() is PrivateBuildingAI)) { // Stop incoming offers to get HandleWorkers() to start fresh TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Building = buildingID; Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker0, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker1, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker2, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker3, offer); int worker0 = 0; int worker1 = 0; int worker2 = 0; int worker3 = 0; ((PrivateBuildingAI)data.Info.GetAI()).CalculateWorkplaceCount(new Randomizer((int)buildingID), data.Width, data.Length, out worker0, out worker1, out worker2, out worker3); // Update the workers required once figuring out how many are needed by the new building workersRequired[0] += worker0; workersRequired[1] += worker1; workersRequired[2] += worker2; workersRequired[3] += worker3; if (workCount < 0) { RemoveWorkerBuilding(buildingID, ref data, totalWorkCount); } else if (homeCount < 0) { RemoveHouseHold(buildingID, ref data, totalHomeCount); } /* * if (visitCount < 0) * { * RemoveVisitorsBuilding(buildingID, ref data, totalVisitCount); * } */ PromoteWorkers(buildingID, ref data, ref workersRequired); // Do nothing for students } // end if PrivateBuildingAI } // end strictCapacity } // end if good building } // end EnsureCitizenUnits
//PostOfficeAI.CalculateOwnVehicles rewritten as a public static method (private instance method). public static void CalculateVehicles(ushort buildingID, ref Building data, ref int unsortedMail, ref int sortedMail, ref int unsortedCapacity, ref int sortedCapacity, ref int ownVanCount, ref int ownTruckCount, ref int import, ref int export) { VehicleManager instance = Singleton <VehicleManager> .instance; ushort num = data.m_ownVehicles; int num2 = 0; while (num != 0) { switch (instance.m_vehicles.m_buffer[num].m_transferType) { case 92: { ownVanCount++; VehicleInfo info = instance.m_vehicles.m_buffer[num].Info; info.m_vehicleAI.GetSize(num, ref instance.m_vehicles.m_buffer[num], out int size, out int max); unsortedMail += Mathf.Min(size, max); unsortedCapacity += Mathf.Min(size, max); sortedMail += Mathf.Max(0, max - size); sortedCapacity += Mathf.Max(0, max - size); break; } case 93: ownTruckCount++; if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.TransferToTarget) != 0) { VehicleInfo info4 = instance.m_vehicles.m_buffer[num].Info; info4.m_vehicleAI.GetSize(num, ref instance.m_vehicles.m_buffer[num], out int _, out int max4); sortedCapacity += max4; if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Exporting) != 0) { export++; } } else if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.TransferToSource) != 0) { VehicleInfo info5 = instance.m_vehicles.m_buffer[num].Info; info5.m_vehicleAI.GetSize(num, ref instance.m_vehicles.m_buffer[num], out int size5, out int max5); unsortedMail += Mathf.Min(size5, max5); unsortedCapacity += max5; if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Importing) != 0) { import++; } } break; case 94: case 96: ownTruckCount++; if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.TransferToTarget) != 0) { VehicleInfo info2 = instance.m_vehicles.m_buffer[num].Info; info2.m_vehicleAI.GetSize(num, ref instance.m_vehicles.m_buffer[num], out int _, out int max2); unsortedCapacity += max2; if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Exporting) != 0) { export++; } } else if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.TransferToSource) != 0) { VehicleInfo info3 = instance.m_vehicles.m_buffer[num].Info; info3.m_vehicleAI.GetSize(num, ref instance.m_vehicles.m_buffer[num], out int size3, out int max3); sortedMail += Mathf.Min(size3, max3); sortedCapacity += max3; if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Importing) != 0) { import++; } } break; case 95: ownTruckCount++; if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Exporting) != 0) { export++; } break; } num = instance.m_vehicles.m_buffer[num].m_nextOwnVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } num = data.m_guestVehicles; num2 = 0; do { if (num == 0) { return; } switch (instance.m_vehicles.m_buffer[num].m_transferType) { case 93: if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.TransferToSource) != 0) { if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Exporting) != 0) { export++; } } else if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.TransferToTarget) != 0) { VehicleInfo info6 = instance.m_vehicles.m_buffer[num].Info; info6.m_vehicleAI.GetSize(num, ref instance.m_vehicles.m_buffer[num], out int size6, out int max6); unsortedMail += Mathf.Min(size6, max6); unsortedCapacity += Mathf.Min(size6, max6); if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Importing) != 0) { import++; } } break; case 94: case 96: if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.TransferToSource) != 0) { if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Exporting) != 0) { export++; } } else if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.TransferToTarget) != 0) { VehicleInfo info7 = instance.m_vehicles.m_buffer[num].Info; info7.m_vehicleAI.GetSize(num, ref instance.m_vehicles.m_buffer[num], out int size7, out int max7); sortedMail += Mathf.Min(size7, max7); sortedCapacity += Mathf.Min(size7, max7); if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Importing) != 0) { import++; } } break; case 95: if ((instance.m_vehicles.m_buffer[num].m_flags & Vehicle.Flags.Exporting) != 0) { export++; } break; } num = instance.m_vehicles.m_buffer[num].m_nextGuestVehicle; }while (++num2 <= 16384); CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); }
public void updateBidings() { BuildingInfo basicInfo = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building].Info; DepotAI basicAI = basicInfo.GetAI() as DepotAI; if (basicAI == null) { closeDepotInfo(null, null); return; } TransportStationAI stationAI = basicInfo.GetAI() as TransportStationAI; HarborAI harborAI = basicInfo.GetAI() as HarborAI; vehiclesInUseLabel.text = LocaleFormatter.FormatGeneric("TRANSPORT_LINE_VEHICLECOUNT", new object[] { basicAI.GetVehicleCount(m_buildingIdSelecionado.Building, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building]).ToString() }); if (stationAI != null) { passengersLastWeek.isVisible = true; int passengerCount = stationAI.GetPassengerCount(m_buildingIdSelecionado.Building, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building]); passengersLastWeek.text = LocaleFormatter.FormatGeneric("AIINFO_PASSENGERS_SERVICED", new object[] { passengerCount }); } else { passengersLastWeek.isVisible = false; } upkeepCost.text = LocaleFormatter.FormatUpkeep(basicAI.GetResourceRate(m_buildingIdSelecionado.Building, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)m_buildingIdSelecionado.Building], EconomyManager.Resource.Maintenance), false); uint num = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building].m_citizenUnits; int num2 = 0; int num3 = 0; int unskill = 0; int oneSchool = 0; int twoSchool = 0; int threeSchool = 0; CitizenManager instance = Singleton <CitizenManager> .instance; while (num != 0u) { uint nextUnit = instance.m_units.m_buffer[(int)((UIntPtr)num)].m_nextUnit; if ((ushort)(instance.m_units.m_buffer[(int)((UIntPtr)num)].m_flags & CitizenUnit.Flags.Work) != 0) { for (int i = 0; i < 5; i++) { uint citizen = instance.m_units.m_buffer[(int)((UIntPtr)num)].GetCitizen(i); if (citizen != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].Dead && (instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) { num3++; switch (instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].EducationLevel) { case Citizen.Education.Uneducated: unskill++; break; case Citizen.Education.OneSchool: oneSchool++; break; case Citizen.Education.TwoSchools: twoSchool++; break; case Citizen.Education.ThreeSchools: threeSchool++; break; } } } } num = nextUnit; if (++num2 > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } workerChart.SetValues(new int[] { unskill, oneSchool, twoSchool, threeSchool }, new int[] { basicAI.m_workPlaceCount0, basicAI.m_workPlaceCount1, basicAI.m_workPlaceCount2, basicAI.m_workPlaceCount3 }); }
public static bool FindPathPositionWithSpiralLoop(Vector3 position, Vector3?secondaryPosition, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleType, VehicleInfo.VehicleType stopType, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPosA, out PathUnit.Position pathPosB, out float distanceSqrA, out float distanceSqrB) { int iMin = Mathf.Max((int)((position.z - (float)NetManager.NODEGRID_CELL_SIZE) / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f), 0); int iMax = Mathf.Min((int)((position.z + (float)NetManager.NODEGRID_CELL_SIZE) / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f), NetManager.NODEGRID_RESOLUTION - 1); int jMin = Mathf.Max((int)((position.x - (float)NetManager.NODEGRID_CELL_SIZE) / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f), 0); int jMax = Mathf.Min((int)((position.x + (float)NetManager.NODEGRID_CELL_SIZE) / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f), NetManager.NODEGRID_RESOLUTION - 1); int width = iMax - iMin + 1; int height = jMax - jMin + 1; int centerI = (int)(position.z / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f); int centerJ = (int)(position.x / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f); NetManager netManager = Singleton <NetManager> .instance; /*pathPosA.m_segment = 0; * pathPosA.m_lane = 0; * pathPosA.m_offset = 0;*/ distanceSqrA = 1E+10f; /*pathPosB.m_segment = 0; * pathPosB.m_lane = 0; * pathPosB.m_offset = 0;*/ distanceSqrB = 1E+10f; float minDist = float.MaxValue; PathUnit.Position myPathPosA = default(PathUnit.Position); float myDistanceSqrA = float.MaxValue; PathUnit.Position myPathPosB = default(PathUnit.Position); float myDistanceSqrB = float.MaxValue; int lastSpiralDist = 0; bool found = false; LoopUtil.SpiralLoop(centerI, centerJ, width, height, delegate(int i, int j) { if (i < 0 || i >= NetManager.NODEGRID_RESOLUTION || j < 0 || j >= NetManager.NODEGRID_RESOLUTION) { return(true); } int spiralDist = Math.Max(Math.Abs(i - centerI), Math.Abs(j - centerJ)); // maximum norm if (found && spiralDist > lastSpiralDist) { // last iteration return(false); } ushort segmentId = netManager.m_segmentGrid[i * NetManager.NODEGRID_RESOLUTION + j]; int iterations = 0; while (segmentId != 0) { NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info; if (segmentInfo != null && segmentInfo.m_class.m_service == service && (netManager.m_segments.m_buffer[segmentId].m_flags & (NetSegment.Flags.Collapsed | NetSegment.Flags.Flooded)) == NetSegment.Flags.None && (allowUnderground || !segmentInfo.m_netAI.IsUnderground()) ) { ushort startNodeId = netManager.m_segments.m_buffer[segmentId].m_startNode; ushort endNodeId = netManager.m_segments.m_buffer[segmentId].m_endNode; Vector3 startNodePos = netManager.m_nodes.m_buffer[startNodeId].m_position; Vector3 endNodePos = netManager.m_nodes.m_buffer[endNodeId].m_position; Vector3 posA; int laneIndexA; float laneOffsetA; Vector3 posB; int laneIndexB; float laneOffsetB; if (netManager.m_segments.m_buffer[segmentId].GetClosestLanePosition(position, laneType, vehicleType, stopType, requireConnect, out posA, out laneIndexA, out laneOffsetA, out posB, out laneIndexB, out laneOffsetB)) { float dist = Vector3.SqrMagnitude(position - posA); if (secondaryPosition != null) { dist += Vector3.SqrMagnitude((Vector3)secondaryPosition - posA); } if (dist < minDist) { found = true; minDist = dist; myPathPosA.m_segment = segmentId; myPathPosA.m_lane = (byte)laneIndexA; myPathPosA.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(laneOffsetA * 255f), 0, 255); myDistanceSqrA = dist; dist = Vector3.SqrMagnitude(position - posB); if (secondaryPosition != null) { dist += Vector3.SqrMagnitude((Vector3)secondaryPosition - posB); } if (laneIndexB < 0) { myPathPosB.m_segment = 0; myPathPosB.m_lane = 0; myPathPosB.m_offset = 0; myDistanceSqrB = float.MaxValue; } else { myPathPosB.m_segment = segmentId; myPathPosB.m_lane = (byte)laneIndexB; myPathPosB.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(laneOffsetB * 255f), 0, 255); myDistanceSqrB = dist; } } } } segmentId = netManager.m_segments.m_buffer[segmentId].m_nextGridSegment; if (++iterations >= NetManager.MAX_SEGMENT_COUNT) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } lastSpiralDist = spiralDist; return(true); }); pathPosA = myPathPosA; distanceSqrA = myDistanceSqrA; pathPosB = myPathPosB; distanceSqrB = myDistanceSqrB; return(pathPosA.m_segment != 0); }
public void SimulationStep(ushort lineID) { TransportInfo info = this.Info; if (this.Complete) { int num = 0; if (this.m_vehicles != 0) { VehicleManager instance = Singleton <VehicleManager> .instance; ushort num2 = this.m_vehicles; int num3 = 0; while (num2 != 0) { ushort nextLineVehicle = instance.m_vehicles.m_buffer [(int)num2].m_nextLineVehicle; num++; num2 = nextLineVehicle; if (++num3 > 65536) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } bool flag; if (Singleton <SimulationManager> .instance.m_isNightTime) { flag = ((this.m_flags & TransportLine.Flags.DisabledNight) == TransportLine.Flags.None); } else { flag = ((this.m_flags & TransportLine.Flags.DisabledDay) == TransportLine.Flags.None); } uint num4 = 0u; float num5 = 0f; if (this.m_stops != 0) { NetManager instance2 = Singleton <NetManager> .instance; ushort stops = this.m_stops; ushort num6 = stops; int num7 = 0; while (num6 != 0) { ushort num8 = 0; if (flag) { NetNode[] expr_107_cp_0 = instance2.m_nodes.m_buffer; ushort expr_107_cp_1 = num6; expr_107_cp_0 [(int)expr_107_cp_1].m_flags = (expr_107_cp_0 [(int)expr_107_cp_1].m_flags & ~NetNode.Flags.Disabled); } else { NetNode[] expr_12D_cp_0 = instance2.m_nodes.m_buffer; ushort expr_12D_cp_1 = num6; expr_12D_cp_0 [(int)expr_12D_cp_1].m_flags = (expr_12D_cp_0 [(int)expr_12D_cp_1].m_flags | NetNode.Flags.Disabled); } for (int i = 0; i < 8; i++) { ushort segment = instance2.m_nodes.m_buffer [(int)num6].GetSegment(i); if (segment != 0 && instance2.m_segments.m_buffer [(int)segment].m_startNode == num6) { num5 += instance2.m_segments.m_buffer [(int)segment].m_averageLength; num8 = instance2.m_segments.m_buffer [(int)segment].m_endNode; break; } } num4 += 1u; num6 = num8; if (num6 == stops) { break; } if (++num7 >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } int num9 = num * info.m_maintenanceCostPerVehicle / 100; if (num9 != 0) { Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.Maintenance, num9, info.m_class); } int budget = Singleton <EconomyManager> .instance.GetBudget(info.m_class); int num10; if (flag) { num10 = Mathf.CeilToInt((float)budget * num5 / (info.m_defaultVehicleDistance * 100f)); } else { num10 = 0; } if (num4 != 0u && num < num10) { TransferManager.TransferReason vehicleReason = info.m_vehicleReason; int index = Singleton <SimulationManager> .instance.m_randomizer.Int32(num4); ushort stop = this.GetStop(index); if (vehicleReason != TransferManager.TransferReason.None && stop != 0) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Priority = num10 - num + 1; offer.TransportLine = lineID; offer.Position = Singleton <NetManager> .instance.m_nodes.m_buffer [(int)stop].m_position; offer.Amount = 1; offer.Active = false; Singleton <TransferManager> .instance.AddIncomingOffer(vehicleReason, offer); } } else { if (num > num10) { int index2 = Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)num); ushort vehicle = this.GetVehicle(index2); if (vehicle != 0) { VehicleManager instance3 = Singleton <VehicleManager> .instance; VehicleInfo info2 = instance3.m_vehicles.m_buffer [(int)vehicle].Info; info2.m_vehicleAI.SetTransportLine(vehicle, ref instance3.m_vehicles.m_buffer [(int)vehicle], 0); } } } } if ((Singleton <SimulationManager> .instance.m_currentFrameIndex & 4095u) >= 3840u) { this.m_passengers.Update(); Singleton <TransportManager> .instance.m_passengers [(int)info.m_transportType].Add(ref this.m_passengers); this.m_passengers.Reset(); } }
private HashSet <Instance> GetMarqueeList(Ray mouseRay) { HashSet <Instance> list = new HashSet <Instance>(); Building[] buildingBuffer = Singleton <BuildingManager> .instance.m_buildings.m_buffer; NetNode[] nodeBuffer = Singleton <NetManager> .instance.m_nodes.m_buffer; NetSegment[] segmentBuffer = Singleton <NetManager> .instance.m_segments.m_buffer; TreeInstance[] treeBuffer = Singleton <TreeManager> .instance.m_trees.m_buffer; m_selection.a = m_clickPositionAbs; m_selection.c = RaycastMouseLocation(mouseRay); if (m_selection.a.x == m_selection.c.x && m_selection.a.z == m_selection.c.z) { m_selection = default; } else { float angle = Camera.main.transform.localEulerAngles.y * Mathf.Deg2Rad; Vector3 down = new Vector3(Mathf.Cos(angle), 0, -Mathf.Sin(angle)); Vector3 right = new Vector3(-down.z, 0, down.x); Vector3 a = m_selection.c - m_selection.a; float dotDown = Vector3.Dot(a, down); float dotRight = Vector3.Dot(a, right); if ((dotDown > 0 && dotRight > 0) || (dotDown <= 0 && dotRight <= 0)) { m_selection.b = m_selection.a + dotDown * down; m_selection.d = m_selection.a + dotRight * right; } else { m_selection.b = m_selection.a + dotRight * right; m_selection.d = m_selection.a + dotDown * down; } Vector3 min = m_selection.Min(); Vector3 max = m_selection.Max(); int gridMinX = Mathf.Max((int)((min.x - 16f) / 64f + 135f), 0); int gridMinZ = Mathf.Max((int)((min.z - 16f) / 64f + 135f), 0); int gridMaxX = Mathf.Min((int)((max.x + 16f) / 64f + 135f), 269); int gridMaxZ = Mathf.Min((int)((max.z + 16f) / 64f + 135f), 269); InstanceID id = new InstanceID(); ItemClass.Layer itemLayers = GetItemLayers(); if (PO.Active && (filterProcs || filterPicker)) { foreach (PO_Object obj in PO.Objects) { if (!filterProcs) { // Implies filterPicker is true if (obj.GetPrefab() != Filters.Picker.Info) { continue; } } if (!obj.isHidden() && PointInRectangle(m_selection, obj.Position)) { id.NetLane = obj.Id; list.AddObject(id); } } } for (int i = gridMinZ; i <= gridMaxZ; i++) { for (int j = gridMinX; j <= gridMaxX; j++) { if (filterBuildings || filterSurfaces || (filterPicker && Filters.Picker.IsBuilding)) { ushort building = BuildingManager.instance.m_buildingGrid[i * 270 + j]; int count = 0; while (building != 0u) { if (IsBuildingValid(ref buildingBuffer[building], itemLayers) && PointInRectangle(m_selection, buildingBuffer[building].m_position)) { if (Filters.Filter(buildingBuffer[building].Info, ref buildingBuffer[building])) { id.Building = Building.FindParentBuilding(building); if (id.Building == 0) { id.Building = building; } list.Add(id); } } building = buildingBuffer[building].m_nextGridBuilding; if (++count > 49152) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Buildings: Invalid list detected!\n" + Environment.StackTrace); break; } } } if (filterProps || filterDecals || filterSurfaces || (filterPicker && Filters.Picker.IsProp)) { PropLayer.Manager.GetMarqueeList(ref i, ref j, ref id, ref m_selection, ref list); } if (filterNodes || filterBuildings || (filterPicker && Filters.Picker.IsNode)) { ushort node = NetManager.instance.m_nodeGrid[i * 270 + j]; int count = 0; while (node != 0u) { if (IsNodeValid(ref nodeBuffer[node], itemLayers) && PointInRectangle(m_selection, nodeBuffer[node].m_position)) { ushort building = NetNode.FindOwnerBuilding(node, 363f); if (building != 0) { if (filterBuildings) { id.Building = Building.FindParentBuilding(building); if (id.Building == 0) { id.Building = building; } list.Add(id); } } else if (filterNodes || (filterPicker && Filters.Picker.IsNode)) { if (Filters.Filter(nodeBuffer[node])) { id.NetNode = node; list.Add(id); } } } node = nodeBuffer[node].m_nextGridNode; if (++count > 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Nodes: Invalid list detected!\n" + Environment.StackTrace); } } } if (filterSegments || filterBuildings || (filterPicker && Filters.Picker.IsSegment)) { ushort segment = NetManager.instance.m_segmentGrid[i * 270 + j]; int count = 0; while (segment != 0u) { if (IsSegmentValid(ref segmentBuffer[segment], itemLayers) && PointInRectangle(m_selection, segmentBuffer[segment].m_bounds.center)) { ushort building = FindOwnerBuilding(segment, 363f); if (building != 0) { if (filterBuildings) { id.Building = Building.FindParentBuilding(building); if (id.Building == 0) { id.Building = building; } list.Add(id); } } else if (filterSegments || (filterPicker && Filters.Picker.IsSegment)) { if (Filters.Filter(segmentBuffer[segment])) { id.NetSegment = segment; list.Add(id); } } } segment = segmentBuffer[segment].m_nextGridSegment; if (++count > 36864) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Segments: Invalid list detected!\n" + Environment.StackTrace); } } } } } if (filterTrees || (filterPicker && Filters.Picker.IsTree)) { gridMinX = Mathf.Max((int)((min.x - 8f) / 32f + 270f), 0); gridMinZ = Mathf.Max((int)((min.z - 8f) / 32f + 270f), 0); gridMaxX = Mathf.Min((int)((max.x + 8f) / 32f + 270f), 539); gridMaxZ = Mathf.Min((int)((max.z + 8f) / 32f + 270f), 539); for (int i = gridMinZ; i <= gridMaxZ; i++) { for (int j = gridMinX; j <= gridMaxX; j++) { uint tree = TreeManager.instance.m_treeGrid[i * 540 + j]; while (tree != 0) { if (PointInRectangle(m_selection, treeBuffer[tree].Position)) { if (Filters.Filter(treeBuffer[tree].Info)) { id.Tree = tree; list.Add(id); } } tree = treeBuffer[tree].m_nextGridTree; } } } } } return(list); }
/*********** building updates *************/ //residential building history updates public void UpdateResidentFamilies(int resilient_index) { if (!Settings.inst.listResidentsAndWorkers) { return; } List <uint> current_families_id = new List <uint>(); Building build = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_resilients[resilient_index].buildingID]; CitizenManager instance = Singleton <CitizenManager> .instance; uint num = build.m_citizenUnits; int num2 = 0; int aliveHomeCount = 0; while (num != 0u) { uint nextUnit = instance.m_units.m_buffer[(int)((UIntPtr)num)].m_nextUnit; if ((ushort)(instance.m_units.m_buffer[(int)((UIntPtr)num)].m_flags & CitizenUnit.Flags.Home) != 0) { current_families_id.Add(num); aliveHomeCount++; } num = nextUnit; if (++num2 > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } //update history family list with any new names int index_families_before_now = Math.Max(m_resilients[resilient_index].namesBuffer.Count - aliveHomeCount, 0); for (int i = 0; i < current_families_id.Count; i++) { // if(!m_resilients[resilient_index].idsBuffer.Contains(current_families_id[i])) // { // m_resilients[resilient_index].idsBuffer.Add(current_families_id[i]); // } uint valid_citizen = 0u; CitizenUnit cu = Singleton <CitizenManager> .instance.m_units.m_buffer[current_families_id[i]]; if (cu.m_citizen0 != 0u) { valid_citizen = cu.m_citizen0; } else if (cu.m_citizen1 != 0u) { valid_citizen = cu.m_citizen1; } else if (cu.m_citizen2 != 0u) { valid_citizen = cu.m_citizen2; } else if (cu.m_citizen3 != 0u) { valid_citizen = cu.m_citizen3; } else if (cu.m_citizen4 != 0u) { valid_citizen = cu.m_citizen4; } if (valid_citizen != 0u) { int family = Singleton <CitizenManager> .instance.m_citizens.m_buffer[valid_citizen].m_family; Randomizer randomizer2 = new Randomizer(family); string name = "NAME_FEMALE_LAST"; // if (Citizen.GetGender(citizenID) == Citizen.Gender.Male) // { // text = "NAME_MALE_FIRST"; // text2 = "NAME_MALE_LAST"; // } name = Locale.Get(name, randomizer2.Int32(Locale.Count(name))); name = name.Substring(4); //remove placeholder in front if (m_resilients[resilient_index].namesBuffer.Count == 0 || m_resilients[resilient_index].namesBuffer.LastIndexOf(name) < index_families_before_now) //-1 if family was never present, otherwise check if it is not currently in { m_resilients[resilient_index].namesBuffer.Add(name); } } } }
//workers building history update public void UpdateWorkers(int resilient_index) { if (!Settings.inst.listResidentsAndWorkers) { return; } List <uint> current_workers_ids = new List <uint>(); Building build = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_resilients[resilient_index].buildingID]; CitizenManager instance = Singleton <CitizenManager> .instance; uint num = build.m_citizenUnits; int num2 = 0; while (num != 0u) { if ((ushort)(instance.m_units.m_buffer[(int)((UIntPtr)num)].m_flags & CitizenUnit.Flags.Work) != 0) { CitizenUnit work_unit = instance.m_units.m_buffer[(int)((UIntPtr)num)]; if (work_unit.m_citizen0 != 0u) { current_workers_ids.Add(work_unit.m_citizen0); } if (work_unit.m_citizen1 != 0u) { current_workers_ids.Add(work_unit.m_citizen1); } if (work_unit.m_citizen2 != 0u) { current_workers_ids.Add(work_unit.m_citizen2); } if (work_unit.m_citizen3 != 0u) { current_workers_ids.Add(work_unit.m_citizen3); } if (work_unit.m_citizen4 != 0u) { current_workers_ids.Add(work_unit.m_citizen4); } current_workers_ids.Add(num); } num = instance.m_units.m_buffer[(int)((UIntPtr)num)].m_nextUnit; if (++num2 > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } //update history family list with any new names for (int i = 0; i < current_workers_ids.Count; i++) { // if(!m_resilients[resilient_index].idsBuffer.Contains(current_workers_ids[i])) // { // m_resilients[resilient_index].idsBuffer.Add(current_workers_ids[i]); // } string name = Singleton <CitizenManager> .instance.GetCitizenName(current_workers_ids[i]); if (name == null || name.Length == 0) { //CODebugBase<LogChannel>.Error(LogChannel.Modding, "empty citizen name for " + current_workers_ids[i]); } else if (!m_resilients[resilient_index].namesBuffer.Contains(name)) { m_resilients[resilient_index].namesBuffer.Add(name); } } }
/// <summary> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { PathManager pathMan = Singleton <PathManager> .instance; #if DEBUG /*if (!Options.disableSomething1) { * Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}) called. flags: {vehicleData.m_flags} pfFlags: {pathMan.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags}"); * }*/ #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; #if USEPATHWAITCOUNTER if ((pathFindFlags & (PathUnit.FLAG_READY | PathUnit.FLAG_FAILED)) != 0) { VehicleState state = VehicleStateManager.Instance()._GetVehicleState(vehicleId); state.PathWaitCounter = 0; // NON-STOCK CODE } #endif if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) // path == 0: non-stock code! { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } #if USEPATHWAITCOUNTER else { VehicleState state = VehicleStateManager.Instance()._GetVehicleState(vehicleId); state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1); // NON-STOCK CODE } #endif } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } /// NON-STOCK CODE START /// VehicleStateManager vehStateManager = VehicleStateManager.Instance(); if (Options.prioritySignsEnabled || Options.timedLightsEnabled) { try { vehStateManager.UpdateVehiclePos(vehicleId, ref vehicleData); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } } if (!Options.isStockLaneChangerUsed()) { try { vehStateManager.LogTraffic(vehicleId, ref vehicleData, true); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } } /// NON-STOCK CODE END /// Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager instance2 = Singleton <VehicleManager> .instance; ushort num = vehicleData.m_trailingVehicle; int num2 = 0; while (num != 0) { ushort trailingVehicle = instance2.m_vehicles.m_buffer[(int)num].m_trailingVehicle; VehicleInfo info = instance2.m_vehicles.m_buffer[(int)num].Info; info.m_vehicleAI.SimulationStep(num, ref instance2.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics); num = trailingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } #if PATHRECALC ushort recalcSegmentId = 0; #endif int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter >= maxBlockCounter && Options.enableDespawning) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } #if PATHRECALC else if (vehicleData.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref vehicleData, maxBlockCounter, out recalcSegmentId)) { CustomVehicleAI.MarkPathRecalculation(vehicleId, recalcSegmentId); InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData); } #endif }
protected override void StartActions() { if (m_ghostMode) { for (ushort a = 1; a < BuildingManager.instance.m_buildings.m_buffer.Length; a++) { if (BuildingManager.instance.m_buildings.m_buffer[a].Info.m_buildingAI is PrivateBuildingAI) { Vector3 position = BuildingManager.instance.m_buildings.m_buffer[a].m_position; int num = Mathf.Max((int)((position.x - 35f) / 64f + 135f), 0); int num2 = Mathf.Max((int)((position.z - 35f) / 64f + 135f), 0); int num3 = Mathf.Min((int)((position.x + 35f) / 64f + 135f), 269); int num4 = Mathf.Min((int)((position.z + 35f) / 64f + 135f), 269); Array16 <Building> buildings = Singleton <BuildingManager> .instance.m_buildings; ushort[] buildingGrid = Singleton <BuildingManager> .instance.m_buildingGrid; for (int i = num2; i <= num4; i++) { for (int j = num; j <= num3; j++) { ushort num5 = buildingGrid[i * 270 + j]; int num6 = 0; while (num5 != 0) { ushort nextGridBuilding = buildings.m_buffer[num5].m_nextGridBuilding; Building.Flags flags = buildings.m_buffer[num5].m_flags; if ((flags & (Building.Flags.Created | Building.Flags.Deleted | Building.Flags.Demolishing | Building.Flags.Collapsed)) == Building.Flags.Created) { BuildingInfo info = buildings.m_buffer[num5].Info; if (info != null && info.m_placementStyle == ItemClass.Placement.Automatic) { ItemClass.Zone zone = info.m_class.GetZone(); ItemClass.Zone secondaryZone = info.m_class.GetSecondaryZone(); if (zone != ItemClass.Zone.None && VectorUtils.LengthSqrXZ(buildings.m_buffer[num5].m_position - position) <= 1225f) { buildings.m_buffer[num5].CheckZoning(zone, secondaryZone, true); } } } num5 = nextGridBuilding; if (++num6 >= 49152) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } } } for (ushort i = 1; i < ZoneManager.instance.m_blocks.m_buffer.Length; i++) { bool changed = false; for (int x = 0; x < 4; x++) { for (int z = 0; z < 8; z++) { changed = ZoneMixerOverrides.GetBlockZoneSanitize(ref ZoneManager.instance.m_blocks.m_buffer[i], x, z) | changed; } } if (changed) { ZoneManager.instance.m_blocks.m_buffer[i].RefreshZoning(i); } } K45DialogControl.ShowModal(new K45DialogControl.BindProperties() { icon = ZoneMixerMod.Instance.IconName, title = Locale.Get("K45_ZM_GHOST_MODE_MODAL_TITLE"), message = Locale.Get("K45_ZM_GHOST_MODE_MODAL_MESSAGE"), showButton1 = true, textButton1 = Locale.Get("K45_ZM_OK_BUTTON") }, (x) => true); } }
/// <summary> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { #if DEBUG bool vehDebug = GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.VehicleId == vehicleId; bool debug = GlobalConfig.Instance.Debug.Switches[2] && vehDebug; bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && vehDebug; #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; // NON-STOCK CODE START ExtPathState mainPathState = ExtPathState.Calculating; if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) { mainPathState = ExtPathState.Failed; } else if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { mainPathState = ExtPathState.Ready; } #if DEBUG if (debug) { Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Path: {vehicleData.m_path}, mainPathState={mainPathState}"); } #endif ExtSoftPathState finalPathState = ExtSoftPathState.None; #if BENCHMARK using (var bm = new Benchmark(null, "UpdateCarPathState")) { #endif finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState); if (Options.prohibitPocketCars && VehicleStateManager.Instance.VehicleStates[vehicleId].vehicleType == ExtVehicleType.PassengerCar) { ushort driverInstanceId = CustomPassengerCarAI.GetDriverInstanceId(vehicleId, ref vehicleData); finalPathState = AdvancedParkingManager.Instance.UpdateCarPathState(vehicleId, ref vehicleData, ref Singleton <CitizenManager> .instance.m_instances.m_buffer[driverInstanceId], ref ExtCitizenInstanceManager.Instance.ExtInstances[driverInstanceId], mainPathState); #if DEBUG if (debug) { Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Applied Parking AI logic. Path: {vehicleData.m_path}, mainPathState={mainPathState}, finalPathState={finalPathState}"); } #endif } #if BENCHMARK } #endif switch (finalPathState) { case ExtSoftPathState.Ready: #if DEBUG if (debug) { Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding succeeded for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- calling CarAI.PathfindSuccess"); } #endif vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); break; case ExtSoftPathState.Ignore: #if DEBUG if (debug) { Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding result shall be ignored for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- ignoring"); } #endif return; case ExtSoftPathState.Calculating: default: #if DEBUG if (debug) { Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding result undetermined for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- continue"); } #endif break; case ExtSoftPathState.FailedHard: #if DEBUG if (debug) { Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): HARD path-finding failure for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- calling CarAI.PathfindFailure"); } #endif vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; case ExtSoftPathState.FailedSoft: #if DEBUG if (debug) { Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): SOFT path-finding failure for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- calling CarAI.InvalidPath"); } #endif // path mode has been updated, repeat path-finding vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; this.InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData); break; } // NON-STOCK CODE END } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } // NON-STOCK CODE START #if BENCHMARK using (var bm = new Benchmark(null, "UpdateVehiclePosition")) { #endif VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData); #if BENCHMARK } #endif if (!Options.isStockLaneChangerUsed() && (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0) { #if BENCHMARK using (var bm = new Benchmark(null, "LogTraffic")) { #endif // Advanced AI traffic measurement VehicleStateManager.Instance.LogTraffic(vehicleId); #if BENCHMARK } #endif } // NON-STOCK CODE END Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager vehManager = Singleton <VehicleManager> .instance; ushort trailerId = vehicleData.m_trailingVehicle; int numIters = 0; while (trailerId != 0) { ushort trailingVehicle = vehManager.m_vehicles.m_buffer[(int)trailerId].m_trailingVehicle; VehicleInfo info = vehManager.m_vehicles.m_buffer[(int)trailerId].Info; info.m_vehicleAI.SimulationStep(trailerId, ref vehManager.m_vehicles.m_buffer[(int)trailerId], vehicleId, ref vehicleData, lodPhysics); trailerId = trailingVehicle; if (++numIters > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter >= maxBlockCounter) { // NON-STOCK CODE START bool mayDespawn = true; #if BENCHMARK using (var bm = new Benchmark(null, "MayDespawn")) { #endif mayDespawn = VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData); #if BENCHMARK } #endif if (mayDespawn) { // NON-STOCK CODE END Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } // NON-STOCK CODE } }
private bool GetStopPosition(TransportInfo info, ushort segment, ushort building, ushort firstStop, ref Vector3 hitPos, out bool fixedPlatform) { //begin mod(+): detect key bool alternateMode = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift); //end mod NetManager instance1 = Singleton <NetManager> .instance; BuildingManager instance2 = Singleton <BuildingManager> .instance; TransportManager instance3 = Singleton <TransportManager> .instance; fixedPlatform = false; if (info.m_transportType == TransportInfo.TransportType.Pedestrian) { Vector3 position = Vector3.zero; float laneOffset = 0.0f; uint laneID = 0; int laneIndex; if ((int)segment != 0 && !instance1.m_segments.m_buffer[(int)segment].GetClosestLanePosition(hitPos, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, VehicleInfo.VehicleType.None, out position, out laneID, out laneIndex, out laneOffset)) { laneID = 0U; if ((instance1.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None && (int)building == 0) { building = NetSegment.FindOwnerBuilding(segment, 363f); } } if ((int)building != 0) { if (instance2.m_buildings.m_buffer[(int)building].Info.m_hasPedestrianPaths) { laneID = instance2.m_buildings.m_buffer[(int)building].FindLane(NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, hitPos, out position, out laneOffset); } if ((int)laneID == 0) { Vector3 sidewalkPosition = instance2.m_buildings.m_buffer[(int)building].CalculateSidewalkPosition(); laneID = instance2.m_buildings.m_buffer[(int)building].FindAccessLane(NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, sidewalkPosition, out position, out laneOffset); } } if ((int)laneID == 0) { return(false); } if ((double)laneOffset < 0.00392156885936856) { laneOffset = 0.003921569f; position = instance1.m_lanes.m_buffer[laneID].CalculatePosition(laneOffset); } else if ((double)laneOffset > 0.996078431606293) { laneOffset = 0.9960784f; position = instance1.m_lanes.m_buffer[laneID].CalculatePosition(laneOffset); } if ((int)this.m_line != 0) { firstStop = instance3.m_lines.m_buffer[(int)this.m_line].m_stops; ushort stop = firstStop; int num = 0; while ((int)stop != 0) { if ((int)instance1.m_nodes.m_buffer[(int)stop].m_lane == (int)laneID) { hitPos = instance1.m_nodes.m_buffer[(int)stop].m_position; fixedPlatform = true; return(true); } stop = TransportLine.GetNextStop(stop); if ((int)stop != (int)firstStop) { if (++num >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace); break; } } else { break; } } } hitPos = position; fixedPlatform = true; return(true); } if ((int)segment != 0) { if ((instance1.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None) { building = NetSegment.FindOwnerBuilding(segment, 363f); if ((int)building != 0) { BuildingInfo info1 = instance2.m_buildings.m_buffer[(int)building].Info; TransportInfo transportLineInfo1 = info1.m_buildingAI.GetTransportLineInfo(); TransportInfo transportLineInfo2 = info1.m_buildingAI.GetSecondaryTransportLineInfo(); //begin mod(*): check for !alternateMode if (!alternateMode && transportLineInfo1 != null && transportLineInfo1.m_transportType == info.m_transportType || !alternateMode && transportLineInfo2 != null && transportLineInfo2.m_transportType == info.m_transportType) { //end mod segment = (ushort)0; } else { building = (ushort)0; } } } Vector3 position1; uint laneID1; int laneIndex1; float laneOffset1; if ((int)segment != 0 && instance1.m_segments.m_buffer[(int)segment].GetClosestLanePosition(hitPos, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, info.m_vehicleType, out position1, out laneID1, out laneIndex1, out laneOffset1)) { if (info.m_vehicleType == VehicleInfo.VehicleType.None) { NetLane.Flags flags1 = (NetLane.Flags)((int)instance1.m_lanes.m_buffer[laneID1].m_flags & 768); NetLane.Flags flags2 = info.m_stopFlag; NetInfo info1 = instance1.m_segments.m_buffer[(int)segment].Info; if (info1.m_vehicleTypes != VehicleInfo.VehicleType.None) { flags2 = NetLane.Flags.None; } if (flags1 != NetLane.Flags.None && flags2 != NetLane.Flags.None && flags1 != flags2) { return(false); } float stopOffset = info1.m_lanes[laneIndex1].m_stopOffset; if ((instance1.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { stopOffset = -stopOffset; } Vector3 direction; instance1.m_lanes.m_buffer[laneID1].CalculateStopPositionAndDirection(0.5019608f, stopOffset, out hitPos, out direction); fixedPlatform = true; return(true); } Vector3 position2; uint laneID2; int laneIndex2; float laneOffset2; if (instance1.m_segments.m_buffer[(int)segment].GetClosestLanePosition(position1, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, out position2, out laneID2, out laneIndex2, out laneOffset2)) { NetLane.Flags flags = (NetLane.Flags)((int)instance1.m_lanes.m_buffer[laneID1].m_flags & 768); if (flags != NetLane.Flags.None && info.m_stopFlag != NetLane.Flags.None && flags != info.m_stopFlag) { return(false); } float stopOffset = instance1.m_segments.m_buffer[(int)segment].Info.m_lanes[laneIndex2].m_stopOffset; if ((instance1.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { stopOffset = -stopOffset; } Vector3 direction; instance1.m_lanes.m_buffer[laneID2].CalculateStopPositionAndDirection(0.5019608f, stopOffset, out hitPos, out direction); fixedPlatform = true; return(true); } } } //begin mod(*): check for !alternateMode if (!alternateMode && (int)building != 0) { //end mod ushort num1 = 0; if ((instance2.m_buildings.m_buffer[(int)building].m_flags & Building.Flags.Untouchable) != Building.Flags.None) { num1 = Building.FindParentBuilding(building); } if (this.m_building != 0 && (int)firstStop != 0 && (this.m_building == (int)building || this.m_building == (int)num1)) { hitPos = instance1.m_nodes.m_buffer[(int)firstStop].m_position; return(true); } VehicleInfo randomVehicleInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref Singleton <SimulationManager> .instance.m_randomizer, info.m_class.m_service, info.m_class.m_subService, info.m_class.m_level); if (randomVehicleInfo != null) { BuildingInfo info1 = instance2.m_buildings.m_buffer[(int)building].Info; TransportInfo transportLineInfo1 = info1.m_buildingAI.GetTransportLineInfo(); if (transportLineInfo1 == null && (int)num1 != 0) { building = num1; info1 = instance2.m_buildings.m_buffer[(int)building].Info; transportLineInfo1 = info1.m_buildingAI.GetTransportLineInfo(); } TransportInfo transportLineInfo2 = info1.m_buildingAI.GetSecondaryTransportLineInfo(); if (transportLineInfo1 != null && transportLineInfo1.m_transportType == info.m_transportType || transportLineInfo2 != null && transportLineInfo2.m_transportType == info.m_transportType) { Vector3 vector3 = Vector3.zero; int num2 = 1000000; for (int index = 0; index < 12; ++index) { Randomizer randomizer = new Randomizer((ulong)index); Vector3 position; Vector3 target; info1.m_buildingAI.CalculateSpawnPosition(building, ref instance2.m_buildings.m_buffer[(int)building], ref randomizer, randomVehicleInfo, out position, out target); int num3 = 0; if (info.m_avoidSameStopPlatform) { num3 = this.GetLineCount(position, target - position, info.m_transportType); } if (num3 < num2) { vector3 = position; num2 = num3; } else if (num3 == num2 && (double)Vector3.SqrMagnitude(position - hitPos) < (double)Vector3.SqrMagnitude(vector3 - hitPos)) { vector3 = position; } } if ((int)firstStop != 0) { Vector3 position = instance1.m_nodes.m_buffer[(int)firstStop].m_position; if ((double)Vector3.SqrMagnitude(position - vector3) < 16384.0) { uint lane = instance1.m_nodes.m_buffer[(int)firstStop].m_lane; if ((int)lane != 0) { ushort segment1 = instance1.m_lanes.m_buffer[lane].m_segment; if ((int)segment1 != 0 && (instance1.m_segments.m_buffer[(int)segment1].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None) { ushort ownerBuilding = NetSegment.FindOwnerBuilding(segment1, 363f); if ((int)building == (int)ownerBuilding) { hitPos = position; return(true); } } } } } hitPos = vector3; return(num2 != 1000000); } } } return(false); }
private static void ApplyBrush(TreeTool tt) { //uint useless1 = 0; unsafe { float single; float single1; uint num; int num1; Vector3 vector3 = new Vector3(); Randomizer value = (Randomizer)tt.GetType().GetField("m_randomizer", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tt); ToolController toolController = (ToolController)tt.GetType().GetField("m_toolController", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tt); Vector3 value1 = (Vector3)tt.GetType().GetField("m_mousePosition", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tt); bool flag = (bool)tt.GetType().GetField("m_mouseLeftDown", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tt); bool flag1 = (bool)tt.GetType().GetField("m_mouseRightDown", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tt); TreeInfo treeInfo = (TreeInfo)tt.GetType().GetField("m_treeInfo", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tt); float[] brushData = toolController.BrushData; float mBrushSize = tt.m_brushSize * 0.5f; float single2 = 32f; int num2 = 540; TreeInstance[] mBuffer = Singleton <TreeManager> .instance.m_trees.m_buffer; uint[] mTreeGrid = Singleton <TreeManager> .instance.m_treeGrid; float mStrength = tt.m_strength; int num3 = Mathf.Max((int)((value1.x - mBrushSize) / single2 + (float)num2 * 0.5f), 0); int num4 = Mathf.Max((int)((value1.z - mBrushSize) / single2 + (float)num2 * 0.5f), 0); int num5 = Mathf.Min((int)((value1.x + mBrushSize) / single2 + (float)num2 * 0.5f), num2 - 1); int num6 = Mathf.Min((int)((value1.z + mBrushSize) / single2 + (float)num2 * 0.5f), num2 - 1); for (int i = num4; i <= num6; i++) { float mBrushSize1 = (float)(((float)i - (float)num2 * 0.5f + 0.5f) * single2 - value1.z + mBrushSize) / tt.m_brushSize * 64f - 0.5f; int num7 = Mathf.Clamp(Mathf.FloorToInt(mBrushSize1), 0, 63); int num8 = Mathf.Clamp(Mathf.CeilToInt(mBrushSize1), 0, 63); for (int j = num3; j <= num5; j++) { float mBrushSize2 = (float)(((float)j - (float)num2 * 0.5f + 0.5f) * single2 - value1.x + mBrushSize) / tt.m_brushSize * 64f - 0.5f; int num9 = Mathf.Clamp(Mathf.FloorToInt(mBrushSize2), 0, 63); int num10 = Mathf.Clamp(Mathf.CeilToInt(mBrushSize2), 0, 63); float single3 = brushData[num7 * 64 + num9]; float single4 = brushData[num7 * 64 + num10]; float single5 = brushData[num8 * 64 + num9]; float single6 = brushData[num8 * 64 + num10]; float single7 = single3 + (float)((single4 - single3) * (mBrushSize2 - (float)num9)); float single8 = single5 + (float)((single6 - single5) * (mBrushSize2 - (float)num9)); float single9 = single7 + (float)((single8 - single7) * (mBrushSize1 - (float)num7)); int num11 = (int)(mStrength * (single9 * 1.2f - 0.2f) * 10000f); if (flag && tt.m_prefab != null) { if (value.Int32(10000) < num11) { TreeInfo treeInfo1 = ((Singleton <ToolManager> .instance.m_properties.m_mode & ItemClass.Availability.AssetEditor) == ItemClass.Availability.None ? tt.m_prefab.GetVariation(ref value) : tt.m_prefab); vector3.x = ((float)j - (float)num2 * 0.5f) * single2; vector3.z = ((float)i - (float)num2 * 0.5f) * single2; vector3.x = vector3.x + (float)(((float)value.Int32(10000) + 0.5f) * (single2 / 10000f)); vector3.z = vector3.z + (float)(((float)value.Int32(10000) + 0.5f) * (single2 / 10000f)); vector3.y = 0f; vector3.y = Singleton <TerrainManager> .instance.SampleDetailHeight(vector3, out single, out single1); if (Mathf.Max(Mathf.Abs(single), Mathf.Abs(single1)) < (float)value.Int32(10000) * 5E-05f) { float mSize = treeInfo.m_generatedInfo.m_size.y; float mMinScale = treeInfo.m_minScale; Randomizer randomizer = new Randomizer(Singleton <TreeManager> .instance.m_trees.NextFreeItem(ref value)); mMinScale = mMinScale + (float)randomizer.Int32(10000) * ((treeInfo.m_maxScale - treeInfo.m_minScale) * 0.0001f); mSize = mSize * mMinScale; float single11 = 4.5f; Vector2 vector2 = VectorUtils.XZ(vector3); Quad2 quad22 = new Quad2() { a = vector2 + new Vector2(-single11, -single11), b = vector2 + new Vector2(-single11, single11), c = vector2 + new Vector2(single11, single11), d = vector2 + new Vector2(single11, -single11) }; Quad2 quad2 = quad22; Quad2 quad23 = new Quad2() { a = vector2 + new Vector2(-8f, -8f), b = vector2 + new Vector2(-8f, 8f), c = vector2 + new Vector2(8f, 8f), d = vector2 + new Vector2(8f, -8f) }; Quad2 quad21 = quad23; float single12 = value1.y - 1000f; float single13 = value1.y + mSize; ItemClass.CollisionType collisionType = ItemClass.CollisionType.Terrain; if (!Singleton <PropManager> .instance.OverlapQuad(quad2, single12, single13, collisionType, 0, 0) && !Singleton <TreeManager> .instance.OverlapQuad(quad21, single12, single13, collisionType, 0, 0) && !Singleton <NetManager> .instance.OverlapQuad(quad2, single12, single13, collisionType, treeInfo1.m_class.m_layer, 0, 0, 0) && !Singleton <BuildingManager> .instance.OverlapQuad(quad2, single12, single13, collisionType, treeInfo1.m_class.m_layer, 0, 0, 0) && !Singleton <TerrainManager> .instance.HasWater(vector2) && !Singleton <GameAreaManager> .instance.QuadOutOfArea(quad2) && !Singleton <TreeManager> .instance.CreateTree(out num, ref value, treeInfo1, vector3, false)) { } } } } else if (flag1 || tt.m_prefab == null) { uint num12 = mTreeGrid[i * num2 + j]; int num13 = 0; do { if (num12 == 0) { goto Label10; } uint mNextGridTree = mBuffer[num12].m_nextGridTree; if (value.Int32(10000) < num11) { Singleton <TreeManager> .instance.ReleaseTree(num12); } num12 = mNextGridTree; num1 = num13 + 1; num13 = num1; }while (num1 < LimitTreeManager.Helper.TreeLimit); CODebugBase <LogChannel> .Error(LogChannel.Core, string.Concat("Invalid list detected!\n", Environment.StackTrace)); } Label10: ;//useless1++; } } } }
protected override bool SpawnVehicle(ushort instanceID, ref CitizenInstance citizenData, PathUnit.Position pathPos) { VehicleManager instance = Singleton <VehicleManager> .instance; float num = 20f; int num2 = Mathf.Max((int)((citizenData.m_targetPos.x - num) / 32f + 270f), 0); int num3 = Mathf.Max((int)((citizenData.m_targetPos.z - num) / 32f + 270f), 0); int num4 = Mathf.Min((int)((citizenData.m_targetPos.x + num) / 32f + 270f), 539); int num5 = Mathf.Min((int)((citizenData.m_targetPos.z + num) / 32f + 270f), 539); for (int i = num3; i <= num5; i++) { for (int j = num2; j <= num4; j++) { ushort num6 = instance.m_vehicleGrid [i * 540 + j]; int num7 = 0; while (num6 != 0) { if (this.TryJoinVehicle(instanceID, ref citizenData, num6, ref instance.m_vehicles.m_buffer [(int)num6])) { citizenData.m_flags |= CitizenInstance.Flags.EnteringVehicle; citizenData.m_flags &= ~CitizenInstance.Flags.TryingSpawnVehicle; citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting; citizenData.m_waitCounter = 0; return(true); } num6 = instance.m_vehicles.m_buffer [(int)num6].m_nextGridVehicle; if (++num7 > 65536) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } NetManager instance2 = Singleton <NetManager> .instance; CitizenManager instance3 = Singleton <CitizenManager> .instance; Vector3 vector = Vector3.zero; Quaternion rotation = Quaternion.identity; ushort num8 = instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle; if (num8 != 0) { vector = instance.m_parkedVehicles.m_buffer [(int)num8].m_position; rotation = instance.m_parkedVehicles.m_buffer [(int)num8].m_rotation; } VehicleInfo vehicleInfo = this.GetVehicleInfo(instanceID, ref citizenData, false); if (vehicleInfo == null || vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle) { instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle(citizenData.m_citizen, 0); if ((citizenData.m_flags & CitizenInstance.Flags.TryingSpawnVehicle) == CitizenInstance.Flags.None) { citizenData.m_flags |= CitizenInstance.Flags.TryingSpawnVehicle; citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting; citizenData.m_waitCounter = 0; } return(true); } if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi) { instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle(citizenData.m_citizen, 0); if ((citizenData.m_flags & CitizenInstance.Flags.WaitingTaxi) == CitizenInstance.Flags.None) { citizenData.m_flags |= CitizenInstance.Flags.WaitingTaxi; citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting; citizenData.m_waitCounter = 0; } return(true); } uint laneID = PathManager.GetLaneID(pathPos); Vector3 vector2 = citizenData.m_targetPos; if (num8 != 0 && Vector3.SqrMagnitude(vector - vector2) < 1024f) { vector2 = vector; } else { num8 = 0; } Vector3 a; float num9; instance2.m_lanes.m_buffer [(int)((UIntPtr)laneID)].GetClosestPosition(vector2, out a, out num9); byte lastPathOffset = (byte)Mathf.Clamp(Mathf.RoundToInt(num9 * 255f), 0, 255); a = vector2 + Vector3.ClampMagnitude(a - vector2, 5f); ushort num10; if (instance.CreateVehicle(out num10, ref Singleton <SimulationManager> .instance.m_randomizer, vehicleInfo, vector2, TransferManager.TransferReason.None, false, false)) { Vehicle.Frame frame = instance.m_vehicles.m_buffer [(int)num10].m_frame0; if (num8 != 0) { frame.m_rotation = rotation; } else { Vector3 forward = a - citizenData.GetLastFrameData().m_position; if (forward.sqrMagnitude > 0.01f) { frame.m_rotation = Quaternion.LookRotation(forward); } } instance.m_vehicles.m_buffer [(int)num10].m_frame0 = frame; instance.m_vehicles.m_buffer [(int)num10].m_frame1 = frame; instance.m_vehicles.m_buffer [(int)num10].m_frame2 = frame; instance.m_vehicles.m_buffer [(int)num10].m_frame3 = frame; vehicleInfo.m_vehicleAI.FrameDataUpdated(num10, ref instance.m_vehicles.m_buffer [(int)num10], ref frame); instance.m_vehicles.m_buffer [(int)num10].m_targetPos0 = new Vector4(a.x, a.y, a.z, 2f); Vehicle[] expr_4E5_cp_0 = instance.m_vehicles.m_buffer; ushort expr_4E5_cp_1 = num10; expr_4E5_cp_0 [(int)expr_4E5_cp_1].m_flags = (expr_4E5_cp_0 [(int)expr_4E5_cp_1].m_flags | Vehicle.Flags.Stopped); instance.m_vehicles.m_buffer [(int)num10].m_path = citizenData.m_path; instance.m_vehicles.m_buffer [(int)num10].m_pathPositionIndex = citizenData.m_pathPositionIndex; instance.m_vehicles.m_buffer [(int)num10].m_lastPathOffset = lastPathOffset; instance.m_vehicles.m_buffer [(int)num10].m_transferSize = (ushort)(citizenData.m_citizen & 65535u); vehicleInfo.m_vehicleAI.TrySpawn(num10, ref instance.m_vehicles.m_buffer [(int)num10]); if (num8 != 0) { InstanceID empty = InstanceID.Empty; empty.ParkedVehicle = num8; InstanceID empty2 = InstanceID.Empty; empty2.Vehicle = num10; Singleton <InstanceManager> .instance.ChangeInstance(empty, empty2); } citizenData.m_path = 0u; instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle(citizenData.m_citizen, 0); instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetVehicle(citizenData.m_citizen, num10, 0u); citizenData.m_flags |= CitizenInstance.Flags.EnteringVehicle; citizenData.m_flags &= ~CitizenInstance.Flags.TryingSpawnVehicle; citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting; citizenData.m_waitCounter = 0; return(true); } instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle(citizenData.m_citizen, 0); if ((citizenData.m_flags & CitizenInstance.Flags.TryingSpawnVehicle) == CitizenInstance.Flags.None) { citizenData.m_flags |= CitizenInstance.Flags.TryingSpawnVehicle; citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting; citizenData.m_waitCounter = 0; } return(true); }
/// <summary> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; // NON-STOCK CODE START ExtPathState mainPathState = ExtPathState.Calculating; if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) { mainPathState = ExtPathState.Failed; } else if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { mainPathState = ExtPathState.Ready; } #if BENCHMARK using (var bm = new Benchmark(null, "UpdateCarPathState")) { #endif if (Options.prohibitPocketCars && VehicleStateManager.Instance.VehicleStates[vehicleId].vehicleType == ExtVehicleType.PassengerCar) { mainPathState = AdvancedParkingManager.Instance.UpdateCarPathState(vehicleId, ref vehicleData, ref ExtCitizenInstanceManager.Instance.ExtInstances[CustomPassengerCarAI.GetDriverInstanceId(vehicleId, ref vehicleData)], mainPathState); } #if BENCHMARK } #endif // NON-STOCK CODE END if (mainPathState == ExtPathState.Ready) { vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); } else if (mainPathState == ExtPathState.Failed) { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } // NON-STOCK CODE START #if BENCHMARK using (var bm = new Benchmark(null, "UpdateVehiclePosition")) { #endif VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData); #if BENCHMARK } #endif if (!Options.isStockLaneChangerUsed()) { #if BENCHMARK using (var bm = new Benchmark(null, "LogTraffic")) { #endif // Advanced AI traffic measurement VehicleStateManager.Instance.LogTraffic(vehicleId); #if BENCHMARK } #endif } // NON-STOCK CODE END Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager vehManager = Singleton <VehicleManager> .instance; ushort trailerId = vehicleData.m_trailingVehicle; int numIters = 0; while (trailerId != 0) { ushort trailingVehicle = vehManager.m_vehicles.m_buffer[(int)trailerId].m_trailingVehicle; VehicleInfo info = vehManager.m_vehicles.m_buffer[(int)trailerId].Info; info.m_vehicleAI.SimulationStep(trailerId, ref vehManager.m_vehicles.m_buffer[(int)trailerId], vehicleId, ref vehicleData, lodPhysics); trailerId = trailingVehicle; if (++numIters > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter >= maxBlockCounter) { // NON-STOCK CODE START bool mayDespawn = true; #if BENCHMARK using (var bm = new Benchmark(null, "MayDespawn")) { #endif mayDespawn = VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData); #if BENCHMARK } #endif if (mayDespawn) { // NON-STOCK CODE END Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } // NON-STOCK CODE } }
public ushort FindRoad(Vector3 position) { Bounds bounds = new Bounds(position, new Vector3(20f, 20f, 20f)); int num = Mathf.Max((int)((bounds.min.x - 64f) / 64f + 135f), 0); int num2 = Mathf.Max((int)((bounds.min.z - 64f) / 64f + 135f), 0); int num3 = Mathf.Min((int)((bounds.max.x + 64f) / 64f + 135f), 269); int num4 = Mathf.Min((int)((bounds.max.z + 64f) / 64f + 135f), 269); NetManager instance = netManager; for (int i = num2; i <= num4; i++) { for (int j = num; j <= num3; j++) { ushort num5 = instance.m_segmentGrid[i * 270 + j]; int num6 = 0; while (num5 != 0) { NetInfo info = instance.m_segments.m_buffer[(int)num5].Info; if (info.m_class.m_service == ItemClass.Service.Road && !info.m_netAI.IsUnderground() && (info.m_hasForwardVehicleLanes || info.m_hasBackwardVehicleLanes)) { ushort startNode = instance.m_segments.m_buffer[(int)num5].m_startNode; ushort endNode = instance.m_segments.m_buffer[(int)num5].m_endNode; Vector3 position2 = instance.m_nodes.m_buffer[(int)startNode].m_position; Vector3 position3 = instance.m_nodes.m_buffer[(int)endNode].m_position; float num7 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position2.x, bounds.min.z - 64f - position2.z), Mathf.Max(position2.x - bounds.max.x - 64f, position2.z - bounds.max.z - 64f)); float num8 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position3.x, bounds.min.z - 64f - position3.z), Mathf.Max(position3.x - bounds.max.x - 64f, position3.z - bounds.max.z - 64f)); if ((num7 < 0f || num8 < 0f) && instance.m_segments.m_buffer[(int)num5].m_bounds.Intersects(bounds) && instance .m_segments.m_buffer[(int)num5].GetClosestLanePosition(position, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.All, VehicleInfo.VehicleType.None, false, out Vector3 b, out int num9, out float num10, out Vector3 vector, out int num11, out float num12)) { float num13 = Vector3.SqrMagnitude(position - b); if (num13 < 400f) { return(num5); } } } num5 = instance.m_segments.m_buffer[(int)num5].m_nextGridSegment; if (++num6 >= 36864) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } return(0); }
private void UnloadPassengers(ushort vehicleID, ref Vehicle data, ushort currentStop, ushort nextStop) { if ((int)currentStop == 0) { return; } VehicleManager instance1 = Singleton <VehicleManager> .instance; NetManager instance2 = Singleton <NetManager> .instance; TransportManager instance3 = Singleton <TransportManager> .instance; Vector3 position = instance2.m_nodes.m_buffer[(int)currentStop].m_position; Vector3 targetPos = Vector3.zero; if ((int)nextStop != 0) { targetPos = instance2.m_nodes.m_buffer[(int)nextStop].m_position; } int serviceCounter = 0; int num = 0; //begin mod (+): calculate passenger count before unloading passengers ushort vehicleID1 = vehicleID; GetBufferStatus(vehicleID1, ref instance1.m_vehicles.m_buffer[(int)vehicleID1], out string localeKey, out int bufferStatusBefore, out int max); //end mod while ((int)vehicleID != 0) { if ((int)data.m_transportLine != 0) { BusAI.TransportArriveAtTarget(vehicleID, ref instance1.m_vehicles.m_buffer[(int)vehicleID], position, targetPos, ref serviceCounter, ref instance3.m_lines.m_buffer[(int)data.m_transportLine].m_passengers, (int)nextStop == 0); } else { BusAI.TransportArriveAtTarget(vehicleID, ref instance1.m_vehicles.m_buffer[(int)vehicleID], position, targetPos, ref serviceCounter, ref instance3.m_passengers[(int)this.m_transportInfo.m_transportType], (int)nextStop == 0); } vehicleID = instance1.m_vehicles.m_buffer[(int)vehicleID].m_trailingVehicle; if (++num > VehicleManagerMod.MaxVehicleCount) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace); break; } } Singleton <StatisticsManager> .instance.Acquire <StatisticArray>(StatisticType.PassengerCount) .Acquire <StatisticInt32>((int)this.m_transportInfo.m_transportType, 10) .Add(serviceCounter); serviceCounter += (int)instance2.m_nodes.m_buffer[(int)currentStop].m_tempCounter; instance2.m_nodes.m_buffer[(int)currentStop].m_tempCounter = (ushort)Mathf.Min(serviceCounter, (int)ushort.MaxValue); //begin mod (+): calculate passenger count after unloading passengers GetBufferStatus(vehicleID1, ref instance1.m_vehicles.m_buffer[(int)vehicleID1], out localeKey, out int bufferStatusAfter, out max); int diff = bufferStatusBefore - bufferStatusAfter; VehicleManagerMod.m_cachedVehicleData[(int)vehicleID1].LastStopGonePassengers = diff; VehicleManagerMod.m_cachedVehicleData[(int)vehicleID1].CurrentStop = currentStop; NetManagerMod.m_cachedNodeData[(int)currentStop].PassengersOut += diff; //end mod }
private void RaycastHoverInstance(Ray mouseRay) { Vector3 origin = mouseRay.origin; Vector3 normalized = mouseRay.direction.normalized; Vector3 vector = mouseRay.origin + normalized * Camera.main.farClipPlane; Segment3 ray = new Segment3(origin, vector); Building[] buildingBuffer = Singleton <BuildingManager> .instance.m_buildings.m_buffer; NetNode[] nodeBuffer = Singleton <NetManager> .instance.m_nodes.m_buffer; NetSegment[] segmentBuffer = Singleton <NetManager> .instance.m_segments.m_buffer; TreeInstance[] treeBuffer = Singleton <TreeManager> .instance.m_trees.m_buffer; Vector3 location = RaycastMouseLocation(mouseRay); InstanceID id = InstanceID.Empty; ItemClass.Layer itemLayers = GetItemLayers(); bool selectPicker = false; bool selectBuilding = true; bool selectProps = true; bool selectDecals = true; bool selectSurfaces = true; bool selectNodes = true; bool selectSegments = true; bool selectTrees = true; bool selectProc = PO.Active; if (marqueeSelection) { selectPicker = filterPicker; selectBuilding = filterBuildings; selectProps = filterProps; selectDecals = filterDecals; selectSurfaces = filterSurfaces; selectNodes = filterNodes; selectSegments = filterSegments; selectTrees = filterTrees; selectProc = PO.Active && filterProcs; } if (MT_Tool == MT_Tools.Group || MT_Tool == MT_Tools.Inplace) { selectNodes = false; selectTrees = false; } else if (MT_Tool == MT_Tools.Mirror) { selectBuilding = false; selectProps = false; selectDecals = false; selectSurfaces = false; selectProc = false; selectTrees = false; selectNodes = false; } float smallestDist = 640000f; bool repeatSearch; do { if (PO.Active && (selectProc || selectPicker)) { foreach (PO_Object obj in PO.Objects) { if (!obj.isHidden() && stepOver.isValidPO(obj.Id)) { if (!selectProc) { // Implies selectPicker is true if (obj.GetPrefab() != Filters.Picker.Info) { continue; } } float radius = obj.Size / 2; bool inXBounds = obj.Position.x > (location.x - radius) && obj.Position.x < (location.x + radius); bool inZBounds = obj.Position.z > (location.z - radius) && obj.Position.z < (location.z + radius); if (inXBounds && inZBounds) { float t = obj.GetDistance(location); if (t < smallestDist) { id.NetLane = obj.Id; smallestDist = t; } } } } } int gridMinX = Mathf.Max((int)((location.x - 16f) / 64f + 135f) - 1, 0); int gridMinZ = Mathf.Max((int)((location.z - 16f) / 64f + 135f) - 1, 0); int gridMaxX = Mathf.Min((int)((location.x + 16f) / 64f + 135f) + 1, 269); int gridMaxZ = Mathf.Min((int)((location.z + 16f) / 64f + 135f) + 1, 269); for (int i = gridMinZ; i <= gridMaxZ; i++) { for (int j = gridMinX; j <= gridMaxX; j++) { if (selectBuilding || selectSurfaces || (selectPicker && Filters.Picker.IsBuilding)) { ushort building = BuildingManager.instance.m_buildingGrid[i * 270 + j]; int count = 0; while (building != 0u) { if (stepOver.isValidB(building) && IsBuildingValid(ref buildingBuffer[building], itemLayers) && buildingBuffer[building].RayCast(building, ray, out float t) && t < smallestDist) { if (Filters.Filter(buildingBuffer[building].Info, ref buildingBuffer[building], true)) { id.Building = Building.FindParentBuilding(building); if (id.Building == 0) { id.Building = building; } smallestDist = t; } } building = buildingBuffer[building].m_nextGridBuilding; if (++count > 49152) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Buildings: Invalid list detected!\n" + Environment.StackTrace); break; } } } if (selectProps || selectDecals || selectSurfaces || (selectPicker && Filters.Picker.IsProp)) { PropLayer.Manager.RaycastHoverInstance(ref i, ref j, ref stepOver, ref ray, ref smallestDist, ref id); } if (selectNodes || selectBuilding || (selectPicker && Filters.Picker.IsNode)) { ushort node = NetManager.instance.m_nodeGrid[i * 270 + j]; int count = 0; while (node != 0u) { if (stepOver.isValidN(node) && IsNodeValid(ref nodeBuffer[node], itemLayers) && RayCastNode(ref nodeBuffer[node], ray, -1000f, out float t, out float priority) && t < smallestDist) { ushort building = 0; if (!Event.current.alt) { building = NetNode.FindOwnerBuilding(node, 363f); } if (building != 0) { if (selectBuilding) { id.Building = Building.FindParentBuilding(building); if (id.Building == 0) { id.Building = building; } smallestDist = t; } } else if (selectNodes || (selectPicker && Filters.Picker.IsNode)) { if (Filters.Filter(nodeBuffer[node])) { id.NetNode = node; smallestDist = t; } } } node = nodeBuffer[node].m_nextGridNode; if (++count > 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Nodes: Invalid list detected!\n" + Environment.StackTrace); } } } if (selectSegments || selectBuilding || (selectPicker && Filters.Picker.IsSegment)) { ushort segment = NetManager.instance.m_segmentGrid[i * 270 + j]; int count = 0; while (segment != 0u) { if (stepOver.isValidS(segment) && IsSegmentValid(ref segmentBuffer[segment], itemLayers) && segmentBuffer[segment].RayCast(segment, ray, -1000f, false, out float t, out float priority) && t < smallestDist) { ushort building = 0; if (!Event.current.alt) { building = FindOwnerBuilding(segment, 363f); } if (building != 0) { if (selectBuilding) { id.Building = Building.FindParentBuilding(building); if (id.Building == 0) { id.Building = building; } smallestDist = t; } } else if (selectSegments || (selectPicker && Filters.Picker.IsSegment)) { if (!selectNodes || ( (!stepOver.isValidN(segmentBuffer[segment].m_startNode) || !RayCastNode(ref nodeBuffer[segmentBuffer[segment].m_startNode], ray, -1000f, out float t2, out priority)) && (!stepOver.isValidN(segmentBuffer[segment].m_endNode) || !RayCastNode(ref nodeBuffer[segmentBuffer[segment].m_endNode], ray, -1000f, out t2, out priority)) )) { if (Filters.Filter(segmentBuffer[segment])) { id.NetSegment = segment; smallestDist = t; } } } } segment = segmentBuffer[segment].m_nextGridSegment; if (++count > 36864) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Segments: Invalid list detected!\n" + Environment.StackTrace); segment = 0; } } } } } if (selectTrees || (selectPicker && Filters.Picker.IsTree)) { gridMinX = Mathf.Max((int)((location.x - 8f) / 32f + 270f), 0); gridMinZ = Mathf.Max((int)((location.z - 8f) / 32f + 270f), 0); gridMaxX = Mathf.Min((int)((location.x + 8f) / 32f + 270f), 539); gridMaxZ = Mathf.Min((int)((location.z + 8f) / 32f + 270f), 539); for (int i = gridMinZ; i <= gridMaxZ; i++) { for (int j = gridMinX; j <= gridMaxX; j++) { uint tree = TreeManager.instance.m_treeGrid[i * 540 + j]; while (tree != 0) { if (stepOver.isValidT(tree) && treeBuffer[tree].RayCast(tree, ray, out float t, out float targetSqr) && t < smallestDist) { if (Filters.Filter(treeBuffer[tree].Info)) { id.Tree = tree; smallestDist = t; } } tree = treeBuffer[tree].m_nextGridTree; } } } } repeatSearch = false; if (OptionsKeymapping.stepOverKey.IsPressed()) { if (!_stepProcessed) { _stepProcessed = true; repeatSearch = true; stepOver.Add(id); } } else { _stepProcessed = false; } }while (repeatSearch); m_hoverInstance = id; m_debugPanel?.UpdatePanel(id); ActionQueue.instance.current?.OnHover(); }
private void LoadPassengers(ushort vehicleID, ref Vehicle data, ushort currentStop, ushort nextStop) { if ((int)currentStop == 0 || (int)nextStop == 0) { return; } CitizenManager instance1 = Singleton <CitizenManager> .instance; VehicleManager instance2 = Singleton <VehicleManager> .instance; NetManager instance3 = Singleton <NetManager> .instance; Vector3 position1 = instance3.m_nodes.m_buffer[(int)currentStop].m_position; Vector3 position2 = instance3.m_nodes.m_buffer[(int)nextStop].m_position; instance3.m_nodes.m_buffer[(int)currentStop].m_maxWaitTime = (byte)0; int tempCounter = (int)instance3.m_nodes.m_buffer[(int)currentStop].m_tempCounter; bool flag = false; int num1 = Mathf.Max((int)(((double)position1.x - 64.0) / 8.0 + 1080.0), 0); int num2 = Mathf.Max((int)(((double)position1.z - 64.0) / 8.0 + 1080.0), 0); int num3 = Mathf.Min((int)(((double)position1.x + 64.0) / 8.0 + 1080.0), 2159); int num4 = Mathf.Min((int)(((double)position1.z + 64.0) / 8.0 + 1080.0), 2159); //begin mod(+): track passengers in int passengersIn = 0; //end mod for (int index1 = num2; index1 <= num4 && !flag; ++index1) { for (int index2 = num1; index2 <= num3 && !flag; ++index2) { ushort instanceID = instance1.m_citizenGrid[index1 * 2160 + index2]; int num5 = 0; while ((int)instanceID != 0 && !flag) { ushort nextGridInstance = instance1.m_instances.m_buffer[(int)instanceID].m_nextGridInstance; if ((instance1.m_instances.m_buffer[(int)instanceID].m_flags & CitizenInstance.Flags.WaitingTransport) != CitizenInstance.Flags.None) { Vector3 targetPos = (Vector3)instance1.m_instances.m_buffer[(int)instanceID].m_targetPos; if ((double)Vector3.SqrMagnitude(targetPos - position1) < 4096.0) { CitizenInfo info = instance1.m_instances.m_buffer[(int)instanceID].Info; if (info.m_citizenAI.TransportArriveAtSource(instanceID, ref instance1.m_instances.m_buffer[(int)instanceID], position1, position2)) { ushort trailerID; uint unitID; if (Vehicle.GetClosestFreeTrailer(vehicleID, targetPos, out trailerID, out unitID)) { if (info.m_citizenAI.SetCurrentVehicle(instanceID, ref instance1.m_instances.m_buffer[(int)instanceID], trailerID, unitID, position1)) { ++tempCounter; ++instance2.m_vehicles.m_buffer[(int)trailerID].m_transferSize; //begin mod(+): increment passengers in ++passengersIn; //end mod } else { flag = true; } } else { flag = true; } } } } instanceID = nextGridInstance; if (++num5 > 65536) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace); break; } } } } instance3.m_nodes.m_buffer[(int)currentStop].m_tempCounter = (ushort)Mathf.Min(tempCounter, (int)ushort.MaxValue); //begin mod (+): calculate statistics after loading passengers int ticketPrice = data.Info.m_vehicleAI.GetTicketPrice(vehicleID, ref data); VehicleManagerMod.m_cachedVehicleData[(int)vehicleID].Add(passengersIn, ticketPrice); NetManagerMod.m_cachedNodeData[(int)currentStop].PassengersIn += passengersIn; //end mod }
public static void DestroyBuildings(int seed, InstanceManager.Group group, Vector3 position, float preRadius, float removeRadius, float destructionRadiusMin, float destructionRadiusMax, float burnRadiusMin, float burnRadiusMax, float probability) { int num = Mathf.Max((int)((position.x - preRadius - 72f) / 64f + 135f), 0); int num2 = Mathf.Max((int)((position.z - preRadius - 72f) / 64f + 135f), 0); int num3 = Mathf.Min((int)((position.x + preRadius + 72f) / 64f + 135f), 269); int num4 = Mathf.Min((int)((position.z + preRadius + 72f) / 64f + 135f), 269); Array16 <Building> buildings = Singleton <BuildingManager> .instance.m_buildings; ushort[] buildingGrid = Singleton <BuildingManager> .instance.m_buildingGrid; for (int i = num2; i <= num4; i++) { for (int j = num; j <= num3; j++) { ushort num5 = buildingGrid[i * 270 + j]; int num6 = 0; while (num5 != 0) { ushort nextGridBuilding = buildings.m_buffer[(int)num5].m_nextGridBuilding; Building.Flags flags = buildings.m_buffer[(int)num5].m_flags; if ((flags & (Building.Flags.Created | Building.Flags.Deleted | Building.Flags.Untouchable | Building.Flags.Demolishing)) == Building.Flags.Created) { Vector3 position2 = buildings.m_buffer[(int)num5].m_position; float num7 = VectorUtils.LengthXZ(position2 - position); if (num7 < preRadius) { Randomizer randomizer = new Randomizer((int)num5 | seed << 16); float num8 = (destructionRadiusMax - num7) / Mathf.Max(1f, destructionRadiusMax - destructionRadiusMin); float num9 = (burnRadiusMax - num7) / Mathf.Max(1f, burnRadiusMax - burnRadiusMin); bool flag = false; bool flag2 = (float)randomizer.Int32(10000u) < num8 * probability * 10000f; bool flag3 = (float)randomizer.Int32(10000u) < num9 * probability * 10000f; if (removeRadius != 0f && num7 - 72f < removeRadius) { BuildingInfo info = buildings.m_buffer[(int)num5].Info; if (info.m_circular) { float num10 = (float)(buildings.m_buffer[(int)num5].Width + buildings.m_buffer[(int)num5].Length) * 2f; flag = (num7 < removeRadius + num10); } else { float angle = buildings.m_buffer[(int)num5].m_angle; Vector2 a = VectorUtils.XZ(position2); Vector2 vector = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); Vector2 vector2 = new Vector2(vector.y, -vector.x); vector *= (float)buildings.m_buffer[(int)num5].Width * 4f; vector2 *= (float)buildings.m_buffer[(int)num5].Length * 4f; Quad2 quad = default(Quad2); quad.a = a - vector - vector2; quad.b = a + vector - vector2; quad.c = a + vector + vector2; quad.d = a - vector + vector2; float num11 = VectorUtils.LengthXZ(position - new Vector3(quad.a.x, position2.y, quad.a.y)); float num12 = VectorUtils.LengthXZ(position - new Vector3(quad.b.x, position2.y, quad.b.y)); float num13 = VectorUtils.LengthXZ(position - new Vector3(quad.c.x, position2.y, quad.c.y)); float num14 = VectorUtils.LengthXZ(position - new Vector3(quad.d.x, position2.y, quad.d.y)); flag = (quad.Intersect(VectorUtils.XZ(position)) || num11 < removeRadius || num12 < removeRadius || num13 < removeRadius || num14 < removeRadius); } } if (flag) { BuildingInfo info2 = buildings.m_buffer[(int)num5].Info; info2.m_buildingAI.CollapseBuilding(num5, ref buildings.m_buffer[(int)num5], group, false, true, Mathf.RoundToInt(num9 * 255f)); } else if (flag2) { BuildingInfo info3 = buildings.m_buffer[(int)num5].Info; ItemClass.Level lvl = (ItemClass.Level)buildings.m_buffer[(int)num5].m_level; float p = 0.5f; if (info3.m_buildingAI as OfficeBuildingAI != null || info3.m_buildingAI as CommercialBuildingAI != null || info3.m_buildingAI as IndustrialBuildingAI != null) { switch (lvl) { case ItemClass.Level.Level1: p = 1f; break; case ItemClass.Level.Level2: p = 0.6f; break; case ItemClass.Level.Level3: p = 0.2f; break; } } else if (info3.m_buildingAI as ResidentialBuildingAI != null) { switch (lvl) { case ItemClass.Level.Level1: p = 1f; break; case ItemClass.Level.Level2: p = 0.8f; break; case ItemClass.Level.Level3: p = 0.6f; break; case ItemClass.Level.Level4: p = 0.4f; break; case ItemClass.Level.Level5: p = 0.2f; break; } } // Large buildings are tougher float s = Mathf.Sqrt(buildings.m_buffer[(int)num5].Length * buildings.m_buffer[(int)num5].Width); if (s > 4) { p -= s / 16; } // Make shelters a little more useful if ((flags & Building.Flags.Evacuating) == Building.Flags.Evacuating) { p -= 0.2f; } if (p > 0 && (float)randomizer.Int32(10000u) < p * 10000f) { //Debug.Log("Destroyed: " + info3.name + " (" + info3.m_buildingAI.name + "), level: " + lvl.ToString()); info3.m_buildingAI.CollapseBuilding(num5, ref buildings.m_buffer[(int)num5], group, false, false, Mathf.RoundToInt(num9 * 255f)); } } else if (flag3 && (flags & Building.Flags.Collapsed) == Building.Flags.None && buildings.m_buffer[(int)num5].m_fireIntensity == 0) { BuildingInfo info4 = buildings.m_buffer[(int)num5].Info; info4.m_buildingAI.BurnBuilding(num5, ref buildings.m_buffer[(int)num5], group, false); } } } num5 = nextGridBuilding; if (++num6 >= 49152) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } }
private void BaseSimulationStep(ushort vehicleId, ref Vehicle data, Vector3 physicsLodRefPos) { if ((data.m_flags & Vehicle.Flags.WaitingPath) != Vehicle.Flags.None) { PathManager instance = Singleton <PathManager> .instance; byte pathFindFlags = instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { data.m_pathPositionIndex = 255; data.m_flags &= ~Vehicle.Flags.WaitingPath; data.m_flags &= ~Vehicle.Flags.Arriving; PathfindSuccess(vehicleId, ref data); TrySpawn(vehicleId, ref data); } else if ((pathFindFlags & 8) != 0) { data.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(data.m_path); data.m_path = 0u; PathfindFailure(vehicleId, ref data); return; } } else if ((data.m_flags & Vehicle.Flags.WaitingSpace) != Vehicle.Flags.None) { TrySpawn(vehicleId, ref data); } Vector3 lastFramePosition = data.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if ( Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } SimulationStep(vehicleId, ref data, vehicleId, ref data, lodPhysics); if (data.m_leadingVehicle == 0 && data.m_trailingVehicle != 0) { VehicleManager instance2 = Singleton <VehicleManager> .instance; ushort num = data.m_trailingVehicle; int num2 = 0; while (num != 0) { ushort trailingVehicle = instance2.m_vehicles.m_buffer[num].m_trailingVehicle; VehicleInfo info = instance2.m_vehicles.m_buffer[num].Info; info.m_vehicleAI.SimulationStep(num, ref instance2.m_vehicles.m_buffer[num], vehicleId, ref data, lodPhysics); num = trailingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } int maxBlockCounter = (m_info.m_class.m_service > ItemClass.Service.Office) ? 150 : 100; if ((data.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == Vehicle.Flags.None && data.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if (data.m_blockCounter >= maxBlockCounter && Options.enableDespawning) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if (data.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref data, maxBlockCounter)) { CustomVehicleAI.MarkPathRecalculation(vehicleId); InvalidPath(vehicleId, ref data, vehicleId, ref data); } }
private static bool RayCast(TreeManager tm, Segment3 ray, ItemClass.Service service, ItemClass.SubService subService, ItemClass.Layer itemLayers, TreeInstance.Flags ignoreFlags, out Vector3 hit, out uint treeIndex) { unsafe { int num; int num1; int num2; int num3; int num4; int num5; float single; float single1; Bounds bound = new Bounds(new Vector3(0f, 512f, 0f), new Vector3(17280f, 1152f, 17280f)); if (ray.Clip(bound)) { Vector3 vector3 = ray.b - ray.a; int num6 = (int)((double)ray.a.x / 32 + 270); int num7 = (int)((double)ray.a.z / 32 + 270); int num8 = (int)((double)ray.b.x / 32 + 270); int num9 = (int)((double)ray.b.z / 32 + 270); float single2 = Mathf.Abs(vector3.x); float single3 = Mathf.Abs(vector3.z); if ((double)single2 < (double)single3) { num = 0; num1 = ((double)vector3.z <= 0 ? -1 : 1); if ((double)single3 != 0) { vector3 = vector3 * (32f / single3); } } else { num = ((double)vector3.x <= 0 ? -1 : 1); num1 = 0; if ((double)single2 != 0) { vector3 = vector3 * (32f / single2); } } float single4 = 2f; float single5 = 10000f; treeIndex = 0; Vector3 vector31 = ray.a; Vector3 vector32 = ray.a; int num10 = num6; int num11 = num7; do { Vector3 vector33 = vector32 + vector3; if (num == 0) { num4 = ((num11 != num7 || num1 <= 0) && (num11 != num9 || num1 >= 0) ? Mathf.Max(num11, 0) : Mathf.Max((int)(((double)vector33.z - 72) / 32 + 270), 0)); num5 = ((num11 != num7 || num1 >= 0) && (num11 != num9 || num1 <= 0) ? Mathf.Min(num11, 539) : Mathf.Min((int)(((double)vector33.z + 72) / 32 + 270), 539)); num2 = Mathf.Max((int)(((double)Mathf.Min(vector31.x, vector33.x) - 72) / 32 + 270), 0); num3 = Mathf.Min((int)(((double)Mathf.Max(vector31.x, vector33.x) + 72) / 32 + 270), 539); } else { num2 = ((num10 != num6 || num <= 0) && (num10 != num8 || num >= 0) ? Mathf.Max(num10, 0) : Mathf.Max((int)(((double)vector33.x - 72) / 32 + 270), 0)); num3 = ((num10 != num6 || num >= 0) && (num10 != num8 || num <= 0) ? Mathf.Min(num10, 539) : Mathf.Min((int)(((double)vector33.x + 72) / 32 + 270), 539)); num4 = Mathf.Max((int)(((double)Mathf.Min(vector31.z, vector33.z) - 72) / 32 + 270), 0); num5 = Mathf.Min((int)(((double)Mathf.Max(vector31.z, vector33.z) + 72) / 32 + 270), 539); } for (int i = num4; i <= num5; i++) { for (int j = num2; j <= num3; j++) { uint mTreeGrid = tm.m_treeGrid[i * 540 + j]; int num12 = 0; while (mTreeGrid != 0) { if ((tm.m_trees.m_buffer[mTreeGrid].m_flags & (ushort)ignoreFlags) == (ushort)TreeInstance.Flags.None && (double)ray.DistanceSqr(tm.m_trees.m_buffer[mTreeGrid].Position) < 2500) { TreeInfo info = tm.m_trees.m_buffer[mTreeGrid].Info; if ((service == ItemClass.Service.None || info.m_class.m_service == service) && (subService == ItemClass.SubService.None || info.m_class.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (info.m_class.m_layer & itemLayers) != ItemClass.Layer.None) && tm.m_trees.m_buffer[mTreeGrid].RayCast(mTreeGrid, ray, out single, out single1) && ((double)single < (double)single4 - 9.99999974737875E-05 || (double)single < (double)single4 + 9.99999974737875E-05 && (double)single1 < (double)single5)) { single4 = single; single5 = single1; treeIndex = mTreeGrid; } } mTreeGrid = tm.m_trees.m_buffer[mTreeGrid].m_nextGridTree; int num13 = num12 + 1; num12 = num13; if (num13 <= LimitTreeManager.Helper.TreeLimit) { continue; } CODebugBase<LogChannel>.Error(LogChannel.Core, string.Concat("Invalid list detected!\n", Environment.StackTrace)); break; } } } vector31 = vector32; vector32 = vector33; num10 = num10 + num; num11 = num11 + num1; } while ((num10 <= num8 || num <= 0) && (num10 >= num8 || num >= 0) && (num11 <= num9 || num1 <= 0) && (num11 >= num9 || num1 >= 0)); if ((double)single4 != 2) { hit = ray.Position(single4); return true; } } hit = Vector3.zero; treeIndex = 0; return false; } }
public void SimulationStep(ushort lineID) { if (!m_initialized) { m_initialized = true; for (int i = 0; i < Singleton <TransportManager> .instance.m_lines.m_buffer.Length; i++) { m_flagsLastState[i] = Singleton <TransportManager> .instance.m_lines.m_buffer[i].m_flags; } } var flagsChanged = (m_flagsLastState[lineID] ^ Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags); m_flagsLastState[lineID] = Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags; if ((flagsChanged & TransportLine.Flags.Complete) != TransportLine.Flags.None) { if (TLMConfigWarehouse.getCurrentConfigBool(TLMConfigWarehouse.ConfigIndex.AUTO_COLOR_ENABLED)) { TLMController.instance.AutoColor(lineID); } if (TLMConfigWarehouse.getCurrentConfigBool(TLMConfigWarehouse.ConfigIndex.AUTO_NAME_ENABLED)) { TLMUtils.setLineName(lineID, TLMUtils.calculateAutoName(lineID)); } } if (TransportLinesManagerMod.instance != null && TransportLinesManagerMod.debugMode) { TLMUtils.doLog("LTLMTransportLine SimulationStep!"); } TransportInfo info = Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].Info; TLMCW.ConfigIndex lineType = TLMCW.getDefinitionForLine(lineID).toConfigIndex(); float defaultCostPerPassengerCapacity = TLMCW.getCostPerPassengerCapacityLine(lineType); if (Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].Complete) { int vehicleCount = 0; int installedCapacity = 0; if (Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_vehicles != 0) { VehicleManager instance = Singleton <VehicleManager> .instance; ushort nextId = Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_vehicles; int loopCount = 0; while (nextId != 0) { ushort nextLineVehicle = instance.m_vehicles.m_buffer[(int)nextId].m_nextLineVehicle; vehicleCount++; installedCapacity += TLMLineUtils.getVehicleCapacity(nextId); nextId = nextLineVehicle; if (++loopCount > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } uint prefix = 0; if (TLMConfigWarehouse.getCurrentConfigInt(TLMConfigWarehouse.getConfigIndexForTransportInfo(info) | TLMConfigWarehouse.ConfigIndex.PREFIX) != (int)ModoNomenclatura.Nenhum) { prefix = Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_lineNumber / 1000u; } float budgetMultiplierPrefix = TLMUtils.getExtensionFromConfigIndex(TLMCW.getConfigIndexForTransportInfo(info)).getBudgetMultiplierForHour(prefix, (int)Singleton <SimulationManager> .instance.m_currentDayTimeHour) / 100f; var flagToCheck = (TransportLine.Flags.DisabledNight | TransportLine.Flags.DisabledDay); if (budgetMultiplierPrefix == 0 && (Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & flagToCheck) == TransportLine.Flags.None) { int flagsToAdd = (int)(TransportLine.Flags.DisabledDay | TransportLine.Flags.DisabledNight) | (int)(TLMTransportLineFlags.ZERO_BUDGET_SETTED); if ((Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & (TransportLine.Flags)TLMTransportLineFlags.ZERO_BUDGET_SETTED) == TransportLine.Flags.None) { if ((Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & TransportLine.Flags.DisabledDay) == TransportLine.Flags.None) { flagsToAdd |= (int)TLMTransportLineFlags.ZERO_BUDGET_DAY; } if ((Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & TransportLine.Flags.DisabledNight) == TransportLine.Flags.None) { flagsToAdd |= (int)TLMTransportLineFlags.ZERO_BUDGET_NIGHT; } } Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags |= (TransportLine.Flags)flagsToAdd; } else if ((budgetMultiplierPrefix > 0 && (Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & (TransportLine.Flags)(TLMTransportLineFlags.ZERO_BUDGET_SETTED)) != TransportLine.Flags.None)) { bool actDay = (Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & (TransportLine.Flags)TLMTransportLineFlags.ZERO_BUDGET_DAY) != TransportLine.Flags.None; bool actNight = (Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & (TransportLine.Flags)TLMTransportLineFlags.ZERO_BUDGET_NIGHT) != TransportLine.Flags.None; Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags &= (TransportLine.Flags) ~(TLMTransportLineFlags.ZERO_BUDGET_DAY | TLMTransportLineFlags.ZERO_BUDGET_NIGHT | TLMTransportLineFlags.ZERO_BUDGET_SETTED); TLMLineUtils.setLineActive(ref Singleton <TransportManager> .instance.m_lines.m_buffer[lineID], actDay, actNight); } bool active; if (Singleton <SimulationManager> .instance.m_isNightTime) { active = ((Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & TransportLine.Flags.DisabledNight) == TransportLine.Flags.None); } else { active = ((Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_flags & TransportLine.Flags.DisabledDay) == TransportLine.Flags.None); } uint steps = 0u; float distance = 0f; bool broken = false; if (Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_stops != 0) { NetManager instance2 = Singleton <NetManager> .instance; ushort stops = Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_stops; ushort nextStop = stops; int count = 0; while (nextStop != 0) { ushort num8 = 0; if (active) { NetNode[] expr_10A_cp_0 = instance2.m_nodes.m_buffer; ushort expr_10A_cp_1 = nextStop; expr_10A_cp_0[(int)expr_10A_cp_1].m_flags = (expr_10A_cp_0[(int)expr_10A_cp_1].m_flags & ~NetNode.Flags.Disabled); } else { NetNode[] expr_130_cp_0 = instance2.m_nodes.m_buffer; ushort expr_130_cp_1 = nextStop; expr_130_cp_0[(int)expr_130_cp_1].m_flags = (expr_130_cp_0[(int)expr_130_cp_1].m_flags | NetNode.Flags.Disabled); } for (int i = 0; i < 8; i++) { ushort segment = instance2.m_nodes.m_buffer[(int)nextStop].GetSegment(i); if (segment != 0 && instance2.m_segments.m_buffer[(int)segment].m_startNode == nextStop) { distance += instance2.m_segments.m_buffer[(int)segment].m_averageLength; num8 = instance2.m_segments.m_buffer[(int)segment].m_endNode; if ((instance2.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.PathLength) == NetSegment.Flags.None) { broken = true; } break; } } steps += 1u; nextStop = num8; if (nextStop == stops) { break; } if (++count >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } float lineCost = vehicleCount * info.m_maintenanceCostPerVehicle / 100;// * defaultCostPerPassengerCapacity; if (lineCost != 0) { Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.Maintenance, m_linesCost.m_buffer[lineID], info.m_class); } int budget = Singleton <EconomyManager> .instance.GetBudget(info.m_class); int necessaryVehicles; if (!active) { necessaryVehicles = 0; } else { necessaryVehicles = TLMVehiclesLineManager.instance[lineID]; if (necessaryVehicles == 0) { if (broken) { necessaryVehicles = vehicleCount; } else { necessaryVehicles = Mathf.CeilToInt(budget * budgetMultiplierPrefix * distance / (info.m_defaultVehicleDistance * 100f)); } } } if (steps != 0u && vehicleCount < necessaryVehicles) { TransferManager.TransferReason vehicleReason = info.m_vehicleReason; int index = Singleton <SimulationManager> .instance.m_randomizer.Int32(steps); ushort stop = Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].GetStop(index); if (vehicleReason != TransferManager.TransferReason.None && stop != 0) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Priority = necessaryVehicles - vehicleCount + 1; offer.TransportLine = lineID; offer.Position = Singleton <NetManager> .instance.m_nodes.m_buffer[stop].m_position; offer.Amount = 1; offer.Active = false; Singleton <TransferManager> .instance.AddIncomingOffer(vehicleReason, offer); } } else if (vehicleCount > necessaryVehicles) { int index2 = Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)vehicleCount); ushort vehicle = Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].GetVehicle(index2); if (vehicle != 0) { VehicleManager instance3 = Singleton <VehicleManager> .instance; VehicleInfo info2 = instance3.m_vehicles.m_buffer[(int)vehicle].Info; info2.m_vehicleAI.SetTransportLine(vehicle, ref instance3.m_vehicles.m_buffer[(int)vehicle], 0); } } } if ((Singleton <SimulationManager> .instance.m_currentFrameIndex & 4095u) >= 3840u) { Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_passengers.Update(); Singleton <TransportManager> .instance.m_passengers[(int)info.m_transportType].Add(ref Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_passengers); Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].m_passengers.Reset(); } }
internal bool ExtParkVehicle(ushort vehicleID, ref Vehicle vehicleData, uint driverCitizenId, ushort driverCitizenInstanceId, ref ExtCitizenInstance driverExtInstance, ushort targetBuildingId, PathUnit.Position pathPos, uint nextPath, int nextPositionIndex, out byte segmentOffset) { #if DEBUG bool citDebug = GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.CitizenId == driverExtInstance.GetCitizenId(); bool debug = GlobalConfig.Instance.Debug.Switches[2] && citDebug; bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && citDebug; #endif PathManager pathManager = Singleton <PathManager> .instance; CitizenManager citizenManager = Singleton <CitizenManager> .instance; NetManager netManager = Singleton <NetManager> .instance; VehicleManager vehicleManager = Singleton <VehicleManager> .instance; // NON-STOCK CODE START bool prohibitPocketCars = false; // NON-STOCK CODE END if (driverCitizenId != 0u) { if (Options.prohibitPocketCars && driverCitizenInstanceId != 0) { prohibitPocketCars = true; } uint laneID = PathManager.GetLaneID(pathPos); segmentOffset = (byte)Singleton <SimulationManager> .instance.m_randomizer.Int32(1, 254); Vector3 refPos; Vector3 vector; netManager.m_lanes.m_buffer[laneID].CalculatePositionAndDirection((float)segmentOffset * 0.003921569f, out refPos, out vector); NetInfo info = netManager.m_segments.m_buffer[(int)pathPos.m_segment].Info; bool isSegmentInverted = (netManager.m_segments.m_buffer[(int)pathPos.m_segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None; bool isPosNegative = info.m_lanes[(int)pathPos.m_lane].m_position < 0f; vector.Normalize(); Vector3 searchDir; if (isSegmentInverted != isPosNegative) { searchDir.x = -vector.z; searchDir.y = 0f; searchDir.z = vector.x; } else { searchDir.x = vector.z; searchDir.y = 0f; searchDir.z = -vector.x; } ushort homeID = 0; if (driverCitizenId != 0u) { homeID = Singleton <CitizenManager> .instance.m_citizens.m_buffer[driverCitizenId].m_homeBuilding; } Vector3 parkPos = default(Vector3); Quaternion parkRot = default(Quaternion); float parkOffset = -1f; // NON-STOCK CODE START bool foundParkingSpace = false; if (prohibitPocketCars) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleID} tries to park on a parking position now (flags: {vehicleData.m_flags})! CurrentPathMode={driverExtInstance.pathMode} path={vehicleData.m_path} pathPositionIndex={vehicleData.m_pathPositionIndex} segmentId={pathPos.m_segment} laneIndex={pathPos.m_lane} offset={pathPos.m_offset} nextPath={nextPath} refPos={refPos} searchDir={searchDir} home={homeID} driverCitizenId={driverCitizenId} driverCitizenInstanceId={driverCitizenInstanceId}"); } #endif if (driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToAltParkPos || driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToKnownParkPos) { // try to use previously found parking space #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleID} tries to park on an (alternative) parking position now! CurrentPathMode={driverExtInstance.pathMode} altParkingSpaceLocation={driverExtInstance.parkingSpaceLocation} altParkingSpaceLocationId={driverExtInstance.parkingSpaceLocationId}"); } #endif switch (driverExtInstance.parkingSpaceLocation) { case ExtCitizenInstance.ExtParkingSpaceLocation.RoadSide: uint parkLaneID; int parkLaneIndex; #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleID} wants to park road-side @ segment {driverExtInstance.parkingSpaceLocationId}"); } #endif foundParkingSpace = AdvancedParkingManager.Instance.FindParkingSpaceRoadSideForVehiclePos(this.m_info, 0, driverExtInstance.parkingSpaceLocationId, refPos, out parkPos, out parkRot, out parkOffset, out parkLaneID, out parkLaneIndex); break; case ExtCitizenInstance.ExtParkingSpaceLocation.Building: float maxDist = 9999f; #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleID} wants to park @ building {driverExtInstance.parkingSpaceLocationId}"); } #endif foundParkingSpace = AdvancedParkingManager.Instance.FindParkingSpacePropAtBuilding(this.m_info, homeID, 0, driverExtInstance.parkingSpaceLocationId, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[driverExtInstance.parkingSpaceLocationId], pathPos.m_segment, refPos, ref maxDist, true, out parkPos, out parkRot, out parkOffset); break; default: #if DEBUG Log.Error($"No alternative parking position stored for vehicle {vehicleID}! PathMode={driverExtInstance.pathMode}"); #endif foundParkingSpace = CustomFindParkingSpace(this.m_info, homeID, refPos, searchDir, pathPos.m_segment, out parkPos, out parkRot, out parkOffset); break; } } } if (!foundParkingSpace) { foundParkingSpace = /*prohibitPocketCars ?*/ CustomFindParkingSpace(this.m_info, homeID, refPos, searchDir, pathPos.m_segment, out parkPos, out parkRot, out parkOffset) /*: * FindParkingSpace(homeID, refPos, searchDir, pathPos.m_segment, this.m_info.m_generatedInfo.m_size.x, this.m_info.m_generatedInfo.m_size.z, out parkPos, out parkRot, out parkOffset)*/; } // NON-STOCK CODE END ushort parkedVehicleId = 0; bool parkedCarCreated = foundParkingSpace && vehicleManager.CreateParkedVehicle(out parkedVehicleId, ref Singleton <SimulationManager> .instance.m_randomizer, this.m_info, parkPos, parkRot, driverCitizenId); if (foundParkingSpace && parkedCarCreated) { // we have reached a parking position #if DEBUG float sqrDist = (refPos - parkPos).sqrMagnitude; if (fineDebug) { Log._Debug($"Vehicle {vehicleID} succeeded in parking! CurrentPathMode={driverExtInstance.pathMode} sqrDist={sqrDist}"); } if (GlobalConfig.Instance.Debug.Switches[6] && sqrDist >= 16000) { Log._Debug($"CustomPassengerCarAI.CustomParkVehicle: FORCED PAUSE. Distance very large! Vehicle {vehicleID}. dist={sqrDist}"); Singleton <SimulationManager> .instance.SimulationPaused = true; } #endif citizenManager.m_citizens.m_buffer[driverCitizenId].SetParkedVehicle(driverCitizenId, parkedVehicleId); if (parkOffset >= 0f) { segmentOffset = (byte)(parkOffset * 255f); } // NON-STOCK CODE START if (prohibitPocketCars) { if ((driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToAltParkPos || driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToKnownParkPos) && targetBuildingId != 0) { // decrease parking space demand of target building ExtBuildingManager.Instance.ExtBuildings[targetBuildingId].ModifyParkingSpaceDemand(parkPos, GlobalConfig.Instance.ParkingAI.MinFoundParkPosParkingSpaceDemandDelta, GlobalConfig.Instance.ParkingAI.MaxFoundParkPosParkingSpaceDemandDelta); } //if (driverExtInstance.CurrentPathMode == ExtCitizenInstance.PathMode.DrivingToAltParkPos || driverExtInstance.CurrentPathMode == ExtCitizenInstance.PathMode.DrivingToKnownParkPos) { // we have reached an (alternative) parking position and succeeded in finding a parking space driverExtInstance.pathMode = ExtCitizenInstance.ExtPathMode.RequiresWalkingPathToTarget; driverExtInstance.failedParkingAttempts = 0; driverExtInstance.parkingSpaceLocation = ExtCitizenInstance.ExtParkingSpaceLocation.None; driverExtInstance.parkingSpaceLocationId = 0; #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleID} has reached an (alternative) parking position! CurrentPathMode={driverExtInstance.pathMode} position={parkPos}"); } #endif //} } } else if (prohibitPocketCars) { // could not find parking space. vehicle would despawn. if (targetBuildingId != 0 && (Singleton <BuildingManager> .instance.m_buildings.m_buffer[targetBuildingId].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None) { // target is an outside connection return(true); } // Find parking space in the vicinity, redo path-finding to the parking space, park the vehicle and do citizen path-finding to the current target if (!foundParkingSpace && (driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToAltParkPos || driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToKnownParkPos) && targetBuildingId != 0) { // increase parking space demand of target building if (driverExtInstance.failedParkingAttempts > 1) { ExtBuildingManager.Instance.ExtBuildings[targetBuildingId].AddParkingSpaceDemand(GlobalConfig.Instance.ParkingAI.FailedParkingSpaceDemandIncrement * (uint)(driverExtInstance.failedParkingAttempts - 1)); } } if (!foundParkingSpace) { ++driverExtInstance.failedParkingAttempts; } else { #if DEBUG if (debug) { Log._Debug($"Parking failed for vehicle {vehicleID}: Parked car could not be created. ABORT."); } #endif driverExtInstance.failedParkingAttempts = GlobalConfig.Instance.ParkingAI.MaxParkingAttempts + 1; } driverExtInstance.pathMode = ExtCitizenInstance.ExtPathMode.ParkingFailed; driverExtInstance.parkingPathStartPosition = pathPos; #if DEBUG if (debug) { Log._Debug($"Parking failed for vehicle {vehicleID}! (flags: {vehicleData.m_flags}) pathPos segment={pathPos.m_segment}, lane={pathPos.m_lane}, offset={pathPos.m_offset}. Trying to find parking space in the vicinity. FailedParkingAttempts={driverExtInstance.failedParkingAttempts}, CurrentPathMode={driverExtInstance.pathMode} foundParkingSpace={foundParkingSpace}"); } #endif // invalidate paths of all passengers in order to force path recalculation uint curUnitId = vehicleData.m_citizenUnits; int numIter = 0; while (curUnitId != 0u) { uint nextUnit = citizenManager.m_units.m_buffer[curUnitId].m_nextUnit; for (int i = 0; i < 5; i++) { uint curCitizenId = citizenManager.m_units.m_buffer[curUnitId].GetCitizen(i); if (curCitizenId != 0u) { ushort citizenInstanceId = citizenManager.m_citizens.m_buffer[curCitizenId].m_instance; if (citizenInstanceId != 0) { #if DEBUG if (debug) { Log._Debug($"Releasing path for citizen instance {citizenInstanceId} sitting in vehicle {vehicleID} (was {citizenManager.m_instances.m_buffer[citizenInstanceId].m_path})."); } #endif if (citizenInstanceId != driverCitizenInstanceId) { #if DEBUG if (debug) { Log._Debug($"Resetting pathmode for passenger citizen instance {citizenInstanceId} sitting in vehicle {vehicleID} (was {ExtCitizenInstanceManager.Instance.ExtInstances[citizenInstanceId].pathMode})."); } #endif ExtCitizenInstanceManager.Instance.ExtInstances[citizenInstanceId].Reset(); } if (citizenManager.m_instances.m_buffer[citizenInstanceId].m_path != 0) { Singleton <PathManager> .instance.ReleasePath(citizenManager.m_instances.m_buffer[citizenInstanceId].m_path); citizenManager.m_instances.m_buffer[citizenInstanceId].m_path = 0u; } } } } curUnitId = nextUnit; if (++numIter > CitizenManager.MAX_UNIT_COUNT) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } return(false); // NON-STOCK CODE END } } else { segmentOffset = pathPos.m_offset; } // parking has succeeded if (driverCitizenId != 0u) { uint curCitizenUnitId = vehicleData.m_citizenUnits; int numIter = 0; while (curCitizenUnitId != 0u) { uint nextUnit = citizenManager.m_units.m_buffer[curCitizenUnitId].m_nextUnit; for (int j = 0; j < 5; j++) { uint citId = citizenManager.m_units.m_buffer[curCitizenUnitId].GetCitizen(j); if (citId != 0u) { ushort citizenInstanceId = citizenManager.m_citizens.m_buffer[citId].m_instance; if (citizenInstanceId != 0) { // NON-STOCK CODE START if (prohibitPocketCars) { if (driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.RequiresWalkingPathToTarget) { #if DEBUG if (debug) { Log._Debug($"Parking succeeded: Doing nothing for citizen instance {citizenInstanceId}! path: {citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_path}"); } #endif ExtCitizenInstanceManager.Instance.ExtInstances[citizenInstanceId].pathMode = ExtCitizenInstance.ExtPathMode.RequiresWalkingPathToTarget; continue; } } // NON-STOCK CODE END if (pathManager.AddPathReference(nextPath)) { if (citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_path != 0u) { pathManager.ReleasePath(citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_path); } citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_path = nextPath; citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_pathPositionIndex = (byte)nextPositionIndex; citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_lastPathOffset = segmentOffset; #if DEBUG if (debug) { Log._Debug($"Parking succeeded (default): Setting path of citizen instance {citizenInstanceId} to {nextPath}!"); } #endif } } } } curCitizenUnitId = nextUnit; if (++numIter > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } if (prohibitPocketCars) { if (driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.RequiresWalkingPathToTarget) { #if DEBUG if (debug) { Log._Debug($"Parking succeeded (alternative parking spot): Citizen instance {driverExtInstance} has to walk for the remaining path!"); } #endif /*driverExtInstance.CurrentPathMode = ExtCitizenInstance.PathMode.CalculatingWalkingPathToTarget; * if (debug) * Log._Debug($"Setting CurrentPathMode of vehicle {vehicleID} to {driverExtInstance.CurrentPathMode}");*/ } } return(true); }
// from TransportLine public static bool UpdateMeshData(ref TransportLine transportLine, ushort lineID) { //return transportLine.UpdateMeshData(lineID); bool flag = true; int num = 0; int num2 = 0; int num3 = 0; float num4 = 0f; TransportManager instance = Singleton <TransportManager> .instance; NetManager instance2 = Singleton <NetManager> .instance; PathManager instance3 = Singleton <PathManager> .instance; ushort stops = transportLine.m_stops; ushort num5 = stops; int num6 = 0; while (num5 != 0) { ushort num7 = 0; for (int i = 0; i < 8; i++) { ushort segment = instance2.m_nodes.m_buffer[(int)num5].GetSegment(i); if (segment != 0 && instance2.m_segments.m_buffer[(int)segment].m_startNode == num5) { uint path = instance2.m_segments.m_buffer[(int)segment].m_path; if (path != 0u) { byte pathFindFlags = instance3.m_pathUnits.m_buffer[(int)((UIntPtr)path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { if (!TransportLine.CalculatePathSegmentCount(path, ref num2, ref num3, ref num4)) { TransportInfo info = transportLine.Info; BusTransportLineAI.StartPathFind(segment, ref instance2.m_segments.m_buffer[(int)segment], info.m_netService, info.m_vehicleType, (transportLine.m_flags & TransportLine.Flags.Temporary) != TransportLine.Flags.None); flag = false; } } else if ((pathFindFlags & 8) == 0) { flag = false; } } num7 = instance2.m_segments.m_buffer[(int)segment].m_endNode; break; } } num++; num2++; num5 = num7; if (num5 == stops) { break; } if (!flag) { break; } if (++num6 >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } if (!flag) { return(flag); } RenderGroup.MeshData meshData = new RenderGroup.MeshData(); meshData.m_vertices = new Vector3[num2 * 8]; meshData.m_normals = new Vector3[num2 * 8]; meshData.m_tangents = new Vector4[num2 * 8]; meshData.m_uvs = new Vector2[num2 * 8]; meshData.m_uvs1 = new Vector2[num2 * 8]; meshData.m_colors = new Color32[num2 * 8]; meshData.m_triangles = new int[num2 * 30]; TransportManager.LineSegment[] array = new TransportManager.LineSegment[num]; Bezier3[] array2 = new Bezier3[num3]; int num8 = 0; int num9 = 0; int num10 = 0; float lengthScale = Mathf.Ceil(num4 / 64f) / num4; float num11 = 0f; num5 = stops; Vector3 vector = new Vector3(100000f, 100000f, 100000f); Vector3 vector2 = new Vector3(-100000f, -100000f, -100000f); num6 = 0; while (num5 != 0) { ushort num12 = 0; for (int j = 0; j < 8; j++) { ushort segment2 = instance2.m_nodes.m_buffer[(int)num5].GetSegment(j); if (segment2 != 0 && instance2.m_segments.m_buffer[(int)segment2].m_startNode == num5) { uint path2 = instance2.m_segments.m_buffer[(int)segment2].m_path; if (path2 != 0u && (instance3.m_pathUnits.m_buffer[(int)((UIntPtr)path2)].m_pathFindFlags & 4) != 0) { array[num8].m_curveStart = num10; Vector3 vector3; Vector3 vector4; TransportLine.FillPathSegments(path2, meshData, array2, ref num9, ref num10, ref num11, lengthScale, out vector3, out vector4); vector = Vector3.Min(vector, vector3); vector2 = Vector3.Max(vector2, vector4); array[num8].m_bounds.SetMinMax(vector3, vector4); array[num8].m_curveEnd = num10; } num12 = instance2.m_segments.m_buffer[(int)segment2].m_endNode; break; } } TransportLine.FillPathNode(instance2.m_nodes.m_buffer[(int)num5].m_position, meshData, num9); num8++; num9++; num5 = num12; if (num5 == stops) { break; } if (++num6 >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } while (!Monitor.TryEnter(instance.m_lineMeshData, SimulationManager.SYNCHRONIZE_TIMEOUT)) { } try { instance.m_lineMeshData[(int)lineID] = meshData; instance.m_lineSegments[(int)lineID] = array; instance.m_lineCurves[(int)lineID] = array2; transportLine.m_bounds.SetMinMax(vector, vector2); } finally { Monitor.Exit(instance.m_lineMeshData); } return(flag); }
public void Update() { if (!this.m_buildingInfoPanel.isVisible) { return; } Building b = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building]; if (!(b.Info.GetAI() is BuildingAI basicAI)) { closeBuildingInfo(null, null); return; } var ssds = ServiceSystemDefinition.from(b.Info); List <string> textVehicles = new List <string>(); foreach (var ssd in ssds) { var defLevel = Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)m_buildingIdSelecionado.Building].Info.m_class.m_level; int count = 0; int cargo = 0; int capacity = 0; int inbound = 0; int outbound = 0; var extstr = SVMBuildingAIOverrideUtils.getBuildingOverrideExtensionStrict(b.Info); SVMBuildingUtils.CalculateOwnVehicles(m_buildingIdSelecionado.Building, ref b, extstr.GetManagedReasons(b.Info).Where(x => (x.Value.vehicleLevel ?? defLevel) == ssd.level).Select(x => x.Key), ref count, ref cargo, ref capacity, ref inbound, ref outbound); var maxField = extstr.GetVehicleMaxCountField(ssd.vehicleType, ssd.level); int maxVehicles = (SVMUtils.GetPrivateField <int>(b.Info.GetAI(), maxField) * SVMBuildingUtils.GetProductionRate(ref b) / 100); string maxVehiclesStr = maxField == null || maxVehicles > 0x3FFF ? "∞" : maxVehicles.ToString(); textVehicles.Add($"{count}/{maxVehiclesStr} ({Locale.Get("SVM_VEHICLE_TYPE", ssd.vehicleType.ToString())})"); } vehiclesInUseLabel.text = string.Join(" | ", textVehicles.ToArray()); upkeepCost.text = LocaleFormatter.FormatUpkeep(basicAI.GetResourceRate(m_buildingIdSelecionado.Building, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)m_buildingIdSelecionado.Building], EconomyManager.Resource.Maintenance), false); uint num = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building].m_citizenUnits; int num2 = 0; int num3 = 0; int unskill = 0; int oneSchool = 0; int twoSchool = 0; int threeSchool = 0; CitizenManager instance = Singleton <CitizenManager> .instance; while (num != 0u) { uint nextUnit = instance.m_units.m_buffer[(int)((UIntPtr)num)].m_nextUnit; if ((ushort)(instance.m_units.m_buffer[(int)((UIntPtr)num)].m_flags & CitizenUnit.Flags.Work) != 0) { for (int i = 0; i < 5; i++) { uint citizen = instance.m_units.m_buffer[(int)((UIntPtr)num)].GetCitizen(i); if (citizen != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].Dead && (instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) { num3++; switch (instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].EducationLevel) { case Citizen.Education.Uneducated: unskill++; break; case Citizen.Education.OneSchool: oneSchool++; break; case Citizen.Education.TwoSchools: twoSchool++; break; case Citizen.Education.ThreeSchools: threeSchool++; break; } } } } num = nextUnit; if (++num2 > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } workerChart.SetValues(new int[] { unskill, oneSchool, twoSchool, threeSchool }, new int[] { SVMUtils.GetPrivateField <int>(basicAI, "m_workPlaceCount0"), SVMUtils.GetPrivateField <int>(basicAI, "m_workPlaceCount1"), SVMUtils.GetPrivateField <int>(basicAI, "m_workPlaceCount2"), SVMUtils.GetPrivateField <int>(basicAI, "m_workPlaceCount3") }); }
class CustomTramBaseAI : TramBaseAI { // TODO inherit from VehicleAI (in order to keep the correct references to `base`) public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { byte pathFindFlags = Singleton <PathManager> .instance.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { try { this.PathfindSuccess(vehicleId, ref vehicleData); this.PathFindReady(vehicleId, ref vehicleData); } catch (Exception e) { Log.Warning($"TramBaseAI.PathFindSuccess/PathFindReady({vehicleId}) threw an exception: {e.ToString()}"); vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } // NON-STOCK CODE START #if BENCHMARK using (var bm = new Benchmark(null, "UpdateVehiclePosition")) { #endif VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData); #if BENCHMARK } #endif if (!Options.isStockLaneChangerUsed()) { #if BENCHMARK using (var bm = new Benchmark(null, "LogTraffic")) { #endif // Advanced AI traffic measurement VehicleStateManager.Instance.LogTraffic(vehicleId); #if BENCHMARK } #endif } // NON-STOCK CODE END VehicleManager instance = Singleton <VehicleManager> .instance; VehicleInfo info = instance.m_vehicles.m_buffer[(int)vehicleId].Info; info.m_vehicleAI.SimulationStep(vehicleId, ref instance.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } ushort trailingVehicle = instance.m_vehicles.m_buffer[(int)vehicleId].m_trailingVehicle; int num = 0; while (trailingVehicle != 0) { info = instance.m_vehicles.m_buffer[(int)trailingVehicle].Info; info.m_vehicleAI.SimulationStep(trailingVehicle, ref instance.m_vehicles.m_buffer[(int)trailingVehicle], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } trailingVehicle = instance.m_vehicles.m_buffer[(int)trailingVehicle].m_trailingVehicle; if (++num > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if (vehicleData.m_blockCounter == 255) { // NON-STOCK CODE START bool mayDespawn = true; #if BENCHMARK using (var bm = new Benchmark(null, "MayDespawn")) { #endif mayDespawn = VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData); #if BENCHMARK } #endif if (mayDespawn) { // NON-STOCK CODE END Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } // NON-STOCK CODE } }
class CustomTramBaseAI : TramBaseAI { // TODO inherit from VehicleAI (in order to keep the correct references to `base`) public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { #if USEPATHWAITCOUNTER VehicleState state = VehicleStateManager._GetVehicleState(vehicleId); #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { byte pathFindFlags = Singleton <PathManager> .instance.m_pathUnits.m_buffer[(int)((UIntPtr)vehicleData.m_path)].m_pathFindFlags; #if USEPATHWAITCOUNTER if ((pathFindFlags & (PathUnit.FLAG_READY | PathUnit.FLAG_FAILED)) != 0) { VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId); state.PathWaitCounter = 0; // NON-STOCK CODE } #endif if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { try { this.PathfindSuccess(vehicleId, ref vehicleData); this.PathFindReady(vehicleId, ref vehicleData); } catch (Exception e) { Log.Warning($"TramBaseAI.PathFindSuccess/PathFindReady({vehicleId}) threw an exception: {e.ToString()}"); vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } #if USEPATHWAITCOUNTER else { VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId); state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1); // NON-STOCK CODE } #endif } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } /// NON-STOCK CODE START /// VehicleStateManager vehStateManager = VehicleStateManager.Instance; bool reversed = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0; ushort frontVehicleId; if (reversed) { frontVehicleId = vehicleData.GetLastVehicle(vehicleId); } else { frontVehicleId = vehicleId; } if (Options.prioritySignsEnabled || Options.timedLightsEnabled) { try { vehStateManager.UpdateVehiclePos(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId]); } catch (Exception e) { Log.Error("TramAI CustomSimulationStep (2) Error: " + e.ToString()); } } if (!Options.isStockLaneChangerUsed()) { try { //Log._Debug($"HandleVehicle for trams. vehicleId={vehicleId} frontVehicleId={frontVehicleId}"); vehStateManager.LogTraffic(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId], true); } catch (Exception e) { Log.Error("TramAI CustomSimulationStep (1) Error: " + e.ToString()); } } /// NON-STOCK CODE END /// VehicleManager instance = Singleton <VehicleManager> .instance; VehicleInfo info = instance.m_vehicles.m_buffer[(int)vehicleId].Info; info.m_vehicleAI.SimulationStep(vehicleId, ref instance.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } ushort trailingVehicle = instance.m_vehicles.m_buffer[(int)vehicleId].m_trailingVehicle; int num = 0; while (trailingVehicle != 0) { info = instance.m_vehicles.m_buffer[(int)trailingVehicle].Info; info.m_vehicleAI.SimulationStep(trailingVehicle, ref instance.m_vehicles.m_buffer[(int)trailingVehicle], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } trailingVehicle = instance.m_vehicles.m_buffer[(int)trailingVehicle].m_trailingVehicle; if (++num > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0 || vehicleData.m_blockCounter == 255) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } }
private static void ApplyZoning(ZoneTool z) { Vector3 m_startPosition = (Vector3)z.GetType().GetField("m_startPosition", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(z); Vector3 m_mousePosition = (Vector3)z.GetType().GetField("m_mousePosition", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(z); Vector3 m_startDirection = (Vector3)z.GetType().GetField("m_startDirection", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(z); Vector2 vector2_1 = VectorUtils.XZ(m_startPosition); Vector2 vector2_2 = VectorUtils.XZ(m_mousePosition); Vector2 vector2_3 = VectorUtils.XZ(m_startDirection); Vector2 vector2_4 = new Vector2(vector2_3.y, -vector2_3.x); float num1 = Mathf.Round((float)((((double)vector2_2.x - (double)vector2_1.x) * (double)vector2_3.x + ((double)vector2_2.y - (double)vector2_1.y) * (double)vector2_3.y) * 0.125)) * 8f; float num2 = Mathf.Round((float)((((double)vector2_2.x - (double)vector2_1.x) * (double)vector2_4.x + ((double)vector2_2.y - (double)vector2_1.y) * (double)vector2_4.y) * 0.125)) * 8f; float num3 = (double)num1 < 0.0 ? -4f : 4f; float num4 = (double)num2 < 0.0 ? -4f : 4f; Quad2 quad2 = new Quad2(); quad2.a = vector2_1 - vector2_3 * num3 - vector2_4 * num4; quad2.b = vector2_1 - vector2_3 * num3 + vector2_4 * (num2 + num4); quad2.c = vector2_1 + vector2_3 * (num1 + num3) + vector2_4 * (num2 + num4); quad2.d = vector2_1 + vector2_3 * (num1 + num3) - vector2_4 * num4; if ((double)num3 == (double)num4) { Vector2 vector2_5 = quad2.b; quad2.b = quad2.d; quad2.d = vector2_5; } Vector2 vector2_6 = quad2.Min(); Vector2 vector2_7 = quad2.Max(); int num5 = Mathf.Max((int)((vector2_6.x - 46f) / 64f + FakeZoneManager.HALFGRID), 0); int num6 = Mathf.Max((int)((vector2_6.y - 46f) / 64f + FakeZoneManager.HALFGRID), 0); int num7 = Mathf.Min((int)((vector2_7.x + 46f) / 64f + FakeZoneManager.HALFGRID), FakeZoneManager.GRIDSIZE - 1); int num8 = Mathf.Min((int)((vector2_7.y + 46f) / 64f + FakeZoneManager.HALFGRID), FakeZoneManager.GRIDSIZE - 1); var instance1 = ZoneManager.instance; bool flag = false; for (int index1 = num6; index1 <= num8; ++index1) { for (int index2 = num5; index2 <= num7; ++index2) { ushort blockIndex = instance1.m_zoneGrid[index1 * FakeZoneManager.GRIDSIZE + index2]; int num9 = 0; while ((int)blockIndex != 0) { Vector3 vector3 = instance1.m_blocks.m_buffer[(int)blockIndex].m_position; if ((double)Mathf.Max(Mathf.Max(vector2_6.x - 46f - vector3.x, vector2_6.y - 46f - vector3.z), Mathf.Max((float)((double)vector3.x - (double)vector2_7.x - 46.0), (float)((double)vector3.z - (double)vector2_7.y - 46.0))) < 0.0 && ApplyZoning(z, blockIndex, ref instance1.m_blocks.m_buffer[(int)blockIndex], quad2)) { flag = true; } blockIndex = instance1.m_blocks.m_buffer[(int)blockIndex].m_nextGridBlock; if (++num9 >= ZoneManager.MAX_BLOCK_COUNT) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace); break; } } } } if (!flag) { return; } bool m_zoning = (bool)z.GetType().GetField("m_validPosition", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(z); if (m_zoning) { UsedZone(z, z.m_zone); } EffectInfo effect = instance1.m_properties.m_fillEffect; if (effect == null) { return; } InstanceID instance2 = new InstanceID(); EffectInfo.SpawnArea spawnArea = new EffectInfo.SpawnArea((Vector3)((vector2_1 + vector2_2) * 0.5f), Vector3.up, 1f); Singleton <EffectManager> .instance.DispatchEffect(effect, instance2, spawnArea, Vector3.zero, 0.0f, 1f, Singleton <AudioManager> .instance.DefaultGroup); }