Skip to content

Commit

Permalink
TMPE 1.8.3:
Browse files Browse the repository at this point in the history
- Bugfix: Despite having the Parking AI activated, cims sometimes still spawn pocket cars.
- Bugfix: When the Parking AI is active, bicycle lanes are not used (thanks to @informmanuel for reporting this issue)
- Tweaked u-turn behavior
- Improved info views
  • Loading branch information
VictorPhilipp committed Dec 4, 2016
1 parent 7047a65 commit a09d91c
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 207 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ A work-in-progress modification for **Cities: Skylines** to add additional traff
User manual: http://www.viathinksoft.de/tmpe

# Changelog
1.8.3, 12/4/2016
- Bugfix: Despite having the Parking AI activated, cims sometimes still spawn pocket cars.
- Bugfix: When the Parking AI is active, bicycle lanes are not used (thanks to @informmanuel for reporting this issue)
- Tweaked u-turn behavior
- Improved info views

1.8.2, 12/3/2016
- Bugfix: Taxis were not used (thanks to @[Delta ²k5] for reporting)
- Bugfix: Minor UI fix in Default speed limits dialog
Expand Down
35 changes: 24 additions & 11 deletions TLM/TLM/Custom/AI/CustomCitizenAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,15 @@ public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenDa
}
// NON-STOCK CODE END

NetInfo.LaneType laneType = NetInfo.LaneType.Pedestrian;
NetInfo.LaneType laneTypes = NetInfo.LaneType.Pedestrian;
VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
bool randomParking = false;
if (vehicleInfo != null) {
if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi) {
if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTaxi) == CitizenInstance.Flags.None && Singleton<DistrictManager>.instance.m_districts.m_buffer[0].m_productionData.m_finalTaxiCapacity != 0u) {
SimulationManager instance = Singleton<SimulationManager>.instance;
if (instance.m_isNightTime || instance.m_randomizer.Int32(2u) == 0) {
laneType |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
laneTypes |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
vehicleType |= vehicleInfo.m_vehicleType;
extVehicleType = ExtVehicleType.Taxi; // NON-STOCK CODE
// NON-STOCK CODE START
Expand All @@ -197,13 +197,13 @@ public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenDa
if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Car) {
if (mayUseOwnPassengerCar) {
extVehicleType = ExtVehicleType.PassengerCar;
laneType |= NetInfo.LaneType.Vehicle;
laneTypes |= NetInfo.LaneType.Vehicle;
vehicleType |= vehicleInfo.m_vehicleType;
canUseOwnPassengerCar = true;
}
} else if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle) {
extVehicleType = ExtVehicleType.Bicycle;
laneType |= NetInfo.LaneType.Vehicle;
laneTypes |= NetInfo.LaneType.Vehicle;
vehicleType |= vehicleInfo.m_vehicleType;
if (citizenData.m_targetBuilding != 0 && Singleton<BuildingManager>.instance.m_buildings.m_buffer[citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office) {
randomParking = true;
Expand All @@ -212,7 +212,7 @@ public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenDa
// NON-STOCK CODE END
}
}
NetInfo.LaneType startLaneType = laneType;
NetInfo.LaneType startLaneType = laneTypes;
PathUnit.Position vehiclePosition = default(PathUnit.Position);

// NON-STOCK CODE START
Expand Down Expand Up @@ -306,7 +306,7 @@ public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenDa
Log._Debug($"Requesting path-finding for citizen instance {instanceID}, citizen {citizenData.m_citizen}, extVehicleType={extVehicleType}, extPathType={extPathType}, startPos={startPos}, endPos={endPos}, sourceBuilding={citizenData.m_sourceBuilding}, targetBuilding={citizenData.m_targetBuilding}");
#endif

bool foundEndPos = !calculateEndPos || FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA); // NON-STOCK CODE
bool foundEndPos = !calculateEndPos || FindPathPosition(instanceID, ref citizenData, endPos, Options.prohibitPocketCars ? NetInfo.LaneType.Pedestrian : (laneTypes | NetInfo.LaneType.Pedestrian), vehicleType, false, out endPosA); // NON-STOCK CODE

PathUnit.Position startPosA;
if (FindPathPosition(instanceID, ref citizenData, startPos, startLaneType, vehicleType, allowUnderground, out startPosA) &&
Expand All @@ -323,17 +323,30 @@ public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenDa
}
}

if (!forceUseCar && (citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None) {
laneType |= NetInfo.LaneType.PublicTransport;
bool canUseTransport = (citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None;
if (canUseTransport) {
if (!forceUseCar) {
laneTypes |= NetInfo.LaneType.PublicTransport;
}
} else if (Options.prohibitPocketCars) {
// cim tried to use public transport but waiting time was too long
if (citizenData.m_sourceBuilding != 0) {
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2])
Log._Debug($"Citizen instance {instanceID} cannot uses public transport from building {citizenData.m_sourceBuilding} to {citizenData.m_targetBuilding}. Incrementing public transport demand.");
#endif
ExtBuildingManager.Instance.GetExtBuilding(citizenData.m_sourceBuilding).AddPublicTransportDemand((uint)GlobalConfig.Instance.PublicTransportDemandWaitingIncrement, true);
}
}

PathUnit.Position dummyPathPos = default(PathUnit.Position);
uint path;
bool res = CustomPathManager._instance.CreatePath(false, extVehicleType, 0, extPathType, out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, dummyPathPos, endPosA, dummyPathPos, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, randomParking, false, allowEscapeTransport);
bool res = CustomPathManager._instance.CreatePath(false, extVehicleType, 0, extPathType, out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, dummyPathPos, endPosA, dummyPathPos, vehiclePosition, laneTypes, vehicleType, 20000f, false, false, false, false, randomParking, false, allowEscapeTransport);

if (res) {
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2])
Log._Debug($"Path-finding starts for citizen instance {instanceID}, path={path}, extVehicleType={extVehicleType}, startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, laneType={laneType}, vehicleType={vehicleType}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}, vehiclePos.m_segment={vehiclePosition.m_segment}, vehiclePos.m_lane={vehiclePosition.m_lane}, vehiclePos.m_offset={vehiclePosition.m_offset}, allowEscapeTransport={allowEscapeTransport}");
Log._Debug($"Path-finding starts for citizen instance {instanceID}, path={path}, extVehicleType={extVehicleType}, startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, laneType={laneTypes}, vehicleType={vehicleType}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}, vehiclePos.m_segment={vehiclePosition.m_segment}, vehiclePos.m_lane={vehiclePosition.m_lane}, vehiclePos.m_offset={vehiclePosition.m_offset}, allowEscapeTransport={allowEscapeTransport}");
#endif

if (citizenData.m_path != 0u) {
Expand Down Expand Up @@ -402,7 +415,7 @@ protected static bool TrySpawnParkedPassengerCarBuilding(uint citizenId, ushort
Quaternion parkRot = Quaternion.identity;
float parkOffset;

if (CustomPassengerCarAI.FindParkingSpaceBuilding(vehicleInfo, homeId, 0, 0, refPos, GlobalConfig.Instance.VicinityParkingSpaceSearchRadius, out parkPos, out parkRot, out parkOffset)) {
if (CustomPassengerCarAI.FindParkingSpaceBuilding(vehicleInfo, homeId, 0, 0, refPos, GlobalConfig.Instance.VicinityParkingSpaceSearchRadius, GlobalConfig.Instance.VicinityParkingSpaceSearchRadius, out parkPos, out parkRot, out parkOffset)) {
// position found, spawn a parked vehicle
ushort parkedVehicleId;
if (Singleton<VehicleManager>.instance.CreateParkedVehicle(out parkedVehicleId, ref Singleton<SimulationManager>.instance.m_randomizer, vehicleInfo, parkPos, parkRot, citizenId)) {
Expand Down
29 changes: 23 additions & 6 deletions TLM/TLM/Custom/AI/CustomHumanAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void CustomSimulationStep(ushort instanceID, ref CitizenInstance instance

if (pathFindSucceeded) {
bool handleSoftPathFindFailure;
if (!CustomHumanAI.OnPathFindSuccess(instanceID, ref instanceData, out handleSoftPathFindFailure, out handleSuccess)) {
if (!CustomHumanAI.OnPathFindSuccess(instanceID, ref instanceData, ref Singleton<CitizenManager>.instance.m_citizens.m_buffer[instanceData.m_citizen], out handleSoftPathFindFailure, out handleSuccess)) {
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2]) {
ushort parkedVehicleId = Singleton<CitizenManager>.instance.m_citizens.m_buffer[instanceData.m_citizen].m_parkedVehicle;
Expand Down Expand Up @@ -201,6 +201,7 @@ internal static bool OnPathFindFailure(ushort instanceID, ref CitizenInstance in
case ExtPathMode.None:
case ExtPathMode.CalculatingWalkingPathToParkedCar:
case ExtPathMode.CalculatingWalkingPathToTarget:
case ExtPathMode.TaxiToTarget:
if ((instanceData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None) {
if (instanceData.m_targetBuilding != 0) {
ExtBuildingManager.Instance.GetExtBuilding(instanceData.m_targetBuilding).AddPublicTransportDemand((uint)GlobalConfig.Instance.PublicTransportDemandIncrement, false);
Expand Down Expand Up @@ -247,32 +248,46 @@ internal static bool OnPathFindFailure(ushort instanceID, ref CitizenInstance in
return ret;
}

internal static bool OnPathFindSuccess(ushort instanceID, ref CitizenInstance instanceData, out bool handleSoftPathFindFailure, out bool handleSuccess) {
internal static bool OnPathFindSuccess(ushort instanceID, ref CitizenInstance instanceData, ref Citizen citizenData, out bool handleSoftPathFindFailure, out bool handleSuccess) {
handleSoftPathFindFailure = false;
handleSuccess = true;
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2])
Log._Debug($"CustomHumanAI.OnPathFindSuccess: Path-finding succeeded for citizen instance {instanceID}. Path: {instanceData.m_path} vehicle={Singleton<CitizenManager>.instance.m_citizens.m_buffer[instanceData.m_citizen].m_vehicle}");
Log._Debug($"CustomHumanAI.OnPathFindSuccess: Path-finding succeeded for citizen instance {instanceID}. Path: {instanceData.m_path} vehicle={citizenData.m_vehicle}");
#endif

if (Singleton<CitizenManager>.instance.m_citizens.m_buffer[instanceData.m_citizen].m_vehicle == 0) {
if (citizenData.m_vehicle == 0) {
ExtCitizenInstance extInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(instanceID);

if (extInstance.PathMode == ExtPathMode.TaxiToTarget) {
// cim uses taxi
if (instanceData.m_sourceBuilding != 0)
ExtBuildingManager.Instance.GetExtBuilding(instanceData.m_sourceBuilding).RemovePublicTransportDemand((uint)GlobalConfig.Instance.PublicTransportDemandUsageDecrement, true);
if (instanceData.m_targetBuilding != 0)
ExtBuildingManager.Instance.GetExtBuilding(instanceData.m_targetBuilding).RemovePublicTransportDemand((uint)GlobalConfig.Instance.PublicTransportDemandUsageDecrement, false);

return true;
}

ushort parkedVehicleId = Singleton<CitizenManager>.instance.m_citizens.m_buffer[instanceData.m_citizen].m_parkedVehicle;
ushort parkedVehicleId = citizenData.m_parkedVehicle;
float sqrDistToParkedVehicle = 0f;
if (parkedVehicleId != 0) {
sqrDistToParkedVehicle = (instanceData.GetLastFramePosition() - Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position).sqrMagnitude;
}

byte laneTypes = CustomPathManager._instance.m_pathUnits.m_buffer[instanceData.m_path].m_laneTypes;
byte vehicleTypes = CustomPathManager._instance.m_pathUnits.m_buffer[instanceData.m_path].m_vehicleTypes;
bool usesPublicTransport = (laneTypes & (byte)(NetInfo.LaneType.PublicTransport)) != 0;
bool usesCar = (laneTypes & (byte)(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0;
bool usesCar = (laneTypes & (byte)(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0 && (vehicleTypes & (byte)(VehicleInfo.VehicleType.Car)) != 0;

if (usesPublicTransport && usesCar && extInstance.PathMode == ExtPathMode.CalculatingCarPathToKnownParkPos) {
/*
* when using public transport together with a car (assuming a "source -> walk -> drive -> walk -> use public transport -> walk -> target" path)
* discard parking space information since the cim has to park near the public transport stop
* (instead of parking in the vicinity of the target building).
*
* TODO we could check if the path looks like "source -> walk -> use public transport -> walk -> drive -> [walk ->] target" (in this case parking space information would still be valid)
*/
extInstance.PathMode = ExtPathMode.CalculatingCarPathToTarget;
extInstance.ParkingSpaceLocation = ExtParkingSpaceLocation.None;
extInstance.ParkingSpaceLocationId = 0;
Expand All @@ -298,6 +313,8 @@ internal static bool OnPathFindSuccess(ushort instanceID, ref CitizenInstance in
ushort sourceBuildingId = instanceData.m_sourceBuilding;
if (sourceBuildingId != 0) {
isAtOutsideConnection = (Singleton<BuildingManager>.instance.m_buildings.m_buffer[sourceBuildingId].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None;// Info.m_buildingAI is OutsideConnectionAI;
if (isAtOutsideConnection && (instanceData.GetLastFramePosition() - Singleton<BuildingManager>.instance.m_buildings.m_buffer[sourceBuildingId].m_position).magnitude > GlobalConfig.Instance.MaxBuildingToPedestrianLaneDistance)
isAtOutsideConnection = false;
//isAtOutsideConnection = Singleton<BuildingManager>.instance.m_buildings.m_buffer[sourceBuildingId].Info.m_buildingAI is OutsideConnectionAI;
}

Expand Down
Loading

0 comments on commit a09d91c

Please sign in to comment.