private static void InitializePath(ushort vehicleID, ref Vehicle vehicleData)
        {
            PathManager    instance        = Singleton <PathManager> .instance;
            VehicleManager instance2       = Singleton <VehicleManager> .instance;
            ushort         trailingVehicle = vehicleData.m_trailingVehicle;
            int            num             = 0;

            while (trailingVehicle != 0)
            {
                if (instance2.m_vehicles.m_buffer [(int)trailingVehicle].m_path != 0u)
                {
                    instance.ReleasePath(instance2.m_vehicles.m_buffer [(int)trailingVehicle].m_path);
                    instance2.m_vehicles.m_buffer [(int)trailingVehicle].m_path = 0u;
                }
                if (instance.AddPathReference(vehicleData.m_path))
                {
                    instance2.m_vehicles.m_buffer [(int)trailingVehicle].m_path = vehicleData.m_path;
                    instance2.m_vehicles.m_buffer [(int)trailingVehicle].m_pathPositionIndex = 0;
                }
                ResetTargets(trailingVehicle, ref instance2.m_vehicles.m_buffer [(int)trailingVehicle], vehicleID, ref vehicleData, false);
                trailingVehicle = instance2.m_vehicles.m_buffer [(int)trailingVehicle].m_trailingVehicle;
                if (++num > 65536)
                {
                    CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                    break;
                }
            }
            vehicleData.m_pathPositionIndex = 0;
            ResetTargets(vehicleID, ref vehicleData, vehicleID, ref vehicleData, false);
        }
Ejemplo n.º 2
0
        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
                        ExtBuildingManager.Instance.ExtBuildings[targetBuildingId].AddParkingSpaceDemand(GlobalConfig.Instance.ParkingAI.FailedParkingSpaceDemandIncrement * (uint)driverExtInstance.failedParkingAttempts);
                    }

                    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);
        }