/// <summary>Accepts an event attendee with specified properties.</summary> /// <param name="age">The attendee age.</param> /// <param name="gender">The attendee gender.</param> /// <param name="education">The attendee education.</param> /// <param name="wealth">The attendee wealth.</param> /// <param name="wellbeing">The attendee wellbeing.</param> /// <param name="happiness">The attendee happiness.</param> /// <param name="randomizer">A reference to the game's randomizer.</param> /// <returns> /// <c>true</c> if the event attendee with specified properties is accepted and can attend this city event; /// otherwise, <c>false</c>. /// </returns> public override bool TryAcceptAttendee( Citizen.AgeGroup age, Citizen.Gender gender, Citizen.Education education, Citizen.Wealth wealth, Citizen.Wellbeing wellbeing, Citizen.Happiness happiness, IRandomizer randomizer) { if (attendeesCount > eventTemplate.Capacity) { return(false); } if (eventTemplate.Costs != null && eventTemplate.Costs.Entry > GetCitizenBudgetForEvent(wealth, randomizer)) { return(false); } CityEventAttendees attendees = eventTemplate.Attendees; float randomPercentage = randomizer.GetRandomValue(100u); if (!CheckAge(age, attendees, randomPercentage)) { return(false); } randomPercentage = randomizer.GetRandomValue(100u); if (!CheckGender(gender, attendees, randomPercentage)) { return(false); } randomPercentage = randomizer.GetRandomValue(100u); if (!CheckEducation(education, attendees, randomPercentage)) { return(false); } randomPercentage = randomizer.GetRandomValue(100u); if (!CheckWealth(wealth, attendees, randomPercentage)) { return(false); } randomPercentage = randomizer.GetRandomValue(100u); if (!CheckWellbeing(wellbeing, attendees, randomPercentage)) { return(false); } randomPercentage = randomizer.GetRandomValue(100u); if (!CheckHappiness(happiness, attendees, randomPercentage)) { return(false); } attendeesCount++; return(true); }
/// <summary>Accepts an event attendee with specified properties.</summary> /// <param name="age">The attendee age.</param> /// <param name="gender">The attendee gender.</param> /// <param name="education">The attendee education.</param> /// <param name="wealth">The attendee wealth.</param> /// <param name="wellbeing">The attendee wellbeing.</param> /// <param name="happiness">The attendee happiness.</param> /// <param name="randomizer">A reference to the game's randomizer.</param> /// <returns> /// <c>true</c> if the event attendee with specified properties is accepted and can attend /// this city event; otherwise, <c>false</c>. /// </returns> public override bool TryAcceptAttendee( Citizen.AgeGroup age, Citizen.Gender gender, Citizen.Education education, Citizen.Wealth wealth, Citizen.Wellbeing wellbeing, Citizen.Happiness happiness, IRandomizer randomizer) => ticketPrice <= GetCitizenBudgetForEvent(wealth, randomizer);
/// <summary>Accepts an event attendee with specified properties.</summary> /// <param name="age">The attendee age.</param> /// <param name="gender">The attendee gender.</param> /// <param name="education">The attendee education.</param> /// <param name="wealth">The attendee wealth.</param> /// <param name="wellbeing">The attendee wellbeing.</param> /// <param name="happiness">The attendee happiness.</param> /// <param name="randomizer">A reference to the game's randomizer.</param> /// <returns> /// <c>true</c> if the event attendee with specified properties is accepted and can attend /// this city event; otherwise, <c>false</c>. /// </returns> public virtual bool TryAcceptAttendee( Citizen.AgeGroup age, Citizen.Gender gender, Citizen.Education education, Citizen.Wealth wealth, Citizen.Wellbeing wellbeing, Citizen.Happiness happiness, IRandomizer randomizer) => true;
public override bool CitizenCanGo(uint citizenID, ref Citizen person) { Citizen.Wealth _citizenWealth = person.WealthLevel; Citizen.Education _citizenEducation = person.EducationLevel; Citizen.Wellbeing _citizenWellbeing = Citizen.GetWellbeingLevel(_citizenEducation, person.m_wellbeing); return _citizenWealth > Citizen.Wealth.Low && _citizenEducation > Citizen.Education.Uneducated && _citizenWellbeing > Citizen.Wellbeing.VeryUnhappy; }
private bool CanAttendEvent(uint citizenId, ref TCitizen citizen, ICityEvent cityEvent) { Citizen.AgeGroup age = CitizenProxy.GetAge(ref citizen); Citizen.Gender gender = CitizenProxy.GetGender(citizenId); Citizen.Education education = CitizenProxy.GetEducationLevel(ref citizen); Citizen.Wealth wealth = CitizenProxy.GetWealthLevel(ref citizen); Citizen.Wellbeing wellbeing = CitizenProxy.GetWellbeingLevel(ref citizen); Citizen.Happiness happiness = CitizenProxy.GetHappinessLevel(ref citizen); return(cityEvent.TryAcceptAttendee(age, gender, education, wealth, wellbeing, happiness, Random)); }
public override bool CitizenCanGo(uint citizenID, ref Citizen person) { Citizen.Wealth _citizenWealth = person.WealthLevel; Citizen.Education _citizenEducation = person.EducationLevel; Citizen.Happiness _citizenHappiness = Citizen.GetHappinessLevel(Citizen.GetHappiness(person.m_health, person.m_wellbeing)); Citizen.Wellbeing _citizenWellbeing = Citizen.GetWellbeingLevel(_citizenEducation, person.m_wellbeing); return(_citizenWealth > Citizen.Wealth.Low && _citizenHappiness > Citizen.Happiness.Poor && _citizenWellbeing > Citizen.Wellbeing.VeryUnhappy); }
public override bool CitizenCanGo(uint citizenID, ref Citizen person) { Citizen.Wealth _citizenWealth = person.WealthLevel; Citizen.Education _citizenEducation = person.EducationLevel; Citizen.Happiness _citizenHappiness = Citizen.GetHappinessLevel(Citizen.GetHappiness(person.m_health, person.m_wellbeing)); Citizen.Wellbeing _citizenWellbeing = Citizen.GetWellbeingLevel(_citizenEducation, person.m_wellbeing); return(_citizenWealth > Citizen.Wealth.Low && _citizenEducation > Citizen.Education.TwoSchools && _citizenHappiness >= Citizen.Happiness.Good && _citizenWellbeing >= Citizen.Wellbeing.Satisfied); }
public override bool CitizenCanGo(uint citizenID, ref Citizen person) { Citizen.Wealth _citizenWealth = person.WealthLevel; Citizen.Education _citizenEducation = person.EducationLevel; Citizen.AgeGroup _citizenAge = Citizen.GetAgeGroup(person.Age); Citizen.Gender _citizenGender = Citizen.GetGender(citizenID); Citizen.Happiness _citizenHappiness = Citizen.GetHappinessLevel(Citizen.GetHappiness(person.m_health, person.m_wellbeing)); Citizen.Wellbeing _citizenWellbeing = Citizen.GetWellbeingLevel(_citizenEducation, person.m_wellbeing); return(_citizenWealth >= Citizen.Wealth.Medium && _citizenAge == Citizen.AgeGroup.Senior && _citizenHappiness >= Citizen.Happiness.Good && _citizenWellbeing > Citizen.Wellbeing.Unhappy); }
public override bool CitizenCanGo(uint citizenID, ref Citizen person) { Citizen.Wealth _citizenWealth = person.WealthLevel; Citizen.Education _citizenEducation = person.EducationLevel; Citizen.AgeGroup _citizenAge = Citizen.GetAgeGroup(person.Age); Citizen.Happiness _citizenHappiness = Citizen.GetHappinessLevel(Citizen.GetHappiness(person.m_health, person.m_wellbeing)); Citizen.Wellbeing _citizenWellbeing = Citizen.GetWellbeingLevel(_citizenEducation, person.m_wellbeing); return(_citizenWealth == Citizen.Wealth.High && _citizenEducation >= Citizen.Education.TwoSchools && _citizenAge >= Citizen.AgeGroup.Young && _citizenHappiness >= Citizen.Happiness.Good && _citizenWellbeing > Citizen.Wellbeing.Unhappy); }
private static bool CheckWealth(Citizen.Wealth wealth, CityEventAttendees attendees, float randomPercentage) { switch (wealth) { case Citizen.Wealth.Low: return(randomPercentage < attendees.LowWealth); case Citizen.Wealth.Medium: return(randomPercentage < attendees.MediumWealth); case Citizen.Wealth.High: return(randomPercentage < attendees.HighWealth); } return(false); }
/// <summary> /// Calculates the citizen's maximum budget for visiting a city event. It depends on the /// citizen's wealth. /// </summary> /// /// /// <param name="wealth">The citizen's wealth.</param> /// <param name="randomizer">A reference to the game's randomizer.</param> /// <returns>The citizen's budget for attending an event.</returns> protected static float GetCitizenBudgetForEvent(Citizen.Wealth wealth, IRandomizer randomizer) { switch (wealth) { case Citizen.Wealth.Low: return(30f + randomizer.GetRandomValue(60)); case Citizen.Wealth.Medium: return(80f + randomizer.GetRandomValue(80)); case Citizen.Wealth.High: return(120f + randomizer.GetRandomValue(320)); default: return(0); } }
public override bool CitizenCanGo(uint citizenID, ref Citizen person) { Citizen.Wealth _citizenWealth = person.WealthLevel; Citizen.Education _citizenEducation = person.EducationLevel; Citizen.AgeGroup _citizenAge = Citizen.GetAgeGroup(person.Age); Citizen.Gender _citizenGender = Citizen.GetGender(citizenID); Citizen.Happiness _citizenHappiness = Citizen.GetHappinessLevel(Citizen.GetHappiness(person.m_health, person.m_wellbeing)); Citizen.Wellbeing _citizenWellbeing = Citizen.GetWellbeingLevel(_citizenEducation, person.m_wellbeing); int percentage = Singleton <SimulationManager> .instance.m_randomizer.Int32(100); return(_citizenWealth >= Citizen.Wealth.Medium && (_citizenGender == Citizen.Gender.Male || (_citizenGender == Citizen.Gender.Female && percentage < 40)) && _citizenAge >= Citizen.AgeGroup.Young && _citizenAge < Citizen.AgeGroup.Senior && _citizenHappiness >= Citizen.Happiness.Good && _citizenWellbeing > Citizen.Wellbeing.Unhappy); }
public override bool CitizenCanGo(uint citizenID, ref Citizen person) { Citizen.Wealth _citizenWealth = person.WealthLevel; Citizen.Education _citizenEducation = person.EducationLevel; Citizen.Gender _citizenGender = Citizen.GetGender(citizenID); Citizen.Happiness _citizenHappiness = Citizen.GetHappinessLevel(Citizen.GetHappiness(person.m_health, person.m_wellbeing)); Citizen.Wellbeing _citizenWellbeing = Citizen.GetWellbeingLevel(_citizenEducation, person.m_wellbeing); Citizen.AgeGroup _citizenAgeGroup = Citizen.GetAgeGroup(person.Age); int percentage = Singleton <SimulationManager> .instance.m_randomizer.Int32(100); return(_citizenWealth < Citizen.Wealth.High && (_citizenEducation < Citizen.Education.ThreeSchools || _citizenEducation == Citizen.Education.ThreeSchools && percentage < 5) && (_citizenGender == Citizen.Gender.Male || (_citizenGender == Citizen.Gender.Female && percentage < 20)) && _citizenHappiness > Citizen.Happiness.Bad && _citizenWellbeing > Citizen.Wellbeing.Unhappy); }
/// <summary> /// Selects the appropriate data array based on parameters. /// </summary> /// <param name="wealthLevel">Citizen wealth level</param> /// <param name="subService">Building subservice</param> /// <param name="ageGroup">Citizen age group</param> /// <returns></returns> public static int[] GetArray(Citizen.Wealth wealthLevel, ItemClass.SubService subService, Citizen.AgeGroup ageGroup) { int[][] array; // TODO - split for eco bool eco = (subService == ItemClass.SubService.ResidentialHighEco) || (subService == ItemClass.SubService.ResidentialLowEco); int densityIndex = (subService == ItemClass.SubService.ResidentialHigh) || (subService == ItemClass.SubService.ResidentialHighEco) ? 1 : 0; if (eco) { switch (wealthLevel) { case Citizen.Wealth.High: array = DataStore.eco_wealth_high[densityIndex]; break; case Citizen.Wealth.Medium: array = DataStore.eco_wealth_med[densityIndex]; break; case Citizen.Wealth.Low: default: array = DataStore.eco_wealth_low[densityIndex]; break; } } else { switch (wealthLevel) { case Citizen.Wealth.High: array = DataStore.wealth_high[densityIndex]; break; case Citizen.Wealth.Medium: array = DataStore.wealth_med[densityIndex]; break; case Citizen.Wealth.Low: default: array = DataStore.wealth_low[densityIndex]; break; } } return(array[(int)ageGroup]); }
} // copied from original code private void CreateMoreTourists_ByMultiplier(uint modelCitizen, ushort sourceBuilding) // the newly arrived tourist that led to creation of more tourists { CitizenManager citizenManager = Singleton <CitizenManager> .instance; BuildingManager buildingManager = Singleton <BuildingManager> .instance; Randomizer randomizer = Singleton <SimulationManager> .instance.m_randomizer; if ((citizenManager.m_citizens.m_buffer[modelCitizen].m_flags & Citizen.Flags.DummyTraffic) == Citizen.Flags.None) // not dummy traffic { float multiplier = DataStorage.instance.multiplier; int i = (int)Math.Truncate(multiplier); System.Random random = new System.Random(); i += (float)random.NextDouble() < multiplier - i ? 1 : 0; for (int index = 0; index < i; ++index) { TransferManager.TransferReason transferReason = GetRandomTransferReason(0); TransferManager.TransferOffer offer = Utils.FindOffer(transferReason, true); ushort targetBuilding = offer.Building; uint unitID = buildingManager.m_buildings.m_buffer[targetBuilding].GetEmptyCitizenUnit(CitizenUnit.Flags.Visit); int family = Singleton <SimulationManager> .instance.m_randomizer.Int32(256U); // no need to keep to same values int age = Singleton <SimulationManager> .instance.m_randomizer.Int32(0, 240); // this is exactly the original code if (citizenManager.CreateCitizen(out uint citizen, age, family, ref Singleton <SimulationManager> .instance.m_randomizer)) { citizenManager.m_citizens.m_buffer[citizen].m_flags |= Citizen.Flags.Tourist; citizenManager.m_citizens.m_buffer[citizen].m_flags |= Citizen.Flags.MovingIn; Citizen.Wealth wealth = citizenManager.m_citizens.m_buffer[modelCitizen].WealthLevel; citizenManager.m_citizens.m_buffer[citizen].WealthLevel = wealth; // same wealth citizenManager.m_citizens.m_buffer[citizen].SetVisitplace(citizen, (ushort)0, unitID); CitizenInfo citizenInfo = citizenManager.m_citizens.m_buffer[citizen].GetCitizenInfo(citizen); if (citizenInfo != null && citizenManager.CreateCitizenInstance(out ushort citizenInstance, ref Singleton <SimulationManager> .instance.m_randomizer, citizenInfo, citizen)) { citizenInfo.m_citizenAI.SetSource(citizenInstance, ref citizenManager.m_instances.m_buffer[(int)citizenInstance], sourceBuilding); _SetTarget(citizenInstance, ref citizenManager.m_instances.m_buffer[(int)citizenInstance], targetBuilding, false); citizenManager.m_citizens.m_buffer[citizen].CurrentLocation = Citizen.Location.Moving; Singleton <StatisticsManager> .instance.Acquire <StatisticArray>(StatisticType.IncomingTourists).Acquire <StatisticInt32>((int)wealth, 3).Add(1); } } } } }
/// <summary>Gets a precise probability (in percent multiplied by 100) for a citizen with specified /// wealth to go on vacation on current day.</summary> /// <param name="wealth">The citizen's wealth.</param> /// <returns>The precise probability (in percent multiplied by 100) for the citizen to go on vacation /// on current day.</returns> public uint GetPreciseVacationChance(Citizen.Wealth wealth) { return(vacationChances[(int)wealth]); }
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); }
int failedTimes; // how many times creation of tourists has failed public void Update() // called every frame by UnityEngine { // create tourists every minute, perhaps choose at which outside connections to create them // PROBABLY NOT spawn vehicles at outside connections more frequently, with reference to in game time? // TODO: Space Elevator NOT CONSIDERED!!!!! Debug.Log("Update() called by unity engine"); if (DataStorage.instance.modifierType == TourismIncreaseType.PopulationSizeRelated) { if (Utils.ComponentActionRequired) { ushort[] carConnections = Utils.GetConnectedOutsideConnections(ItemClass.SubService.None); // ItemClass.Service.Road ushort[] trainConnections = Utils.GetConnectedOutsideConnections(ItemClass.SubService.PublicTransportTrain); ushort[] planeConnections = Utils.GetConnectedOutsideConnections(ItemClass.SubService.PublicTransportPlane); ushort[] shipConnections = Utils.GetConnectedOutsideConnections(ItemClass.SubService.PublicTransportShip); // use avg land value to calculate the probability (percentage) of different modes of transport int avgLandValue = Singleton <DistrictManager> .instance.m_districts.m_buffer[0].GetLandValue(); int planeProb = planeConnections.Length == 0 ? 0 : 100 * avgLandValue / (avgLandValue + 40); int trainProb = trainConnections.Length == 0 ? 0 : planeProb == 0 ? ((100 - planeProb) * avgLandValue / (avgLandValue + 10)) / 2 : ((100 - planeProb) * avgLandValue / (avgLandValue + 15)) / 2; // ship and train prob, maybe just divide by 2 for each of these int shipProb = 0; if (trainProb == 0) { if (!(shipConnections.Length == 0)) // no train connections, do have ship connections { shipProb = planeProb == 0 ? ((100 - planeProb) * avgLandValue / (avgLandValue + 10)) : ((100 - planeProb) * avgLandValue / (avgLandValue + 15)); } } else { if (!(shipConnections.Length == 0)) { shipProb = trainProb; } else // have train connections but no ship connections { trainProb *= 2; } } int carProb = 100 - (planeProb + trainProb + shipProb); // would be pretty low even when land value is quite low //int trainProb = trainConnections.Length == 0 ? 0 : 100 - 100 * (avgLandValue / (avgLandValue + 25)); // TODO: maybe customize this //int shipProb = shipConnections.Length == 0 ? 0 : (100 - trainProb) - (100 - trainProb) * (avgLandValue / (avgLandValue + 30)); //int planeProb = 100 - (trainProb + shipProb); float amountOfTouristsThisMinute = DataStorage.instance.amountOfTouristsThisMinute; int amount = (int)Math.Truncate(amountOfTouristsThisMinute); amount += (float)random.NextDouble() < amountOfTouristsThisMinute - amount ? 1 : 0; amount += createTouristFailed; Debug.Log(string.Format("amount of tourists to create decided: {0}", amount)); int i; // for debug purpose for (i = 0; i < amount; ++i) { // decide which type of outside connection they are going to spawn at, hence decide the wealth level accordingly ItemClass.SubService typeOfTransport = ItemClass.SubService.PublicTransportPlane; int prob = randomizer.Int32(1, 100); if (prob < carProb) { typeOfTransport = ItemClass.SubService.None; } else if (prob < trainProb + shipProb) { typeOfTransport = randomizer.Int32(2) < 1 ? ItemClass.SubService.PublicTransportTrain : ItemClass.SubService.PublicTransportShip; } // else it's plane // decide the wealth of the tourist based on which type of outside connection it will come from Citizen.Wealth wealth = Citizen.Wealth.Low; if (typeOfTransport == ItemClass.SubService.PublicTransportPlane) { int rand = randomizer.Int32(100); wealth = rand > 18 ? Citizen.Wealth.High : Citizen.Wealth.Medium; } else if (typeOfTransport == ItemClass.SubService.PublicTransportTrain) { int rand = randomizer.Int32(100); wealth = rand > 80 ? Citizen.Wealth.High : rand > 40 ? Citizen.Wealth.Medium : Citizen.Wealth.Low; } else if (typeOfTransport == ItemClass.SubService.PublicTransportShip) { int rand = randomizer.Int32(100); wealth = rand > 70 ? Citizen.Wealth.High : rand > 25 ? Citizen.Wealth.Medium : Citizen.Wealth.Low; } else // roads, ItemClass.SubService.None { int rand = randomizer.Int32(100); wealth = rand > 70 ? Citizen.Wealth.High : rand > 30 ? Citizen.Wealth.Medium : Citizen.Wealth.Low; } // randomly choose which sourceBuilding aka the outside connection building the tourist is coming from ushort sourceBuilding = 0; try { switch (typeOfTransport) { case ItemClass.SubService.PublicTransportPlane: sourceBuilding = planeConnections[randomizer.Int32(Convert.ToUInt32(planeConnections.Length))]; break; case ItemClass.SubService.PublicTransportTrain: sourceBuilding = trainConnections[randomizer.Int32(Convert.ToUInt32(trainConnections.Length))]; break; case ItemClass.SubService.PublicTransportShip: sourceBuilding = shipConnections[randomizer.Int32(Convert.ToUInt32(shipConnections.Length))]; break; default: // road connections sourceBuilding = carConnections[randomizer.Int32(Convert.ToUInt32(carConnections.Length))]; break; } Debug.Log("will be spawned at this outside connection: " + sourceBuilding); } catch { Debug.Log("choosing connection building has thrown an exception"); } TransferManager.TransferReason transferReason = NewTouristAI.GetRandomTransferReason(0); TransferManager.TransferOffer offer = Utils.FindOffer(transferReason, true); ushort targetBuilding = offer.Building; Debug.Log(string.Format("component found building {0} for new tourist", targetBuilding)); uint unitID = buildingManager.m_buildings.m_buffer[targetBuilding].GetEmptyCitizenUnit(CitizenUnit.Flags.Visit); int family = Singleton <SimulationManager> .instance.m_randomizer.Int32(256U); int age = Singleton <SimulationManager> .instance.m_randomizer.Int32(0, 240); if (citizenManager.CreateCitizen(out uint citizen, age, family, ref Singleton <SimulationManager> .instance.m_randomizer)) { citizenManager.m_citizens.m_buffer[citizen].m_flags |= Citizen.Flags.Tourist; citizenManager.m_citizens.m_buffer[citizen].m_flags |= Citizen.Flags.MovingIn; citizenManager.m_citizens.m_buffer[citizen].WealthLevel = wealth; citizenManager.m_citizens.m_buffer[citizen].SetVisitplace(citizen, (ushort)0, unitID); CitizenInfo citizenInfo = citizenManager.m_citizens.m_buffer[citizen].GetCitizenInfo(citizen); if (citizenInfo != null && citizenManager.CreateCitizenInstance(out ushort citizenInstance, ref Singleton <SimulationManager> .instance.m_randomizer, citizenInfo, citizen)) { citizenInfo.m_citizenAI.SetSource(citizenInstance, ref citizenManager.m_instances.m_buffer[(int)citizenInstance], sourceBuilding); citizenInfo.m_citizenAI.SetTarget(citizenInstance, ref citizenManager.m_instances.m_buffer[(int)citizenInstance], targetBuilding, false); citizenManager.m_citizens.m_buffer[citizen].CurrentLocation = Citizen.Location.Moving; Singleton <StatisticsManager> .instance.Acquire <StatisticArray>(StatisticType.IncomingTourists).Acquire <StatisticInt32>((int)wealth, 3).Add(1); } else { failedTimes += 1; createTouristFailed += amount - i; citizenManager.ReleaseCitizen(citizen); break; } } else { failedTimes += 1; createTouristFailed += amount - i; break; } } Debug.Log(i + " amount of tourists created in this loop"); } } }
// 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); }
public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceCar, out VehicleInfo trailer) { #if DEBUG bool citDebug = GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.CitizenId == citizenData.m_citizen; bool debug = GlobalConfig.Instance.Debug.Switches[2] && citDebug; bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && citDebug; #endif trailer = null; if (citizenData.m_citizen == 0u) { return(null); } // NON-STOCK CODE START bool forceTaxi = false; #if BENCHMARK using (var bm = new Benchmark(null, "forceTaxi")) { #endif if (Options.prohibitPocketCars) { if (ExtCitizenInstanceManager.Instance.ExtInstances[instanceID].pathMode == ExtPathMode.TaxiToTarget) { forceTaxi = true; } } #if BENCHMARK } #endif // 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 = this.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 BENCHMARK using (var bm = new Benchmark(null, "find-parked-vehicle")) { #endif 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 (debug) { Log._Debug($"CustomTouristAI.CustomGetVehicleInfo({instanceID}): Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. Reusing vehicle info."); } #endif carInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info; } } #if BENCHMARK } #endif 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 static float getWealthChanceValue(uint[] familyWithStudents, int quality) { Citizen.Wealth wealth = getFamilyWealth(familyWithStudents); float chance = NO_CHANCE; switch (quality) { case 0: // Quality 0 homes are more for jokes, so better chance to move into a 0 quality than a 1 quality switch (wealth) { case Citizen.Wealth.High: chance = QUALITY_MAX_CHANCE_VALUE * -0.5f; break; case Citizen.Wealth.Medium: chance = QUALITY_MAX_CHANCE_VALUE * 0.25f; break; case Citizen.Wealth.Low: chance = QUALITY_MAX_CHANCE_VALUE * 2f; break; } break; case 1: // Quality 1's should be mainly for Low Wealth citizens, but not impossible for medium switch (wealth) { case Citizen.Wealth.High: chance = QUALITY_MAX_CHANCE_VALUE * -1f; break; case Citizen.Wealth.Medium: chance = QUALITY_MAX_CHANCE_VALUE * -0.1f; break; case Citizen.Wealth.Low: chance = QUALITY_MAX_CHANCE_VALUE * 1.5f; break; } break; case 2: // Quality 2's should be for both medium and low wealth citizens switch (wealth) { case Citizen.Wealth.High: chance = QUALITY_MAX_CHANCE_VALUE * -0.5f; break; case Citizen.Wealth.Medium: chance = QUALITY_MAX_CHANCE_VALUE * 0.5f; break; case Citizen.Wealth.Low: chance = QUALITY_MAX_CHANCE_VALUE * 0.5f; break; } break; case 3: // Quality 3 are ideal for medium wealth citizens, but possible for all switch (wealth) { case Citizen.Wealth.High: chance = QUALITY_MAX_CHANCE_VALUE * 0.2f; break; case Citizen.Wealth.Medium: chance = QUALITY_MAX_CHANCE_VALUE * 1f; break; case Citizen.Wealth.Low: chance = QUALITY_MAX_CHANCE_VALUE * 0.2f; break; } break; case 4: // Quality 4's start to become hard for low wealth citizens and more suited for medium to high wealth citizens switch (wealth) { case Citizen.Wealth.High: chance = QUALITY_MAX_CHANCE_VALUE * 0.5f;; break; case Citizen.Wealth.Medium: chance = QUALITY_MAX_CHANCE_VALUE * 0.5f; break; case Citizen.Wealth.Low: chance = QUALITY_MAX_CHANCE_VALUE * -1f; break; } break; case 5: // Quality 5's are best suited for high wealth citizens, but some medium wealth citizens can afford it switch (wealth) { case Citizen.Wealth.High: chance = QUALITY_MAX_CHANCE_VALUE * 1f; break; case Citizen.Wealth.Medium: chance = 0.0f; break; case Citizen.Wealth.Low: chance = QUALITY_MAX_CHANCE_VALUE * -2f; break; } break; } Logger.logInfo(LOG_CHANCES, "MoveInProbabilityHelper.getQualityLevelChanceValue -- Wealth Chance Value: {0} -- Family Wealth: {1} -- Building Quality: {2}", chance, wealth, quality); return(chance); }
private int GetCamperProbability(Citizen.Wealth wealth) { Log._DebugOnlyError("CustomTouristAI.GetCamperProbability called!"); return(20); }
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 int GetElectricCarProbability(Citizen.Wealth wealth) { Log.Error("CustomTouristAI.GetElectricCarProbability 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); }
protected override bool CitizenRegistered(uint citizenID, ref Citizen person) { bool canAttend = true; float maxSpend = 0f; if (m_eventData.m_userEvent) { SimulationManager simulationManager = Singleton <SimulationManager> .instance; Citizen.Wealth wealth = person.WealthLevel; switch (wealth) { case Citizen.Wealth.Low: maxSpend = 30f + simulationManager.m_randomizer.Int32(60); break; case Citizen.Wealth.Medium: maxSpend = 80f + simulationManager.m_randomizer.Int32(80); break; case Citizen.Wealth.High: maxSpend = 120f + simulationManager.m_randomizer.Int32(320); break; } if (m_eventCosts != null) { maxSpend -= m_eventCosts._entry; canAttend = maxSpend > 0; if (m_eventData.m_incentives != null && m_eventData.m_incentives.Length > 0) { int startFrom = simulationManager.m_randomizer.Int32(0, m_eventData.m_incentives.Length - 1); int index = startFrom; string buying = m_eventData.m_eventName + " "; do { CityEventDataIncentives incentive = m_eventData.m_incentives[index]; if (incentive.boughtItems < incentive.itemCount && maxSpend - incentive.returnCost >= 0) { maxSpend -= incentive.returnCost; ++incentive.boughtItems; buying += "[" + incentive.name + " (" + incentive.boughtItems + "/" + incentive.itemCount + ")] "; } if (++index >= m_eventData.m_incentives.Length) { index = 0; } } while (index != startFrom); CimTools.CimToolsHandler.CimToolBase.DetailedLogger.Log(buying); } } } if (!canAttend) { CimTools.CimToolsHandler.CimToolBase.DetailedLogger.Log("Cim is too poor to attend the event :("); } return(canAttend); }
public override bool CitizenCanGo(uint citizenID, ref Citizen person) { bool canGo = false; if (m_eventChances != null && m_eventData.m_registeredCitizens < GetCapacity()) { canGo = true; Citizen.Wealth _citizenWealth = person.WealthLevel; Citizen.Education _citizenEducation = person.EducationLevel; Citizen.Gender _citizenGender = Citizen.GetGender(citizenID); Citizen.Happiness _citizenHappiness = Citizen.GetHappinessLevel(Citizen.GetHappiness(person.m_health, person.m_wellbeing)); Citizen.Wellbeing _citizenWellbeing = Citizen.GetWellbeingLevel(_citizenEducation, person.m_wellbeing); Citizen.AgeGroup _citizenAgeGroup = Citizen.GetAgeGroup(person.Age); float percentageChange = GetAdjustedChancePercentage(); int randomPercentage = Singleton <SimulationManager> .instance.m_randomizer.Int32(100U); switch (_citizenWealth) { case Citizen.Wealth.Low: canGo = canGo && randomPercentage < Adjust(m_eventChances._lowWealth, percentageChange); break; case Citizen.Wealth.Medium: canGo = canGo && randomPercentage < Adjust(m_eventChances._mediumWealth, percentageChange); break; case Citizen.Wealth.High: canGo = canGo && randomPercentage < Adjust(m_eventChances._highWealth, percentageChange); break; } randomPercentage = Singleton <SimulationManager> .instance.m_randomizer.Int32(100U); switch (_citizenEducation) { case Citizen.Education.Uneducated: canGo = canGo && randomPercentage < Adjust(m_eventChances._uneducated, percentageChange); break; case Citizen.Education.OneSchool: canGo = canGo && randomPercentage < Adjust(m_eventChances._oneSchool, percentageChange); break; case Citizen.Education.TwoSchools: canGo = canGo && randomPercentage < Adjust(m_eventChances._twoSchools, percentageChange); break; case Citizen.Education.ThreeSchools: canGo = canGo && randomPercentage < Adjust(m_eventChances._threeSchools, percentageChange); break; } randomPercentage = Singleton <SimulationManager> .instance.m_randomizer.Int32(100U); switch (_citizenGender) { case Citizen.Gender.Female: canGo = canGo && randomPercentage < Adjust(m_eventChances._females, percentageChange); break; case Citizen.Gender.Male: canGo = canGo && randomPercentage < Adjust(m_eventChances._males, percentageChange); break; } randomPercentage = Singleton <SimulationManager> .instance.m_randomizer.Int32(100U); switch (_citizenHappiness) { case Citizen.Happiness.Bad: canGo = canGo && randomPercentage < Adjust(m_eventChances._badHappiness, percentageChange); break; case Citizen.Happiness.Poor: canGo = canGo && randomPercentage < Adjust(m_eventChances._poorHappiness, percentageChange); break; case Citizen.Happiness.Good: canGo = canGo && randomPercentage < Adjust(m_eventChances._goodHappiness, percentageChange); break; case Citizen.Happiness.Excellent: canGo = canGo && randomPercentage < Adjust(m_eventChances._excellentHappiness, percentageChange); break; case Citizen.Happiness.Suberb: canGo = canGo && randomPercentage < Adjust(m_eventChances._superbHappiness, percentageChange); break; } randomPercentage = Singleton <SimulationManager> .instance.m_randomizer.Int32(100U); switch (_citizenWellbeing) { case Citizen.Wellbeing.VeryUnhappy: canGo = canGo && randomPercentage < Adjust(m_eventChances._veryUnhappyWellbeing, percentageChange); break; case Citizen.Wellbeing.Unhappy: canGo = canGo && randomPercentage < Adjust(m_eventChances._unhappyWellbeing, percentageChange); break; case Citizen.Wellbeing.Satisfied: canGo = canGo && randomPercentage < Adjust(m_eventChances._satisfiedWellbeing, percentageChange); break; case Citizen.Wellbeing.Happy: canGo = canGo && randomPercentage < Adjust(m_eventChances._happyWellbeing, percentageChange); break; case Citizen.Wellbeing.VeryHappy: canGo = canGo && randomPercentage < Adjust(m_eventChances._veryHappyWellbeing, percentageChange); break; } randomPercentage = Singleton <SimulationManager> .instance.m_randomizer.Int32(100U); switch (_citizenAgeGroup) { case Citizen.AgeGroup.Child: canGo = canGo && randomPercentage < Adjust(m_eventChances._children, percentageChange); break; case Citizen.AgeGroup.Teen: canGo = canGo && randomPercentage < Adjust(m_eventChances._teens, percentageChange); break; case Citizen.AgeGroup.Young: canGo = canGo && randomPercentage < Adjust(m_eventChances._youngAdults, percentageChange); break; case Citizen.AgeGroup.Adult: canGo = canGo && randomPercentage < Adjust(m_eventChances._adults, percentageChange); break; case Citizen.AgeGroup.Senior: canGo = canGo && randomPercentage < Adjust(m_eventChances._seniors, percentageChange); break; } CimTools.CimToolsHandler.CimToolBase.DetailedLogger.Log( (canGo ? "[Can Go]" : "[Ignoring]") + " Citizen " + citizenID + " for " + m_eventData.m_eventName + "\n\t" + _citizenWealth.ToString() + ", " + _citizenEducation.ToString() + ", " + _citizenGender.ToString() + ", " + _citizenHappiness.ToString() + ", " + _citizenWellbeing.ToString() + ", " + _citizenAgeGroup.ToString()); } return(canGo); }
internal static void EnsureCitizenUnits(ref PrivateBuildingAI __instance, ushort buildingID, ref Building data, int homeCount, int workCount, int visitCount, int studentCount) { int totalWorkCount = (workCount + 4) / 5; int totalVisitCount = (visitCount + 4) / 5; int totalHomeCount = homeCount; int[] workersRequired = new int[] { 0, 0, 0, 0 }; if ((data.m_flags & (Building.Flags.Abandoned | Building.Flags.BurnedDown)) == Building.Flags.None) { Citizen.Wealth wealthLevel = Citizen.GetWealthLevel(__instance.m_info.m_class.m_level); uint num = 0u; uint num2 = data.m_citizenUnits; int num3 = 0; while (num2 != 0u) { CitizenUnit.Flags flags = citizenUnitArray[(int)((UIntPtr)num2)].m_flags; if ((ushort)(flags & CitizenUnit.Flags.Home) != 0) { citizenUnitArray[(int)((UIntPtr)num2)].SetWealthLevel(wealthLevel); homeCount--; } if ((ushort)(flags & CitizenUnit.Flags.Work) != 0) { workCount -= 5; for (int i = 0; i < 5; i++) { uint citizen = citizenUnitArray[(int)((UIntPtr)num2)].GetCitizen(i); if (citizen != 0u) { // Tick off education to see what is there workersRequired[(int)citizenArray[(int)((UIntPtr)citizen)].EducationLevel]--; } } } if ((ushort)(flags & CitizenUnit.Flags.Visit) != 0) { visitCount -= 5; } if ((ushort)(flags & CitizenUnit.Flags.Student) != 0) { studentCount -= 5; } num = num2; num2 = citizenUnitArray[(int)((UIntPtr)num2)].m_nextUnit; if (++num3 > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } // end while /* * homeCount = Mathf.Max(0, homeCount); * workCount = Mathf.Max(0, workCount); */ visitCount = Mathf.Max(0, visitCount); studentCount = Mathf.Max(0, studentCount); if (homeCount > 0 || workCount > 0 || visitCount > 0 || studentCount > 0) { uint num4 = 0u; if (citizenManager.CreateUnits(out num4, ref Singleton <SimulationManager> .instance.m_randomizer, buildingID, 0, homeCount, workCount, visitCount, 0, studentCount)) { if (num != 0u) { citizenUnitArray[(int)((UIntPtr)num)].m_nextUnit = num4; } else { data.m_citizenUnits = num4; } } } // Stop incoming offers to get HandleWorkers() to start fresh TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Building = buildingID; Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker0, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker1, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker2, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker3, offer); int worker0 = 0; int worker1 = 0; int worker2 = 0; int worker3 = 0; ItemClass.Level level = ((PrivateBuildingAI)data.Info.GetAI()).m_info.m_class.m_level; ((PrivateBuildingAI)data.Info.GetAI()).CalculateWorkplaceCount(level, new Randomizer((int)buildingID), data.Width, data.Length, out worker0, out worker1, out worker2, out worker3); // Update the workers required once figuring out how many are needed by the new building workersRequired[0] += worker0; workersRequired[1] += worker1; workersRequired[2] += worker2; workersRequired[3] += worker3; if (workCount < 0) { RemoveWorkerBuilding(buildingID, ref data, totalWorkCount); } else if (homeCount < 0) { RemoveHouseHold(buildingID, ref data, totalHomeCount); } /* * if (visitCount < 0) * { * RemoveVisitorsBuilding(buildingID, ref data, totalVisitCount); * } */ PromoteWorkers(buildingID, ref data, ref workersRequired); // Do nothing for students } // end if good building } // end EnsureCitizenUnits
/// <summary>Gets a precise probability (in percent multiplied by 100) for a citizen with specified /// wealth to go on vacation on current day.</summary> /// <param name="wealth">The citizen's wealth.</param> /// <returns>The precise probability (in percent multiplied by 100) for the citizen to go on vacation /// on current day.</returns> public uint GetPreciseVacationChance(Citizen.Wealth wealth) => vacationChances[(int)wealth];