<commit_before>﻿using System;
using System.Numerics;
using OpenSage.Content;
using OpenSage.Data.Ini;
using OpenSage.FX;

namespace OpenSage.Logic.Object
{
    public sealed class MissileAIUpdate : AIUpdate
    {
        private readonly MissileAIUpdateModuleData _moduleData;

        private MissileState _state;
        private TimeSpan _nextStateChangeTime;

        internal FXList DetonationFX { get; set; }

        internal MissileAIUpdate(GameObject gameObject, MissileAIUpdateModuleData moduleData)
            : base(gameObject, moduleData)
        {
            _moduleData = moduleData;

            _state = MissileState.Inactive;
        }

        internal override void Update(BehaviorUpdateContext context)
        {
            switch (_state)
            {
                case MissileState.Inactive:
                    _nextStateChangeTime = context.Time.TotalTime + _moduleData.IgnitionDelay;
                    _state = MissileState.WaitingForIgnition;
                    goto case MissileState.WaitingForIgnition;

                case MissileState.WaitingForIgnition:
                    if (context.Time.TotalTime > _nextStateChangeTime)
                    {
                        _moduleData.IgnitionFX?.Value?.Execute(
                            new FXListExecutionContext(
                                GameObject.Transform.Rotation,
                                GameObject.Transform.Translation,
                                context.GameContext));

                        if (_moduleData.DistanceToTravelBeforeTurning > 0)
                        {
                            var pointToReachBeforeTurning = context.GameObject.Transform.Translation
                                + Vector3.TransformNormal(Vector3.UnitX, context.GameObject.Transform.Matrix) * _moduleData.DistanceToTravelBeforeTurning;
                            AddTargetPoint(pointToReachBeforeTurning);
                        }

                        AddTargetPoint(context.GameObject.CurrentWeapon.CurrentTarget.TargetPosition);

                        context.GameObject.Speed = _moduleData.InitialVelocity;

                        _state = MissileState.Moving;
                    }
                    break;

                case MissileState.Moving:
                    // TODO: TryToFollowTarget
                    BezierProjectileBehavior.CheckForHit(context, _moduleData.DetonateCallsKill, DetonationFX);
                    break;

                default:
                    throw new InvalidOperationException();
            }

            base.Update(context);
        }

        private enum MissileState
        {
            Inactive,
            WaitingForIgnition,
            Moving,
        }
    }<commit_msg>Fix crash when missile target doesn't exist anymore<commit_after>﻿using System;
using System.Numerics;
using OpenSage.Content;
using OpenSage.Data.Ini;
using OpenSage.FX;

namespace OpenSage.Logic.Object
{
    public sealed class MissileAIUpdate : AIUpdate
    {
        private readonly MissileAIUpdateModuleData _moduleData;

        private MissileState _state;
        private TimeSpan _nextStateChangeTime;

        internal FXList DetonationFX { get; set; }

        internal MissileAIUpdate(GameObject gameObject, MissileAIUpdateModuleData moduleData)
            : base(gameObject, moduleData)
        {
            _moduleData = moduleData;

            _state = MissileState.Inactive;
        }

        internal override void Update(BehaviorUpdateContext context)
        {
            switch (_state)
            {
                case MissileState.Inactive:
                    _nextStateChangeTime = context.Time.TotalTime + _moduleData.IgnitionDelay;
                    _state = MissileState.WaitingForIgnition;
                    goto case MissileState.WaitingForIgnition;

                case MissileState.WaitingForIgnition:
                    if (context.Time.TotalTime > _nextStateChangeTime)
                    {
                        _moduleData.IgnitionFX?.Value?.Execute(
                            new FXListExecutionContext(
                                GameObject.Transform.Rotation,
                                GameObject.Transform.Translation,
                                context.GameContext));

                        if (_moduleData.DistanceToTravelBeforeTurning > 0)
                        {
                            var pointToReachBeforeTurning = context.GameObject.Transform.Translation
                                + Vector3.TransformNormal(Vector3.UnitX, context.GameObject.Transform.Matrix) * _moduleData.DistanceToTravelBeforeTurning;
                            AddTargetPoint(pointToReachBeforeTurning);
                        }

                        // TODO: What to do if target doesn't exist anymore?
                        if (context.GameObject.CurrentWeapon.CurrentTarget != null)
                        {
                            AddTargetPoint(context.GameObject.CurrentWeapon.CurrentTarget.TargetPosition);
                        }

                        context.GameObject.Speed = _moduleData.InitialVelocity;

                        _state = MissileState.Moving;
                    }
                    break;

                case MissileState.Moving:
                    // TODO: TryToFollowTarget
                    BezierProjectileBehavior.CheckForHit(context, _moduleData.DetonateCallsKill, DetonationFX);
                    break;

                default:
                    throw new InvalidOperationException();
            }

            base.Update(context);
        }

        private enum MissileState
        {
            Inactive,
            WaitingForIgnition,
            Moving,
        }
    }
{'fraction_non_alphanumeric': 0.05635512398127276, 'fraction_numerical': 0.0010404022888850356, 'mean_word_length': 1.4744744744744744, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3019861', 'n_tokens_mistral': 1381, 'n_tokens_neox': 1273, 'n_words': 231}