internal override void SetTargetPoint(Vector3 targetPoint) { if (_moduleData.KeepsParkingSpaceWhenAirborne) // check if not a helicopter { switch (CurrentJetAIState) { case JetAIState.JustCreated: case JetAIState.MovingToParkingPlace: case JetAIState.ReachedParkingPlace: case JetAIState.Rotating: case JetAIState.Parked: case JetAIState.MovingTowardsStart: case JetAIState.Starting: case JetAIState.MovingBackToHangar: _currentTargetPoint = targetPoint; _unparkingRequested = true; return; case JetAIState.Started: case JetAIState.MovingTowardsTarget: case JetAIState.ReachedTargetPoint: case JetAIState.ReturningToBase: CurrentJetAIState = JetAIState.MovingTowardsTarget; break; } } base.SetTargetPoint(targetPoint); }
internal override void Update(BehaviorUpdateContext context) { base.Update(context); if (!_moduleData.KeepsParkingSpaceWhenAirborne) { return; // helicopters are way more simple (at least for now) } if (Base == null) { // fix for mapObject aircrafts etc (e.g. ZH shellmap) // TODO: handle scenario of a destroyed airfield return; } var parkingPlaceBehavior = Base.FindBehavior <ParkingPlaceBehaviour>(); var isMoving = GameObject.ModelConditionFlags.Get(ModelConditionFlag.Moving); var transform = GameObject.Transform; var trans = transform.Translation; var terrainHeight = context.GameContext.Terrain.HeightMap.GetHeight(trans.X, trans.Y); switch (CurrentJetAIState) { case JetAIState.JustCreated: var parkingTransform = parkingPlaceBehavior.GetParkingTransform(GameObject); var parkingOffset = Vector4.Transform(new Vector4(_moduleData.ParkingOffset, 0, 0, 1), parkingTransform.Rotation).ToVector3(); base.SetTargetPoint(Base.ToWorldspace(parkingTransform.Translation + parkingOffset)); CurrentJetAIState = JetAIState.MovingToParkingPlace; break; case JetAIState.MovingToParkingPlace: if (isMoving) { break; } CurrentJetAIState = JetAIState.ReachedParkingPlace; break; case JetAIState.ReachedParkingPlace: var createTransform = Base.ToWorldspace(parkingPlaceBehavior.GetUnitCreateTransform(GameObject)); SetTargetDirection(createTransform.LookDirection); CurrentJetAIState = JetAIState.Rotating; break; case JetAIState.Rotating: if (isMoving) { break; } //base.SetTargetPoint(GameObject.Transform.Translation + GameObject.Transform.LookDirection * _moduleData.ParkingOffset); CurrentJetAIState = JetAIState.Parked; break; case JetAIState.Parked: if (_unparkingRequested) { _pathToStart = parkingPlaceBehavior.GetPathToStart(GameObject); CurrentJetAIState = JetAIState.MovingTowardsStart; _unparkingRequested = false; } break; case JetAIState.MovingTowardsStart: if (isMoving || ProcessWaypointPath(context, parkingPlaceBehavior, _pathToStart)) { break; } CurrentJetAIState = JetAIState.PreparingStart; _waitUntil = context.Time.TotalTime + TimeSpan.FromMilliseconds(_moduleData.TakeoffPause); break; case JetAIState.PreparingStart: if (context.Time.TotalTime < _waitUntil) { break; } SetLocomotor(LocomotorSetType.Normal); GameObject.ModelConditionFlags.Set(ModelConditionFlag.JetExhaust, true); GameObject.ModelConditionFlags.Set(ModelConditionFlag.JetAfterburner, true); _afterburnerEnabled = true; var endPointPosition = Base.ToWorldspace(parkingPlaceBehavior.GetRunwayEndPoint(GameObject)); base.SetTargetPoint(endPointPosition); AddTargetPoint(_currentTargetPoint); CurrentJetAIState = JetAIState.Starting; _currentLocomotor.LiftFactor = 0; break; case JetAIState.Starting: var speedPercentage = GameObject.Speed / _currentLocomotor.GetSpeed(); _currentLocomotor.LiftFactor = speedPercentage; if (speedPercentage < _moduleData.TakeoffSpeedForMaxLift) { break; } CurrentJetAIState = JetAIState.MovingTowardsTarget; break; case JetAIState.MovingTowardsTarget: if (isMoving) { if (_afterburnerEnabled && trans.Z - terrainHeight >= _currentLocomotor.GetLocomotorValue(_ => _.PreferredHeight)) { GameObject.ModelConditionFlags.Set(ModelConditionFlag.JetAfterburner, false); _afterburnerEnabled = false; } break; } CurrentJetAIState = JetAIState.ReachedTargetPoint; _waitUntil = context.Time.TotalTime + TimeSpan.FromMilliseconds(_moduleData.ReturnToBaseIdleTime); break; case JetAIState.ReachedTargetPoint: if (context.Time.TotalTime < _waitUntil) { break; } var endPosition = Base.ToWorldspace(parkingPlaceBehavior.GetRunwayEndPoint(GameObject)); base.SetTargetPoint(endPosition); CurrentJetAIState = JetAIState.ReturningToBase; break; case JetAIState.ReturningToBase: if (isMoving) { break; } GameObject.ModelConditionFlags.Set(ModelConditionFlag.JetExhaust, false); CurrentJetAIState = JetAIState.MovingBackToHangar; SetLocomotor(LocomotorSetType.Taxiing); _pathToParking = parkingPlaceBehavior.GetPathToHangar(GameObject); break; case JetAIState.MovingBackToHangar: if (isMoving || ProcessWaypointPath(context, parkingPlaceBehavior, _pathToParking)) { break; } CurrentJetAIState = JetAIState.JustCreated; break; } if (trans.Z - terrainHeight < _moduleData.MinHeight) { trans.Z = terrainHeight + _moduleData.MinHeight; transform.Translation = trans; } if (GameObject.ModelConditionFlags.Get(ModelConditionFlag.Dying)) { parkingPlaceBehavior.ClearObjectFromSlot(GameObject); Base.ProductionUpdate?.CloseDoor(context.Time, parkingPlaceBehavior.GetCorrespondingSlot(GameObject)); } }
internal JetAIUpdate(GameObject gameObject, JetAIUpdateModuleData moduleData) : base(gameObject, moduleData) { _moduleData = moduleData; CurrentJetAIState = JetAIState.Parked; }