public bool CheckCitizenInstanceFlags(ushort citizenInstanceId, CitizenInstance.Flags flagMask, CitizenInstance.Flags?expectedResult = default(CitizenInstance.Flags?)) { bool ret = false; ProcessCitizenInstance(citizenInstanceId, delegate(ushort ciId, ref CitizenInstance citizenInstance) { ret = LogicUtil.CheckFlags((uint)citizenInstance.m_flags, (uint)flagMask, (uint?)expectedResult); return(true); }); return(ret); }
/// <summary> /// Check citizen instance flags contain at least one of the flags in <paramref name="flagMask"/>. /// </summary> /// /// <param name="citizenInstanceId">The id of the citizen instance to inspect.</param> /// <param name="flagMask">The flags to test.</param> /// <param name="expectedResult">If specified, ensure only the expected flags are found.</param> /// /// <returns>Returns <c>true</c> if the test passes, otherwise <c>false</c>.</returns> public bool CheckCitizenInstanceFlags(ushort citizenInstanceId, CitizenInstance.Flags flagMask, CitizenInstance.Flags?expectedResult = null) { CitizenInstance.Flags result = Singleton <CitizenManager> .instance.m_instances.m_buffer[citizenInstanceId].m_flags & flagMask; return(expectedResult == null ? result != 0 : result == expectedResult); }
public void ResetTrip() //Reset a trip (Mistakenly written, likely will never be used) { activated = false; currentVehicleType = Leg.Flags.None; m_citizen = 0; m_current = 0; m_flags = CitizenInstance.Flags.None; m_legCount = 0; m_legs = new Leg[0]; m_source = 0; m_target = 0; previousVehicleType = Leg.Flags.None; valid = false; }
private bool MediateMode(CitizenInstance.Flags t_flags) //Called if a new leg is not established to update leg information for later analysis by checking { if (activated && m_legs[m_current].getMode() != Leg.Flags.None) //Check if current leg has been initialized { long tickInterval = ticksCurrent.Ticks - ticksPrevious.Ticks; double sx = GetMyVelocity().x; double sz = GetMyVelocity().z; double sv = Math.Sqrt((sx * sx) + (sz * sz)); m_legs[m_current].addSpeed((float)sv); switch (m_legs[m_current].getMode()) //TODO: Write MediateMode() cases to record data { //TODO: Determine what needs to be done for each Leg.Flags case in MediateMode() case Leg.Flags.Bicycle: if ((m_flags & CitizenInstance.Flags.OnBikeLane) != CitizenInstance.Flags.None) { m_legs[m_current].addTimeOnBikeLane(tickInterval); } break; case Leg.Flags.Bus: break; case Leg.Flags.Car: break; case Leg.Flags.Metro: break; case Leg.Flags.Plane: break; case Leg.Flags.Ship: break; case Leg.Flags.Taxi: break; case Leg.Flags.Train: break; case Leg.Flags.Tram: break; case Leg.Flags.Walk: break; } return(true); } return(false); }
public void TryAddLeg() //Gets new CitizenInstance flags for analysis: [new , update, ignore, close, invalidate] { CitizenInstance.Flags t_flags = Singleton <CitizenManager> .instance.m_instances.m_buffer[m_citizen].m_flags; if (CheckMoving()) //If the CI is moving { if (CheckNewVehicle()) //If the CI has a new vehicle { FinalizeLeg(GetMyPosition()); AddLeg(); //[New] previousVehicleType = currentVehicleType; //Update previousVehicleType } CheckFlags(t_flags); //Check CI flags int num = (int)t_flags; //Cast CI flags to int MediateMode(t_flags); //[Update] } UpdateMyFlags(t_flags); //Update m_flags for next cycle }
private void UpdateMyFlags(CitizenInstance.Flags t_flags) //Update flags upon simulation step { m_flags = t_flags; }
private void CheckFlags(CitizenInstance.Flags t_flags) //Checks changes to CitizenInstance flags { if (m_flags != t_flags) //If Flags have been updated { //then evaluate if a new trip must be added if ((m_flags & CitizenInstance.Flags.Underground) != (t_flags & CitizenInstance.Flags.Underground)) { if ((m_flags & CitizenInstance.Flags.Underground) != CitizenInstance.Flags.None) //Start Underground { } else //Cease Underground { } } if ((m_flags & CitizenInstance.Flags.BorrowCar) != (t_flags & CitizenInstance.Flags.BorrowCar)) { if ((m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None) //Start BorrowCar { } else //Cease BrorrowCar { } } if ((m_flags & CitizenInstance.Flags.EnteringVehicle) != (t_flags & CitizenInstance.Flags.EnteringVehicle)) { if ((m_flags & CitizenInstance.Flags.EnteringVehicle) != CitizenInstance.Flags.None) //Start EnteringVehicle { } else //Cease EnteringVehicle { } } if ((m_flags & CitizenInstance.Flags.RidingBicycle) != (t_flags & CitizenInstance.Flags.RidingBicycle)) { if ((m_flags & CitizenInstance.Flags.RidingBicycle) != CitizenInstance.Flags.None) //Start RidingBicycle { } else //Cease RidingBicycle { } } if ((m_flags & CitizenInstance.Flags.OnBikeLane) != (t_flags & CitizenInstance.Flags.OnBikeLane)) { if ((m_flags & CitizenInstance.Flags.OnBikeLane) != CitizenInstance.Flags.None) //Start OnBikeLane { } else //Cease OnBikeLane { } } if ((m_flags & CitizenInstance.Flags.OnPath) != (t_flags & CitizenInstance.Flags.OnPath)) { if ((m_flags & CitizenInstance.Flags.OnPath) != CitizenInstance.Flags.None) //Start OnPath { } else //End OnPath { } } if ((m_flags & CitizenInstance.Flags.SittingDown) != (t_flags & CitizenInstance.Flags.SittingDown)) { if ((m_flags & CitizenInstance.Flags.SittingDown) != CitizenInstance.Flags.SittingDown) //Start SittingDown { } else //Cease SittingDown { } } if ((m_flags & CitizenInstance.Flags.TryingSpawnVehicle) != (t_flags & CitizenInstance.Flags.TryingSpawnVehicle)) { } if ((m_flags & CitizenInstance.Flags.WaitingPath) != (t_flags & CitizenInstance.Flags.WaitingPath)) { } if ((m_flags & CitizenInstance.Flags.WaitingTransport) != (t_flags & CitizenInstance.Flags.WaitingTransport)) { } if ((m_flags & CitizenInstance.Flags.WaitingTaxi) != (t_flags & CitizenInstance.Flags.WaitingTaxi)) { if ((m_flags & CitizenInstance.Flags.WaitingTaxi) != CitizenInstance.Flags.None) { } } if ((m_flags & CitizenInstance.Flags.BoredOfWaiting) != (t_flags & CitizenInstance.Flags.BoredOfWaiting)) { if ((m_flags & CitizenInstance.Flags.BoredOfWaiting) != CitizenInstance.Flags.None) //Start BoredOfWaiting { } else //Cease BoredOfWaiting { } } if ((m_flags & CitizenInstance.Flags.Panicking) != (t_flags & CitizenInstance.Flags.Panicking)) { } if ((m_flags & CitizenInstance.Flags.AtTarget) != (t_flags & CitizenInstance.Flags.AtTarget)) { if ((m_flags & CitizenInstance.Flags.AtTarget) != CitizenInstance.Flags.None) //Start AtTarget { } else //Cease AtTarget { } } if ((m_flags & CitizenInstance.Flags.InsideBuilding) != (t_flags & CitizenInstance.Flags.InsideBuilding)) { } if ((m_flags & CitizenInstance.Flags.Deleted) != (t_flags & CitizenInstance.Flags.Deleted)) { } if ((m_flags & CitizenInstance.Flags.CannotUseTransport) != (t_flags & CitizenInstance.Flags.CannotUseTransport)) { } if ((m_flags & CitizenInstance.Flags.CannotUseTaxi) != (t_flags & CitizenInstance.Flags.CannotUseTaxi)) { } /* * ---------------------------------------------------------------------------------------------------------------------------------------------------------- * UNUSED: TargetFlags ; RequireSlowStart ; Transition ; Created ; CustomName ; CustomColor ; HangAround ; * ---------------------------------------------------------------------------------------------------------------------------------------------------------- */ } }
private static void Postfix(BuildingAI __instance, ushort buildingID, ref Building data, ref Randomizer randomizer, CitizenInfo info, ref Vector3 position, ref Vector3 target, ref CitizenInstance.Flags specialFlags) { if (WeatherInfo?.IsBadWeather != true || data.Info == null || data.Info.m_enterDoors == null) { return; } BuildingInfo.Prop[] enterDoors = data.Info.m_enterDoors; bool doorFound = false; for (int i = 0; i < enterDoors.Length; ++i) { PropInfo prop = enterDoors[i].m_finalProp; if (prop == null) { continue; } if (prop.m_doorType == PropInfo.DoorType.Enter || prop.m_doorType == PropInfo.DoorType.Both) { doorFound = true; break; } } if (!doorFound) { return; } __instance.CalculateSpawnPosition(buildingID, ref data, ref randomizer, info, out Vector3 spawnPosition, out Vector3 spawnTarget); position = spawnPosition; target = spawnTarget; specialFlags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.SittingDown); }
public static void CalculateUnspawnPositionPostfix(BuildingAI __instance, ushort buildingID, ref Building data, ref Randomizer randomizer, CitizenInfo info, ref Vector3 position, ref Vector3 target, ref CitizenInstance.Flags specialFlags) { if (UserModSettings.Settings.Enabled) { var simulationManager = SimulationManager.instance; var weatherManager = WeatherManager.instance; var rainPercentage = weatherManager.m_currentRain * 100f; if (data.m_eventIndex == 0 && data.Enterable() && rainPercentage > 0.5 && UserModSettings.Settings.Citizens_ReactToWeather) { __instance.CalculateSpawnPosition(buildingID, ref data, ref randomizer, info, out var spawnPosition, out var spawnTarget); position = spawnPosition; target = spawnTarget; specialFlags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.SittingDown); } } }
internal static bool IsFlagSet(this CitizenInstance.Flags value, CitizenInstance.Flags flag) => (value & flag) != 0;
internal static bool CheckFlags(this CitizenInstance.Flags value, CitizenInstance.Flags required, CitizenInstance.Flags forbidden = 0) => (value & (required | forbidden)) == required;
public override void CalculateUnspawnPosition(ushort buildingID, ref Building data, ref Randomizer randomizer, CitizenInfo info, ushort ignoreInstance, out Vector3 position, out Vector3 target, out Vector2 direction, out CitizenInstance.Flags specialFlags) { float localMeshOffset = Building.CalculateLocalMeshOffset(this.m_info, data.Length); bool flag1 = this.m_info.m_specialPlaces != null && this.m_info.m_specialPlaces.Length != 0; bool flag2 = this.m_info.m_enterDoors != null && this.m_info.m_enterDoors.Length != 0; if (flag1 && (!flag2 || randomizer.Int32(4U) == 0)) { BuildingInfo.Prop prop = this.m_info.m_specialPlaces[randomizer.Int32((uint)this.m_info.m_specialPlaces.Length)]; if (new Randomizer((int)buildingID << 6 | prop.m_index).Int32(100U) < prop.m_probability && data.Length >= prop.m_requiredLength) { Vector3 offset = prop.m_position; offset.z = localMeshOffset - offset.z; position = data.CalculatePosition(offset); int index = randomizer.Int32((uint)prop.m_finalProp.m_specialPlaces.Length); PropInfo.SpecialPlace specialPlace = prop.m_finalProp.m_specialPlaces[index]; float f = data.m_angle + prop.m_radAngle; float num1 = Mathf.Cos(f); float num2 = Mathf.Sin(f); if (!prop.m_fixedHeight) { position.y = Singleton <TerrainManager> .instance.SampleDetailHeight(position); } else if (this.m_info.m_requireHeightMap) { position.y = Singleton <TerrainManager> .instance.SampleDetailHeight(position) + offset.y; } position.x += (float)((double)specialPlace.m_position.x * (double)num1 + (double)specialPlace.m_position.z * (double)num2); position.y += specialPlace.m_position.y; position.z += (float)((double)specialPlace.m_position.x * (double)num2 - (double)specialPlace.m_position.z * (double)num1); if (!this.IsSomeBodyThere(position, ignoreInstance)) { direction.x = (float)((double)specialPlace.m_direction.x * (double)num1 + (double)specialPlace.m_direction.z * (double)num2); direction.y = (float)((double)specialPlace.m_direction.x * (double)num2 - (double)specialPlace.m_direction.z * (double)num1); //specialFlags = hangaround _ specialPlace.specialFlags specialFlags = CitizenInstance.Flags.HangAround | specialPlace.m_specialFlags; Debug.Log("SF: " + specialFlags.ToString().PadRight(25, ' ') + "; SP: " + specialPlace.m_specialFlags.ToString().PadRight(25, ' ') + "; Layer: " + data.Info.m_class.m_layer.ToString().PadRight(15, ' ') + "; Level: " + data.Info.m_class.m_level.ToString().PadRight(5, ' ') + "; Service: " + data.Info.m_class.m_service.ToString().PadRight(20, ' ') + "; Subservice: " + data.Info.m_class.m_subService.ToString().PadRight(25, ' ') + ";"); if (this.m_info.m_hasPedestrianPaths) { target = position; return; } target = data.CalculateSidewalkPosition(offset.x, 0.0f); return; } } } if (flag2) { BuildingInfo.Prop prop = this.m_info.m_enterDoors[randomizer.Int32((uint)this.m_info.m_enterDoors.Length)]; if (new Randomizer((int)buildingID << 6 | prop.m_index).Int32(100U) < prop.m_probability && data.Length >= prop.m_requiredLength) { Vector3 offset = prop.m_position; offset.z = localMeshOffset - offset.z; float num1 = prop.m_finalProp.m_generatedInfo.m_size.x * 0.5f - info.m_radius; if ((double)num1 >= 0.100000001490116) { float num2 = num1 * Mathf.Sqrt((float)randomizer.Int32(1000U) * (1f / 1000f)); float f = (float)randomizer.Int32(1000U) * ((float)System.Math.PI / 500f); offset.x += Mathf.Cos(f) * num2; offset.z += Mathf.Sin(f) * num2; } position = data.CalculatePosition(offset); if (!prop.m_fixedHeight) { position.y = Singleton <TerrainManager> .instance.SampleDetailHeight(position); } else if (this.m_info.m_requireHeightMap) { position.y = Singleton <TerrainManager> .instance.SampleDetailHeight(position) + offset.y; } direction = Vector2.zero; specialFlags = (prop.m_finalProp.m_doorType & PropInfo.DoorType.HangAround) != PropInfo.DoorType.HangAround ? CitizenInstance.Flags.None : CitizenInstance.Flags.HangAround; if (this.m_info.m_hasPedestrianPaths) { target = position; return; } target = data.CalculateSidewalkPosition(offset.x, 0.0f); return; } } Vector3 offset1 = new Vector3(0.0f, 0.0f, localMeshOffset); position = data.CalculatePosition(offset1); position.y = Singleton <TerrainManager> .instance.SampleDetailHeight(position); direction = Vector2.zero; specialFlags = CitizenInstance.Flags.None; if (this.m_info.m_hasPedestrianPaths) { target = position; } else { target = data.CalculateSidewalkPosition(offset1.x, 0.0f); } }
public override void SimulationStep(ushort instanceID, ref CitizenInstance citizenData, ref CitizenInstance.Frame frameData, bool lodPhysics) { if (IsCagedAnimal(citizenData)) { SimulationStepCaged(instanceID, ref citizenData, ref frameData, lodPhysics); return; } else if (LivestockAIDetour.isFreeAnimal(citizenData)) { SimulationStepWild(instanceID, ref citizenData, ref frameData, lodPhysics); return; } float sqrMagnitude1 = frameData.m_velocity.sqrMagnitude; if ((double)sqrMagnitude1 > 0.00999999977648258) { frameData.m_position += frameData.m_velocity * 0.5f; } CitizenInstance.Flags flags1 = CitizenInstance.Flags.None; if ((int)citizenData.m_targetBuilding != 0) { CitizenManager instance = Singleton <CitizenManager> .instance; CitizenInstance.Flags flags2 = instance.m_instances.m_buffer[(int)citizenData.m_targetBuilding].m_flags; if ((flags2 & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None) { Randomizer randomizer = new Randomizer((int)instanceID); CitizenInstance.Frame lastFrameData = instance.m_instances.m_buffer[(int)citizenData.m_targetBuilding].GetLastFrameData(); Vector3 vector3 = lastFrameData.m_rotation * new Vector3(0.5f, 0.0f, 0.0f); if (randomizer.Int32(2U) == 0) { vector3 = -vector3; } Vector4 vector4 = instance.m_instances.m_buffer[(int)citizenData.m_targetBuilding].m_targetPos + (Vector4)vector3; if ((double)Vector3.SqrMagnitude(lastFrameData.m_position - frameData.m_position) > 10000.0) { citizenData.m_targetBuilding = (ushort)0; } else { flags1 = flags2 & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.InsideBuilding | CitizenInstance.Flags.Transition); citizenData.m_targetPos = vector4; } } else { citizenData.m_targetBuilding = (ushort)0; } } citizenData.m_flags = citizenData.m_flags & ~(CitizenInstance.Flags.Underground | CitizenInstance.Flags.InsideBuilding | CitizenInstance.Flags.Transition) | flags1; Vector3 v = (Vector3)citizenData.m_targetPos - frameData.m_position; float f = lodPhysics || (double)citizenData.m_targetPos.w <= 1.0 / 1000.0 ? v.sqrMagnitude : VectorUtils.LengthSqrXZ(v); float a = this.m_info.m_walkSpeed; float b = 2f; if ((double)f < 1.0) { v = Vector3.zero; } else { float num = Mathf.Sqrt(f); float maxLength = Mathf.Min(a, num * 0.75f); v = Quaternion.Inverse(frameData.m_rotation) * v; if ((double)v.z < (double)Mathf.Abs(v.x)) { v.x = (double)v.x < 0.0 ? Mathf.Min(-1f, v.x) : Mathf.Max(1f, v.x); v.z = Mathf.Abs(v.x); maxLength = Mathf.Min(0.5f, num * 0.1f); } v = Vector3.ClampMagnitude(frameData.m_rotation * v, maxLength); } Vector3 vector3_1 = v - frameData.m_velocity; float magnitude = vector3_1.magnitude; Vector3 vector3_2 = vector3_1 * (b / Mathf.Max(magnitude, b)); frameData.m_velocity += vector3_2; float sqrMagnitude2 = frameData.m_velocity.sqrMagnitude; bool flag = !lodPhysics && (double)citizenData.m_targetPos.w > 1.0 / 1000.0 && ((double)sqrMagnitude2 > 0.00999999977648258 || (double)sqrMagnitude1 > 0.00999999977648258); ushort buildingID = !flag ? (ushort)0 : Singleton <BuildingManager> .instance.GetWalkingBuilding(frameData.m_position + frameData.m_velocity * 0.5f); if ((double)sqrMagnitude2 > 0.00999999977648258) { Vector3 forward = frameData.m_velocity; if (!lodPhysics) { Vector3 pushAmount = Vector3.zero; float pushDivider = 0.0f; this.CheckCollisions(instanceID, ref citizenData, frameData.m_position, frameData.m_position + frameData.m_velocity, buildingID, ref pushAmount, ref pushDivider); if ((double)pushDivider > 0.00999999977648258) { pushAmount *= 1f / pushDivider; pushAmount = Vector3.ClampMagnitude(pushAmount, Mathf.Sqrt(sqrMagnitude2) * 0.5f); frameData.m_velocity += pushAmount; forward += pushAmount * 0.25f; } } frameData.m_position += frameData.m_velocity * 0.5f; if ((double)forward.sqrMagnitude > 0.00999999977648258) { frameData.m_rotation = Quaternion.LookRotation(forward); } } if (flag) { Vector3 worldPos = frameData.m_position; float terrainHeight = Singleton <TerrainManager> .instance.SampleDetailHeight(worldPos); if ((int)buildingID != 0) { float num = Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)buildingID].SampleWalkingHeight(worldPos, terrainHeight); worldPos.y = worldPos.y + (num - worldPos.y) * Mathf.Min(1f, citizenData.m_targetPos.w * 4f); frameData.m_position.y = worldPos.y; } else if ((double)Mathf.Abs(terrainHeight - worldPos.y) < 2.0) { worldPos.y = worldPos.y + (terrainHeight - worldPos.y) * Mathf.Min(1f, citizenData.m_targetPos.w * 4f); frameData.m_position.y = worldPos.y; } } frameData.m_underground = (citizenData.m_flags & CitizenInstance.Flags.Underground) != CitizenInstance.Flags.None; frameData.m_insideBuilding = (citizenData.m_flags & CitizenInstance.Flags.InsideBuilding) != CitizenInstance.Flags.None; frameData.m_transition = (citizenData.m_flags & CitizenInstance.Flags.Transition) != CitizenInstance.Flags.None; var mRandomEffect = ((PetAI)Convert.ChangeType(this, typeof(PetAI))).m_randomEffect; if (mRandomEffect == null || Singleton <SimulationManager> .instance.m_randomizer.Int32(40U) != 0) { return; } InstanceID instance1 = new InstanceID(); instance1.CitizenInstance = instanceID; EffectInfo.SpawnArea spawnArea = new EffectInfo.SpawnArea(frameData.m_position, Vector3.up, 0.0f); float num1 = 3.75f; Singleton <EffectManager> .instance.DispatchEffect(mRandomEffect, instance1, spawnArea, frameData.m_velocity *num1, 0.0f, 1f, Singleton <CitizenManager> .instance.m_audioGroup); }
public override void CalculateUnspawnPosition(ushort buildingID, ref Building data, ref Randomizer randomizer, CitizenInfo info, ushort ignoreInstance, out Vector3 position, out Vector3 target, out Vector2 direction, out CitizenInstance.Flags specialFlags) { if (info.m_citizenAI.IsAnimal() && info.m_class.m_service == ItemClass.Service.Residential && info.m_class.m_subService == ItemClass.SubService.ResidentialLow) { int max1 = data.Width * 30; int max2 = data.Length * 30; position.x = (float)randomizer.Int32(-max1, max1) * 0.1f; position.y = 0.0f; position.z = (float)randomizer.Int32(-max2, max2) * 0.1f; position = data.CalculatePosition(position); target = position; direction = Vector2.zero; specialFlags = CitizenInstance.Flags.HangAround; } else { base.CalculateUnspawnPosition(buildingID, ref data, ref randomizer, info, ignoreInstance, out position, out target, out direction, out specialFlags); } }