// from CitizenAI
 public static bool FindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, out PathUnit.Position position)
 {
     position = default(PathUnit.Position);
     float num = 1E+10f;
     PathUnit.Position position2;
     PathUnit.Position position3;
     float num2;
     float num3;
     if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Road, laneTypes, vehicleTypes, allowUnderground, 32f, out position2, out position3, out num2, out num3, RoadManager.VehicleType.PassengerCar) && num2 < num)
     {
         num = num2;
         position = position2;
     }
     PathUnit.Position position4;
     PathUnit.Position position5;
     float num4;
     float num5;
     if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Beautification, laneTypes, vehicleTypes, allowUnderground, 32f, out position4, out position5, out num4, out num5, RoadManager.VehicleType.PassengerCar) && num4 < num)
     {
         num = num4;
         position = position4;
     }
     PathUnit.Position position6;
     PathUnit.Position position7;
     float num6;
     float num7;
     if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None && CustomPathManager.FindPathPosition(pos, ItemClass.Service.PublicTransport, laneTypes, vehicleTypes, allowUnderground, 32f, out position6, out position7, out num6, out num7, RoadManager.VehicleType.PassengerCar) && num6 < num)
     {
         position = position6;
     }
     return position.m_segment != 0;
 }
 protected new bool StartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo)
 {
     NetInfo.LaneType laneType = 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);
                     vehicleType |= vehicleInfo.m_vehicleType;
                 }
             }
         }
         else
         {
             laneType |= NetInfo.LaneType.Vehicle;
             vehicleType |= vehicleInfo.m_vehicleType;
             if (citizenData.m_targetBuilding != 0 && Singleton<BuildingManager>.instance.m_buildings.m_buffer[(int)citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
             {
                 randomParking = true;
             }
         }
     }
     PathUnit.Position vehiclePosition = default(PathUnit.Position);
     ushort parkedVehicle = Singleton<CitizenManager>.instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle;
     if (parkedVehicle != 0)
     {
         Vector3 position = Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position;
         PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition);
     }
     bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;
     PathUnit.Position startPosA;
     PathUnit.Position endPosA;
     if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) && this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA))
     {
         if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)
         {
             laneType |= NetInfo.LaneType.PublicTransport;
         }
         PathUnit.Position position2 = default(PathUnit.Position);
         uint path;
         if (Singleton<PathManager>.instance.CreatePath(ExtendedVehicleType.PassengerCar, out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, randomParking))
         {
             if (citizenData.m_path != 0u)
             {
                 Singleton<PathManager>.instance.ReleasePath(citizenData.m_path);
             }
             citizenData.m_path = path;
             citizenData.m_flags |= CitizenInstance.Flags.WaitingPath;
             return true;
         }
     }
     return false;
 }
        public override void SimulationStep(ushort instanceID, ref CitizenInstance citizenData, ref CitizenInstance.Frame frameData, bool lodPhysics)
        {
            base.SimulationStep(instanceID, ref citizenData, ref frameData, lodPhysics);

            if ((citizenData.m_flags & CitizenInstance.Flags.WaitingTransport) != CitizenInstance.Flags.None && citizenData.m_waitCounter > 0)
            {
                if (Singleton<SimulationManager>.instance.m_randomizer.Int32(3) == 0)
                {
                    citizenData.m_waitCounter = (byte)(citizenData.m_waitCounter - 1);
                }
                else
                {
                    AddCommuteWait(citizenData.m_citizen, 1);
                }
            }
        }
 protected override VehicleInfo GetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceProbability)
 {
     if (citizenData.m_citizen == 0u)
     {
         return null;
     }
     int num;
     int num2;
     int num3;
     if (forceProbability || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None)
     {
         num = 100;
         num2 = 0;
         num3 = 0;
     }
     else
     {
         num = this.GetCarProbability ();
         num2 = this.GetBikeProbability ();
         num3 = this.GetTaxiProbability ();
     }
     Randomizer randomizer = new Randomizer (citizenData.m_citizen);
     bool flag = randomizer.Int32 (100u) < num;
     bool flag2 = randomizer.Int32 (100u) < num2;
     bool flag3 = randomizer.Int32 (100u) < num3;
     ItemClass.Service service = ItemClass.Service.Residential;
     ItemClass.SubService subService = ItemClass.SubService.ResidentialLow;
     if (!flag && flag3)
     {
         service = ItemClass.Service.PublicTransport;
         subService = ItemClass.SubService.PublicTransportTaxi;
     }
     VehicleInfo randomVehicleInfo = Singleton<VehicleManager>.instance.GetRandomVehicleInfo (ref randomizer, service, subService, ItemClass.Level.Level1);
     VehicleInfo randomVehicleInfo2 = Singleton<VehicleManager>.instance.GetRandomVehicleInfo (ref randomizer, ItemClass.Service.Residential, ItemClass.SubService.ResidentialHigh, ItemClass.Level.Level2);
     if (flag2 && randomVehicleInfo2 != null)
     {
         return randomVehicleInfo2;
     }
     if ((flag || flag3) && randomVehicleInfo != null)
     {
         return randomVehicleInfo;
     }
     return null;
 }
 private ushort CheckCollisions(ushort instanceID, ref CitizenInstance citizenData, Segment3 segment, Vector3 min, Vector3 max, ushort otherID, ref CitizenInstance otherData, ref Vector3 pushAmount, ref float pushDivider)
 {
     if (otherID == instanceID)
     {
         return otherData.m_nextGridInstance;
     }
     if (((citizenData.m_flags | otherData.m_flags) & CitizenInstance.Flags.Transition) == CitizenInstance.Flags.None && (citizenData.m_flags & CitizenInstance.Flags.Underground) != (citizenData.m_flags & CitizenInstance.Flags.Underground))
     {
         return otherData.m_nextGridInstance;
     }
     CitizenInfo info = otherData.Info;
     CitizenInstance.Frame lastFrameData = otherData.GetLastFrameData ();
     Vector3 position = lastFrameData.m_position;
     Vector3 b = lastFrameData.m_position + lastFrameData.m_velocity;
     Segment3 segment2 = new Segment3 (position, b);
     Vector3 vector = segment2.Min ();
     vector.x -= info.m_radius;
     vector.z -= info.m_radius;
     Vector3 vector2 = segment2.Max ();
     vector2.x += info.m_radius;
     vector2.y += info.m_height;
     vector2.z += info.m_radius;
     if (min.x < vector2.x && max.x > vector.x && min.z < vector2.z && max.z > vector.z && min.y < vector2.y && max.y > vector.y)
     {
         float num = this.m_info.m_radius + info.m_radius;
         float num3;
         float t;
         float num2 = segment.DistanceSqr (segment2, out num3, out t);
         if (num2 < num * num)
         {
             float num4 = num - Mathf.Sqrt (num2);
             float num5 = 1f - num2 / (num * num);
             Vector3 a = segment.Position (num3 * 0.9f);
             Vector3 b2 = segment2.Position (t);
             a.y = 0f;
             b2.y = 0f;
             Vector3 vector3 = a - b2;
             Vector3 vector4 = new Vector3 (segment.b.z - segment.a.z, 0f, segment.a.x - segment.b.x);
             if (Vector3.Dot (vector3, vector4) >= 0f)
             {
                 vector3 += vector4;
             }
             else
             {
                 vector3 -= vector4;
             }
             pushAmount += vector3.normalized * (num4 * num5);
             pushDivider += num5;
         }
     }
     return otherData.m_nextGridInstance;
 }
Example #6
0
 public bool CustomFindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, out PathUnit.Position position)
 {
     return(CustomPathManager.FindCitizenPathPosition(pos, laneTypes, vehicleTypes, (citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None, allowUnderground, out position));
 }
 /// <summary>
 /// Check if resident is confused.
 /// </summary>
 /// <param name="data">The citizen instance.</param>
 /// <returns>True if resident is confused.</returns>
 private static bool ResidentConfused(ref CitizenInstance data)
 {
     // From ResidentAI.GetLocalizedStatus from original game code at version 1.4.1-f2.
     ////CitizenManager instance1 = Singleton<CitizenManager>.instance;
     ////uint num1 = data.m_citizen;
     ////bool flag1 = false;
     ////ushort num2 = (ushort)0;
     ////ushort num3 = (ushort)0;
     ////ushort vehicleID = (ushort)0;
     ////if ((int)num1 != 0)
     ////{
     ////    num2 = instance1.m_citizens.m_buffer[(IntPtr)num1].m_homeBuilding;
     ////    num3 = instance1.m_citizens.m_buffer[(IntPtr)num1].m_workBuilding;
     ////    vehicleID = instance1.m_citizens.m_buffer[(IntPtr)num1].m_vehicle;
     ////    flag1 = (instance1.m_citizens.m_buffer[(IntPtr)num1].m_flags & Citizen.Flags.Student) != Citizen.Flags.None;
     ////}
     ushort num4 = data.m_targetBuilding;
     if ((int)num4 != 0)
     {
         ////bool flag2 = (Singleton<BuildingManager>.instance.m_buildings.m_buffer[(int)num4].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None;
         ////bool flag3 = (int)data.m_path == 0 && (data.m_flags & CitizenInstance.Flags.HangAround) != CitizenInstance.Flags.None;
         ////if ((int)vehicleID != 0)
         ////{
         ////    VehicleManager instance2 = Singleton<VehicleManager>.instance;
         ////    VehicleInfo info = instance2.m_vehicles.m_buffer[(int)vehicleID].Info;
         ////    if (info.m_class.m_service == ItemClass.Service.Residential && info.m_vehicleType != VehicleInfo.VehicleType.Bicycle)
         ////    {
         ////        if ((int)info.m_vehicleAI.GetOwnerID(vehicleID, ref instance2.m_vehicles.m_buffer[(int)vehicleID]).Citizen == (int)num1)
         ////        {
         ////            if (flag2)
         ////            {
         ////                target = InstanceID.Empty;
         ////                return Locale.Get("CITIZEN_STATUS_DRIVINGTO_OUTSIDE");
         ////            }
         ////            if ((int)num4 == (int)num2)
         ////            {
         ////                target = InstanceID.Empty;
         ////                return Locale.Get("CITIZEN_STATUS_DRIVINGTO_HOME");
         ////            }
         ////            if ((int)num4 == (int)num3)
         ////            {
         ////                target = InstanceID.Empty;
         ////                return Locale.Get(!flag1 ? "CITIZEN_STATUS_DRIVINGTO_WORK" : "CITIZEN_STATUS_DRIVINGTO_SCHOOL");
         ////            }
         ////            target = InstanceID.Empty;
         ////            target.Building = num4;
         ////            return Locale.Get("CITIZEN_STATUS_DRIVINGTO");
         ////        }
         ////    }
         ////    else if (info.m_class.m_service == ItemClass.Service.PublicTransport)
         ////    {
         ////        if ((data.m_flags & CitizenInstance.Flags.WaitingTaxi) != CitizenInstance.Flags.None)
         ////        {
         ////            target = InstanceID.Empty;
         ////            return Locale.Get("CITIZEN_STATUS_WAITING_TAXI");
         ////        }
         ////        if (flag2)
         ////        {
         ////            target = InstanceID.Empty;
         ////            return Locale.Get("CITIZEN_STATUS_TRAVELLINGTO_OUTSIDE");
         ////        }
         ////        if ((int)num4 == (int)num2)
         ////        {
         ////            target = InstanceID.Empty;
         ////            return Locale.Get("CITIZEN_STATUS_TRAVELLINGTO_HOME");
         ////        }
         ////        if ((int)num4 == (int)num3)
         ////        {
         ////            target = InstanceID.Empty;
         ////            return Locale.Get(!flag1 ? "CITIZEN_STATUS_TRAVELLINGTO_WORK" : "CITIZEN_STATUS_TRAVELLINGTO_SCHOOL");
         ////        }
         ////        target = InstanceID.Empty;
         ////        target.Building = num4;
         ////        return Locale.Get("CITIZEN_STATUS_TRAVELLINGTO");
         ////    }
         ////}
         ////if (flag2)
         ////{
         ////    target = InstanceID.Empty;
         ////    return Locale.Get("CITIZEN_STATUS_GOINGTO_OUTSIDE");
         ////}
         ////if ((int)num4 == (int)num2)
         ////{
         ////    if (flag3)
         ////    {
         ////        target = InstanceID.Empty;
         ////        return Locale.Get("CITIZEN_STATUS_AT_HOME");
         ////    }
         ////    target = InstanceID.Empty;
         ////    return Locale.Get("CITIZEN_STATUS_GOINGTO_HOME");
         ////}
         ////if ((int)num4 == (int)num3)
         ////{
         ////    if (flag3)
         ////    {
         ////        target = InstanceID.Empty;
         ////        return Locale.Get(!flag1 ? "CITIZEN_STATUS_AT_WORK" : "CITIZEN_STATUS_AT_SCHOOL");
         ////    }
         ////    target = InstanceID.Empty;
         ////    return Locale.Get(!flag1 ? "CITIZEN_STATUS_GOINGTO_WORK" : "CITIZEN_STATUS_GOINGTO_SCHOOL");
         ////}
         ////if (flag3)
         ////{
         ////    target = InstanceID.Empty;
         ////    target.Building = num4;
         ////    return Locale.Get("CITIZEN_STATUS_VISITING");
         ////}
         ////target = InstanceID.Empty;
         ////target.Building = num4;
         ////return Locale.Get("CITIZEN_STATUS_GOINGTO");
         return false;
     }
     ////target = InstanceID.Empty;
     ////return Locale.Get("CITIZEN_STATUS_CONFUSED");
     return true;
 }
 private ushort CheckCollisions(ushort instanceID, ref CitizenInstance citizenData, Segment3 segment, Vector3 min, Vector3 max, ushort otherID, ref Vehicle otherData, ref Vector3 pushAmount, ref float pushDivider)
 {
     VehicleInfo info = otherData.Info;
     if (info.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
     {
         return otherData.m_nextGridVehicle;
     }
     if ((otherData.m_flags & Vehicle.Flags.Transition) == Vehicle.Flags.None && (citizenData.m_flags & CitizenInstance.Flags.Transition) == CitizenInstance.Flags.None && (otherData.m_flags & Vehicle.Flags.Underground) != Vehicle.Flags.None != ((citizenData.m_flags & CitizenInstance.Flags.Underground) != CitizenInstance.Flags.None))
     {
         return otherData.m_nextGridVehicle;
     }
     Segment3 segment2 = otherData.m_segment;
     Vector3 vector = Vector3.Min (segment2.Min (), otherData.m_targetPos1);
     vector.x -= 1f;
     vector.z -= 1f;
     Vector3 vector2 = Vector3.Max (segment2.Max (), otherData.m_targetPos1);
     vector2.x += 1f;
     vector2.y += 1f;
     vector2.z += 1f;
     if (min.x < vector2.x && max.x > vector.x && min.z < vector2.z && max.z > vector.z && min.y < vector2.y && max.y > vector.y)
     {
         float num = this.m_info.m_radius + 1f;
         float num3;
         float t;
         float num2 = segment.DistanceSqr (segment2, out num3, out t);
         if (num2 < num * num)
         {
             float num4 = num - Mathf.Sqrt (num2);
             float num5 = 1f - num2 / (num * num);
             Vector3 a = segment.Position (num3 * 0.9f);
             Vector3 b = segment2.Position (t);
             a.y = 0f;
             b.y = 0f;
             Vector3 vector3 = Vector3.Normalize (a - b);
             Vector3 rhs = Vector3.Normalize (new Vector3 (segment.b.x - segment.a.x, 0f, segment.b.z - segment.a.z));
             Vector3 vector4 = new Vector3 (rhs.z, 0f, -rhs.x) * Mathf.Abs (Vector3.Dot (vector3, rhs) * 0.5f);
             if (Vector3.Dot (vector3, vector4) >= 0f)
             {
                 vector3 += vector4;
             }
             else
             {
                 vector3 -= vector4;
             }
             pushAmount += vector3 * (num4 * num5);
             pushDivider += num5;
         }
         float magnitude = otherData.GetLastFrameVelocity ().magnitude;
         if (magnitude > 0.1f)
         {
             float num6 = this.m_info.m_radius + 3f;
             segment2.a = segment2.b;
             segment2.b += Vector3.ClampMagnitude (((Vector3)otherData.m_targetPos1) - segment2.b, magnitude * 4f);
             num2 = segment.DistanceSqr (segment2, out num3, out t);
             if (num2 > num * num && num2 < num6 * num6)
             {
                 float num7 = num6 - Mathf.Sqrt (num2);
                 float num8 = 1f - num2 / (num6 * num6);
                 Vector3 a2 = segment.Position (num3 * 0.9f);
                 Vector3 b2 = segment2.Position (t);
                 a2.y = 0f;
                 b2.y = 0f;
                 Vector3 vector5 = a2 - b2;
                 pushAmount += vector5.normalized * (num7 * num8);
                 pushDivider += num8;
             }
         }
     }
     return otherData.m_nextGridVehicle;
 }
 protected override bool StartPathFind(ushort instanceID, ref CitizenInstance citizenData)
 {
     if (citizenData.m_citizen != 0u)
     {
         CitizenManager instance = Singleton<CitizenManager>.instance;
         VehicleManager instance2 = Singleton<VehicleManager>.instance;
         ushort vehicle = instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].m_vehicle;
         if (vehicle != 0)
         {
             VehicleInfo info = instance2.m_vehicles.m_buffer[(int)vehicle].Info;
             if (info != null)
             {
                 uint citizen = info.m_vehicleAI.GetOwnerID(vehicle, ref instance2.m_vehicles.m_buffer[(int)vehicle]).Citizen;
                 if (citizen == citizenData.m_citizen)
                 {
                     info.m_vehicleAI.SetTarget(vehicle, ref instance2.m_vehicles.m_buffer[(int)vehicle], 0);
                     return false;
                 }
                 else
                 {
                     instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].SetVehicle(citizenData.m_citizen, 0, 0u);
                 }
             }
             instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].SetVehicle(citizenData.m_citizen, 0, 0u);
             return false;
         }
     }
     if (citizenData.m_targetBuilding != 0)
     {
         VehicleInfo vehicleInfo = base.GetVehicleInfo(instanceID, ref citizenData, false);
         BuildingManager instance3 = Singleton<BuildingManager>.instance;
         BuildingInfo info2 = instance3.m_buildings.m_buffer[(int)citizenData.m_targetBuilding].Info;
         Randomizer randomizer = new Randomizer((int)instanceID << 8 | (int)citizenData.m_targetSeed);
         Vector3 vector;
         Vector3 endPos;
         Vector2 vector2;
         CitizenInstance.Flags flags;
         info2.m_buildingAI.CalculateUnspawnPosition(citizenData.m_targetBuilding, ref instance3.m_buildings.m_buffer[(int)citizenData.m_targetBuilding], ref randomizer, this.m_info, instanceID, out vector, out endPos, out vector2, out flags);
         if (!base.StartPathFind(instanceID, ref citizenData, citizenData.m_targetPos, endPos, vehicleInfo))
         {
             if (vehicleInfo == null)
             {
                 vehicleInfo = base.GetVehicleInfo(instanceID, ref citizenData, true);
                 var result = base.StartPathFind(instanceID, ref citizenData, citizenData.m_targetPos, endPos, vehicleInfo);
                 return result;
             }
             else
             {
                 return false;
             }
         }
         else
         {
             return true;
         }
     }
     return false;
 }
Example #10
0
        public bool ExtStartPathFind(ushort instanceID, ref CitizenInstance instanceData, ref ExtCitizenInstance extInstance, ref ExtCitizen extCitizen, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo, bool enableTransport, bool ignoreCost)
        {
#if DEBUG
            bool citDebug  = GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.CitizenId == instanceData.m_citizen;
            bool debug     = GlobalConfig.Instance.Debug.Switches[2] && citDebug;
            bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && citDebug;

            if (debug)
            {
                Log.Warning($"CustomCitizenAI.ExtStartPathFind({instanceID}): called for citizen {instanceData.m_citizen}, startPos={startPos}, endPos={endPos}, sourceBuilding={instanceData.m_sourceBuilding}, targetBuilding={instanceData.m_targetBuilding}, pathMode={extInstance.pathMode}, enableTransport={enableTransport}, ignoreCost={ignoreCost}");
            }
#endif

            // NON-STOCK CODE START
            CitizenManager citizenManager  = Singleton <CitizenManager> .instance;
            ushort         parkedVehicleId = citizenManager.m_citizens.m_buffer[instanceData.m_citizen].m_parkedVehicle;
            ushort         homeId          = citizenManager.m_citizens.m_buffer[instanceData.m_citizen].m_homeBuilding;
            CarUsagePolicy carUsageMode    = CarUsagePolicy.Allowed;

#if BENCHMARK
            using (var bm = new Benchmark(null, "ParkingAI.Preparation")) {
#endif
            if (Options.prohibitPocketCars)
            {
                switch (extInstance.pathMode)
                {
                case ExtPathMode.RequiresWalkingPathToParkedCar:
                case ExtPathMode.CalculatingWalkingPathToParkedCar:
                case ExtPathMode.WalkingToParkedCar:
                case ExtPathMode.ApproachingParkedCar:
                    if (parkedVehicleId == 0)
                    {
                        /*
                         * Parked vehicle not present but citizen wants to reach it
                         * -> Reset path mode
                         */
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode} but no parked vehicle present. Change to 'None'.");
                        }
#endif

                        extInstance.Reset();
                    }
                    else
                    {
                        /*
                         * Parked vehicle is present and citizen wants to reach it
                         * -> Prohibit car usage
                         */
#if DEBUG
                        if (fineDebug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode}.  Change to 'CalculatingWalkingPathToParkedCar'.");
                        }
#endif
                        extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToParkedCar;
                        carUsageMode         = CarUsagePolicy.Forbidden;
                    }
                    break;

                case ExtPathMode.RequiresWalkingPathToTarget:
                case ExtPathMode.CalculatingWalkingPathToTarget:
                case ExtPathMode.WalkingToTarget:
                    /*
                     * Citizen walks to target
                     * -> Reset path mode
                     */
#if DEBUG
                    if (fineDebug)
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode}. Change to 'CalculatingWalkingPathToTarget'.");
                    }
#endif
                    extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget;
                    carUsageMode         = CarUsagePolicy.Forbidden;
                    break;

                case ExtPathMode.RequiresCarPath:
                case ExtPathMode.RequiresMixedCarPathToTarget:
                case ExtPathMode.DrivingToTarget:
                case ExtPathMode.DrivingToKnownParkPos:
                case ExtPathMode.DrivingToAltParkPos:
                case ExtPathMode.CalculatingCarPathToAltParkPos:
                case ExtPathMode.CalculatingCarPathToKnownParkPos:
                case ExtPathMode.CalculatingCarPathToTarget:
                    if (parkedVehicleId == 0)
                    {
                        /*
                         * Citizen wants to drive to target but parked vehicle is not present
                         * -> Reset path mode
                         */

#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode} but no parked vehicle present. Change to 'None'.");
                        }
#endif

                        extInstance.Reset();
                    }
                    else
                    {
                        /*
                         * Citizen wants to drive to target and parked vehicle is present
                         * -> Force parked car usage
                         */

#if DEBUG
                        if (fineDebug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode}.  Change to 'RequiresCarPath'.");
                        }
#endif

                        extInstance.pathMode = ExtPathMode.RequiresCarPath;
                        carUsageMode         = CarUsagePolicy.ForcedParked;
                        startPos             = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;                   // force to start from the parked car
                    }
                    break;

                default:
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode}. Change to 'None'.");
                    }
#endif
                    extInstance.Reset();
                    break;
                }

                if (extInstance.pathMode == ExtPathMode.None)
                {
                    if ((instanceData.m_flags & CitizenInstance.Flags.OnTour) != CitizenInstance.Flags.None || ignoreCost)
                    {
                        /*
                         * Citizen is on a walking tour or is a mascot
                         * -> Prohibit car usage
                         */
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen ignores cost ({ignoreCost}) or is on a walking tour ({(instanceData.m_flags & CitizenInstance.Flags.OnTour) != CitizenInstance.Flags.None}): Setting path mode to 'CalculatingWalkingPathToTarget'");
                        }
#endif
                        carUsageMode         = CarUsagePolicy.Forbidden;
                        extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget;
                    }
                    else
                    {
                        /*
                         * Citizen is not on a walking tour and is not a mascot
                         * -> Check if citizen is located at an outside connection and make them obey Parking AI restrictions
                         */

                        if (instanceData.m_sourceBuilding != 0)
                        {
                            ItemClass.Service sourceBuildingService = Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_sourceBuilding].Info.m_class.m_service;

                            if (
                                (Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_sourceBuilding].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None &&
                                (startPos - Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_sourceBuilding].m_position).magnitude <= GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance
                                )
                            {
                                if (sourceBuildingService == ItemClass.Service.Road)
                                {
                                    if (vehicleInfo != null)
                                    {
                                        /*
                                         * Citizen is located at a road outside connection and can spawn a car
                                         * -> Force car usage
                                         */
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen is located at a road outside connection: Setting path mode to 'RequiresCarPath' and carUsageMode to 'ForcedPocket'");
                                        }
#endif
                                        extInstance.pathMode = ExtPathMode.RequiresCarPath;
                                        carUsageMode         = CarUsagePolicy.ForcedPocket;
                                    }
                                    else
                                    {
                                        /*
                                         * Citizen is located at a non-road outside connection and cannot spawn a car
                                         * -> Path-finding fails
                                         */
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen is located at a road outside connection but does not have a car template: ABORTING PATH-FINDING");
                                        }
#endif
                                        return(false);
                                    }
                                }
                                else
                                {
                                    /*
                                     * Citizen is located at a non-road outside connection
                                     * -> Prohibit car usage
                                     */
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen is located at a non-road outside connection: Setting path mode to 'CalculatingWalkingPathToTarget'");
                                    }
#endif
                                    extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget;
                                    carUsageMode         = CarUsagePolicy.Forbidden;
                                }
                            }
                        }
                    }
                }

                if ((carUsageMode == CarUsagePolicy.Allowed || carUsageMode == CarUsagePolicy.ForcedParked) && parkedVehicleId != 0)
                {
                    /*
                     * Reuse parked vehicle info
                     */
                    vehicleInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;

                    /*
                     * Check if the citizen should return their car back home
                     */
                    if (extInstance.pathMode == ExtPathMode.None && // initiating a new path
                        homeId != 0 &&                              // home building present
                        instanceData.m_targetBuilding == homeId     // current target is home
                        )
                    {
                        /*
                         * citizen travels back home
                         * -> check if their car should be returned
                         */
                        if ((extCitizen.lastTransportMode & ExtCitizen.ExtTransportMode.Car) != ExtCitizen.ExtTransportMode.None)
                        {
                            /*
                             * citizen travelled by car
                             * -> return car back home
                             */
                            extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar;
                            carUsageMode         = CarUsagePolicy.Forbidden;

#if DEBUG
                            if (fineDebug)
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen used their car before and is not at home. Forcing to walk to parked car.");
                            }
#endif
                        }
                        else
                        {
                            /*
                             * citizen travelled by other means of transport
                             * -> check distance between home and parked car. if too far away: force to take the car back home
                             */
                            float distHomeToParked = (Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position - Singleton <BuildingManager> .instance.m_buildings.m_buffer[homeId].m_position).magnitude;

                            if (distHomeToParked > GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToHome)
                            {
                                /*
                                 * force to take car back home
                                 */
                                extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar;
                                carUsageMode         = CarUsagePolicy.Forbidden;

#if DEBUG
                                if (fineDebug)
                                {
                                    Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen wants to go home and parked car is too far away ({distHomeToParked}). Forcing walking to parked car.");
                                }
#endif
                            }
                        }
                    }
                }

                /*
                 * The following holds:
                 * - pathMode is now either CalculatingWalkingPathToParkedCar, CalculatingWalkingPathToTarget, RequiresCarPath or None.
                 * - if pathMode is CalculatingWalkingPathToParkedCar or RequiresCarPath: parked car is present and citizen is not on a walking tour
                 * - carUsageMode is valid
                 * - if pathMode is RequiresCarPath: carUsageMode is either ForcedParked or ForcedPocket
                 */

                /*
                 * modify path-finding constraints (vehicleInfo, endPos) if citizen is forced to walk
                 */
                if (extInstance.pathMode == ExtPathMode.CalculatingWalkingPathToParkedCar || extInstance.pathMode == ExtPathMode.CalculatingWalkingPathToTarget)
                {
                    /*
                     * vehicle must not be used since we need a walking path to either
                     * 1. a parked car or
                     * 2. the target building
                     */

                    if (extInstance.pathMode == ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar)
                    {
                        /*
                         * walk to parked car
                         * -> end position is parked car
                         */
                        endPos = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;
#if DEBUG
                        if (fineDebug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen shall go to parked vehicle @ {endPos}");
                        }
#endif
                    }
                }
            }
#if BENCHMARK
        }
#endif
#if DEBUG
            if (fineDebug)
            {
                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen is allowed to drive their car? {carUsageMode}");
            }
#endif
            // NON-STOCK CODE END

            /*
             * semi-stock code: determine path-finding parameters (laneTypes, vehicleTypes, extVehicleType, etc.)
             */
            NetInfo.LaneType laneTypes           = NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleTypes = VehicleInfo.VehicleType.None;
            bool randomParking            = false;
            bool combustionEngine         = false;
            ExtVehicleType extVehicleType = ExtVehicleType.None;
            if (vehicleInfo != null)
            {
                if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi)
                {
                    if ((instanceData.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)
                        {
                            laneTypes     |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                            vehicleTypes  |= vehicleInfo.m_vehicleType;
                            extVehicleType = ExtVehicleType.Taxi;                             // NON-STOCK CODE
                            // NON-STOCK CODE START
                            if (Options.prohibitPocketCars)
                            {
                                extInstance.pathMode = ExtPathMode.TaxiToTarget;
                            }
                            // NON-STOCK CODE END
                        }
                    }
                }
                else
                // NON-STOCK CODE START
                if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Car)
                {
                    if (carUsageMode != CarUsagePolicy.Forbidden)
                    {
                        extVehicleType   = ExtVehicleType.PassengerCar;
                        laneTypes       |= NetInfo.LaneType.Vehicle;
                        vehicleTypes    |= vehicleInfo.m_vehicleType;
                        combustionEngine = vehicleInfo.m_class.m_subService == ItemClass.SubService.ResidentialLow;
                    }
                }
                else if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                {
                    extVehicleType = ExtVehicleType.Bicycle;
                    laneTypes     |= NetInfo.LaneType.Vehicle;
                    vehicleTypes  |= vehicleInfo.m_vehicleType;
                }
                // NON-STOCK CODE END
            }

            // NON-STOCK CODE START
            ExtPathType extPathType   = ExtPathType.None;
            PathUnit.Position endPosA = default(PathUnit.Position);
            bool calculateEndPos      = true;
            bool allowRandomParking   = true;
#if BENCHMARK
            using (var bm = new Benchmark(null, "ParkingAI.Main")) {
#endif
            if (Options.prohibitPocketCars)
            {
                // Parking AI

                if (extInstance.pathMode == ExtCitizenInstance.ExtPathMode.RequiresCarPath)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Setting startPos={startPos} for citizen instance {instanceID}. CurrentDepartureMode={extInstance.pathMode}");
                    }
#endif

                    if (
                        instanceData.m_targetBuilding == 0 ||
                        (Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None
                        )
                    {
                        /*
                         * the citizen is starting their journey and the target is not an outside connection
                         * -> find a suitable parking space near the target
                         */

#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Finding parking space at target for citizen instance {instanceID}. CurrentDepartureMode={extInstance.pathMode} parkedVehicleId={parkedVehicleId}");
                        }
#endif

                        // find a parking space in the vicinity of the target
                        bool    calcEndPos;
                        Vector3 parkPos;
                        if (
                            AdvancedParkingManager.Instance.FindParkingSpaceForCitizen(endPos, vehicleInfo, ref extInstance, homeId, instanceData.m_targetBuilding == homeId, 0, false, out parkPos, ref endPosA, out calcEndPos) &&
                            extInstance.CalculateReturnPath(parkPos, endPos)
                            )
                        {
                            // success
                            extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingCarPathToKnownParkPos;
                            calculateEndPos      = calcEndPos;                      // if true, the end path position still needs to be calculated
                            allowRandomParking   = false;                           // find a direct path to the calculated parking position
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Finding known parking space for citizen instance {instanceID}, parked vehicle {parkedVehicleId} succeeded and return path {extInstance.returnPathId} ({extInstance.returnPathState}) is calculating. PathMode={extInstance.pathMode}");
                            }
#endif

                            /*if (! extInstance.CalculateReturnPath(parkPos, endPos)) {
                             *      // TODO retry?
                             *      if (debug)
                             *              Log._Debug($"CustomCitizenAI.CustomStartPathFind: [PFFAIL] Could not calculate return path for citizen instance {instanceID}, parked vehicle {parkedVehicleId}. Calling OnPathFindFailed.");
                             *      CustomHumanAI.OnPathFindFailure(extInstance);
                             *      return false;
                             * }*/
                        }
                    }

                    if (extInstance.pathMode == ExtPathMode.RequiresCarPath)
                    {
                        /*
                         * no known parking space found (pathMode has not been updated in the block above)
                         * -> calculate direct path to target
                         */
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} is still at CurrentPathMode={extInstance.pathMode} (no parking space found?). Setting it to CalculatingCarPath. parkedVehicleId={parkedVehicleId}");
                        }
#endif
                        extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingCarPathToTarget;
                    }
                }

                /*
                 * determine path type from path mode
                 */
                extPathType = extInstance.GetPathType();

                /*
                 * the following holds:
                 * - pathMode is now either CalculatingWalkingPathToParkedCar, CalculatingWalkingPathToTarget, CalculatingCarPathToTarget, CalculatingCarPathToKnownParkPos or None.
                 */
            }
#if BENCHMARK
        }
#endif

            /*
             * enable random parking if exact parking space was not calculated yet
             */
            if (extVehicleType == ExtVehicleType.PassengerCar || extVehicleType == ExtVehicleType.Bicycle)
            {
                if (allowRandomParking &&
                    instanceData.m_targetBuilding != 0 &&
                    (
                        Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office ||
                        (instanceData.m_flags & CitizenInstance.Flags.TargetIsNode) != 0
                    ))
                {
                    randomParking = true;
                }
            }
            // NON-STOCK CODE END

            /*
             * determine the path position of the parked vehicle
             */
            PathUnit.Position parkedVehiclePathPos = default(PathUnit.Position);
            if (parkedVehicleId != 0 && extVehicleType == ExtVehicleType.PassengerCar)
            {
                Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;
                CustomPathManager.FindPathPositionWithSpiralLoop(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, false, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out parkedVehiclePathPos);
            }
            bool allowUnderground = (instanceData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;

#if DEBUG
            if (debug)
            {
                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Requesting path-finding for citizen instance {instanceID}, citizen {instanceData.m_citizen}, extVehicleType={extVehicleType}, extPathType={extPathType}, startPos={startPos}, endPos={endPos}, sourceBuilding={instanceData.m_sourceBuilding}, targetBuilding={instanceData.m_targetBuilding} pathMode={extInstance.pathMode}");
            }
#endif

            /*
             * determine start & end path positions
             */
            bool foundEndPos   = !calculateEndPos || FindPathPosition(instanceID, ref instanceData, endPos, Options.prohibitPocketCars && (instanceData.m_targetBuilding == 0 || (Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None) ? NetInfo.LaneType.Pedestrian : laneTypes, vehicleTypes, false, out endPosA);         // NON-STOCK CODE: with Parking AI enabled, the end position must be a pedestrian position
            bool foundStartPos = false;
            PathUnit.Position startPosA;

            if (Options.prohibitPocketCars && (extInstance.pathMode == ExtPathMode.CalculatingCarPathToTarget || extInstance.pathMode == ExtPathMode.CalculatingCarPathToKnownParkPos))
            {
                /*
                 * citizen will enter their car now
                 * -> find a road start position
                 */
                foundStartPos = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, laneTypes & ~NetInfo.LaneType.Pedestrian, vehicleTypes, allowUnderground, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out startPosA);
            }
            else
            {
                foundStartPos = FindPathPosition(instanceID, ref instanceData, startPos, laneTypes, vehicleTypes, allowUnderground, out startPosA);
            }

            /*
             * start path-finding
             */
            if (foundStartPos &&            // TODO probably fails if vehicle is parked too far away from road
                foundEndPos                 // NON-STOCK CODE
                )
            {
                if (enableTransport)
                {
                    /*
                     * public transport usage is allowed for this path
                     */
                    if ((instanceData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)
                    {
                        /*
                         * citizen may use public transport
                         */
                        laneTypes |= NetInfo.LaneType.PublicTransport;

                        uint citizenId = instanceData.m_citizen;
                        if (citizenId != 0u && (citizenManager.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Evacuating) != Citizen.Flags.None)
                        {
                            laneTypes |= NetInfo.LaneType.EvacuationTransport;
                        }
                    }
                    else if (Options.prohibitPocketCars)                         // TODO check for incoming connection

                    /*
                     * citizen tried to use public transport but waiting time was too long
                     * -> add public transport demand for source building
                     */
                    {
                        if (instanceData.m_sourceBuilding != 0)
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} cannot uses public transport from building {instanceData.m_sourceBuilding} to {instanceData.m_targetBuilding}. Incrementing public transport demand.");
                            }
#endif
                            ExtBuildingManager.Instance.ExtBuildings[instanceData.m_sourceBuilding].AddPublicTransportDemand((uint)GlobalConfig.Instance.ParkingAI.PublicTransportDemandWaitingIncrement, true);
                        }
                    }
                }

                PathUnit.Position dummyPathPos = default(PathUnit.Position);
                uint path;
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = extPathType;
                args.extVehicleType      = extVehicleType;
                args.vehicleId           = 0;
                args.spawned             = (instanceData.m_flags & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None;
                args.buildIndex          = Singleton <SimulationManager> .instance.m_currentBuildIndex;
                args.startPosA           = startPosA;
                args.startPosB           = dummyPathPos;
                args.endPosA             = endPosA;
                args.endPosB             = dummyPathPos;
                args.vehiclePosition     = parkedVehiclePathPos;
                args.laneTypes           = laneTypes;
                args.vehicleTypes        = vehicleTypes;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = false;
                args.hasCombustionEngine = combustionEngine;
                args.ignoreBlocked       = false;
                args.ignoreFlooded       = false;
                args.ignoreCosts         = ignoreCost;
                args.randomParking       = randomParking;
                args.stablePath          = false;
                args.skipQueue           = false;

                if ((instanceData.m_flags & CitizenInstance.Flags.OnTour) != 0)
                {
                    args.stablePath = true;
                    args.maxLength  = 160000f;
                    //args.laneTypes &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                }
                else
                {
                    args.stablePath = false;
                    args.maxLength  = 20000f;
                }

                bool res = CustomPathManager._instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args);
                // NON-STOCK CODE END

                if (res)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Path-finding starts for citizen instance {instanceID}, path={path}, extVehicleType={extVehicleType}, extPathType={extPathType}, startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, laneType={laneTypes}, vehicleType={vehicleTypes}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}, vehiclePos.m_segment={parkedVehiclePathPos.m_segment}, vehiclePos.m_lane={parkedVehiclePathPos.m_lane}, vehiclePos.m_offset={parkedVehiclePathPos.m_offset}");
                    }
#endif

                    if (instanceData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(instanceData.m_path);
                    }
                    instanceData.m_path   = path;
                    instanceData.m_flags |= CitizenInstance.Flags.WaitingPath;
                    return(true);
                }
            }

#if DEBUG
            if (Options.prohibitPocketCars)
            {
                if (debug)
                {
                    Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): CustomCitizenAI.CustomStartPathFind: [PFFAIL] failed for citizen instance {instanceID} (CurrentPathMode={extInstance.pathMode}). startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, startPosA.offset={startPosA.m_offset}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}, endPosA.offset={endPosA.m_offset}, foundStartPos={foundStartPos}, foundEndPos={foundEndPos}");
                }
            }
#endif
            return(false);
        }
        public string CustomGetLocalizedStatus(ushort instanceID, ref CitizenInstance data, out InstanceID target)
        {
            if ((data.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None)
            {
                target = InstanceID.Empty;
                return(Locale.Get("CITIZEN_STATUS_CONFUSED"));
            }
            CitizenManager citMan    = Singleton <CitizenManager> .instance;
            uint           citizenId = data.m_citizen;
            bool           isStudent = false;
            ushort         homeId    = 0;
            ushort         workId    = 0;
            ushort         vehicleId = 0;

            if (citizenId != 0u)
            {
                homeId    = citMan.m_citizens.m_buffer[citizenId].m_homeBuilding;
                workId    = citMan.m_citizens.m_buffer[citizenId].m_workBuilding;
                vehicleId = citMan.m_citizens.m_buffer[citizenId].m_vehicle;
                isStudent = ((citMan.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Student) != Citizen.Flags.None);
            }
            ushort targetBuilding = data.m_targetBuilding;

            if (targetBuilding == 0)
            {
                target = InstanceID.Empty;
                return(Locale.Get("CITIZEN_STATUS_CONFUSED"));
            }
            bool   isOutsideConnection = (Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetBuilding].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None;
            bool   hangsAround         = data.m_path == 0u && (data.m_flags & CitizenInstance.Flags.HangAround) != CitizenInstance.Flags.None;
            String ret = "";

            if (vehicleId != 0)
            {
                VehicleManager instance2 = Singleton <VehicleManager> .instance;
                VehicleInfo    info      = instance2.m_vehicles.m_buffer[(int)vehicleId].Info;
                if (info.m_class.m_service == ItemClass.Service.Residential && info.m_vehicleType != VehicleInfo.VehicleType.Bicycle)
                {
                    if (info.m_vehicleAI.GetOwnerID(vehicleId, ref instance2.m_vehicles.m_buffer[(int)vehicleId]).Citizen == citizenId)
                    {
                        if (isOutsideConnection)
                        {
                            target = InstanceID.Empty;
                            return(Locale.Get("CITIZEN_STATUS_DRIVINGTO_OUTSIDE"));
                        }

                        if (targetBuilding == homeId)
                        {
                            target = InstanceID.Empty;
                            return(Locale.Get("CITIZEN_STATUS_DRIVINGTO_HOME"));
                        }
                        else if (targetBuilding == workId)
                        {
                            target = InstanceID.Empty;
                            return(Locale.Get((!isStudent) ? "CITIZEN_STATUS_DRIVINGTO_WORK" : "CITIZEN_STATUS_DRIVINGTO_SCHOOL"));
                        }
                        else
                        {
                            target          = InstanceID.Empty;
                            target.Building = targetBuilding;
                            return(Locale.Get("CITIZEN_STATUS_DRIVINGTO"));
                        }
                    }
                }
                else if (info.m_class.m_service == ItemClass.Service.PublicTransport || info.m_class.m_service == ItemClass.Service.Disaster)
                {
                    if ((data.m_flags & CitizenInstance.Flags.WaitingTaxi) != CitizenInstance.Flags.None)
                    {
                        target = InstanceID.Empty;
                        return(Locale.Get("CITIZEN_STATUS_WAITING_TAXI"));
                    }
                    if (isOutsideConnection)
                    {
                        target = InstanceID.Empty;
                        return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO_OUTSIDE"));
                    }
                    if (targetBuilding == homeId)
                    {
                        target = InstanceID.Empty;
                        return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO_HOME"));
                    }
                    if (targetBuilding == workId)
                    {
                        target = InstanceID.Empty;
                        return(Locale.Get((!isStudent) ? "CITIZEN_STATUS_TRAVELLINGTO_WORK" : "CITIZEN_STATUS_TRAVELLINGTO_SCHOOL"));
                    }
                    target          = InstanceID.Empty;
                    target.Building = targetBuilding;
                    return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO"));
                }
            }
            if (isOutsideConnection)
            {
                target = InstanceID.Empty;
                return(Locale.Get("CITIZEN_STATUS_GOINGTO_OUTSIDE"));
            }

            if (targetBuilding == homeId)
            {
                if (hangsAround)
                {
                    target = InstanceID.Empty;
                    return(Locale.Get("CITIZEN_STATUS_AT_HOME"));
                }
                target = InstanceID.Empty;
                ret    = Locale.Get("CITIZEN_STATUS_GOINGTO_HOME");
            }
            else if (targetBuilding == workId)
            {
                if (hangsAround)
                {
                    target = InstanceID.Empty;
                    return(Locale.Get((!isStudent) ? "CITIZEN_STATUS_AT_WORK" : "CITIZEN_STATUS_AT_SCHOOL"));
                }
                target = InstanceID.Empty;
                ret    = Locale.Get((!isStudent) ? "CITIZEN_STATUS_GOINGTO_WORK" : "CITIZEN_STATUS_GOINGTO_SCHOOL");
            }
            else
            {
                if (hangsAround)
                {
                    target          = InstanceID.Empty;
                    target.Building = targetBuilding;
                    return(Locale.Get("CITIZEN_STATUS_VISITING"));
                }
                target          = InstanceID.Empty;
                target.Building = targetBuilding;
                ret             = Locale.Get("CITIZEN_STATUS_GOINGTO");
            }

            // NON-STOCK CODE START
            if (Options.prohibitPocketCars)
            {
                ret = AdvancedParkingManager.Instance.EnrichLocalizedCitizenStatus(ret, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID]);
            }
            // NON-STOCK CODE END
            return(ret);
        }
		// CitizenAI
		public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo) {
			NetInfo.LaneType laneType = NetInfo.LaneType.Pedestrian;
			VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
			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);
							vehicleType |= vehicleInfo.m_vehicleType;
						}
					}
				} else {
					laneType |= NetInfo.LaneType.Vehicle;
					vehicleType |= vehicleInfo.m_vehicleType;
				}
			}
			PathUnit.Position vehiclePosition = default(PathUnit.Position);
			ushort parkedVehicle = Singleton<CitizenManager>.instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle;
			if (parkedVehicle != 0) {
				Vector3 position = Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position;
				PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition);
			}
			bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;
			PathUnit.Position startPosA;
			PathUnit.Position endPosA;
			if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) &&
				this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA)) {

				// NON-STOCK CODE START //
				Citizen.Wealth wealthLevel = Singleton<CitizenManager>.instance.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel;

				byte districtId = Singleton<DistrictManager>.instance.GetDistrict(startPos);
				DistrictPolicies.Services servicePolicies = Singleton<DistrictManager>.instance.m_districts.m_buffer[(int)districtId].m_servicePolicies;
				int transportUsageProb = (servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None ? FREE_TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel] : TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel];

				//bool mayUseTransport = false;
				if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None) { // STOCK CODE
					if (vehicleInfo == null || (instanceID % 100)+1 <= transportUsageProb) {
						laneType |= NetInfo.LaneType.PublicTransport; // STOCK CODE
						//mayUseTransport = true;
						//Log._Debug($"CustomCitizenAI: citizen {instanceID} can use public transport");
					}
				}
				// NON-STOCK CODE END //
				PathUnit.Position position2 = default(PathUnit.Position);
				uint path;
				// NON-STOCK CODE START //
				ExtVehicleType? extVehicleType = null;
				if (vehicleInfo != null)
					extVehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicleInfo(vehicleInfo);
				//Log._Debug($"CustomCitizenAI: citizen instance {instanceID}, id {citizenData.m_citizen}. {vehicleType} {extVehicleType} mayUseTransport={mayUseTransport} wealthLevel={wealthLevel}");
                bool res = false;
				if (Options.disableSomething5 || extVehicleType == null)
				// NON-STOCK CODE END //
					res = Singleton<CustomPathManager>.instance.CreatePath(out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, false);
				// NON-STOCK CODE START //
				else
					res = Singleton<CustomPathManager>.instance.CreatePath((ExtVehicleType)extVehicleType, out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false);
				// NON-STOCK CODE END //
				if (res) {
					if (citizenData.m_path != 0u) {
						Singleton<PathManager>.instance.ReleasePath(citizenData.m_path);
					}
					citizenData.m_path = path;
					citizenData.m_flags |= CitizenInstance.Flags.WaitingPath;
					return true;
				}
			}
			return false;
		}
Example #13
0
 private static ushort CheckCitizen(ushort vehicleID, ref Vehicle vehicleData, Segment3 segment, float lastLen, float nextLen, ref float maxSpeed, ref bool blocked, float maxBraking, ushort otherID, ref CitizenInstance otherData, Vector3 min, Vector3 max)
 {
     Log.Error("CustomCarAI.CheckCitizen called");
     return(0);
 }
        public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceCar)
        {
            if (citizenData.m_citizen == 0u)
            {
                return(null);
            }

            // NON-STOCK CODE START
            bool forceTaxi = false;

            if (Options.prohibitPocketCars)
            {
                if (ExtCitizenInstanceManager.Instance.ExtInstances[instanceID].pathMode == ExtPathMode.TaxiToTarget)
                {
                    forceTaxi = true;
                }
            }
            // NON-STOCK CODE END

            Citizen.AgeGroup ageGroup = CustomCitizenAI.GetAgeGroup(citizenData.Info.m_agePhase);

            int carProb;
            int bikeProb;
            int taxiProb;

            // NON-STOCK CODE START
            if (forceTaxi)
            {
                carProb  = 0;
                bikeProb = 0;
                taxiProb = 100;
            }
            else
            // NON-STOCK CODE END
            if (forceCar || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None)
            {
                carProb  = 100;
                bikeProb = 0;
                taxiProb = 0;
            }
            else
            {
                carProb  = GetCarProbability(instanceID, ref citizenData, ageGroup);
                bikeProb = GetBikeProbability(instanceID, ref citizenData, ageGroup);
                taxiProb = GetTaxiProbability(instanceID, ref citizenData, ageGroup);
            }
            Randomizer randomizer = new Randomizer(citizenData.m_citizen);
            bool       useCar     = randomizer.Int32(100u) < carProb;
            bool       useBike    = randomizer.Int32(100u) < bikeProb;
            bool       useTaxi    = randomizer.Int32(100u) < taxiProb;

            ItemClass.Service    service    = ItemClass.Service.Residential;
            ItemClass.SubService subService = ItemClass.SubService.ResidentialLow;
            if (!useCar && useTaxi)
            {
                service    = ItemClass.Service.PublicTransport;
                subService = ItemClass.SubService.PublicTransportTaxi;
            }
            // NON-STOCK CODE START
            VehicleInfo carInfo = null;

            if (Options.prohibitPocketCars && useCar && !useTaxi)
            {
                ushort parkedVehicleId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
                if (parkedVehicleId != 0)
                {
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomResidentAI.GetVehicleInfo: Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. Reusing vehicle info.");
                    }
#endif
                    carInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
                }
            }
            if (carInfo == null && (useCar || useTaxi))
            {
                // NON-STOCK CODE END
                carInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref randomizer, service, subService, ItemClass.Level.Level1);
            }

            VehicleInfo bikeInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref randomizer, ItemClass.Service.Residential, ItemClass.SubService.ResidentialHigh, (ageGroup != Citizen.AgeGroup.Child)?ItemClass.Level.Level2 : ItemClass.Level.Level1);

            if (useBike && bikeInfo != null)
            {
                return(bikeInfo);
            }
            if ((useCar || useTaxi) && carInfo != null)
            {
                return(carInfo);
            }
            return(null);
        }
Example #15
0
        public VehicleInfo CustomGetVehicleInfo(ushort instanceId,
                                                ref CitizenInstance citizenData,
                                                bool forceCar,
                                                out VehicleInfo trailer)
        {
#if DEBUG
            bool citizenDebug = (DebugSettings.CitizenInstanceId == 0 ||
                                 DebugSettings.CitizenInstanceId == instanceId) &&
                                (DebugSettings.CitizenId == 0 ||
                                 DebugSettings.CitizenId == citizenData.m_citizen) &&
                                (DebugSettings.SourceBuildingId == 0 ||
                                 DebugSettings.SourceBuildingId == citizenData.m_sourceBuilding) &&
                                (DebugSettings.TargetBuildingId == 0 ||
                                 DebugSettings.TargetBuildingId == citizenData.m_targetBuilding);
            bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && citizenDebug;
#else
            var logParkingAi = false;
#endif

            trailer = null;

            if (citizenData.m_citizen == 0u)
            {
                return(null);
            }

            // NON-STOCK CODE START
            bool forceTaxi = false;
            if (Options.parkingAI)
            {
                if (ExtCitizenInstanceManager.Instance.ExtInstances[instanceId].pathMode == ExtPathMode.TaxiToTarget)
                {
                    forceTaxi = true;
                }
            }

            // NON-STOCK CODE END
            Citizen.Wealth wealthLevel = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel;
            int            carProb;
            int            bikeProb;
            int            taxiProb;

            // NON-STOCK CODE START
            if (forceTaxi)
            {
                carProb  = 0;
                bikeProb = 0;
                taxiProb = 100;
            }
            else   // NON-STOCK CODE END
            if (forceCar || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None)
            {
                carProb  = 100;
                bikeProb = 0;
                taxiProb = 0;
            }
            else
            {
                carProb  = GetCarProbability();
                bikeProb = GetBikeProbability();
                taxiProb = GetTaxiProbability();
            }

            Randomizer randomizer     = new Randomizer(citizenData.m_citizen);
            bool       useCar         = randomizer.Int32(100u) < carProb;
            bool       useBike        = !useCar && randomizer.Int32(100u) < bikeProb;
            bool       useTaxi        = !useCar && !useBike && randomizer.Int32(100u) < taxiProb;
            bool       useCamper      = false;
            bool       useElectricCar = false;

            if (useCar)
            {
                int camperProb = GetCamperProbability(wealthLevel);
                useCamper = randomizer.Int32(100u) < camperProb;

                if (!useCamper)
                {
                    int electricProb = GetElectricCarProbability(wealthLevel);
                    useElectricCar = randomizer.Int32(100u) < electricProb;
                }
            }

            ItemClass.Service    service    = ItemClass.Service.Residential;
            ItemClass.SubService subService = useElectricCar
                                 ? ItemClass.SubService.ResidentialLowEco
                                 : ItemClass.SubService.ResidentialLow;
            if (useTaxi)
            {
                service    = ItemClass.Service.PublicTransport;
                subService = ItemClass.SubService.PublicTransportTaxi;
            }

            // NON-STOCK CODE START
            VehicleInfo carInfo = null;
            if (Options.parkingAI && useCar && !useTaxi)
            {
                ushort parkedVehicleId = Singleton <CitizenManager>
                                         .instance.m_citizens.m_buffer[citizenData.m_citizen]
                                         .m_parkedVehicle;
                if (parkedVehicleId != 0)
                {
                    Log._DebugIf(
                        logParkingAi,
                        () => $"CustomTouristAI.CustomGetVehicleInfo({instanceId}): " +
                        $"Citizen instance {instanceId} owns a parked vehicle {parkedVehicleId}. " +
                        $"Reusing vehicle info.");
                    carInfo = Singleton <VehicleManager>
                              .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
                }
            }

            if (carInfo == null && (useCar || useTaxi))
            {
                // NON-STOCK CODE END
                if (useCamper)
                {
                    Randomizer randomizer2 = randomizer;
                    carInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(
                        ref randomizer,
                        service,
                        subService,
                        ItemClass.Level.Level2);

                    if (carInfo == null || carInfo.m_vehicleAI is CarTrailerAI)
                    {
                        trailer    = carInfo;
                        randomizer = randomizer2;
                        carInfo    = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(
                            ref randomizer,
                            service,
                            subService,
                            ItemClass.Level.Level1);
                    }
                }
                else
                {
                    carInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(
                        ref randomizer,
                        service,
                        subService,
                        ItemClass.Level.Level1);
                }
            }

            if (useBike)
            {
                VehicleInfo bikeInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(
                    ref randomizer,
                    ItemClass.Service.Residential,
                    ItemClass.SubService.ResidentialHigh,
                    ItemClass.Level.Level2);

                if (bikeInfo != null)
                {
                    return(bikeInfo);
                }
            }

            if ((useCar || useTaxi) && carInfo != null)
            {
                return(carInfo);
            }

            return(null);
        }
 private void ReleaseCitizenInstanceImplementation(ushort instanceId, ref CitizenInstance instanceData)
 {
     Log.Error("CustomCitizenManager.ReleaseCitizenInstanceImplementation called.");
 }
 private int GetElectricCarProbability(ushort instanceID, ref CitizenInstance citizenData, Citizen.AgePhase agePhase)
 {
     Log.Error("CustomResidentAI.GetElectricCarProbability called!");
     return(20);
 }
        public static bool RenderInstance(ref CitizenInstance instance, RenderManager.CameraInfo cameraInfo, ushort instanceID)
        {
            if ((instance.m_flags & CitizenInstance.Flags.Character) == CitizenInstance.Flags.None)
                return false;
            CitizenInfo info = instance.Info;
            if ((UnityEngine.Object)info == (UnityEngine.Object)null)
                return false;
            uint num = Singleton<SimulationManager>.instance.m_referenceFrameIndex - ((uint)instanceID << 4) / 65536U;
            CitizenInstance.Frame frameData1 = instance.GetFrameData(num - 32U);
            float maxDistance = Mathf.Min(RenderManager.LevelOfDetailFactor * 800f, info.m_maxRenderDistance + cameraInfo.m_height * 0.5f);
            if (!cameraInfo.CheckRenderDistance(frameData1.m_position, maxDistance) || !cameraInfo.Intersect(frameData1.m_position, 10f))
                return false;

            CitizenInstance.Frame frameData2 = instance.GetFrameData(num - 16U);
            float t = (float)(((double)(num & 15U) + (double)Singleton<SimulationManager>.instance.m_referenceTimer) * (1.0 / 16.0));
            bool flag1 = frameData2.m_underground && frameData1.m_underground;
            bool flag2 = frameData2.m_insideBuilding && frameData1.m_insideBuilding;
            bool flag3 = frameData2.m_transition || frameData1.m_transition;
            if (flag2 && !flag3 || flag1 && !flag3 && (cameraInfo.m_layerMask & 1 << Singleton<CitizenManager>.instance.m_undergroundLayer) == 0)
                return false;
            //begin mod
            info = GetUpdatedInfo(instance, instanceID);
            //end mod
            Vector3 vector3 = new Bezier3()
            {
                a = frameData1.m_position,
                b = (frameData1.m_position + frameData1.m_velocity * 0.333f),
                c = (frameData2.m_position - frameData2.m_velocity * 0.333f),
                d = frameData2.m_position
            }.Position(t);
            Quaternion quaternion = Quaternion.Lerp(frameData1.m_rotation, frameData2.m_rotation, t);
            Color color = info.m_citizenAI.GetColor(instanceID, ref instance, Singleton<InfoManager>.instance.CurrentMode);
            if (cameraInfo.CheckRenderDistance(vector3, info.m_lodRenderDistance))
            {
                InstanceID id = InstanceID.Empty;
                id.CitizenInstance = instanceID;
                CitizenInfo citizenInfo = info.ObtainPrefabInstance<CitizenInfo>(id, (int)byte.MaxValue);
                if ((UnityEngine.Object)citizenInfo != (UnityEngine.Object)null)
                {
                    Vector3 velocity = Vector3.Lerp(frameData1.m_velocity, frameData2.m_velocity, t);
                    //begin mod
                    if (info.m_subCulture == Citizen.SubCulture.Generic)
                    {
                        citizenInfo.m_citizenAI.SetRenderParameters(cameraInfo, instanceID, ref instance, vector3,
                            quaternion, velocity, color,
                            (flag1 || flag3) &&
                            (cameraInfo.m_layerMask & 1 << Singleton<CitizenManager>.instance.m_undergroundLayer) != 0);
                    }
                    else
                    {
                        citizenInfo.SetRenderParameters(vector3, quaternion, velocity, color, 5,
                            (flag1 || flag3) &&
                            (cameraInfo.m_layerMask & 1 << Singleton<CitizenManager>.instance.m_undergroundLayer) != 0);
                    }
                    //end mod
                    return true;
                }
            }
            if (flag1 || flag3)
            {
                info.m_undergroundLodLocations[info.m_undergroundLodCount].SetTRS(vector3, quaternion, Vector3.one);
                info.m_undergroundLodColors[info.m_undergroundLodCount] = color;
                info.m_undergroundLodMin = Vector3.Min(info.m_undergroundLodMin, vector3);
                info.m_undergroundLodMax = Vector3.Max(info.m_undergroundLodMax, vector3);
                if (++info.m_undergroundLodCount == info.m_undergroundLodLocations.Length)
                    CitizenInstance.RenderUndergroundLod(cameraInfo, info);
            }
            if (!flag1 || flag3)
            {
                info.m_lodLocations[info.m_lodCount].SetTRS(vector3, quaternion, Vector3.one);
                info.m_lodColors[info.m_lodCount] = color;
                info.m_lodMin = Vector3.Min(info.m_lodMin, vector3);
                info.m_lodMax = Vector3.Max(info.m_lodMax, vector3);
                if (++info.m_lodCount == info.m_lodLocations.Length)
                    CitizenInstance.RenderLod(cameraInfo, info);
            }
            return true;
        }
        } // end RemoveWorkerBuilding

        /// <summary>
        /// Promote the workers to fit the education bill better.
        /// </summary>
        /// <param name="buildingID"></param>
        /// <param name="data"></param>
        /// <param name="workersRequired"></param>
        /// <param name="instance"></param>
        /// <param name="citizenUnitArray"></param>
        /// <param name="citizenArray"></param>
        private static void PromoteWorkers(ushort buildingID, ref Building data, ref int[] workersRequired)
        {
            if (workersRequired[0] == 0 && workersRequired[1] == 0 && workersRequired[2] == 0 && workersRequired[3] == 0)
            {
                // We are okay with employees, or it's residential. Return
                return;
            }
            //Debugging.writeDebugToFile(buildingID + ". Workers needed: " + workersRequired[0] + ", " + workersRequired[1] + ", " + workersRequired[2] + ", " + workersRequired[3]);

            // Crime and garbage are reset
            data.m_crimeBuffer   = 0;
            data.m_garbageBuffer = 0;

            int  loopCounter  = 0;
            uint previousUnit = data.m_citizenUnits;
            uint currentUnit  = data.m_citizenUnits;

            while (currentUnit != 0u)
            {
                // If this unit matches what we one, send the citizens away or remove citzens
                uint nextUnit = citizenUnitArray[currentUnit].m_nextUnit;

                // Only think about removing if it matches the flag
                if ((ushort)(CitizenUnit.Flags.Work & citizenUnitArray[currentUnit].m_flags) != 0)
                {
                    // Send unit away like empty building
                    for (int i = 0; i < 5; i++)
                    {
                        uint citizen = citizenUnitArray[(int)((UIntPtr)currentUnit)].GetCitizen(i);
                        if (citizen != 0u)
                        {
                            // Do not shift back where possible. There should be enough staff turnover that the spaces aren't worth the intensive checking
                            int             citizenIndex         = (int)((UIntPtr)citizen);
                            ushort          citizenInstanceIndex = citizenArray[citizenIndex].m_instance;
                            CitizenInstance citData = citizenManager.m_instances.m_buffer[(int)citizenInstanceIndex];

                            // Get education level. Perform checks
                            Citizen cit       = citizenArray[(int)((UIntPtr)citizen)];
                            int     education = (int)cit.EducationLevel;

                            // -ve workersRequired means excess workers. Ignoring three schools
                            // Checks if the citizen should be promoted or fire
                            // Remove excess 0, 1, 2. However, give 20 - 50 % change to go up an education level. Don't touch lvl 3 educated (they'll disappear fast given the chance)
                            if ((cit.EducationLevel != Citizen.Education.ThreeSchools) && (workersRequired[education] < 0 && workersRequired[education + 1] > 0))
                            {
                                // Need to be above 50 to be promoted. However, each level is harder to get to, effectively (50, 65, 80)
                                int number = Singleton <SimulationManager> .instance.m_randomizer.Int32(0, 100) - (education * 15);

                                if (number > 50)
                                {
                                    if (cit.EducationLevel == Citizen.Education.Uneducated)
                                    {
                                        cit.Education1 = true;
                                        workersRequired[0]++;
                                        workersRequired[1]--;
                                    }
                                    else if (cit.EducationLevel == Citizen.Education.OneSchool)
                                    {
                                        cit.Education2 = true;
                                        workersRequired[1]++;
                                        workersRequired[2]--;
                                    }
                                    else if (cit.EducationLevel == Citizen.Education.TwoSchools)
                                    {
                                        cit.Education3 = true;
                                        workersRequired[2]++;
                                        workersRequired[3]--;
                                    }
                                }
                                else
                                {
                                    workersRequired[education]++;
                                    citizenManager.m_citizens.m_buffer[(int)((UIntPtr)citizen)].m_workBuilding = 0;
                                    RemoveFromCitizenUnit(currentUnit, i);
                                }
                            }
                            else if (workersRequired[education] < 0)
                            {
                                workersRequired[education]++;
                                citizenManager.m_citizens.m_buffer[(int)((UIntPtr)citizen)].m_workBuilding = 0;
                                RemoveFromCitizenUnit(currentUnit, i);
                            } // end if
                        }     // end citizen
                    }         // end for
                }             // Flag match

                previousUnit = currentUnit;
                currentUnit  = nextUnit;

                if (++loopCounter > 524288)
                {
                    currentUnit = 0u; // Bail out loop
                }
            } // end while
        } // end PromoteWorkers
        private bool IsValid(ref CitizenInstance citizenInstance)
        {
            if ((citizenInstance.m_flags & CitizenInstance.Flags.Deleted) != CitizenInstance.Flags.None)
            {
                return false;
            }

            if (citizenInstance.m_path == 0)
            {
                return false;
            }

            return true;
        }
Example #21
0
        public static bool Prefix(ResidentAI __instance,
                                  ref VehicleInfo __result,
                                  ushort instanceID,
                                  ref CitizenInstance citizenData,
                                  bool forceProbability,
                                  out VehicleInfo trailer)
        {
#if DEBUG
            bool citizenDebug = (DebugSettings.CitizenInstanceId == 0 ||
                                 DebugSettings.CitizenInstanceId == instanceID) &&
                                (DebugSettings.CitizenId == 0 ||
                                 DebugSettings.CitizenId == citizenData.m_citizen) &&
                                (DebugSettings.SourceBuildingId == 0 ||
                                 DebugSettings.SourceBuildingId == citizenData.m_sourceBuilding) &&
                                (DebugSettings.TargetBuildingId == 0 ||
                                 DebugSettings.TargetBuildingId == citizenData.m_targetBuilding);
            bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && citizenDebug;
#else
            var logParkingAi = false;
#endif
            trailer = null;

            if (citizenData.m_citizen == 0u)
            {
                __result = null;
                return(false);
            }

            // NON-STOCK CODE START
            bool forceTaxi = false;
            if (Options.parkingAI)
            {
                if (ExtCitizenInstanceManager.Instance.ExtInstances[instanceID]
                    .pathMode == ExtPathMode.TaxiToTarget)
                {
                    forceTaxi = true;
                }
            }

            // NON-STOCK CODE END
            Citizen.AgeGroup ageGroup =
                Constants.ManagerFactory.ExtCitizenManager.GetAgeGroup(citizenData.Info.m_agePhase);

            int carProb;
            int bikeProb;
            int taxiProb;

            // NON-STOCK CODE START
            if (forceTaxi)
            {
                carProb  = 0;
                bikeProb = 0;
                taxiProb = 100;
            }
            else   // NON-STOCK CODE END
            if (forceProbability ||
                (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) !=
                CitizenInstance.Flags.None)
            {
                carProb  = 100;
                bikeProb = 0;
                taxiProb = 0;
            }
            else
            {
                carProb  = GetCarProbability(__instance, instanceID, ref citizenData, ageGroup);
                bikeProb = GetBikeProbability(__instance, instanceID, ref citizenData, ageGroup);
                taxiProb = GetTaxiProbability(__instance, instanceID, ref citizenData, ageGroup);
            }

            Randomizer randomizer     = new Randomizer(citizenData.m_citizen);
            bool       useCar         = randomizer.Int32(100u) < carProb;
            bool       useBike        = !useCar && randomizer.Int32(100u) < bikeProb;
            bool       useTaxi        = !useCar && !useBike && randomizer.Int32(100u) < taxiProb;
            bool       useElectricCar = false;

            if (useCar)
            {
                int electricProb = GetElectricCarProbability(__instance,
                                                             instanceID,
                                                             ref citizenData,
                                                             __instance.m_info.m_agePhase);
                useElectricCar = randomizer.Int32(100u) < electricProb;
            }

            ItemClass.Service    service    = ItemClass.Service.Residential;
            ItemClass.SubService subService = useElectricCar
                                 ? ItemClass.SubService.ResidentialLowEco
                                 : ItemClass.SubService.ResidentialLow;
            if (useTaxi)
            {
                service    = ItemClass.Service.PublicTransport;
                subService = ItemClass.SubService.PublicTransportTaxi;
            }

            // NON-STOCK CODE START
            VehicleInfo carInfo = null;
            if (Options.parkingAI && useCar)
            {
                ushort parkedVehicleId = Singleton <CitizenManager>
                                         .instance.m_citizens.m_buffer[citizenData.m_citizen]
                                         .m_parkedVehicle;

                if (parkedVehicleId != 0)
                {
                    Log._DebugIf(
                        logParkingAi,
                        () => $"CustomResidentAI.CustomGetVehicleInfo({instanceID}): " +
                        $"Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. " +
                        $"Reusing vehicle info.");
                    carInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
                }
            }

            if (carInfo == null && (useCar || useTaxi))
            {
                // NON-STOCK CODE END
                carInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(
                    ref randomizer,
                    service,
                    subService,
                    ItemClass.Level.Level1);
            }

            if (useBike)
            {
                ItemClass.Level ageGroupLvl = ageGroup != Citizen.AgeGroup.Child
                                      ? ItemClass.Level.Level2
                                      : ItemClass.Level.Level1;
                VehicleInfo bikeInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(
                    ref randomizer,
                    ItemClass.Service.Residential,
                    ItemClass.SubService.ResidentialHigh,
                    ageGroupLvl);

                if (bikeInfo != null)
                {
                    __result = bikeInfo;
                    return(false);
                }
            }

            if ((useCar || useTaxi) && carInfo != null)
            {
                __result = carInfo;
                return(false);
            }

            __result = null;
            return(false);
        }
        protected override void ArriveAtDestination(ushort instanceID, ref CitizenInstance citizenData, bool success)
        {
            uint citizen = citizenData.m_citizen;
            if (citizen != 0)
            {
                CitizenManager instance = Singleton<CitizenManager>.instance;
                if (success)
                {
                    instance.m_citizens.m_buffer[citizen].SetLocationByBuilding(citizen, citizenData.m_targetBuilding);
                    if (citizenData.m_sourceBuilding != 0 && instance.m_citizens.m_buffer[citizen].CurrentLocation == Citizen.Location.Work)
                    {
                        ReachedDestination(citizen, citizenData);
                    }
                    else if (citizenData.m_sourceBuilding != 0 && instance.m_citizens.m_buffer[citizen].CurrentLocation == Citizen.Location.Visit)
                    {
                        ReachedDestination(citizen, citizenData);
                    }
                }
            }

            base.ArriveAtDestination(instanceID, ref citizenData, success);
        }
Example #23
0
        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.AnimalMonitor = true;

                    _initialized = true;

                    _helper.NotifyPlayer("Initialized");
                }
                else
                {
                    CitizenManager instance = Singleton <CitizenManager> .instance;

                    ushort[] seagulls = SkylinesOverwatch.Data.Instance.Seagulls;

                    foreach (ushort i in seagulls)
                    {
                        CitizenInstance seagull = instance.m_instances.m_buffer[(int)i];

                        if (seagull.Info != null)
                        {
                            seagull.Info.m_maxRenderDistance = float.NegativeInfinity;

                            ((BirdAI)seagull.Info.m_citizenAI).m_randomEffect = null;
                        }

                        SkylinesOverwatch.Helper.Instance.RequestAnimalRemoval(i);
                    }
                }
            }
            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);

                _terminated = true;
            }

            base.OnUpdate(realTimeDelta, simulationTimeDelta);
        }
 private int GetBikeProbability(ushort instanceID, ref CitizenInstance citizenData, Citizen.AgeGroup ageGroup)
 {
     Log.Error("CustomResidentAI.GetBikeProbability called!");
     return(20);
 }
        // CitizenAI
        public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo)
        {
            CitizenManager citMan = Singleton <CitizenManager> .instance;

            if (citMan.m_citizens.m_buffer[citizenData.m_citizen].CurrentLocation == Citizen.Location.Home)
            {
                currentTransportMode[instanceID] = TransportMode.None;                 // reset currently used transport mode at home
            }
            SimulationManager simManager = Singleton <SimulationManager> .instance;

            Citizen.Wealth wealthLevel  = citMan.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel;
            bool           couldUseTaxi = false;   // could cim use a taxi if it was not forbidden because of randomization?
            bool           couldUseCar  = false;
            bool           couldUseBike = false;
            bool           wouldAffordTaxiVoluntarily = false;

            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)
                    {
                        couldUseTaxi = true;

                        if (currentTransportMode[instanceID] == TransportMode.Taxi || (currentTransportMode[instanceID] == TransportMode.None &&
                                                                                       ((simManager.m_isNightTime && simManager.m_randomizer.Int32(100) < NIGHT_TAXI_USAGE_PROBABILITY[(int)wealthLevel]) ||
                                                                                        (!simManager.m_isNightTime && simManager.m_randomizer.Int32(100) < DAY_TAXI_USAGE_PROBABILITY[(int)wealthLevel]))))
                        {
                            wouldAffordTaxiVoluntarily = true;                             // NON-STOCK CODE
                        }
                    }
                }
                else
                {
                    // NON-STOCK CODE START
                    if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                    {
                        couldUseBike = true;
                    }
                    else if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Car)
                    {
                        couldUseCar = true;
                    }
                    // NON-STOCK CODE END

                    if (citizenData.m_targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
                    {
                        randomParking = true;
                    }
                }
            }

            byte districtId = Singleton <DistrictManager> .instance.GetDistrict(startPos);

            DistrictPolicies.Services servicePolicies = Singleton <DistrictManager> .instance.m_districts.m_buffer[(int)districtId].m_servicePolicies;
            int transportUsageProb = (servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None ? FREE_TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel] : TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel];

            bool useTaxi            = false;
            bool useBike            = false;
            bool useCar             = false;
            bool usePublicTransport = false;

            if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)               // STOCK CODE
            {
                if (currentTransportMode[instanceID] == TransportMode.PublicTransport || useTaxi ||
                    (currentTransportMode[instanceID] == TransportMode.None && simManager.m_randomizer.Int32(100) < transportUsageProb))
                {
                    usePublicTransport = true;
                }
            }

            ushort parkedVehicle     = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
            bool   couldUseParkedCar = false;           // cims are not allowed to use pocket cars (unless we have no choice)

            PathUnit.Position vehiclePosition = default(PathUnit.Position);
            if (parkedVehicle != 0)
            {
                Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position;
                if (PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition))
                {
                    couldUseParkedCar = true;
                }
            }

            if (couldUseBike)
            {
                // everyone who has a bike may use it
                useBike = true;
            }

            if (!usePublicTransport)
            {
                if (couldUseParkedCar && currentTransportMode[instanceID] == TransportMode.Car)
                {
                    useCar = true;
                }
                else if ((wouldAffordTaxiVoluntarily && currentTransportMode[instanceID] == TransportMode.Taxi) || couldUseTaxi)
                {
                    useTaxi = true;
                }
                else if (couldUseCar)
                {
                    // pocket car fallback
                    useCar = true;
                }
            }

            ExtVehicleType extVehicleType = ExtVehicleType.None;

            NetInfo.LaneType        laneType    = NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;

            if (usePublicTransport)
            {
                currentTransportMode[instanceID] = TransportMode.PublicTransport;
                laneType       |= NetInfo.LaneType.PublicTransport;
                extVehicleType |= ExtVehicleType.PublicTransport;
            }

            if (useBike && vehicleInfo != null)
            {
                laneType       |= NetInfo.LaneType.Vehicle;
                vehicleType    |= vehicleInfo.m_vehicleType;
                extVehicleType |= ExtVehicleType.Bicycle;
            }

            if (useTaxi && vehicleInfo != null)
            {
                currentTransportMode[instanceID] = TransportMode.Taxi;
                laneType       |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                vehicleType    |= vehicleInfo.m_vehicleType;
                extVehicleType |= ExtVehicleType.Taxi;
            }

            if (useCar && vehicleInfo != null)
            {
                currentTransportMode[instanceID] = TransportMode.Car;
                laneType       |= NetInfo.LaneType.Vehicle;
                vehicleType    |= vehicleInfo.m_vehicleType;
                extVehicleType |= ExtVehicleType.PassengerCar;
            }

            //Log._Debug($"Citizen {instanceID}: usePublicTransport={usePublicTransport} useCar={useCar} useTaxi={useTaxi} useBike={useBike} vehicleInfo.vehicleType={vehicleInfo?.m_vehicleType} laneType={laneType} vehicleType={vehicleType} extVehicleType={extVehicleType}");

            bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;

            PathUnit.Position startPosA;
            PathUnit.Position endPosA;
            if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) &&
                this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA))
            {
                PathUnit.Position position2 = default(PathUnit.Position);
                uint path;
#if DEBUG
                //Log._Debug($"CustomCitizenAI: citizen instance {instanceID}, id {citizenData.m_citizen}. vehicleType={vehicleType} laneType={laneType} extVehicleType={extVehicleType} usePublicTransport={usePublicTransport} useTaxi={useTaxi} useBike={useBike} useCar={useCar} wealthLevel={wealthLevel}");
#endif
                // NON-STOCK CODE END //
                if (Singleton <CustomPathManager> .instance.CreatePath(false, (ExtVehicleType)extVehicleType, null, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, randomParking))
                {
                    if (citizenData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(citizenData.m_path);
                    }
                    citizenData.m_path   = path;
                    citizenData.m_flags |= CitizenInstance.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
 /// <summary>
 /// Check if prisoner is confused.
 /// </summary>
 /// <param name="data">The citizen instance.</param>
 /// <returns>True if prisoner is confused.</returns>
 private static bool PrisonerConfused(ref CitizenInstance data)
 {
     // From PrisonerAI.GetLocalizedStatus from original game code at version 1.4.1-f2.
     ushort num = data.m_targetBuilding;
     if ((int)num != 0)
     {
         ////target = InstanceID.Empty;
         ////target.Building = num;
         ////return Locale.Get("CITIZEN_STATUS_VISITING");
         return false;
     }
     ////target = InstanceID.Empty;
     ////return Locale.Get("CITIZEN_STATUS_CONFUSED");
     return true;
 }
Example #27
0
        // CitizenAI
        public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo)
        {
            NetInfo.LaneType        laneType    = NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
            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);
                            vehicleType |= vehicleInfo.m_vehicleType;
                        }
                    }
                }
                else
                {
                    laneType    |= NetInfo.LaneType.Vehicle;
                    vehicleType |= vehicleInfo.m_vehicleType;
                }
            }
            PathUnit.Position vehiclePosition = default(PathUnit.Position);
            ushort            parkedVehicle   = Singleton <CitizenManager> .instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle;

            if (parkedVehicle != 0)
            {
                Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position;
                PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition);
            }
            bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;

            PathUnit.Position startPosA;
            PathUnit.Position endPosA;
            if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) &&
                this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA))
            {
                // NON-STOCK CODE START //
                Citizen.Wealth wealthLevel = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel;

                byte districtId = Singleton <DistrictManager> .instance.GetDistrict(startPos);

                DistrictPolicies.Services servicePolicies = Singleton <DistrictManager> .instance.m_districts.m_buffer[(int)districtId].m_servicePolicies;
                int transportUsageProb = (servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None ? FREE_TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel] : TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel];

                //bool mayUseTransport = false;
                if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)                   // STOCK CODE
                {
                    if (vehicleInfo == null || (instanceID % 100) + 1 <= transportUsageProb)
                    {
                        laneType |= NetInfo.LaneType.PublicTransport;                         // STOCK CODE
                        //mayUseTransport = true;
                        //Log._Debug($"CustomCitizenAI: citizen {instanceID} can use public transport");
                    }
                }
                // NON-STOCK CODE END //
                PathUnit.Position position2 = default(PathUnit.Position);
                uint path;
                // NON-STOCK CODE START //
                ExtVehicleType?extVehicleType = null;
                if (vehicleInfo != null)
                {
                    extVehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicleInfo(vehicleInfo);
                }
                //Log._Debug($"CustomCitizenAI: citizen instance {instanceID}, id {citizenData.m_citizen}. {vehicleType} {extVehicleType} mayUseTransport={mayUseTransport} wealthLevel={wealthLevel}");
                bool res = false;
                if (extVehicleType == null)
                {
                    // NON-STOCK CODE END //
                    res = Singleton <CustomPathManager> .instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false);
                }
                // NON-STOCK CODE START //
                else
                {
                    res = Singleton <CustomPathManager> .instance.CreatePath((ExtVehicleType)extVehicleType, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false);
                }
                // NON-STOCK CODE END //
                if (res)
                {
                    if (citizenData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(citizenData.m_path);
                    }
                    citizenData.m_path   = path;
                    citizenData.m_flags |= CitizenInstance.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
        private String GetStockLocalizedStatus(ushort instanceID, ref CitizenInstance data, out bool addCustomStatus, out InstanceID target)
        {
            if ((data.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None)
            {
                target          = InstanceID.Empty;
                addCustomStatus = false;
                return(Locale.Get("CITIZEN_STATUS_CONFUSED"));
            }

            CitizenManager citMan    = Singleton <CitizenManager> .instance;
            uint           citizenId = data.m_citizen;
            bool           isStudent = false;
            ushort         homeId    = 0;
            ushort         workId    = 0;
            ushort         vehicleId = 0;

            if (citizenId != 0u)
            {
                homeId    = citMan.m_citizens.m_buffer[citizenId].m_homeBuilding;
                workId    = citMan.m_citizens.m_buffer[citizenId].m_workBuilding;
                vehicleId = citMan.m_citizens.m_buffer[citizenId].m_vehicle;
                isStudent = ((citMan.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Student) != Citizen.Flags.None);
            }
            ushort targetBuilding = data.m_targetBuilding;

            if (targetBuilding == 0)
            {
                target          = InstanceID.Empty;
                addCustomStatus = false;
                return(Locale.Get("CITIZEN_STATUS_CONFUSED"));
            }

            if ((data.m_flags & CitizenInstance.Flags.TargetIsNode) != CitizenInstance.Flags.None)
            {
                if (vehicleId != 0)
                {
                    VehicleManager vehManager  = Singleton <VehicleManager> .instance;
                    VehicleInfo    vehicleInfo = vehManager.m_vehicles.m_buffer[vehicleId].Info;
                    if (vehicleInfo.m_class.m_service == ItemClass.Service.Residential && vehicleInfo.m_vehicleType != VehicleInfo.VehicleType.Bicycle)
                    {
                        if (vehicleInfo.m_vehicleAI.GetOwnerID(vehicleId, ref vehManager.m_vehicles.m_buffer[vehicleId]).Citizen == citizenId)
                        {
                            target          = InstanceID.Empty;
                            target.NetNode  = targetBuilding;
                            addCustomStatus = true;
                            return(ColossalFramework.Globalization.Locale.Get("CITIZEN_STATUS_DRIVINGTO"));
                        }
                    }
                    else if (vehicleInfo.m_class.m_service == ItemClass.Service.PublicTransport || vehicleInfo.m_class.m_service == ItemClass.Service.Disaster)
                    {
                        ushort transportLine = Singleton <NetManager> .instance.m_nodes.m_buffer[targetBuilding].m_transportLine;
                        if ((data.m_flags & CitizenInstance.Flags.WaitingTaxi) != 0)
                        {
                            target          = InstanceID.Empty;
                            addCustomStatus = true;
                            return(ColossalFramework.Globalization.Locale.Get("CITIZEN_STATUS_WAITING_TAXI"));
                        }

                        if (vehManager.m_vehicles.m_buffer[vehicleId].m_transportLine != transportLine)
                        {
                            target          = InstanceID.Empty;
                            target.NetNode  = targetBuilding;
                            addCustomStatus = true;
                            return(ColossalFramework.Globalization.Locale.Get("CITIZEN_STATUS_TRAVELLINGTO"));
                        }
                    }
                }

                if ((data.m_flags & CitizenInstance.Flags.OnTour) != 0)
                {
                    target          = InstanceID.Empty;
                    target.NetNode  = targetBuilding;
                    addCustomStatus = true;
                    return(ColossalFramework.Globalization.Locale.Get("CITIZEN_STATUS_VISITING"));
                }

                target          = InstanceID.Empty;
                target.NetNode  = targetBuilding;
                addCustomStatus = true;
                return(ColossalFramework.Globalization.Locale.Get("CITIZEN_STATUS_GOINGTO"));
            }

            bool isOutsideConnection = (Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetBuilding].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None;
            bool hangsAround         = data.m_path == 0u && (data.m_flags & CitizenInstance.Flags.HangAround) != CitizenInstance.Flags.None;

            if (vehicleId != 0)
            {
                VehicleManager vehicleMan  = Singleton <VehicleManager> .instance;
                VehicleInfo    vehicleInfo = vehicleMan.m_vehicles.m_buffer[(int)vehicleId].Info;
                if (vehicleInfo.m_class.m_service == ItemClass.Service.Residential && vehicleInfo.m_vehicleType != VehicleInfo.VehicleType.Bicycle)
                {
                    if (vehicleInfo.m_vehicleAI.GetOwnerID(vehicleId, ref vehicleMan.m_vehicles.m_buffer[(int)vehicleId]).Citizen == citizenId)
                    {
                        if (isOutsideConnection)
                        {
                            target          = InstanceID.Empty;
                            addCustomStatus = true;
                            return(Locale.Get("CITIZEN_STATUS_DRIVINGTO_OUTSIDE"));
                        }

                        if (targetBuilding == homeId)
                        {
                            target          = InstanceID.Empty;
                            addCustomStatus = true;
                            return(Locale.Get("CITIZEN_STATUS_DRIVINGTO_HOME"));
                        }
                        else if (targetBuilding == workId)
                        {
                            target          = InstanceID.Empty;
                            addCustomStatus = true;
                            return(Locale.Get((!isStudent) ? "CITIZEN_STATUS_DRIVINGTO_WORK" : "CITIZEN_STATUS_DRIVINGTO_SCHOOL"));
                        }
                        else
                        {
                            target          = InstanceID.Empty;
                            target.Building = targetBuilding;
                            addCustomStatus = true;
                            return(Locale.Get("CITIZEN_STATUS_DRIVINGTO"));
                        }
                    }
                }
                else if (vehicleInfo.m_class.m_service == ItemClass.Service.PublicTransport || vehicleInfo.m_class.m_service == ItemClass.Service.Disaster)
                {
                    if ((data.m_flags & CitizenInstance.Flags.WaitingTaxi) != CitizenInstance.Flags.None)
                    {
                        target          = InstanceID.Empty;
                        addCustomStatus = true;
                        return(Locale.Get("CITIZEN_STATUS_WAITING_TAXI"));
                    }
                    if (isOutsideConnection)
                    {
                        target          = InstanceID.Empty;
                        addCustomStatus = true;
                        return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO_OUTSIDE"));
                    }
                    if (targetBuilding == homeId)
                    {
                        target          = InstanceID.Empty;
                        addCustomStatus = true;
                        return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO_HOME"));
                    }
                    if (targetBuilding == workId)
                    {
                        target          = InstanceID.Empty;
                        addCustomStatus = true;
                        return(Locale.Get((!isStudent) ? "CITIZEN_STATUS_TRAVELLINGTO_WORK" : "CITIZEN_STATUS_TRAVELLINGTO_SCHOOL"));
                    }
                    target          = InstanceID.Empty;
                    target.Building = targetBuilding;
                    addCustomStatus = true;
                    return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO"));
                }
            }

            if (isOutsideConnection)
            {
                target          = InstanceID.Empty;
                addCustomStatus = true;
                return(Locale.Get("CITIZEN_STATUS_GOINGTO_OUTSIDE"));
            }

            if (targetBuilding == homeId)
            {
                if (hangsAround)
                {
                    target          = InstanceID.Empty;
                    addCustomStatus = false;
                    return(Locale.Get("CITIZEN_STATUS_AT_HOME"));
                }

                target          = InstanceID.Empty;
                addCustomStatus = true;
                return(Locale.Get("CITIZEN_STATUS_GOINGTO_HOME"));
            }
            else if (targetBuilding == workId)
            {
                if (hangsAround)
                {
                    target          = InstanceID.Empty;
                    addCustomStatus = false;
                    return(Locale.Get((!isStudent) ? "CITIZEN_STATUS_AT_WORK" : "CITIZEN_STATUS_AT_SCHOOL"));
                }
                target          = InstanceID.Empty;
                addCustomStatus = true;
                return(Locale.Get((!isStudent) ? "CITIZEN_STATUS_GOINGTO_WORK" : "CITIZEN_STATUS_GOINGTO_SCHOOL"));
            }
            else
            {
                if (hangsAround)
                {
                    target          = InstanceID.Empty;
                    target.Building = targetBuilding;
                    addCustomStatus = false;
                    return(Locale.Get("CITIZEN_STATUS_VISITING"));
                }
                target          = InstanceID.Empty;
                target.Building = targetBuilding;
                addCustomStatus = true;
                return(Locale.Get("CITIZEN_STATUS_GOINGTO"));
            }
        }
Example #29
0
        internal bool ExtSimulationStep(ushort instanceID, ref CitizenInstance instanceData, ref ExtCitizenInstance extInstance, Vector3 physicsLodRefPos)
        {
            // check if the citizen has reached a parked car or target
            if (extInstance.pathMode == ExtPathMode.WalkingToParkedCar || extInstance.pathMode == ExtPathMode.ApproachingParkedCar)
            {
                ushort parkedVehicleId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[instanceData.m_citizen].m_parkedVehicle;
                if (parkedVehicleId == 0)
                {
                    // citizen is reaching their parked car but does not own a parked car
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log.Warning($"CustomHumanAI.ExtSimulationStep({instanceID}): Citizen instance {instanceID} was walking to / reaching their parked car ({extInstance.pathMode}) but parked car has disappeared. RESET.");
                    }
#endif

                    extInstance.Reset();

                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.Cheering);
                    this.InvalidPath(instanceID, ref instanceData);
                    return(true);
                }
                else
                {
                    ParkedCarApproachState approachState = AdvancedParkingManager.Instance.CitizenApproachingParkedCarSimulationStep(instanceID, ref instanceData, ref extInstance, physicsLodRefPos, ref Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId]);
                    switch (approachState)
                    {
                    case ParkedCarApproachState.None:
                    default:
                        break;

                    case ParkedCarApproachState.Approaching:
                        // citizen approaches their parked car
                        return(true);

                    case ParkedCarApproachState.Approached:
                        // citizen reached their parked car
#if DEBUG
                        if (GlobalConfig.Instance.Debug.Switches[4])
                        {
                            Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Citizen instance {instanceID} arrived at parked car. PathMode={extInstance.pathMode}");
                        }
#endif
                        if (instanceData.m_path != 0)
                        {
                            Singleton <PathManager> .instance.ReleasePath(instanceData.m_path);

                            instanceData.m_path = 0;
                        }
                        instanceData.m_flags = instanceData.m_flags & (CitizenInstance.Flags.Created | CitizenInstance.Flags.Cheering | CitizenInstance.Flags.Deleted | CitizenInstance.Flags.Underground | CitizenInstance.Flags.CustomName | CitizenInstance.Flags.Character | CitizenInstance.Flags.BorrowCar | CitizenInstance.Flags.HangAround | CitizenInstance.Flags.InsideBuilding | CitizenInstance.Flags.WaitingPath | CitizenInstance.Flags.TryingSpawnVehicle | CitizenInstance.Flags.CannotUseTransport | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.OnPath | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.AtTarget | CitizenInstance.Flags.RequireSlowStart | CitizenInstance.Flags.Transition | CitizenInstance.Flags.RidingBicycle | CitizenInstance.Flags.OnBikeLane | CitizenInstance.Flags.CannotUseTaxi | CitizenInstance.Flags.CustomColor | CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating | CitizenInstance.Flags.TargetFlags);
                        if (!this.StartPathFind(instanceID, ref instanceData))
                        {
                            instanceData.Unspawn(instanceID);
                            extInstance.Reset();
                        }

                        return(true);

                    case ParkedCarApproachState.Failure:
#if DEBUG
                        if (GlobalConfig.Instance.Debug.Switches[2])
                        {
                            Log._Debug($"CustomHumanAI.ExtSimulationStep({instanceID}): Citizen instance {instanceID} failed to arrive at parked car. PathMode={extInstance.pathMode}");
                        }
#endif
                        // repeat path-finding
                        instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                        instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.Cheering);
                        this.InvalidPath(instanceID, ref instanceData);
                        return(true);
                    }
                }
            }
            else if ((extInstance.pathMode == ExtCitizenInstance.ExtPathMode.WalkingToTarget ||
                      extInstance.pathMode == ExtCitizenInstance.ExtPathMode.PublicTransportToTarget ||
                      extInstance.pathMode == ExtCitizenInstance.ExtPathMode.TaxiToTarget)
                     )
            {
                AdvancedParkingManager.Instance.CitizenApproachingTargetSimulationStep(instanceID, ref instanceData, ref extInstance);
            }
            return(false);
        }
 protected void CheckCollisions(ushort instanceID, ref CitizenInstance citizenData, Vector3 sourcePos, Vector3 targetPos, ushort buildingID, ref Vector3 pushAmount, ref float pushDivider)
 {
     Segment3 segment = new Segment3 (sourcePos, targetPos);
     Vector3 min = segment.Min ();
     min.x -= this.m_info.m_radius;
     min.z -= this.m_info.m_radius;
     Vector3 max = segment.Max ();
     max.x += this.m_info.m_radius;
     max.y += this.m_info.m_height;
     max.z += this.m_info.m_radius;
     CitizenManager instance = Singleton<CitizenManager>.instance;
     int num = Mathf.Max ((int)((min.x - 3f) / 8f + 1080f), 0);
     int num2 = Mathf.Max ((int)((min.z - 3f) / 8f + 1080f), 0);
     int num3 = Mathf.Min ((int)((max.x + 3f) / 8f + 1080f), 2159);
     int num4 = Mathf.Min ((int)((max.z + 3f) / 8f + 1080f), 2159);
     for (int i = num2; i <= num4; i++) {
         for (int j = num; j <= num3; j++) {
             ushort num5 = instance.m_citizenGrid [i * 2160 + j];
             int num6 = 0;
             while (num5 != 0) {
                 num5 = this.CheckCollisions (instanceID, ref citizenData, segment, min, max, num5, ref instance.m_instances.m_buffer [(int)num5], ref pushAmount, ref pushDivider);
                 if (++num6 > 65536) {
                     CODebugBase<LogChannel>.Error (LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                     break;
                 }
             }
         }
     }
     VehicleManager instance2 = Singleton<VehicleManager>.instance;
     int num7 = Mathf.Max ((int)((min.x - 10f) / 32f + 270f), 0);
     int num8 = Mathf.Max ((int)((min.z - 10f) / 32f + 270f), 0);
     int num9 = Mathf.Min ((int)((max.x + 10f) / 32f + 270f), 539);
     int num10 = Mathf.Min ((int)((max.z + 10f) / 32f + 270f), 539);
     for (int k = num8; k <= num10; k++) {
         for (int l = num7; l <= num9; l++) {
             ushort num11 = instance2.m_vehicleGrid [k * 540 + l];
             int num12 = 0;
             while (num11 != 0) {
                 num11 = this.CheckCollisions (instanceID, ref citizenData, segment, min, max, num11, ref instance2.m_vehicles.m_buffer [(int)num11], ref pushAmount, ref pushDivider);
                 if (++num12 > 65536) {
                     CODebugBase<LogChannel>.Error (LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                     break;
                 }
             }
         }
     }
     for (int m = num8; m <= num10; m++) {
         for (int n = num7; n <= num9; n++) {
             ushort num13 = instance2.m_parkedGrid [m * 540 + n];
             int num14 = 0;
             while (num13 != 0) {
                 num13 = this.CheckCollisions (instanceID, ref citizenData, segment, min, max, num13, ref instance2.m_parkedVehicles.m_buffer [(int)num13], ref pushAmount, ref pushDivider);
                 if (++num14 > 65536) {
                     CODebugBase<LogChannel>.Error (LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                     break;
                 }
             }
         }
     }
     if (buildingID != 0) {
         BuildingManager instance3 = Singleton<BuildingManager>.instance;
         BuildingInfo info = instance3.m_buildings.m_buffer [(int)buildingID].Info;
         if (info.m_props != null) {
             Vector3 position = instance3.m_buildings.m_buffer [(int)buildingID].m_position;
             float angle = instance3.m_buildings.m_buffer [(int)buildingID].m_angle;
             int length = instance3.m_buildings.m_buffer [(int)buildingID].Length;
             Matrix4x4 matrix4x = default(Matrix4x4);
             matrix4x.SetTRS (Building.CalculateMeshPosition (info, position, angle, length), Quaternion.AngleAxis (angle * 57.29578f, Vector3.down), Vector3.one);
             for (int num15 = 0; num15 < info.m_props.Length; num15++) {
                 BuildingInfo.Prop prop = info.m_props [num15];
                 Randomizer randomizer = new Randomizer ((int)buildingID << 6 | prop.m_index);
                 if (randomizer.Int32 (100u) < prop.m_probability && length >= prop.m_requiredLength) {
                     Vector3 vector = matrix4x.MultiplyPoint (prop.m_position);
                     if (vector.x >= min.x - 2f && vector.x <= max.x + 2f) {
                         if (vector.z >= min.z - 2f && vector.z <= max.z + 2f) {
                             PropInfo propInfo = prop.m_finalProp;
                             TreeInfo treeInfo = prop.m_finalTree;
                             float num16 = 0f;
                             float num17 = 0f;
                             if (propInfo != null) {
                                 propInfo = propInfo.GetVariation (ref randomizer);
                                 if (propInfo.m_isMarker || propInfo.m_isDecal || !propInfo.m_hasRenderer) {
                                     goto IL_7D3;
                                 }
                                 num16 = propInfo.m_generatedInfo.m_size.x * 0.5f;
                                 num17 = propInfo.m_generatedInfo.m_size.y;
                             } else {
                                 if (treeInfo != null) {
                                     treeInfo = treeInfo.GetVariation (ref randomizer);
                                     num16 = (treeInfo.m_generatedInfo.m_size.x + treeInfo.m_generatedInfo.m_size.z) * 0.125f;
                                     num17 = treeInfo.m_generatedInfo.m_size.y;
                                 }
                             }
                             if (!prop.m_fixedHeight) {
                                 vector.y = Singleton<TerrainManager>.instance.SampleDetailHeight (vector);
                             } else {
                                 if (info.m_requireHeightMap) {
                                     vector.y = Singleton<TerrainManager>.instance.SampleDetailHeight (vector) + prop.m_position.y;
                                 }
                             }
                             if (vector.y + num17 >= min.y && vector.y <= max.y) {
                                 num16 = this.m_info.m_radius + num16;
                                 float num19;
                                 float num18 = segment.DistanceSqr (vector, out num19);
                                 if (num18 < num16 * num16) {
                                     float num20 = num16 - Mathf.Sqrt (num18);
                                     float num21 = 1f - num18 / (num16 * num16);
                                     Vector3 a = segment.Position (num19 * 0.9f);
                                     a.y = 0f;
                                     vector.y = 0f;
                                     Vector3 vector2 = Vector3.Normalize (a - vector);
                                     Vector3 rhs = Vector3.Normalize (new Vector3 (segment.b.x - segment.a.x, 0f, segment.b.z - segment.a.z));
                                     Vector3 vector3 = new Vector3 (rhs.z, 0f, -rhs.x) * Mathf.Abs (Vector3.Dot (vector2, rhs) * 0.5f);
                                     if (Vector3.Dot (vector2, vector3) >= 0f) {
                                         vector2 += vector3;
                                     } else {
                                         vector2 -= vector3;
                                     }
                                     pushAmount += vector2 * (num20 * num21);
                                     pushDivider += num21;
                                 }
                             }
                         }
                     }
                 }
                 IL_7D3:
                 ;
             }
         }
     }
 }
Example #31
0
        public void CustomSimulationStep(ushort instanceID, ref CitizenInstance instanceData, Vector3 physicsLodRefPos)
        {
            uint citizenId = instanceData.m_citizen;

            if ((instanceData.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None && (instanceData.m_flags & CitizenInstance.Flags.Character) == CitizenInstance.Flags.None)
            {
                Singleton <CitizenManager> .instance.ReleaseCitizenInstance(instanceID);

                if (citizenId != 0u)
                {
                    Singleton <CitizenManager> .instance.ReleaseCitizen(citizenId);
                }
                return;
            }

            if ((instanceData.m_flags & CitizenInstance.Flags.WaitingPath) != CitizenInstance.Flags.None)
            {
                PathManager pathManager   = Singleton <PathManager> .instance;
                byte        pathFindFlags = pathManager.m_pathUnits.m_buffer[instanceData.m_path].m_pathFindFlags;

                // NON-STOCK CODE START
                ExtPathState mainPathState = ExtPathState.Calculating;
                if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || instanceData.m_path == 0)
                {
                    mainPathState = ExtPathState.Failed;
                }
                else if ((pathFindFlags & PathUnit.FLAG_READY) != 0)
                {
                    mainPathState = ExtPathState.Ready;
                }

#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path={instanceData.m_path}, mainPathState={mainPathState}");
                }
#endif

                ExtSoftPathState finalPathState = ExtSoftPathState.None;
#if BENCHMARK
                using (var bm = new Benchmark(null, "ConvertPathStateToSoftPathState+UpdateCitizenPathState")) {
#endif
                finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState);
                if (Options.prohibitPocketCars)
                {
                    finalPathState = AdvancedParkingManager.Instance.UpdateCitizenPathState(instanceID, ref instanceData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], ref Singleton <CitizenManager> .instance.m_citizens.m_buffer[instanceData.m_citizen], mainPathState);
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Applied Parking AI logic. Path={instanceData.m_path}, mainPathState={mainPathState}, finalPathState={finalPathState}, extCitizenInstance={ExtCitizenInstanceManager.Instance.ExtInstances[instanceID]}");
                    }
#endif
                }
#if BENCHMARK
            }
#endif

                switch (finalPathState)
                {
                case ExtSoftPathState.Ready:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding succeeded for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.PathfindSuccess");
                    }
#endif
                    this.Spawn(instanceID, ref instanceData);
                    instanceData.m_pathPositionIndex = 255;
                    instanceData.m_flags            &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags            &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.Cheering);
                    // NON-STOCK CODE START (transferred from ResidentAI.PathfindSuccess)
                    if (citizenId != 0 && (Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].m_flags & (Citizen.Flags.Tourist | Citizen.Flags.MovingIn | Citizen.Flags.DummyTraffic)) == Citizen.Flags.MovingIn)
                    {
                        StatisticBase statisticBase = Singleton <StatisticsManager> .instance.Acquire <StatisticInt32>(StatisticType.MoveRate);

                        statisticBase.Add(1);
                    }
                    // NON-STOCK CODE END
                    this.PathfindSuccess(instanceID, ref instanceData);
                    break;

                case ExtSoftPathState.Ignore:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding result shall be ignored for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- ignoring");
                    }
#endif
                    return;

                case ExtSoftPathState.Calculating:
                default:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding result undetermined for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- continue");
                    }
#endif
                    break;

                case ExtSoftPathState.FailedHard:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): HARD path-finding failure for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.PathfindFailure");
                    }
#endif
                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.Cheering);
                    Singleton <PathManager> .instance.ReleasePath(instanceData.m_path);

                    instanceData.m_path = 0u;
                    this.PathfindFailure(instanceID, ref instanceData);
                    return;

                case ExtSoftPathState.FailedSoft:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): SOFT path-finding failure for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.InvalidPath");
                    }
#endif
                    // path mode has been updated, repeat path-finding
                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.Cheering);
                    this.InvalidPath(instanceID, ref instanceData);
                    return;
                }
                // NON-STOCK CODE END
            }

            // NON-STOCK CODE START
#if BENCHMARK
            using (var bm = new Benchmark(null, "ExtSimulationStep")) {
#endif
            if (Options.prohibitPocketCars)
            {
                if (ExtSimulationStep(instanceID, ref instanceData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], physicsLodRefPos))
                {
                    return;
                }
            }
#if BENCHMARK
        }
#endif
            // NON-STOCK CODE END

            base.SimulationStep(instanceID, ref instanceData, physicsLodRefPos);

            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            VehicleManager vehicleManager = Singleton <VehicleManager> .instance;
            ushort vehicleId = 0;
            if (instanceData.m_citizen != 0u)
            {
                vehicleId = citizenManager.m_citizens.m_buffer[instanceData.m_citizen].m_vehicle;
            }
            if (vehicleId != 0)
            {
                VehicleInfo vehicleInfo = vehicleManager.m_vehicles.m_buffer[(int)vehicleId].Info;
                if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                {
                    vehicleInfo.m_vehicleAI.SimulationStep(vehicleId, ref vehicleManager.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleManager.m_vehicles.m_buffer[(int)vehicleId], 0);
                    vehicleId = 0;
                }
            }
            if (vehicleId == 0 && (instanceData.m_flags & (CitizenInstance.Flags.Character | CitizenInstance.Flags.WaitingPath | CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) == CitizenInstance.Flags.None)
            {
                instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown);
                this.ArriveAtDestination(instanceID, ref instanceData, false);
                citizenManager.ReleaseCitizenInstance(instanceID);
            }
        }
 private ushort CheckCollisions(ushort instanceID, ref CitizenInstance citizenData, Segment3 segment, Vector3 min, Vector3 max, ushort otherID, ref VehicleParked otherData, ref Vector3 pushAmount, ref float pushDivider)
 {
     VehicleInfo info = otherData.Info;
     Vector3 position = otherData.m_position;
     Vector3 b = otherData.m_rotation * new Vector3 (0f, 0f, Mathf.Max (0.5f, info.m_generatedInfo.m_size.z * 0.5f - 1f));
     Segment3 segment2;
     segment2.a = position - b;
     segment2.b = position + b;
     Vector3 vector = segment2.Min ();
     vector.x -= 1f;
     vector.z -= 1f;
     Vector3 vector2 = segment2.Max ();
     vector2.x += 1f;
     vector2.y += 1f;
     vector2.z += 1f;
     if (min.x < vector2.x && max.x > vector.x && min.z < vector2.z && max.z > vector.z && min.y < vector2.y && max.y > vector.y)
     {
         float num = this.m_info.m_radius + 1f;
         float num3;
         float t;
         float num2 = segment.DistanceSqr (segment2, out num3, out t);
         if (num2 < num * num)
         {
             float num4 = num - Mathf.Sqrt (num2);
             float num5 = 1f - num2 / (num * num);
             Vector3 a = segment.Position (num3 * 0.9f);
             Vector3 b2 = segment2.Position (t);
             a.y = 0f;
             b2.y = 0f;
             Vector3 vector3 = Vector3.Normalize (a - b2);
             Vector3 rhs = Vector3.Normalize (new Vector3 (segment.b.x - segment.a.x, 0f, segment.b.z - segment.a.z));
             Vector3 vector4 = new Vector3 (rhs.z, 0f, -rhs.x) * Mathf.Abs (Vector3.Dot (vector3, rhs) * 0.5f);
             if (Vector3.Dot (vector3, vector4) >= 0f)
             {
                 vector3 += vector4;
             }
             else
             {
                 vector3 -= vector4;
             }
             pushAmount += vector3 * (num4 * num5);
             pushDivider += num5;
         }
     }
     return otherData.m_nextGridParked;
 }
Example #33
0
        /// <summary>
        /// Makes the given citizen instance enter their parked car.
        /// </summary>
        /// <param name="instanceID">Citizen instance id</param>
        /// <param name="instanceData">Citizen instance data</param>
        /// <param name="parkedVehicleId">Parked vehicle id</param>
        /// <param name="vehicleId">Vehicle id</param>
        /// <returns>true if entering the car succeeded, false otherwise</returns>
        public static bool EnterParkedCar(ushort instanceID, ref CitizenInstance instanceData, ushort parkedVehicleId, out ushort vehicleId)
        {
#if DEBUG
            if (GlobalConfig.Instance.Debug.Switches[2])
            {
                Log._Debug($"CustomHumanAI.EnterParkedCar({instanceID}): parkedVehicleId={parkedVehicleId})");
            }
#endif
            VehicleManager vehManager = Singleton <VehicleManager> .instance;
            NetManager     netManager = Singleton <NetManager> .instance;
            CitizenManager citManager = Singleton <CitizenManager> .instance;

            Vector3     parkedVehPos = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;
            Quaternion  parkedVehRot = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].m_rotation;
            VehicleInfo vehicleInfo  = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].Info;

            PathUnit.Position vehLanePathPos;
            if (!CustomPathManager._instance.m_pathUnits.m_buffer[instanceData.m_path].GetPosition(0, out vehLanePathPos))
            {
#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug($"CustomHumanAI.EnterParkedCar({instanceID}): Could not get first car path position of citizen instance {instanceID}!");
                }
#endif

                vehicleId = 0;
                return(false);
            }
            uint vehLaneId = PathManager.GetLaneID(vehLanePathPos);
#if DEBUG
            if (GlobalConfig.Instance.Debug.Switches[4])
            {
                Log._Debug($"CustomHumanAI.EnterParkedCar({instanceID}): Determined vehicle position for citizen instance {instanceID}: seg. {vehLanePathPos.m_segment}, lane {vehLanePathPos.m_lane}, off {vehLanePathPos.m_offset} (lane id {vehLaneId})");
            }
#endif

            Vector3 vehLanePos;
            float   vehLaneOff;
            netManager.m_lanes.m_buffer[vehLaneId].GetClosestPosition(parkedVehPos, out vehLanePos, out vehLaneOff);
            byte vehLaneOffset = (byte)Mathf.Clamp(Mathf.RoundToInt(vehLaneOff * 255f), 0, 255);

            // movement vector from parked vehicle position to road position
            Vector3 forwardVector = parkedVehPos + Vector3.ClampMagnitude(vehLanePos - parkedVehPos, 5f);
            if (vehManager.CreateVehicle(out vehicleId, ref Singleton <SimulationManager> .instance.m_randomizer, vehicleInfo, parkedVehPos, TransferManager.TransferReason.None, false, false))
            {
                // update frame data
                Vehicle.Frame frame = vehManager.m_vehicles.m_buffer[(int)vehicleId].m_frame0;
                frame.m_rotation = parkedVehRot;

                vehManager.m_vehicles.m_buffer[vehicleId].m_frame0 = frame;
                vehManager.m_vehicles.m_buffer[vehicleId].m_frame1 = frame;
                vehManager.m_vehicles.m_buffer[vehicleId].m_frame2 = frame;
                vehManager.m_vehicles.m_buffer[vehicleId].m_frame3 = frame;
                vehicleInfo.m_vehicleAI.FrameDataUpdated(vehicleId, ref vehManager.m_vehicles.m_buffer[vehicleId], ref frame);

                // update vehicle target position
                vehManager.m_vehicles.m_buffer[vehicleId].m_targetPos0 = new Vector4(vehLanePos.x, vehLanePos.y, vehLanePos.z, 2f);

                // update other fields
                vehManager.m_vehicles.m_buffer[vehicleId].m_flags             = (vehManager.m_vehicles.m_buffer[vehicleId].m_flags | Vehicle.Flags.Stopped);
                vehManager.m_vehicles.m_buffer[vehicleId].m_path              = instanceData.m_path;
                vehManager.m_vehicles.m_buffer[vehicleId].m_pathPositionIndex = 0;
                vehManager.m_vehicles.m_buffer[vehicleId].m_lastPathOffset    = vehLaneOffset;
                vehManager.m_vehicles.m_buffer[vehicleId].m_transferSize      = (ushort)(instanceData.m_citizen & 65535u);

                if (!vehicleInfo.m_vehicleAI.TrySpawn(vehicleId, ref vehManager.m_vehicles.m_buffer[vehicleId]))
                {
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.EnterParkedCar({instanceID}): Could not spawn a {vehicleInfo.m_vehicleType} for citizen instance {instanceID}!");
                    }
#endif
                    return(false);
                }

                // change instances
                InstanceID parkedVehInstance = InstanceID.Empty;
                parkedVehInstance.ParkedVehicle = parkedVehicleId;
                InstanceID vehInstance = InstanceID.Empty;
                vehInstance.Vehicle = vehicleId;
                Singleton <InstanceManager> .instance.ChangeInstance(parkedVehInstance, vehInstance);

                // set vehicle id for citizen instance
                instanceData.m_path = 0u;
                citManager.m_citizens.m_buffer[instanceData.m_citizen].SetParkedVehicle(instanceData.m_citizen, 0);
                citManager.m_citizens.m_buffer[instanceData.m_citizen].SetVehicle(instanceData.m_citizen, vehicleId, 0u);

                // update citizen instance flags
                instanceData.m_flags      &= ~CitizenInstance.Flags.WaitingPath;
                instanceData.m_flags      &= ~CitizenInstance.Flags.EnteringVehicle;
                instanceData.m_flags      &= ~CitizenInstance.Flags.TryingSpawnVehicle;
                instanceData.m_flags      &= ~CitizenInstance.Flags.BoredOfWaiting;
                instanceData.m_waitCounter = 0;

                // unspawn citizen instance
                instanceData.Unspawn(instanceID);

#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[4])
                {
                    Log._Debug($"CustomHumanAI.EnterParkedCar({instanceID}): Citizen instance {instanceID} is now entering vehicle {vehicleId}. Set vehicle target position to {vehLanePos} (segment={vehLanePathPos.m_segment}, lane={vehLanePathPos.m_lane}, offset={vehLanePathPos.m_offset})");
                }
#endif

                return(true);
            }
            else
            {
                // failed to find a road position
#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug($"CustomHumanAI.EnterParkedCar({instanceID}): Could not find a road position for citizen instance {instanceID} near parked vehicle {parkedVehicleId}!");
                }
#endif
                return(false);
            }
        }
 private static CitizenInfo GetUpdatedInfo(CitizenInstance instance, ushort instanceID)
 {
     CitizenInfo originalInfo = instance.Info;
     if (originalInfo == null || originalInfo.GetService() != ItemClass.Service.Residential)
     {
         return originalInfo;
     }
     var originalAI = originalInfo.m_citizenAI;
     if (originalAI is ServicePersonAI || originalAI is AnimalAI)
     {
         return originalInfo;
     }
     if (originalInfo.m_agePhase == Citizen.AgePhase.Teen0 || originalInfo.m_agePhase == Citizen.AgePhase.Teen1 || originalInfo.m_agePhase > Citizen.AgePhase.Adult3)
     {
         return originalInfo;
     }
     var citizenID = instance.m_citizen;
     var citizen = CitizenManager.instance.m_citizens.m_buffer[citizenID];
     if (citizen.m_instance != instanceID || instance.m_flags.IsFlagSet(CitizenInstance.Flags.RidingBicycle) ||
         instance.m_flags.IsFlagSet(CitizenInstance.Flags.OnBikeLane))
     {
         return originalInfo;
     }
     var workBuilding = BuildingManager.instance.m_buildings.m_buffer[citizen.m_workBuilding];
     if (workBuilding.m_flags != Building.Flags.None && originalInfo.m_agePhase != Citizen.AgePhase.Child)
     {
         if (workBuilding.Info.m_buildingAI is FireStationAI)
         {
             return originalInfo.m_gender == Citizen.Gender.Male ? _fireman : _paramedic;
         }
         if (workBuilding.Info.m_buildingAI is HospitalAI || workBuilding.Info.m_buildingAI is PoliceStationAI)
         {
             return originalInfo.m_gender == Citizen.Gender.Female ? _paramedic : _policeOfficer;
         }
         if (workBuilding.Info.m_buildingAI is CemeteryAI && originalInfo.m_gender == Citizen.Gender.Male)
         {
             return _hearseDriver;
         }
         if (workBuilding.Info.m_buildingAI is PlayerBuildingAI && originalInfo.m_gender == Citizen.Gender.Male)
         {
             return _policeOfficer;
         }
     }
     if (!_isDlcEnabled)
     {
         return originalInfo;
     }
     var r1 = new Randomizer(citizenID);
     var value = r1.Int32(15);
     Citizen.SubCulture subCulture;
     switch (value)
     {
         case 0:
             subCulture = Citizen.SubCulture.Hippie;
             break;
         case 1:
             subCulture = Citizen.SubCulture.Hipster;
             break;
         case 2:
             subCulture = Citizen.SubCulture.Redneck;
             break;
         default:
             return originalInfo;
     }
     var r2 = new Randomizer(citizenID);
     var info = Singleton<CitizenManager>.instance.GetGroupCitizenInfo(ref r2,
         originalInfo.GetService(),
         originalInfo.m_gender, subCulture, originalInfo.m_agePhase);
     if (info == null || info.m_citizenAI.GetType() != originalAI.GetType())
     {
         info = originalInfo;
     }
     return info;
 }
Example #35
0
 private void ArriveAtDestination(ushort instanceID, ref CitizenInstance citizenData, bool success)
 {
     Log.Error($"HumanAI.ArriveAtDestination is not overriden!");
 }
 private string GetServiceType(ref CitizenInstance inst)
 {
     if ((inst.m_flags & CitizenInstance.Flags.RidingBicycle) == CitizenInstance.Flags.RidingBicycle)
     {
         return "Citizen/Cycle";
     }
     else
     {
         return "Citizen/Foot";
     }
 }
Example #37
0
 private void PathfindSuccess(ushort instanceID, ref CitizenInstance data)
 {
     Log.Error($"HumanAI.PathfindSuccess is not overriden!");
 }
 private ushort CheckCitizen(ushort vehicleID, ref Vehicle vehicleData, Segment3 segment, float lastLen, float nextLen, ref float maxSpeed, ref bool blocked, float maxBraking, ushort otherID, ref CitizenInstance otherData, Vector3 min, Vector3 max)
 {
     if ((vehicleData.m_flags & Vehicle.Flags.Transition) == Vehicle.Flags.None && (otherData.m_flags & CitizenInstance.Flags.Transition) == CitizenInstance.Flags.None && (vehicleData.m_flags & Vehicle.Flags.Underground) != Vehicle.Flags.None != ((otherData.m_flags & CitizenInstance.Flags.Underground) != CitizenInstance.Flags.None))
     {
         return otherData.m_nextGridInstance;
     }
     CitizenInfo info = otherData.Info;
     CitizenInstance.Frame lastFrameData = otherData.GetLastFrameData();
     Vector3 position = lastFrameData.m_position;
     Vector3 b = lastFrameData.m_position + lastFrameData.m_velocity;
     Segment3 segment2 = new Segment3(position, b);
     Vector3 vector = segment2.Min();
     vector.x -= info.m_radius;
     vector.z -= info.m_radius;
     Vector3 vector2 = segment2.Max();
     vector2.x += info.m_radius;
     vector2.y += info.m_height;
     vector2.z += info.m_radius;
     float num;
     float num2;
     if (min.x < vector2.x + 1f && min.y < vector2.y && min.z < vector2.z + 1f && vector.x < max.x + 1f && vector.y < max.y + 2f && vector.z < max.z + 1f && segment.DistanceSqr(segment2, out num, out num2) < (1f + info.m_radius) * (1f + info.m_radius))
     {
         float num3 = lastLen + nextLen * num;
         if (num3 >= 0.01f)
         {
             num3 -= 2f;
             float b2 = Mathf.Max(1f, CustomCarAI.CalculateMaxSpeed(num3, 0f, maxBraking));
             maxSpeed = Mathf.Min(maxSpeed, b2);
         }
     }
     return otherData.m_nextGridInstance;
 }
        public override void LateUpdate()
        {
            if (FavCimsMainClass.UnLoading)
                return;
            if (this.MyInstanceID.IsEmpty || !FavCimsCore.RowID.ContainsKey (citizenINT)) {
                if(this.MyFamily != null) {
                    this.MyFamily.Hide();
                    this.MyFamily.MyInstanceID = InstanceID.Empty;
                    this.MyFamily = null;
                }
                GameObject.Destroy (this.gameObject);
                return;
            }

            if (this.DeadOrGone || this.HomeLess) {
                this.OtherInfoButton.isEnabled = false;
                this.OtherInfoButton.tooltip = FavCimsLang.text ("Citizen_Details_NoUnit");
            }else if(GetTemplate() == -1 && (this.MyFamily == null || this.MyFamily.MyInstanceID != MyInstanceID)) {
                if(this.MyFamily != null && this.MyFamily.MyInstanceID != MyInstanceID) {
                    this.MyFamily = null;
                }
                this.OtherInfoButton.isEnabled = false;
                this.OtherInfoButton.tooltip = FavCimsLang.text ("Citizen_Details_fullTemplate");
            } else {
                if(this.MyFamily != null && this.MyFamily.MyInstanceID == this.MyInstanceID && this.MyFamily.isVisible) {
                    this.OtherInfoButton.normalBgSprite = "CityInfoFocused";
                }else{
                    this.OtherInfoButton.normalBgSprite = "CityInfo";
                }
                this.OtherInfoButton.isEnabled = true;
                this.OtherInfoButton.tooltip = FavCimsLang.text ("Citizen_Details");
            }

            uint citizen = this.MyInstanceID.Citizen;

            //Is dead?
            if((citizen != 0) && this.MyCitizen.m_citizens.m_buffer[citizen].Dead && !this.CitizenIsDead) {
                this.CitizenIsDead = true;
                this.CitizenRowData ["deathrealage"] = "0";
            }

            if (this.execute) {

                try {

                    this.CitizenName = this.MyInstance.GetName (this.MyInstanceID);

                    citizenINT = (int)((UIntPtr)citizen);

                    if (this.CitizenName != null && this.CitizenName.Length > 0 && this.CitizenName != this.MyInstancedName) {
                        this.MyInstancedName = this.CitizenName;
                    }

                    this.citizenInfo = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].GetCitizenInfo (citizen);

                    this.FavCimsRowCloseButton.tooltip = FavCimsLang.text ("FavStarButton_disable_tooltip");

                    if (this.FavCimsCitizenSingleRowPanel != null && citizen != 0 && this.CitizenName == this.MyInstancedName && FavCimsCore.RowID.ContainsKey (citizenINT)) {

                        //Citizen Gender
                        this.CitizenRowData ["gender"] = Citizen.GetGender (citizen).ToString ();

                        //Name
                        this.CitizenRowData ["name"] = this.MyCitizen.GetCitizenName (citizen);
                        this.FavCimsCitizenName.text = this.CitizenRowData ["name"];
                        if (this.CitizenRowData ["gender"] == "Female") {
                            this.FavCimsCitizenName.textColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                        }

                        if (this.CitizenDistrict == 0) {
                            this.FavCimsCitizenName.tooltip = FavCimsLang.text ("NowInThisDistrict") + FavCimsLang.text ("DistrictNameNoDistrict");
                        } else {
                            this.FavCimsCitizenName.tooltip = FavCimsLang.text ("NowInThisDistrict") + MyDistrict.GetDistrictName (this.CitizenDistrict);
                        }

                        //Citizen Health
                        this.tmp_health = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_health;
                        this.CitizenRowData ["health"] = Citizen.GetHealthLevel (this.tmp_health).ToString ();

                        //Citizen Education
                        var tmp_education = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].EducationLevel;
                        this.CitizenRowData ["education"] = tmp_education.ToString ();
                        this.FavCimsEducation.text = FavCimsLang.text ("Education_" + this.CitizenRowData ["education"] + "_" + this.CitizenRowData ["gender"]);

                        if (this.CitizenRowData ["education"] == "ThreeSchools") {
                            this.FavCimsEducation.textColor = new Color32 (102, 204, 0, 60); //r,g,b,a
                        } else if (this.CitizenRowData ["education"] == "TwoSchools") {
                            this.FavCimsEducation.textColor = new Color32 (255, 204, 0, 32);
                        } else if (this.CitizenRowData ["education"] == "OneSchool") {
                            this.FavCimsEducation.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                        } else {
                            this.FavCimsEducation.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                        }

                        //Citizen Wellbeing
                        this.tmp_wellbeing = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_wellbeing;
                        this.CitizenRowData ["wellbeing"] = Citizen.GetWellbeingLevel (tmp_education, this.tmp_wellbeing).ToString ();

                        //Citizen Happiness
                        this.tmp_happiness = Citizen.GetHappiness (this.tmp_health, this.tmp_wellbeing);
                        //this.CitizenRowData ["happiness"] = Citizen.GetHappinessLevel (this.tmp_happiness).ToString (); //Bad, Poor, Good, Excellent, Suberb
                        this.CitizenRowData ["happiness_icon"] = GetHappinessString (Citizen.GetHappinessLevel (this.tmp_happiness));
                        this.FavCimsHappyIcon.normalBgSprite = this.CitizenRowData ["happiness_icon"];
                        this.FavCimsHappyIcon.tooltip = FavCimsLang.text (this.CitizenRowData ["happiness_icon"]);

                        //Age Group (Age Phase)
                        this.tmp_age = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_age;
                        this.CitizenRowData ["agegroup"] = Citizen.GetAgeGroup (this.tmp_age).ToString ();
                        this.FavCimsAgePhase.text = FavCimsLang.text ("AgePhase_" + this.CitizenRowData ["agegroup"] + "_" + this.CitizenRowData ["gender"]);

                        //Real Age
                        this.RealAge = FavCimsCore.CalculateCitizenAge (this.tmp_age);

                        if (this.RealAge <= 12) { //CHILD
                            this.FavCimsRealAge.text = this.RealAge.ToString ();
                            this.FavCimsRealAge.textColor = new Color32 (102, 204, 0, 60); //r,g,b,a
                            this.FavCimsAgePhase.textColor = new Color32 (102, 204, 0, 60); //r,g,b,a
                        } else if (this.RealAge <= 19) { //TEEN
                            this.FavCimsRealAge.text = this.RealAge.ToString ();
                            this.FavCimsRealAge.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                            this.FavCimsAgePhase.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                        } else if (this.RealAge <= 25) { //YOUNG
                            this.FavCimsRealAge.text = this.RealAge.ToString ();
                            this.FavCimsRealAge.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                            this.FavCimsAgePhase.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                        } else if (this.RealAge <= 65) { //ADULT
                            this.FavCimsRealAge.text = this.RealAge.ToString ();
                            this.FavCimsRealAge.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                            this.FavCimsAgePhase.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                        } else if (this.RealAge <= 90) { //SENIOR
                            this.FavCimsRealAge.text = this.RealAge.ToString ();
                            this.FavCimsRealAge.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                            this.FavCimsAgePhase.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                        } else { //FINAL
                            this.FavCimsRealAge.text = this.RealAge.ToString ();
                            this.FavCimsRealAge.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                            this.FavCimsAgePhase.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                        }

                        //Citizen Home
                        this.CitizenHome = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_homeBuilding;
                        if (this.CitizenHome != 0) {
                            this.HomeLess = false;
                            this.CitizenHomeID.Building = this.CitizenHome;
                            this.FavCimsCitizenHome.text = this.MyBuilding.GetBuildingName (this.CitizenHome, this.MyInstanceID);
                            this.FavCimsCitizenHome.isEnabled = true;
                            this.FavCimsCitizenHomeSprite.texture = TextureDB.FavCimsCitizenHomeTexture;
                            this.HomeInfo = this.MyBuilding.m_buildings.m_buffer [CitizenHomeID.Index].Info;

                            if (this.HomeInfo.m_class.m_service == ItemClass.Service.Residential) {

                                this.FavCimsCitizenHome.tooltip = null;

                                if (this.HomeInfo.m_class.m_subService == ItemClass.SubService.ResidentialHigh) {
                                    this.FavCimsCitizenHome.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                    this.FavCimsCitizenHomeSprite.texture = TextureDB.FavCimsCitizenHomeTextureHigh;
                                    this.FavCimsCitizenHome.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", ItemClass.SubService.ResidentialHigh.ToString ());
                                } else if (this.HomeInfo.m_class.m_subService == ItemClass.SubService.ResidentialLow) {
                                    this.FavCimsCitizenHome.textColor = new Color32 (0, 153, 0, 80); //r,g,b,a
                                    this.FavCimsCitizenHomeSprite.texture = TextureDB.FavCimsCitizenHomeTexture;
                                    this.FavCimsCitizenHome.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", ItemClass.SubService.ResidentialLow.ToString ());
                                }

                                switch (this.HomeInfo.m_class.m_level)
                                {
                                    case ItemClass.Level.Level5:
                                        this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [5];
                                        break;
                                    case ItemClass.Level.Level4:
                                        this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [4];
                                        break;
                                    case ItemClass.Level.Level3:
                                        this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [3];
                                        break;
                                    case ItemClass.Level.Level2:
                                        this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [2];
                                        break;
                                    default:
                                        this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [1];
                                        break;
                                }

                                /*
                                if (this.HomeInfo.m_class.m_level == ItemClass.Level.Level5) {
                                    this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [5];
                                } else if (this.HomeInfo.m_class.m_level == ItemClass.Level.Level4) {
                                    this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [4];
                                } else if (this.HomeInfo.m_class.m_level == ItemClass.Level.Level3) {
                                    this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [3];
                                } else if (this.HomeInfo.m_class.m_level == ItemClass.Level.Level2) {
                                    this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [2];
                                } else {
                                    this.FavCimsCitizenResidentialLevelSprite.texture = TextureDB.FavCimsResidentialLevel [1];
                                }
                                */

                                //District
                                this.HomeDistrict = (int)MyDistrict.GetDistrict (this.MyBuilding.m_buildings.m_buffer [CitizenHomeID.Index].m_position);

                                if (this.HomeDistrict == 0) {
                                    this.FavCimsCitizenHomeSprite.tooltip = FavCimsLang.text ("DistrictLabel") + FavCimsLang.text ("DistrictNameNoDistrict");
                                } else {
                                    this.FavCimsCitizenHomeSprite.tooltip = FavCimsLang.text ("DistrictLabel") + MyDistrict.GetDistrictName (this.HomeDistrict);
                                }
                            }
                        } else {
                            this.FavCimsCitizenHome.text = FavCimsLang.text ("Citizen_HomeLess");
                            this.FavCimsCitizenHome.isEnabled = false;
                            this.FavCimsCitizenHomeSprite.texture = TextureDB.FavCimsCitizenHomeTextureHomeless;
                            this.FavCimsCitizenHomeSprite.tooltip = FavCimsLang.text ("DistrictNameNoDistrict");
                            this.FavCimsCitizenHome.tooltip = FavCimsLang.text ("Citizen_HomeLess_tooltip");
                            this.FavCimsCitizenResidentialLevelSprite.texture = null;
                            this.HomeLess = true;
                        }

                        //Working Place
                        this.WorkPlace = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_workBuilding;
                        if (this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].GetCurrentSchoolLevel (citizen) != ItemClass.Level.None) {
                            this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                            this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsWorkingPlaceTextureStudent;
                            this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                            this.FavCimsWorkingPlace.tooltip = Locale.Get ("CITIZEN_SCHOOL_LEVEL", this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].GetCurrentSchoolLevel (citizen).ToString ());
                        } else if (this.WorkPlace == 0) {
                            this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;

                            if (this.tmp_age >= 180) {
                                //In Pensione
                                this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsWorkingPlaceTextureRetired;
                                this.FavCimsWorkingPlace.text = FavCimsLang.text ("Citizen_Retired");
                                this.FavCimsWorkingPlace.isEnabled = false;
                                this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Citizen_Retired_tooltip");
                                this.FavCimsWorkingPlaceSprite.tooltip = null;
                                this.FavCimsWorkingPlaceButtonGamDefImg.tooltip = null;
                                this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                            } else {
                                this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsWorkingPlaceTexture; //unemployed
                                this.FavCimsWorkingPlace.text = Locale.Get ("CITIZEN_OCCUPATION_UNEMPLOYED");
                                this.FavCimsWorkingPlace.isEnabled = false;
                                this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Unemployed_tooltip");
                                this.FavCimsWorkingPlaceSprite.tooltip = null;
                                this.FavCimsWorkingPlaceButtonGamDefImg.tooltip = null;
                                this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                            }
                        }

                        if (this.WorkPlace != 0) {
                            this.WorkPlaceID.Building = this.WorkPlace;
                            this.FavCimsWorkingPlace.text = this.MyBuilding.GetBuildingName (this.WorkPlace, this.MyInstanceID);
                            this.FavCimsWorkingPlace.isEnabled = true;
                            this.WorkInfo = this.MyBuilding.m_buildings.m_buffer [WorkPlaceID.Index].Info;

                            if (this.WorkInfo.m_class.m_service == ItemClass.Service.Commercial) {
                                this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                                if (this.WorkInfo.m_class.m_subService == ItemClass.SubService.CommercialHigh) {
                                    this.FavCimsWorkingPlace.textColor = new Color32 (0, 51, 153, 147); //r,g,b,a
                                    this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenCommercialHighTexture;
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", ItemClass.SubService.CommercialHigh.ToString ());
                                } else {
                                    this.FavCimsWorkingPlace.textColor = new Color32 (0, 153, 204, 130); //r,g,b,a
                                    this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenCommercialLowTexture;
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", ItemClass.SubService.CommercialLow.ToString ());
                                }

                                switch (this.WorkInfo.m_class.m_level)
                                {
                                    case ItemClass.Level.Level3:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [3];
                                        break;
                                    case ItemClass.Level.Level2:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [2];
                                        break;
                                    default:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [1];
                                        break;
                                }

                                /*
                                if (this.WorkInfo.m_class.m_level == ItemClass.Level.Level3) {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [3];
                                } else if (this.WorkInfo.m_class.m_level == ItemClass.Level.Level2) {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [2];
                                } else {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [1];
                                }
                                */

                            } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Industrial) {

                                this.FavCimsWorkingPlace.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                this.FavCimsWorkingPlace.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", "Industrial");

                                switch (this.WorkInfo.m_class.m_subService)
                                {
                                    case ItemClass.SubService.IndustrialFarming:
                                        this.FavCimsWorkingPlaceSprite.texture = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyFarming";
                                        break;
                                    case ItemClass.SubService.IndustrialForestry:
                                        this.FavCimsWorkingPlaceSprite.texture = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ResourceForestry";
                                        break;
                                    case ItemClass.SubService.IndustrialOil:
                                        this.FavCimsWorkingPlaceSprite.texture = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyOil";
                                        break;
                                    case ItemClass.SubService.IndustrialOre:
                                        this.FavCimsWorkingPlaceSprite.texture = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyOre";
                                        break;
                                    default:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                                        this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenIndustrialGenericTexture;
                                        break;
                                }
                                /*
                                if (this.WorkInfo.m_class.m_subService == ItemClass.SubService.IndustrialFarming) {
                                    this.FavCimsWorkingPlaceSprite.texture = null;
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyFarming";
                                } else if (this.WorkInfo.m_class.m_subService == ItemClass.SubService.IndustrialForestry) {
                                    this.FavCimsWorkingPlaceSprite.texture = null;
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ResourceForestry";
                                } else if (this.WorkInfo.m_class.m_subService == ItemClass.SubService.IndustrialOil) {
                                    this.FavCimsWorkingPlaceSprite.texture = null;
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyOil";
                                } else if (this.WorkInfo.m_class.m_subService == ItemClass.SubService.IndustrialOre) {
                                    this.FavCimsWorkingPlaceSprite.texture = null;
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyOre";
                                } else {
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                                    this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenIndustrialGenericTexture;
                                }
                                */

                                switch (this.WorkInfo.m_class.m_level)
                                {
                                    case ItemClass.Level.Level3:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [3];
                                        break;
                                    case ItemClass.Level.Level2:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [2];
                                        break;
                                    default:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [1];
                                        break;
                                }

                                /*
                                if (this.WorkInfo.m_class.m_level == ItemClass.Level.Level3) {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [3];
                                } else if (this.WorkInfo.m_class.m_level == ItemClass.Level.Level2) {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [2];
                                } else {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [1];
                                }
                                */

                            } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Office) {
                                this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                                this.FavCimsWorkingPlace.textColor = new Color32 (0, 204, 255, 128); //r,g,b,a
                                this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenOfficeTexture;
                                this.FavCimsWorkingPlace.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", "Office");

                                switch (this.WorkInfo.m_class.m_level)
                                {
                                    case ItemClass.Level.Level3:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [3];
                                        break;
                                    case ItemClass.Level.Level2:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [2];
                                        break;
                                    default:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [1];
                                        break;
                                }

                                /*
                                if (this.WorkInfo.m_class.m_level == ItemClass.Level.Level3) {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [3];
                                } else if (this.WorkInfo.m_class.m_level == ItemClass.Level.Level2) {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [2];
                                } else {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [1];
                                }
                                */

                            } else {
                                this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                                this.FavCimsWorkingPlace.textColor = new Color32 (153, 102, 51, 20); //r,g,b,a

                                switch (this.WorkInfo.m_class.m_service)
                                {
                                    case ItemClass.Service.FireDepartment:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "InfoIconFireSafety";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "FireDepartment");
                                        break;
                                    case ItemClass.Service.HealthCare:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconHealthcareFocused";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Healthcare");
                                        break;
                                    case ItemClass.Service.PoliceDepartment:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconPolice";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Police");
                                        break;
                                    case ItemClass.Service.Garbage:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyRecycling";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Garbage");
                                        break;
                                    case ItemClass.Service.Electricity:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyPowerSaving";
                                        this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Electricity_job");
                                        break;
                                    case ItemClass.Service.Education:
                                        this.FavCimsWorkingPlace.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "InfoIconEducationPressed";
                                        break;
                                    case ItemClass.Service.Beautification:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "SubBarBeautificationParksnPlazas";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Beautification");
                                        break;
                                    case ItemClass.Service.Government:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconGovernment";
                                        this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Government_job");
                                        break;
                                    case ItemClass.Service.Water:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyWaterSaving";
                                        this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Water_job");
                                        break;
                                    case ItemClass.Service.PublicTransport:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyFreePublicTransport";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "PublicTransport");
                                        break;
                                    case ItemClass.Service.Monument:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "FeatureMonumentLevel6";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Monuments");
                                        break;
                                    default:
                                        this.FavCimsWorkingPlace.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyNone";
                                        this.FavCimsWorkingPlace.tooltip = null;
                                        break;
                                }

                                /*
                                if (this.WorkInfo.m_class.m_service == ItemClass.Service.FireDepartment) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "InfoIconFireSafety";
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "FireDepartment");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.HealthCare) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconHealthcareFocused";
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Healthcare");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.PoliceDepartment) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconPolice";
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Police");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Garbage) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyRecycling";
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Garbage");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Electricity) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyPowerSaving";
                                    this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Electricity_job");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Education) {

                                    this.FavCimsWorkingPlace.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "InfoIconEducationPressed";

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Beautification) { //parchi

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "SubBarBeautificationParksnPlazas";
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Beautification");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Government) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconGovernment";
                                    this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Government_job");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Water) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyWaterSaving";
                                    this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Water_job");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.PublicTransport) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyFreePublicTransport";
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "PublicTransport");

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Monument) {

                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "FeatureMonumentLevel6";
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Monuments");

                                } else if (this.WorkInfo.m_class.m_service != ItemClass.Service.None) {

                                    this.FavCimsWorkingPlace.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyNone";
                                    this.FavCimsWorkingPlace.tooltip = null;
                                }
                                */
                                this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                            }

                            //District
                            this.WorkDistrict = (int)MyDistrict.GetDistrict (this.MyBuilding.m_buildings.m_buffer [WorkPlaceID.Index].m_position);

                            if (this.WorkDistrict == 0) {
                                this.FavCimsWorkingPlaceSprite.tooltip = FavCimsLang.text ("DistrictLabel") + FavCimsLang.text ("DistrictNameNoDistrict");
                            } else {
                                this.FavCimsWorkingPlaceSprite.tooltip = FavCimsLang.text ("DistrictLabel") + MyDistrict.GetDistrictName (this.WorkDistrict);
                            }

                        } else {
                            this.FavCimsWorkingPlace.isEnabled = false;
                            this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                            this.FavCimsWorkingPlaceButtonGamDefImg.tooltip = null;
                            this.FavCimsWorkingPlaceSprite.tooltip = null;
                        }

                        this.InstanceCitizenID = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_instance;
                        this.citizenInstance = this.MyCitizen.m_instances.m_buffer [InstanceCitizenID];

                        if (this.citizenInstance.m_targetBuilding != 0) {

                            this.CitizenVehicle = this.MyCitizen.m_citizens.m_buffer [citizen].m_vehicle;
                            this.MyVehicleID = InstanceID.Empty;

                            GoingOutside = (MyBuilding.m_buildings.m_buffer [this.citizenInstance.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None;

                            if (this.CitizenVehicle != 0) {

                                this.MyVehicleID.Vehicle = this.CitizenVehicle;

                                this.FavCimsLastActivityVehicleButton.isEnabled = true;

                                this.VehInfo = this.MyVehicle.m_vehicles.m_buffer [this.CitizenVehicle].Info;

                                this.CitizenVehicleName = this.MyVehicle.GetVehicleName (this.CitizenVehicle);

                                if (this.VehInfo.m_class.m_service == ItemClass.Service.Residential) {
                                    //sta usando una macchina
                                    if (this.VehInfo.m_vehicleAI.GetOwnerID (this.CitizenVehicle, ref MyVehicle.m_vehicles.m_buffer [this.CitizenVehicle]).Citizen == citizen) {
                                        //sta usando la sua macchina.
                                        if (GoingOutside)
                                            LeaveCity = true;

                                        this.FavCimsLastActivityVehicleButton.normalBgSprite = "IconCitizenVehicle";
                                        this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "IconTouristVehicle";

                                        this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName;
                                    }

                                } else if (this.VehInfo.m_class.m_service == ItemClass.Service.PublicTransport) {
                                    //sta usando un mezzo pubblico
                                    if (GoingOutside)
                                        LeaveCity = true;

                                    switch (this.VehInfo.m_class.m_subService)
                                    {
                                        case ItemClass.SubService.PublicTransportBus:

                                            this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportBus";
                                            this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportBusHovered";
                                            this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportBusFocused";
                                            this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportBusPressed";
                                            this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Bus");

                                            break;

                                        case ItemClass.SubService.PublicTransportMetro:

                                            this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportMetro";
                                            this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportMetroHovered";
                                            this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportMetroFocused";
                                            this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportMetroPressed";

                                            this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Metro");

                                            break;

                                        case ItemClass.SubService.PublicTransportPlane:

                                            this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportPlane";
                                            this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportPlaneHovered";
                                            this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportPlaneFocused";
                                            this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportPlanePressed";

                                            this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Plane");

                                            break;
                                        case ItemClass.SubService.PublicTransportShip:

                                            this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportShip";
                                            this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportShipHovered";
                                            this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportShipFocused";
                                            this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportShipPressed";

                                            this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Ship");

                                            break;
                                        case ItemClass.SubService.PublicTransportTrain:

                                            this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportTrain";
                                            this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportTrainHovered";
                                            this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportTrainFocused";
                                            this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportTrainPressed";

                                            if (this.CitizenVehicleName == "VEHICLE_TITLE[Train Passenger]:0")
                                                this.CitizenVehicleName = Locale.Get ("VEHICLE_TITLE", "Train Engine");

                                            this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Train");

                                            break;
                                    }
                                    /*
                                    if (this.VehInfo.m_class.m_subService == ItemClass.SubService.PublicTransportBus) {

                                        this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportBus";
                                        this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportBusHovered";
                                        this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportBusFocused";
                                        this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportBusPressed";

                                        this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Bus");

                                    } else if (this.VehInfo.m_class.m_subService == ItemClass.SubService.PublicTransportMetro) {

                                        this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportMetro";
                                        this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportMetroHovered";
                                        this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportMetroFocused";
                                        this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportMetroPressed";

                                        this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Metro");

                                    } else if (this.VehInfo.m_class.m_subService == ItemClass.SubService.PublicTransportPlane) {

                                        this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportPlane";
                                        this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportPlaneHovered";
                                        this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportPlaneFocused";
                                        this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportPlanePressed";

                                        this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Plane");

                                    } else if (this.VehInfo.m_class.m_subService == ItemClass.SubService.PublicTransportShip) {

                                        this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportShip";
                                        this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportShipHovered";
                                        this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportShipFocused";
                                        this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportShipPressed";

                                        this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Ship");

                                    } else if (this.VehInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTrain) {

                                        this.FavCimsLastActivityVehicleButton.normalBgSprite = "SubBarPublicTransportTrain";
                                        this.FavCimsLastActivityVehicleButton.hoveredBgSprite = "SubBarPublicTransportTrainHovered";
                                        this.FavCimsLastActivityVehicleButton.focusedBgSprite = "SubBarPublicTransportTrainFocused";
                                        this.FavCimsLastActivityVehicleButton.pressedBgSprite = "SubBarPublicTransportTrainPressed";

                                        if (this.CitizenVehicleName == "VEHICLE_TITLE[Train Passenger]:0")
                                            this.CitizenVehicleName = Locale.Get ("VEHICLE_TITLE", "Train Engine");

                                        this.FavCimsLastActivityVehicleButton.tooltip = this.CitizenVehicleName + " - " + Locale.Get ("SUBSERVICE_DESC", "Train");
                                    }
                                    */
                                }
                            } else {
                                if (GoingOutside)
                                    LeaveCity = true;

                                this.FavCimsLastActivityVehicleButton.disabledBgSprite = "InfoIconPopulationDisabled";
                                this.FavCimsLastActivityVehicleButton.isEnabled = false;
                                this.FavCimsLastActivityVehicleButton.tooltip = FavCimsLang.text ("Vehicle_on_foot");
                            }
                        } else {

                            this.FavCimsLastActivityVehicleButton.disabledBgSprite = "InfoIconPopulationDisabled";
                            this.FavCimsLastActivityVehicleButton.isEnabled = false;
                            this.FavCimsLastActivityVehicleButton.tooltip = null;
                        }

                        //Citizen Status
                        this.CitizenStatus = citizenInfo.m_citizenAI.GetLocalizedStatus (citizen, ref this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index], out this.MyTargetID);
                        this.CitizenTarget = this.MyBuilding.GetBuildingName (this.MyTargetID.Building, this.MyInstanceID);
                        this.FavCimsLastActivity.text = this.CitizenStatus + " " + this.CitizenTarget;

                        if (!this.MyTargetID.IsEmpty) {

                            //District
                            this.TargetDistrict = (int)MyDistrict.GetDistrict (this.MyBuilding.m_buildings.m_buffer [MyTargetID.Index].m_position);

                            if (this.TargetDistrict == 0) {
                                this.FavCimsLastActivity.tooltip = FavCimsLang.text ("DistrictLabel") + FavCimsLang.text ("DistrictNameNoDistrict");
                            } else {
                                this.FavCimsLastActivity.tooltip = FavCimsLang.text ("DistrictLabel") + MyDistrict.GetDistrictName (this.TargetDistrict);
                            }
                        }

                        //Now in this District
                        this.CitizenDistrict = (int)MyDistrict.GetDistrict (citizenInstance.GetSmoothPosition (InstanceCitizenID));

                        //Il carro funebre lo ha caricato
                        //if (((citizen != 0) && MyCitizen.m_citizens.m_buffer[citizen].Dead) && (MyCitizen.m_citizens.m_buffer[citizen].CurrentLocation == Citizen.Location.Moving)) {
                        if(this.CitizenIsDead) {
                            //try
                            //{
                            this.FavCimsHappyIcon.normalBgSprite = "NotificationIconDead";
                            this.FavCimsHappyIcon.tooltip = FavCimsLang.text ("People_Life_Status_Dead");

                            if(this.CitizenRowData ["deathrealage"] == "0")
                                this.CitizenRowData ["deathrealage"] = this.RealAge.ToString();

                            this.FavCimsRealAge.text = this.CitizenRowData ["deathrealage"];

                            if (this.DeathDate == null) {
                                this.DeathDate = GameTime.FavCimsDate (FavCimsLang.text ("time_format"),"n/a");
                                this.DeathTime = GameTime.FavCimsTime ();
                            }
                            this.FavCimsCitizenName.tooltip =
                                FavCimsLang.text ("People_Life_Status_Dead") + " " +
                                    FavCimsLang.text ("People_Life_Status_Dead_date") + " " + this.DeathDate + " " +
                                    FavCimsLang.text ("People_Life_Status_Dead_time") + " " + this.DeathTime;

                            if(MyCitizen.m_citizens.m_buffer[citizen].CurrentLocation == Citizen.Location.Moving) {
                                this.hearse = this.MyCitizen.m_citizens.m_buffer [citizen].m_vehicle;

                                if(hearse != 0) {
                                    this.CitizenDead.Citizen = citizen;
                                    this.MyVehicleID.Vehicle = hearse;

                                    this.FavCimsLastActivityVehicleButton.normalBgSprite = "NotificationIconVerySick";
                                    this.FavCimsLastActivityVehicleButton.isEnabled = true;
                                    this.FavCimsLastActivityVehicleButton.playAudioEvents = true;
                                    this.FavCimsLastActivityVehicleButton.tooltip = Locale.Get ("VEHICLE_TITLE", "Hearse");
                                    this.FavCimsLastActivity.text = FavCimsLang.text("Citizen_on_hearse");
                                }
                            } else if(MyCitizen.m_citizens.m_buffer[citizen].CurrentLocation != Citizen.Location.Moving && this.hearse == 0) { //Verificare con unspawn
                                //aspetta il carro funebre
                                this.FavCimsLastActivity.text = FavCimsLang.text("Citizen_wait_hearse");
                                this.FavCimsLastActivityVehicleButton.disabledBgSprite = "NotificationIconVerySick";
                                this.FavCimsLastActivityVehicleButton.isEnabled = false;
                            } else {
                                //lo stanno seppellendo
                                this.FavCimsLastActivity.text = FavCimsLang.text("Citizen_hisfuneral");
                                this.FavCimsLastActivityVehicleButton.disabledBgSprite = "NotificationIconVerySick";
                                this.FavCimsLastActivityVehicleButton.isEnabled = false;
                            }
                            //}catch (Exception e) {
                            //	Debug.Log("error + " + e.ToString());
                            //}
                        }

                    } else {
                        if(this.rowLang == null || this.rowLang != FavCimsLang.GameLanguage)
                            this.DeadOrGone = false;

                        if (!this.DeadOrGone) {
                            this.rowLang = FavCimsLang.GameLanguage;
                            this.DeadOrGone = true;

                            if (this.FavCimsCitizenSingleRowPanel != null && FavCimsCore.RowID.ContainsKey (citizenINT) && this.MyInstancedName.Length > 0) {

                                if(this.DeathDate != null) {
                                    this.DeathDate = GameTime.FavCimsDate (FavCimsLang.text ("time_format"), this.DeathDate);
                                }

                                if (this.DeathDate == null) {
                                    this.DeathDate = GameTime.FavCimsDate (FavCimsLang.text ("time_format"),"n/a");
                                    this.DeathTime = GameTime.FavCimsTime ();
                                }

                                //if(this.citflags != null)
                                    //Debug.Log(this.citflags);

                                //Debug.Log(this.FavCimsCitizenName.text + " is dead on date " + this.DeathDate + " at time " + this.DeathTime);

                                this.FavCimsCitizenName.disabledTextColor = new Color32 (51, 51, 51, 160); //r,g,b,a
                                this.FavCimsCitizenName.isEnabled = false;
                                this.FavCimsEducation.textColor = new Color32 (51, 51, 51, 160); //r,g,b,a
                                this.FavCimsRealAge.textColor = new Color32 (51, 51, 51, 160); //r,g,b,a
                                this.FavCimsAgePhase.textColor = new Color32 (51, 51, 51, 160); //r,g,b,a

                                if (!LeaveCity && (this.CitizenIsDead || this.RealAge > 65)) { //Dead Peoples (this.CitizenDead == this.MyInstanceID || this.RealAge > 65)

                                    try
                                    {
                                        //Citizen Life Status
                                        //this.CitizenRowData ["lifestatus"] = "People_Life_Status_Dead";

                                        //Happiness x.x
                                        //this.CitizenRowData ["happiness_icon"] = "NotificationIconDead";
                                        this.FavCimsHappyIcon.normalBgSprite = "NotificationIconDead";
                                        this.FavCimsHappyIcon.tooltip = FavCimsLang.text ("People_Life_Status_Dead");

                                        //Name
                                        //this.CitizenRowData ["name"] = this.MyInstancedName;
                                        this.FavCimsCitizenName.text = this.MyInstancedName;
                                        this.FavCimsCitizenName.tooltip =
                                            FavCimsLang.text ("People_Life_Status_Dead") + " " +
                                            FavCimsLang.text ("People_Life_Status_Dead_date") + " " + this.DeathDate + " " +
                                            FavCimsLang.text ("People_Life_Status_Dead_time") + " " + this.DeathTime;

                                        //Info Button
                                        this.OtherInfoButton.isEnabled = false;

                                        //AgePhase
                                        //this.CitizenRowData ["agegroup"] = "Dead";
                                        this.FavCimsAgePhase.text = FavCimsLang.text ("AgePhaseDead_" + this.CitizenRowData ["gender"]);

                                        //Home
                                        this.FavCimsCitizenHome.text = FavCimsLang.text ("Home_Location_Dead");
                                        this.FavCimsCitizenHomeSprite.texture = TextureDB.FavCimsCitizenHomeTextureDead;
                                        this.FavCimsCitizenHome.tooltip = null;
                                        this.FavCimsCitizenHome.isEnabled = false;
                                        this.FavCimsCitizenResidentialLevelSprite.texture = null;
                                        this.FavCimsCitizenHomeSprite.tooltip = null;

                                        //Working Place
                                        this.FavCimsWorkingPlace.isEnabled = false;
                                        this.FavCimsWorkingPlace.tooltip = null;
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                                        this.FavCimsWorkingPlaceSprite.tooltip = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.tooltip = null;

                                        //Last Activity
                                        this.FavCimsLastActivity.isEnabled = false;
                                        this.FavCimsLastActivityVehicleButton.isEnabled = false;
                                        this.FavCimsLastActivityVehicleButton.disabledBgSprite = "NotificationIconDead";
                                        this.FavCimsLastActivityVehicleButton.tooltip = null;
                                        this.FavCimsLastActivity.tooltip = null;
                                        this.FavCimsLastActivity.text = FavCimsLang.text("Citizen_buried");

                                        this.CitizenRowData.Clear ();
                                    }catch (Exception e) {
                                        Debug.Error("error " + e.ToString());
                                    }

                                } else {

                                    //Citizen Life Status
                                    //this.CitizenRowData ["lifestatus"] = "People_Life_Status_IsGone";

                                    //Happiness ==>
                                    //this.CitizenRowData ["happiness_icon"] = "";
                                    this.FavCimsHappyIcon.normalBgSprite = "";
                                    this.FavCimsHappyIcon.tooltip = null;

                                    //Happiness Icon Override (For leaving people)
                                    this.FavCimsHappyOverride.texture = TextureDB.FavCimsHappyOverride_texture;
                                    this.FavCimsHappyOverride.relativePosition = new Vector3 (0, 0);
                                    this.FavCimsHappyOverride.tooltip = FavCimsLang.text ("People_Life_Status_IsGone");

                                    //Name
                                    //this.CitizenRowData ["name"] = this.MyInstancedName;
                                    this.FavCimsCitizenName.text = this.MyInstancedName;
                                    this.FavCimsCitizenName.tooltip =
                                        FavCimsLang.text ("People_Life_Status_IsGone") + " " +
                                        FavCimsLang.text ("People_Life_Status_Dead_date") + " " + this.DeathDate + " " +
                                        FavCimsLang.text ("People_Life_Status_Dead_time") + " " + this.DeathTime;

                                    //Info Button
                                    this.OtherInfoButton.isEnabled = false;

                                    //Home
                                    this.FavCimsCitizenHome.text = FavCimsLang.text ("HomeOutsideTheCity");
                                    this.FavCimsCitizenHomeSprite.texture = TextureDB.FavCimsCitizenHomeTextureHomeless;
                                    this.FavCimsCitizenHome.tooltip = null;
                                    this.FavCimsCitizenHome.isEnabled = false;
                                    this.FavCimsCitizenResidentialLevelSprite.texture = null;
                                    this.FavCimsCitizenHomeSprite.tooltip = null;

                                    //Working Place
                                    this.FavCimsWorkingPlace.isEnabled = false;
                                    this.FavCimsWorkingPlace.tooltip = null;
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;

                                    //Last Activity
                                    //Ha lasciato la citta'.
                                    this.FavCimsLastActivity.isEnabled = false;
                                    this.FavCimsLastActivityVehicleButton.isEnabled = false;
                                    this.FavCimsLastActivityVehicleButton.disabledBgSprite = "NotificationIconDead";
                                    this.FavCimsLastActivity.tooltip = null;

                                    this.CitizenRowData.Clear ();
                                }

                            } else {

                                try {
                                    if(this.MyFamily != null) {
                                        this.MyFamily.Hide();
                                        this.MyFamily.MyInstanceID = InstanceID.Empty;
                                        this.MyFamily = null;
                                    }
                                    GameObject.Destroy (this.gameObject);
                                } catch { /*(Exception e)*/
                                    //Debug.Log ("CitizenName Error Destroy Object" + e.ToString ());
                                }
                            }
                        }
                    }
                } catch { /*(Exception e)*/
                    //Debug.Error ("Update Row Error" + e.ToString ());
                }
            }
            return;
        }
        internal void FamilyPet(uint m_citizen)
        {
            if (m_citizen == 0)
                return;

            try
            {
                //Family Pets
                this.CitizenInstance = this.MyCitizen.m_citizens.m_buffer[m_citizen].m_instance;

                //if (this.CitizenInstance != 0) {
                this.Pet = (ushort)Array.FindIndex (MyCitizen.m_instances.m_buffer, element => element.m_targetBuilding == this.CitizenInstance);

                this.PetInstance = this.MyCitizen.m_instances.m_buffer [this.Pet];

                //if (this.PetInstance.Info.m_citizenAI.m_info.GetService() == h

                //Citizen.Flags.DummyTraffic
                //Vehicle.Flags.WaitingTarget

                if (this.PetInstance.Info.m_citizenAI.IsAnimal ()) {

                    this.DogOwner = m_citizen;

                    this.MyPetID.CitizenInstance = this.Pet;

                    if (!this.MyPetID.IsEmpty) {

                        InstanceID MyPetTargetID;

                        string petname = MyCitizen.GetInstanceName (Pet);
                        CitizenInfo petinfo = PetInstance.Info;
                        string petstatus = petinfo.m_citizenAI.GetLocalizedStatus (Pet, ref PetInstance, out MyPetTargetID);

                        this.BubbleFamilyBarDogButton.texture = TextureDB.BubbleDog;
                        this.BubbleFamilyBarDogButton.tooltip = petname + " - " + petstatus + " " + this.MyCitizen.GetCitizenName (m_citizen);
                        this.BubbleFamilyBarDogButton.playAudioEvents = true;
                    }
                } else {

                    this.DogOwner = 0;

                    this.BubbleFamilyBarDogButton.texture = TextureDB.BubbleDogDisabled;
                    this.BubbleFamilyBarDogButton.tooltip = null;
                    this.BubbleFamilyBarDogButton.playAudioEvents = false;
                    this.MyPetID = InstanceID.Empty;
                }
                //} else {
                //return;
                //}
            } catch /*(Exception e)*/ {
                //Debug.Log("Family Dog Error - " + e.ToString());
            }
        }
        private bool GetAnimal()
        {
            _animal = _instance.m_instances.m_buffer[(int)_id];

            if (_animal.Info == null)
                return false;

            if (!_animal.Info.m_citizenAI.IsAnimal())
                return false;

            if ((_animal.m_flags & CitizenInstance.Flags.Created) == CitizenInstance.Flags.None)
                return false;

            if (float.IsNegativeInfinity(_animal.Info.m_maxRenderDistance))
                return false;

            return true;
        }
 protected void ReachedDestination(uint citizen, CitizenInstance citizenData)
 {
     BuildingManager manager2 = Singleton<BuildingManager>.instance;
     BuildingInfo info = manager2.m_buildings.m_buffer[citizenData.m_sourceBuilding].Info;
     int amountDelta = 50;
     info.m_buildingAI.ModifyMaterialBuffer(citizenData.m_sourceBuilding, ref manager2.m_buildings.m_buffer[citizenData.m_sourceBuilding], TransferManager.TransferReason.Worker0, ref amountDelta);
     //Logger.dbgLog(citizen.ToString() + "  chappy was:" + commuteHappinness[citizen].ToString() + " *3.0 + cwait:"+ commuteWait[citizen].ToString() + " // 4  will be: " + (((int)commuteHappinness[citizen] * 3.0 + (int)commuteWait[citizen]) / 4.0).ToString());
     commuteHappinness[citizen] = (byte)Mathf.Clamp((int)( ( (int)commuteHappinness[citizen] * 3.0 + (int)commuteWait[citizen]) / 4.0), 0, 255);
     commuteWait[citizen] = 0;
     //            if (commuteHappinness[citizen] > 0)
     //            {
     //                Logger.dbgLog(citizen.ToString() + "  chappy now:" + commuteHappinness[citizen].ToString() + "cwait:" + commuteWait[citizen].ToString());
     //            }
 }
 private bool TryJoinVehicle(ushort instanceID, ref CitizenInstance citizenData, ushort vehicleID, ref Vehicle vehicleData)
 {
     if ((vehicleData.m_flags & Vehicle.Flags.Stopped) == Vehicle.Flags.None)
     {
         return false;
     }
     CitizenManager instance = Singleton<CitizenManager>.instance;
     uint num = vehicleData.m_citizenUnits;
     int num2 = 0;
     while (num != 0u)
     {
         uint nextUnit = instance.m_units.m_buffer [(int)((UIntPtr)num)].m_nextUnit;
         for (int i = 0; i < 5; i++)
         {
             uint citizen = instance.m_units.m_buffer [(int)((UIntPtr)num)].GetCitizen (i);
             if (citizen != 0u)
             {
                 ushort instance2 = instance.m_citizens.m_buffer [(int)((UIntPtr)citizen)].m_instance;
                 if (instance2 != 0 && instance.m_instances.m_buffer [(int)instance2].m_targetBuilding == citizenData.m_targetBuilding)
                 {
                     instance.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetVehicle (citizenData.m_citizen, vehicleID, 0u);
                     if (instance.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].m_vehicle == vehicleID)
                     {
                         if (citizenData.m_path != 0u)
                         {
                             Singleton<PathManager>.instance.ReleasePath (citizenData.m_path);
                             citizenData.m_path = 0u;
                         }
                         return true;
                     }
                 }
                 break;
             }
         }
         num = nextUnit;
         if (++num2 > 524288)
         {
             CODebugBase<LogChannel>.Error (LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
             break;
         }
     }
     return false;
 }
Example #44
0
 private void Spawn(ushort instanceID, ref CitizenInstance data)
 {
     Log.Error($"HumanAI.Spawn is not overriden!");
 }
 public static bool PreGetColor(ushort instanceID, ref CitizenInstance data, InfoManager.InfoMode infoMode, ref Color __result) =>
 ACEColorGenUtils.GetColorGeneric <CitizenAssetFolderRuleXml, CitizenCityDataRuleXml, CitizenInfo>(
     ref __result,
     instanceID,
     ref AssetColorExpanderMod.Controller.CachedColor[(int)CacheOrder.CITIZEN],
     infoMode, ColorParametersGetter, Accepts, (x, y) => instanceID);
Example #46
0
 // CHECKME: check if this method allows to make people get away from traffic
 private static ushort CheckCitizen(Segment3 segment, float lastLen, float nextLen, ref float maxSpeed, ref bool blocked, float maxBraking, ushort otherID, ref CitizenInstance otherData, Vector3 min, Vector3 max)
 {
     CitizenInfo info = otherData.Info;
     CitizenInstance.Frame lastFrameData = otherData.GetLastFrameData();
     Vector3 position = lastFrameData.m_position;
     Vector3 b = lastFrameData.m_position + lastFrameData.m_velocity;
     Segment3 segment2 = new Segment3(position, b);
     Vector3 vector = segment2.Min();
     vector.x -= info.m_radius;
     vector.z -= info.m_radius;
     Vector3 vector2 = segment2.Max();
     vector2.x += info.m_radius;
     vector2.y += info.m_height;
     vector2.z += info.m_radius;
     float num;
     float num2;
     if (min.x < vector2.x + 1f && min.y < vector2.y && min.z < vector2.z + 1f && vector.x < max.x + 1f && vector.y < max.y + 2f && vector.z < max.z + 1f && segment.DistanceSqr(segment2, out num, out num2) < (1f + info.m_radius) * (1f + info.m_radius))
     {
         float num3 = lastLen + nextLen * num;
         if (num3 >= 0.01f)
         {
             num3 -= 2f;
             float b2 = Mathf.Max(1f, CalculateMaxSpeed(num3, 0f, maxBraking));
             maxSpeed = Mathf.Min(maxSpeed, b2);
         }
     }
     return otherData.m_nextGridInstance;
 }
Example #47
0
 private void GetBuildingTargetPosition(ushort instanceID, ref CitizenInstance citizenData, float minSqrDistance)
 {
     Log.Error($"HumanAI.GetBuildingTargetPosition is not overriden!");
 }
Example #48
0
        protected override VehicleInfo GetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceProbability, out VehicleInfo trailer)
        {
            Randomizer r = new Randomizer(citizenData.m_citizen);

            trailer = (VehicleInfo)null;
            if (citizenData.m_citizen == 0U)
            {
                return((VehicleInfo)null);
            }

            try
            {
                if (!Utils.GetOutsideConnections().Contains(citizenData.m_sourceBuilding))  // tourist is NOT at an outside connection
                {
                    Debug.LogWarning("Spawned only bikes for the toursit");
                    return(Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref r, ItemClass.Service.Residential, ItemClass.SubService.ResidentialHigh, ItemClass.Level.Level2));  // bikes
                }
            }
            catch (Exception e)
            {
                Debug.Log("error when trying to spawn only bikes" + e);
            }

            // otherwise use original game code, they are just trying to drive to the city
            Citizen.Wealth wealthLevel = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel;
            int            num1;
            int            num2;
            int            num3;

            if (forceProbability || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None)
            {
                num1 = 100;
                num2 = 0;
                num3 = wealthLevel == Citizen.Wealth.Low ? 20 : wealthLevel == Citizen.Wealth.Medium ? 30 : 40;  // camper prob
            }
            else
            {
                num1 = 20;  // car prob
                num2 = 20;  // bike prob
                num3 = 0;
            }
            bool flag1 = r.Int32(100U) < num1;
            bool flag2 = r.Int32(100U) < num2;
            bool flag3 = r.Int32(100U) < num3;
            bool flag4;
            bool flag5;

            if (flag1)
            {
                int electricCarProbability = wealthLevel == Citizen.Wealth.Low ? 10 : wealthLevel == Citizen.Wealth.Medium ? 15 : 20;;
                flag4 = false;
                flag5 = r.Int32(100U) < electricCarProbability;
            }
            else
            {
                int taxiProbability = 20;
                flag4 = r.Int32(100U) < taxiProbability;
                flag5 = false;
            }
            ItemClass.Service    service    = ItemClass.Service.Residential;
            ItemClass.SubService subService = !flag5 ? ItemClass.SubService.ResidentialLow : ItemClass.SubService.ResidentialLowEco;
            if (!flag1 && flag4)
            {
                service    = ItemClass.Service.PublicTransport;
                subService = ItemClass.SubService.PublicTransportTaxi;
            }
            VehicleInfo randomVehicleInfo1;

            if (flag3)
            {
                Randomizer randomizer = r;
                randomVehicleInfo1 = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref r, service, subService, ItemClass.Level.Level2);

                if (randomVehicleInfo1 == null || randomVehicleInfo1.m_vehicleAI is CarTrailerAI)
                {
                    trailer            = randomVehicleInfo1;
                    r                  = randomizer;
                    randomVehicleInfo1 = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref r, service, subService, ItemClass.Level.Level1);
                }
            }
            else
            {
                randomVehicleInfo1 = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref r, service, subService, ItemClass.Level.Level1);
            }
            VehicleInfo randomVehicleInfo2 = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref r, ItemClass.Service.Residential, ItemClass.SubService.ResidentialHigh, ItemClass.Level.Level2);

            if (flag2 && randomVehicleInfo2 != null)  // Bikes
            {
                return(randomVehicleInfo2);
            }
            if ((flag1 || flag4) && randomVehicleInfo1 != null)
            {
                return(randomVehicleInfo1);
            }
            return((VehicleInfo)null);
        }
Example #49
0
        //private void _SetSource(ushort instanceID, ref CitizenInstance data, ushort sourceBuilding)  // copied from original code
        //{
        //    if ((int)sourceBuilding != (int)data.m_sourceBuilding)
        //    {
        //        if (data.m_sourceBuilding != (ushort)0)
        //            Singleton<BuildingManager>.instance.m_buildings.m_buffer[(int)data.m_sourceBuilding].RemoveSourceCitizen(instanceID, ref data);
        //        data.m_sourceBuilding = sourceBuilding;
        //        if (data.m_sourceBuilding != (ushort)0)
        //            Singleton<BuildingManager>.instance.m_buildings.m_buffer[(int)data.m_sourceBuilding].AddSourceCitizen(instanceID, ref data);
        //    }
        //    if (sourceBuilding == (ushort)0)
        //        return;
        //    BuildingManager instance = Singleton<BuildingManager>.instance;
        //    BuildingInfo info = instance.m_buildings.m_buffer[(int)sourceBuilding].Info;
        //    data.Unspawn(instanceID);
        //    Randomizer randomizer = new Randomizer((int)instanceID);
        //    Vector3 position;
        //    Vector3 target;
        //    info.m_buildingAI.CalculateSpawnPosition(sourceBuilding, ref instance.m_buildings.m_buffer[(int)sourceBuilding], ref randomizer, this.m_info, out position, out target);
        //    Quaternion quaternion = Quaternion.identity;
        //    Vector3 forward = target - position;
        //    if ((double)forward.sqrMagnitude > 0.00999999977648258)
        //        quaternion = Quaternion.LookRotation(forward);
        //    data.m_frame0.m_velocity = Vector3.zero;
        //    data.m_frame0.m_position = position;
        //    data.m_frame0.m_rotation = quaternion;
        //    data.m_frame1 = data.m_frame0;
        //    data.m_frame2 = data.m_frame0;
        //    data.m_frame3 = data.m_frame0;
        //    data.m_targetPos = new Vector4(target.x, target.y, target.z, 1f);
        //    Color32 eventCitizenColor = Singleton<EventManager>.instance.GetEventCitizenColor(instance.m_buildings.m_buffer[(int)sourceBuilding].m_eventIndex, data.m_citizen);
        //    if (eventCitizenColor.a != byte.MaxValue)
        //        return;
        //    data.m_color = eventCitizenColor;
        //    data.m_flags |= CitizenInstance.Flags.CustomColor;
        //}

        private void _SetTarget(ushort instanceID, ref CitizenInstance data, ushort targetIndex, bool targetIsNode)
        {
            if ((int)targetIndex != (int)data.m_targetBuilding || targetIsNode != ((data.m_flags & CitizenInstance.Flags.TargetIsNode) != CitizenInstance.Flags.None))
            {
                if (data.m_targetBuilding != (ushort)0)
                {
                    if ((data.m_flags & CitizenInstance.Flags.TargetIsNode) != CitizenInstance.Flags.None)
                    {
                        Singleton <NetManager> .instance.m_nodes.m_buffer[(int)data.m_targetBuilding].RemoveTargetCitizen(instanceID, ref data);
                        ushort num = 0;
                        if (targetIsNode)
                        {
                            num = Singleton <NetManager> .instance.m_nodes.m_buffer[(int)data.m_targetBuilding].m_transportLine;
                        }
                        if ((data.m_flags & CitizenInstance.Flags.OnTour) != CitizenInstance.Flags.None)
                        {
                            ushort transportLine = Singleton <NetManager> .instance.m_nodes.m_buffer[(int)data.m_targetBuilding].m_transportLine;
                            uint   citizen       = data.m_citizen;
                            if (transportLine != (ushort)0 && (int)transportLine != (int)num && citizen != 0U)
                            {
                                TransportInfo info = Singleton <TransportManager> .instance.m_lines.m_buffer[(int)transportLine].Info;
                                if (info != null && info.m_vehicleType == VehicleInfo.VehicleType.None)
                                {
                                    data.m_flags &= ~CitizenInstance.Flags.OnTour;
                                }
                            }
                        }
                        if (!targetIsNode)
                        {
                            data.m_flags &= ~CitizenInstance.Flags.TargetIsNode;
                        }
                    }
                    else
                    {
                        Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)data.m_targetBuilding].RemoveTargetCitizen(instanceID, ref data);
                    }
                }
                data.m_targetBuilding = targetIndex;
                if (targetIsNode)
                {
                    data.m_flags |= CitizenInstance.Flags.TargetIsNode;
                }
                if (data.m_targetBuilding != (ushort)0)
                {
                    if ((data.m_flags & CitizenInstance.Flags.TargetIsNode) != CitizenInstance.Flags.None)
                    {
                        Singleton <NetManager> .instance.m_nodes.m_buffer[(int)data.m_targetBuilding].AddTargetCitizen(instanceID, ref data);
                    }
                    else
                    {
                        Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)data.m_targetBuilding].AddTargetCitizen(instanceID, ref data);
                    }
                    data.m_targetSeed = (byte)Singleton <SimulationManager> .instance.m_randomizer.Int32(256U);
                }
            }

            if ((data.m_flags & CitizenInstance.Flags.TargetIsNode) == CitizenInstance.Flags.None && IsRoadConnection(targetIndex) || IsRoadConnection(data.m_sourceBuilding))
            {
                data.m_flags |= CitizenInstance.Flags.BorrowCar;
            }
            else
            {
                data.m_flags &= ~CitizenInstance.Flags.BorrowCar;
            }
            if (targetIndex != (ushort)0 && (data.m_flags & (CitizenInstance.Flags.Character | CitizenInstance.Flags.TargetIsNode)) == CitizenInstance.Flags.None)
            {
                Color32 eventCitizenColor = Singleton <EventManager> .instance.GetEventCitizenColor(Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetIndex].m_eventIndex, data.m_citizen);

                if (eventCitizenColor.a == byte.MaxValue)
                {
                    data.m_color  = eventCitizenColor;
                    data.m_flags |= CitizenInstance.Flags.CustomColor;
                }
            }
            if (this.StartPathFind(instanceID, ref data))
            {
                return;
            }
            data.Unspawn(instanceID);
        }  // copied from original code
 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;
 }
Example #51
0
 public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo, bool enableTransport, bool ignoreCost)
 {
     return(ExtStartPathFind(instanceID, ref citizenData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], ref ExtCitizenManager.Instance.ExtCitizens[Singleton <CitizenManager> .instance.m_instances.m_buffer[instanceID].m_citizen], startPos, endPos, vehicleInfo, enableTransport, ignoreCost));
 }