private void ProcessNewPickups() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort pickup in data.BuildingsUpdated) { if (data.IsBuildingWithDead(pickup)) { if (_master.ContainsKey(pickup)) { if (float.IsNegativeInfinity(_master[pickup])) { _master[pickup] = float.PositiveInfinity; } else if (_master[pickup] <= 400) { _master[pickup] = float.NegativeInfinity; } } foreach (ushort id in _cemeteries.Keys) { _cemeteries[id].AddPickup(pickup); } } else { foreach (ushort id in _cemeteries.Keys) { _cemeteries[id].AddCheckup(pickup); } } } }
private void ProcessNewPickups() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort pickup in data.BuildingsUpdated) { if (data.IsLandfillSite(pickup)) { continue; } if (data.IsBuildingWithGarbage(pickup)) { foreach (ushort id in _landfills.Keys) { _landfills[id].AddPickup(pickup); } } else { foreach (ushort id in _landfills.Keys) { _landfills[id].AddCheckup(pickup); } } } }
private void ProcessNewCemeteries() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort x in data.BuildingsUpdated) { if (!data.IsCemetery(x)) { continue; } if (_cemeteries.ContainsKey(x)) { continue; } _cemeteries.Add(x, new Cemetery(x, ref _master)); foreach (ushort pickup in data.BuildingsWithDead) { foreach (ushort id in _cemeteries.Keys) { _cemeteries[id].AddPickup(pickup); } } } }
private void UpdateGarbageTrucks() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; Vehicle[] vehicles = Singleton <VehicleManager> .instance.m_vehicles.m_buffer; InstanceID instanceID = new InstanceID(); foreach (ushort id in data.VehiclesUpdated) { if (!data.IsHearse(id)) { continue; } Vehicle v = vehicles[id]; if (!_landfills.ContainsKey(v.m_sourceBuilding)) { continue; } if (v.Info.m_vehicleAI.GetLocalizedStatus(id, ref v, out instanceID) != _collecting) { continue; } ushort target = _landfills[v.m_sourceBuilding].AssignTarget(v); if (target != 0 && target != v.m_targetBuilding) { v.Info.m_vehicleAI.SetTarget(id, ref vehicles[id], target); } } }
private void ProcessNewPickups() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort pickup in data.BuildingsUpdated) { if (data.IsCemetery(pickup)) { continue; } if (data.IsBuildingWithDead(pickup)) { foreach (ushort id in _cemeteries.Keys) { _cemeteries[id].AddPickup(pickup); } } else { foreach (ushort id in _cemeteries.Keys) { _cemeteries[id].AddCheckup(pickup); } } } }
private void ProcessRemovedCemeteries() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort id in data.BuildingsRemoved) { _cemeteries.Remove(id); } }
private void ProcessRemovedLandfills() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort id in data.BuildingsRemoved) { _landfills.Remove(id); } }
private void UpdateHearses() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; Vehicle[] vehicles = Singleton <VehicleManager> .instance.m_vehicles.m_buffer; InstanceID instanceID = new InstanceID(); foreach (ushort id in data.VehiclesUpdated) { if (!data.IsHearse(id)) { continue; } Vehicle v = vehicles[id]; /* * If a hearse is loading corpse, we will remove it from the vehicle grid, * so other cars can pass it and more than one hearse can service a building. * It doesn't really make sense that only one hearse can be at a high rise * at a time. */ if ((v.m_flags & Vehicle.Flags.Stopped) != Vehicle.Flags.None) { if (!_stopped.Contains(id)) { Singleton <VehicleManager> .instance.RemoveFromGrid(id, ref vehicles[id], false); _stopped.Add(id); } continue; } else { _stopped.Remove(id); } if (!_cemeteries.ContainsKey(v.m_sourceBuilding)) { continue; } if (v.Info.m_vehicleAI.GetLocalizedStatus(id, ref v, out instanceID) != _collecting) { continue; } ushort target = _cemeteries[v.m_sourceBuilding].AssignTarget(v); if (target != 0 && target != v.m_targetBuilding) { v.Info.m_vehicleAI.SetTarget(id, ref vehicles[id], target); } } }
private void ProcessIdleGarbageTrucks() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort x in data.BuildingsUpdated) { if (!_landfills.ContainsKey(x)) { continue; } _landfills[x].DispatchIdleVehicle(); } }
private void ProcessIdleHearses() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort x in data.BuildingsUpdated) { if (!_cemeteries.ContainsKey(x)) { continue; } _cemeteries[x].DispatchIdleVehicle(); } }
private void CreateBaseline() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort id in data.LandfillSites) { _landfills.Add(id, new Landfill(id, ref _master, ref _oldtargets, ref _lastchangetimes)); } foreach (ushort pickup in data.BuildingsWithGarbage) { foreach (ushort id in _landfills.Keys) { _landfills[id].AddPickup(pickup); } } _baselined = true; }
private void CreateBaseline() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort id in data.Cemeteries) { _cemeteries.Add(id, new Cemetery(id, ref _master)); } foreach (ushort pickup in data.BuildingsWithDead) { foreach (ushort id in _cemeteries.Keys) { _cemeteries[id].AddPickup(pickup); } } _baselined = true; }
private void ProcessNewLandfills() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort x in data.BuildingsUpdated) { if (!data.IsLandfillSite(x)) { continue; } if (_landfills.ContainsKey(x)) { continue; } _landfills.Add(x, new Landfill(x, ref _master, ref _oldtargets, ref _lastchangetimes)); foreach (ushort pickup in data.BuildingsWithGarbage) { _landfills[x].AddPickup(pickup); } } }
private void UpdateGarbageTrucks() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort vehicleID in data.VehiclesRemoved) { if (!data.IsGarbageTruck(vehicleID)) { continue; } if (_lasttargets.ContainsKey(vehicleID) && Helper.IsBuildingWithGarbage(_lasttargets[vehicleID])) { foreach (ushort id in _landfills.Keys) { _landfills[id].AddPickup(_lasttargets[vehicleID]); } } _oldtargets.Remove(vehicleID); if (_lasttargets.ContainsKey(vehicleID)) { _master.Remove(_lasttargets[vehicleID]); } _lasttargets.Remove(vehicleID); _lastchangetimes.Remove(vehicleID); _PathfindCount.Remove(vehicleID); } if (!SimulationManager.instance.SimulationPaused) { uint num1 = Singleton <SimulationManager> .instance.m_currentFrameIndex >> 4 & 7u; uint num2 = _lastProcessedFrame >> 4 & 7u; foreach (ushort vehicleID in data.VehiclesUpdated) { if (!data.IsGarbageTruck(vehicleID)) { continue; } Vehicle v = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID]; if (!_landfills.ContainsKey(v.m_sourceBuilding)) { continue; } if (v.m_flags.IsFlagSet(Vehicle.Flags.Stopped) || v.m_flags.IsFlagSet(Vehicle.Flags.WaitingSpace) || v.m_flags.IsFlagSet(Vehicle.Flags.WaitingPath) || v.m_flags.IsFlagSet(Vehicle.Flags.WaitingLoading) || v.m_flags.IsFlagSet(Vehicle.Flags.WaitingCargo)) { continue; } if (!v.m_flags.IsFlagSet(Vehicle.Flags.Spawned)) { continue; } if (v.m_path == 0u) { continue; } _PathfindCount.Remove(vehicleID); if (!v.m_flags.IsFlagSet(Vehicle.Flags.WaitingTarget)) { uint num3 = vehicleID & 7u; if (num1 != num3 && num2 != num3) { _updated.Remove(vehicleID); continue; } else if (_updated.Contains(vehicleID)) { continue; } } _updated.Add(vehicleID); int vehicleStatus = GetGarbageTruckStatus(ref v); if (vehicleStatus == VEHICLE_STATUS_GARBAGE_RETURN && _lasttargets.ContainsKey(vehicleID)) { if (Helper.IsBuildingWithGarbage(_lasttargets[vehicleID])) { foreach (ushort id in _landfills.Keys) { _landfills[id].AddPickup(_lasttargets[vehicleID]); } } _lasttargets.Remove(vehicleID); continue; } if (vehicleStatus != VEHICLE_STATUS_GARBAGE_COLLECT && vehicleStatus != VEHICLE_STATUS_GARBAGE_WAIT) { continue; } ushort target = _landfills[v.m_sourceBuilding].AssignTarget(vehicleID); if (target != 0 && target != v.m_targetBuilding) { if (Helper.IsBuildingWithGarbage(v.m_targetBuilding)) { foreach (ushort id in _landfills.Keys) { _landfills[id].AddPickup(v.m_targetBuilding); } } _master.Remove(v.m_targetBuilding); if (vehicleStatus == VEHICLE_STATUS_GARBAGE_COLLECT) { _lasttargets[vehicleID] = v.m_targetBuilding; if (_lastchangetimes.ContainsKey(vehicleID)) { _lastchangetimes[vehicleID] = SimulationManager.instance.m_currentGameTime; } else { _lastchangetimes.Add(vehicleID, SimulationManager.instance.m_currentGameTime); } } _CustomGarbageTruckAI.SetTarget(vehicleID, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID], target); } else { if (_master.ContainsKey(v.m_targetBuilding)) { if (_master[v.m_targetBuilding].Vehicle != vehicleID) { _master[v.m_targetBuilding] = new Claimant(vehicleID, v.m_targetBuilding); } } else { _master.Add(v.m_targetBuilding, new Claimant(vehicleID, v.m_targetBuilding)); } } } } foreach (ushort vehicleID in data.GarbageTrucks) { if (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_flags.IsFlagSet(Vehicle.Flags.WaitingPath)) { PathManager instance = Singleton <PathManager> .instance; byte pathFindFlags = instance.m_pathUnits.m_buffer[(int)((UIntPtr)Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { _PathfindCount.Remove(vehicleID); } else if ((pathFindFlags & 8) != 0) { int vehicleStatus = GetGarbageTruckStatus(ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID]); if (_lasttargets.ContainsKey(vehicleID)) { Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_path); Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_path = 0u; _CustomGarbageTruckAI.SetTarget(vehicleID, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID], _lasttargets[vehicleID]); _lasttargets.Remove(vehicleID); } else if ((vehicleStatus == VEHICLE_STATUS_GARBAGE_WAIT || vehicleStatus == VEHICLE_STATUS_GARBAGE_COLLECT) && (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_flags.IsFlagSet(Vehicle.Flags.Spawned)) && _landfills.ContainsKey(Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_sourceBuilding) && (!_PathfindCount.ContainsKey(vehicleID) || _PathfindCount[vehicleID] < 20)) { if (!_PathfindCount.ContainsKey(vehicleID)) { _PathfindCount[vehicleID] = 0; } _PathfindCount[vehicleID]++; ushort target = _landfills[Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_sourceBuilding].GetUnclaimedTarget(vehicleID); if (target == 0) { _PathfindCount[vehicleID] = ushort.MaxValue; } else { if (Dispatcher._oldtargets != null) { if (!Dispatcher._oldtargets.ContainsKey(vehicleID)) { Dispatcher._oldtargets.Add(vehicleID, new HashSet <ushort>()); } Dispatcher._oldtargets[vehicleID].Add(target); } Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_path); Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID].m_path = 0u; _CustomGarbageTruckAI.SetTarget(vehicleID, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID], target); } } } } } }
public override void OnUpdate(float realTimeDelta, float simulationTimeDelta) { if (_terminated) { return; } if (!_helper.GameLoaded) { return; } try { if (!_initialized) { if (!IsOverwatched()) { _helper.NotifyPlayer("Skylines Overwatch not found. Terminating..."); _terminated = true; return; } SkylinesOverwatch.Settings.Instance.Enable.VehicleMonitor = true; _initialized = true; _helper.NotifyPlayer("Initialized"); } else { if (WorldInfoPanel.AnyWorldInfoPanelOpen()) { _selected = WorldInfoPanel.GetCurrentInstanceID(); if (_selected.IsEmpty || _selected.Vehicle == 0) { _selected = default(InstanceID); } } else { _selected = default(InstanceID); } VehicleManager instance = Singleton <VehicleManager> .instance; InstanceID instanceID = new InstanceID(); SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort i in data.VehiclesUpdated) { Vehicle v = instance.m_vehicles.m_buffer[(int)i]; bool isBlocked = !data.IsCar(i) && v.m_blockCounter >= 64; // we will let the game decide when to remove a blocked car bool isConfused = v.Info.m_vehicleAI.GetLocalizedStatus(i, ref v, out instanceID) == _confused; if (!isBlocked && !isConfused) { continue; } RemoveVehicle(i); } foreach (ushort i in _helper.ManualRemovalRequests) { RemoveVehicle(i); } _helper.ManualRemovalRequests.Clear(); } } catch (Exception e) { string error = String.Format("Failed to {0}\r\n", !_initialized ? "initialize" : "update"); error += String.Format("Error: {0}\r\n", e.Message); error += "\r\n"; error += "==== STACK TRACE ====\r\n"; error += e.StackTrace; _helper.Log(error); if (!_initialized) { _terminated = true; } } base.OnUpdate(realTimeDelta, simulationTimeDelta); }
public override void OnUpdate(float realTimeDelta, float simulationTimeDelta) { if (_terminated) { return; } if (!_helper.GameLoaded) { return; } try { if (!_initialized) { if (!IsOverwatched()) { _helper.NotifyPlayer("Skylines Overwatch not found. Terminating..."); _terminated = true; return; } else { _helper.NotifyPlayer($"Skylines Overwatch found, initialising {this.GetType()}"); } SkylinesOverwatch.Settings.Instance.Enable.VehicleMonitor = true; SkylinesOverwatch.Settings.Instance.Enable.HumanMonitor = true; SkylinesOverwatch.Settings.Instance.Enable.BuildingMonitor = true; _initialized = true; _helper.NotifyPlayer("Initialized"); } else if (!_baselined) { remove_init = false; SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort i in data.Vehicles) { Vehicle v = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[(int)i]; bool isBlocked = Identity.ModConf.RemoveBlockedVehicles && !data.IsCar(i) && v.m_blockCounter >= 64; // we will let the game decide when to remove a blocked car bool isConfused = Identity.ModConf.RemoveConfusedVehicles && v.Info.m_vehicleAI.GetLocalizedStatus(i, ref v, out instanceID) == _vehicle_confused; if (!isBlocked && !isConfused) { continue; } RemoveVehicle(i); } if (Identity.ModConf.RemoveConfusedCitizensVehicles) { deleteSelectedVehicle(); foreach (uint i in SkylinesOverwatch.Data.Instance.Humans) { deleteParkedVehicle(i); } } _baselined = true; } else { remove_init = false; if ((Singleton <SimulationManager> .instance.m_currentFrameIndex / 16 % 8) == 0) { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; foreach (ushort i in data.VehiclesUpdated) { Vehicle v = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[(int)i]; bool isBlocked = Identity.ModConf.RemoveBlockedVehicles && !data.IsCar(i) && v.m_blockCounter >= 64; // we will let the game decide when to remove a blocked car bool isConfused = Identity.ModConf.RemoveConfusedVehicles && v.Info.m_vehicleAI.GetLocalizedStatus(i, ref v, out instanceID) == _vehicle_confused; if (!isBlocked && !isConfused) { continue; } RemoveVehicle(i); } } if (Identity.ModConf.RemoveConfusedCitizensVehicles) { deleteSelectedVehicle(); foreach (uint i in SkylinesOverwatch.Data.Instance.HumansUpdated) { deleteParkedVehicle(i); } foreach (ushort j in SkylinesOverwatch.Data.Instance.BuildingsUpdated) { uint num = Singleton <BuildingManager> .instance.m_buildings.m_buffer[j].m_citizenUnits; while (num != 0u) { uint nextUnit = Singleton <CitizenManager> .instance.m_units.m_buffer[(int)((UIntPtr)num)].m_nextUnit; for (int i = 0; i < 5; i++) { uint citizen = Singleton <CitizenManager> .instance.m_units.m_buffer[(int)((UIntPtr)num)].GetCitizen(i); if (citizen != 0u) { deleteParkedVehicle(citizen); } } num = nextUnit; } } } if (_helper.ManualRemovalRequests.Any()) { _helper.NotifyPlayer($"Removing {_helper.ManualRemovalRequests.Count} manually requested vehicle(s)"); } foreach (ushort i in _helper.ManualRemovalRequests) { RemoveVehicle(i, true); } _helper.ManualRemovalRequests.Clear(); } } catch (Exception e) { string error = String.Format("Failed to {0}\r\n", !_initialized ? "initialize" : "update"); error += String.Format("Error: {0}\r\n", e.Message); error += "\r\n"; error += "==== STACK TRACE ====\r\n"; error += e.StackTrace; _helper.Log(error); _helper.NotifyPlayer($"Skylines Stuck Vehicles Remover Terminated:{Environment.NewLine}{error}"); if (!_initialized) { _terminated = true; } } base.OnUpdate(realTimeDelta, simulationTimeDelta); }
private void ProcessHumansUpdated() { SkylinesOverwatch.Data data = SkylinesOverwatch.Data.Instance; uint[] humans = data.HumansUpdated; if (humans.Length == 0) { return; } CitizenManager instance = Singleton <CitizenManager> .instance; foreach (uint i in humans) { if (!data.IsResident(i)) { continue; } Citizen[] residents = instance.m_citizens.m_buffer; Citizen resident = residents[(int)i]; if (resident.Dead) { continue; } if ((resident.m_flags & Citizen.Flags.Created) == Citizen.Flags.None) { continue; } if ((resident.m_flags & Citizen.Flags.DummyTraffic) != Citizen.Flags.None) { continue; } if (!Kill(resident)) { continue; } residents[(int)i].Sick = false; residents[(int)i].Dead = true; residents[(int)i].SetParkedVehicle(i, 0); ushort home = resident.GetBuildingByLocation(); if (home == 0) { home = resident.m_homeBuilding; } if (home != 0) { DistrictManager dm = Singleton <DistrictManager> .instance; Vector3 position = Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)home].m_position; byte district = dm.GetDistrict(position); District[] buffer = dm.m_districts.m_buffer; buffer[(int)district].m_deathData.m_tempCount = buffer[(int)district].m_deathData.m_tempCount + 1; } if (_randomizer.Int32(2) == 0) { instance.ReleaseCitizen(i); } SkylinesOverwatch.Helper.Instance.RequestHumanRemoval(i); } }