예제 #1
0
        private float CalculateAIWeight(bool isSiege, bool isInsideCastle)
        {
            FormationQuerySystem formationQuerySystem = this.formation.QuerySystem;
            float num1 = formationQuerySystem.AveragePosition.Distance(formationQuerySystem.ClosestEnemyFormation.MedianPosition.AsVec2) / formationQuerySystem.MovementSpeedMaximum;
            float num2 = formationQuerySystem.IsCavalryFormation || formationQuerySystem.IsRangedCavalryFormation ? ((double)num1 > 4.0 ? MBMath.Lerp(0.1f, 1.4f, (float)(1.0 - ((double)MBMath.ClampFloat(num1, 4f, 10f) - 4.0) / 6.0)) : MBMath.Lerp(0.1f, 1.4f, MBMath.ClampFloat(num1, 0.0f, 4f) / 4f)) : MBMath.Lerp(0.1f, 1f, (float)(1.0 - ((double)MBMath.ClampFloat(num1, 4f, 10f) - 4.0) / 6.0));
            float num3 = 0.0f;

            foreach (Team team in (ReadOnlyCollection <Team>)Mission.Current.Teams)
            {
                if (team.IsEnemyOf(this.formation.Team))
                {
                    foreach (Formation formation in team.FormationsIncludingSpecialAndEmpty)
                    {
                        Formation enemyFormation = formation;
                        if (enemyFormation.CountOfUnits > 0 && formationQuerySystem.ClosestEnemyFormation.Formation != enemyFormation && (!isSiege || TeamAISiegeComponent.IsFormationInsideCastle(enemyFormation, true) == isInsideCastle))
                        {
                            WorldPosition medianPosition = enemyFormation.QuerySystem.MedianPosition;
                            Vec2          asVec2_1       = medianPosition.AsVec2;
                            ref Vec2      local          = ref asVec2_1;
                            medianPosition = formationQuerySystem.ClosestEnemyFormation.MedianPosition;
                            Vec2  asVec2_2   = medianPosition.AsVec2;
                            float reliefTime = local.Distance(asVec2_2) / enemyFormation.QuerySystem.MovementSpeedMaximum;
                            if ((double)reliefTime <= (double)num1 + 4.0 && ((double)num1 > 8.0 || enemyFormation.QuerySystem.ClosestEnemyFormation == this.formation.QuerySystem) && ((double)num1 > 8.0 || !this.formation.QuerySystem.Team.AllyTeams.SelectMany <TeamQuerySystem, Formation>((Func <TeamQuerySystem, IEnumerable <Formation> >)(t => t.Team.FormationsIncludingSpecial)).Any <Formation>((Func <Formation, bool>)(f => f.QuerySystem.ClosestEnemyFormation == enemyFormation.QuerySystem && (double)f.QuerySystem.MedianPosition.AsVec2.Distance(formationQuerySystem.AveragePosition) / (double)f.QuerySystem.MovementSpeedMaximum < (double)reliefTime + 4.0))))
                            {
                                num3 += enemyFormation.QuerySystem.FormationMeleeFightingPower * enemyFormation.QuerySystem.GetClassWeightedFactor(1f, 1f, 1f, 1f);
                            }
                        }
                    }
                }
            }
        protected override float GetAiWeight()
        {
            FormationQuerySystem querySystem = this.formation.QuerySystem;

            if (querySystem.ClosestEnemyFormation == null)
            {
                return(0.0f);
            }
            Vec2          vec2            = querySystem.AveragePosition;
            ref Vec2      local           = ref vec2;
 public BehaviorTacticalCharge(Formation formation)
     : base(formation)
 {
     this._lastTarget                = (FormationQuerySystem)null;
     this.CurrentOrder               = MovementOrder.MovementOrderCharge;
     this.CurrentFacingOrder         = FacingOrder.FacingOrderLookAtEnemy;
     this._chargeState               = BehaviorTacticalCharge.ChargeState.Undetermined;
     this.BehaviorCoherence          = 0.5f;
     this._desiredChargeStopDistance = 20f;
 }
        protected override float GetAiWeight()
        {
            if (this.formation.Team.TeamAI is TeamAISiegeComponent)
            {
                return(this.GetSiegeAIWeight());
            }
            FormationQuerySystem q = this.formation.QuerySystem;

            if (q.ClosestEnemyFormation == null || q.ClosestEnemyFormation.ClosestEnemyFormation != q || (double)q.ClosestEnemyFormation.MovementSpeedMaximum - (double)q.MovementSpeedMaximum > 2.0)
            {
                return(0.0f);
            }
            Vec2          vec2           = q.AveragePosition;
            ref Vec2      local1         = ref vec2;
예제 #5
0
        protected override float GetAiWeight()
        {
            FormationQuerySystem querySystem = this.formation.QuerySystem;

            if (querySystem.ClosestEnemyFormation == null || querySystem.ClosestEnemyFormation.ClosestEnemyFormation == querySystem)
            {
                return(0.0f);
            }
            Vec2          vec2           = (querySystem.ClosestEnemyFormation.MedianPosition.AsVec2 - querySystem.AveragePosition).Normalized();
            WorldPosition medianPosition = querySystem.ClosestEnemyFormation.ClosestEnemyFormation.MedianPosition;
            Vec2          asVec2_1       = medianPosition.AsVec2;

            medianPosition = querySystem.ClosestEnemyFormation.MedianPosition;
            Vec2 asVec2_2 = medianPosition.AsVec2;
            Vec2 v        = (asVec2_1 - asVec2_2).Normalized();

            return((double)vec2.DotProduct(v) > -0.5 ? 0.0f : 1.2f);
        }
        protected override float GetAiWeight()
        {
            FormationQuerySystem querySystem = this.formation.QuerySystem;

            return(MBMath.Lerp(0.1f, 1f, MBMath.ClampFloat(querySystem.RangedUnitRatio + querySystem.RangedCavalryUnitRatio, 0.0f, 0.5f) * 2f));
        }
        public FormationQuerySystem(Formation formation)
        {
            FormationQuerySystem formationQuerySystem = this;

            this.Formation = formation;
            Mission mission = Mission.Current;

            this._formationPower = new QueryData <float>(new Func <float>(formation.GetFormationPower), 2.5f);
            this._formationMeleeFightingPower = new QueryData <float>(new Func <float>(formation.GetFormationMeleeFightingPower), 2.5f);
            this._averagePosition             = new QueryData <Vec2>((Func <Vec2>)(() =>
            {
                Vec2 vec2  = formation.CountOfUnitsWithoutDetachedOnes > 1 ? formation.GetAveragePositionOfUnits(true, true) : (formation.CountOfUnitsWithoutDetachedOnes > 0 ? formation.GetAveragePositionOfUnits(true, false) : formation.OrderPosition.AsVec2);
                float time = MBCommon.GetTime(MBCommon.TimeType.Mission);
                float num  = time - formationQuerySystem._lastAveragePositionCalculateTime;
                if ((double)num > 0.0)
                {
                    formationQuerySystem._currentVelocity.SetValue((vec2 - formationQuerySystem._averagePosition.GetCachedValue()) * (1f / num), time);
                }
                formationQuerySystem._lastAveragePositionCalculateTime = time;
                return(vec2);
            }), 0.05f);
            this._currentVelocity = new QueryData <Vec2>((Func <Vec2>)(() =>
            {
                formationQuerySystem._averagePosition.Evaluate(MBCommon.GetTime(MBCommon.TimeType.Mission));
                return(formationQuerySystem._currentVelocity.GetCachedValue());
            }), 1f);
            this._estimatedDirection = new QueryData <Vec2>((Func <Vec2>)(() =>
            {
                if (formation.CountOfUnitsWithoutDetachedOnes > 0)
                {
                    Vec2 averagePositionOfUnits = formation.GetAveragePositionOfUnits(true, false);
                    float num1 = 0.0f;
                    float num2 = 0.0f;
                    Vec2 localAveragePosition = formation.OrderLocalAveragePosition;
                    foreach (Agent looseDetachedOne in formation.UnitsWithoutLooseDetachedOnes)
                    {
                        Vec2?positionOfUnitOrDefault = formation.arrangement.GetLocalPositionOfUnitOrDefault((IFormationUnit)looseDetachedOne);
                        if (positionOfUnitOrDefault.HasValue)
                        {
                            Vec2 vec2   = positionOfUnitOrDefault.Value;
                            Vec2 asVec2 = looseDetachedOne.Position.AsVec2;
                            num1       += (float)(((double)vec2.x - (double)localAveragePosition.x) * ((double)asVec2.x - (double)averagePositionOfUnits.x) + ((double)vec2.y - (double)localAveragePosition.y) * ((double)asVec2.y - (double)averagePositionOfUnits.y));
                            num2       += (float)(((double)vec2.x - (double)localAveragePosition.x) * ((double)asVec2.y - (double)averagePositionOfUnits.y) - ((double)vec2.y - (double)localAveragePosition.y) * ((double)asVec2.x - (double)averagePositionOfUnits.x));
                        }
                    }
                    float num3 = 1f / (float)formation.CountOfUnitsWithoutDetachedOnes;
                    float num4 = num1 * num3;
                    float num5 = num2 * num3;
                    float num6 = MathF.Sqrt((float)((double)num4 * (double)num4 + (double)num5 * (double)num5));
                    if ((double)num6 > 0.0)
                    {
                        double num7 = Math.Acos((double)MBMath.ClampFloat(num4 / num6, -1f, 1f));
                        Vec2 vec2_1 = Vec2.FromRotation((float)num7);
                        Vec2 vec2_2 = Vec2.FromRotation((float)-num7);
                        float num8  = 0.0f;
                        float num9  = 0.0f;
                        foreach (Agent looseDetachedOne in formation.UnitsWithoutLooseDetachedOnes)
                        {
                            Vec2?positionOfUnitOrDefault = formation.arrangement.GetLocalPositionOfUnitOrDefault((IFormationUnit)looseDetachedOne);
                            if (positionOfUnitOrDefault.HasValue)
                            {
                                Vec2 parentUnitF1 = vec2_1.TransformToParentUnitF(positionOfUnitOrDefault.Value - localAveragePosition);
                                Vec2 parentUnitF2 = vec2_2.TransformToParentUnitF(positionOfUnitOrDefault.Value - localAveragePosition);
                                Vec2 asVec2       = looseDetachedOne.Position.AsVec2;
                                num8 += (parentUnitF1 - asVec2 + averagePositionOfUnits).LengthSquared;
                                num9 += (parentUnitF2 - asVec2 + averagePositionOfUnits).LengthSquared;
                            }
                        }
                        return((double)num8 >= (double)num9 ? vec2_2 : vec2_1);
                    }
                }
                return(new Vec2(0.0f, 1f));
            }), 0.2f);
            this._medianPosition = new QueryData <WorldPosition>((Func <WorldPosition>)(() =>
            {
                if (formation.CountOfUnitsWithoutDetachedOnes != 0)
                {
                    return(formation.CountOfUnitsWithoutDetachedOnes != 1 ? formation.GetMedianAgent(true, true, formationQuerySystem.AveragePosition).GetWorldPosition() : formation.GetMedianAgent(true, false, formationQuerySystem.AveragePosition).GetWorldPosition());
                }
                if (formation.CountOfUnits == 0)
                {
                    return(formation.OrderPosition);
                }
                return(formation.CountOfUnits != 1 ? formation.GetMedianAgent(false, true, formationQuerySystem.AveragePosition).GetWorldPosition() : formation.GetFirstUnit().GetWorldPosition());
            }), 0.05f);
            this._averageAllyPosition = new QueryData <Vec2>((Func <Vec2>)(() =>
            {
                IEnumerable <Formation> source = mission.Teams.GetAlliesOf(formation.Team, true).SelectMany <TaleWorlds.MountAndBlade.Team, Formation>((Func <TaleWorlds.MountAndBlade.Team, IEnumerable <Formation> >)(t => t.FormationsIncludingSpecial)).Where <Formation>(closure_1 ?? (closure_1 = (Func <Formation, bool>)(f => f != formation)));
                if (source.IsEmpty <Formation>())
                {
                    return(closure_0.AveragePosition);
                }
                Vec2 zero = Vec2.Zero;
                int num   = 0;
                foreach (Formation formation1 in source)
                {
                    zero += formation1.GetAveragePositionOfUnits(false, false) * (float)formation1.CountOfUnits;
                    num  += formation1.CountOfUnits;
                }
                return(num == 0 ? Vec2.Invalid : zero *(1f / (float)num));
            }), 5f);
            this._idealAverageDisplacement = new QueryData <float>((Func <float>)(() => (float)Math.Sqrt(Math.Pow((double)formation.Width / 2.0, 2.0) + Math.Pow((double)formation.Depth / 2.0, 2.0)) / 2f), 5f);
            this._formationIntegrityData   = new QueryData <FormationQuerySystem.FormationIntegrityDataGroup>((Func <FormationQuerySystem.FormationIntegrityDataGroup>)(() =>
            {
                if (formation.CountOfUnitsWithoutDetachedOnes > 0)
                {
                    float num1 = 0.0f;
                    List <IFormationUnit> allUnits = formation.arrangement.GetAllUnits();
                    Vec3 vec3;
                    for (int index = 0; index < allUnits.Count; ++index)
                    {
                        Agent unit  = allUnits[index] as Agent;
                        double num2 = (double)num1;
                        Vec2 globalPositionOfUnit = formation.GetCurrentGlobalPositionOfUnit(unit, false);
                        vec3                 = unit.Position;
                        Vec2 asVec2          = vec3.AsVec2;
                        double lengthSquared = (double)(globalPositionOfUnit - asVec2).LengthSquared;
                        num1                 = (float)(num2 + lengthSquared);
                    }
                    Vec2 vec2_1;
                    for (int index = 0; index < formation.LooseDetachedUnits.Count; ++index)
                    {
                        Agent looseDetachedUnit   = formation.LooseDetachedUnits[index];
                        double num2               = (double)num1;
                        Vec2 globalPositionOfUnit = formation.GetCurrentGlobalPositionOfUnit(looseDetachedUnit, false);
                        vec3                 = looseDetachedUnit.Position;
                        Vec2 asVec2          = vec3.AsVec2;
                        vec2_1               = globalPositionOfUnit - asVec2;
                        double lengthSquared = (double)vec2_1.LengthSquared;
                        num1                 = (float)(num2 + lengthSquared);
                    }
                    float num3  = (float)((double)num1 / (double)formation.CountOfUnitsWithoutDetachedOnes * 4.0);
                    float num4  = 0.0f;
                    Vec2 vec2_2 = Vec2.Zero;
                    float num5  = 0.0f;
                    int num6    = 0;
                    for (int index = 0; index < allUnits.Count; ++index)
                    {
                        Agent unit = allUnits[index] as Agent;
                        Vec2 globalPositionOfUnit = formation.GetCurrentGlobalPositionOfUnit(unit, false);
                        vec3                = unit.Position;
                        Vec2 asVec2_1       = vec3.AsVec2;
                        vec2_1              = globalPositionOfUnit - asVec2_1;
                        float lengthSquared = vec2_1.LengthSquared;
                        if ((double)lengthSquared < (double)num3)
                        {
                            num4         += lengthSquared;
                            Vec2 vec2_3   = vec2_2;
                            vec3          = unit.AverageVelocity;
                            Vec2 asVec2_2 = vec3.AsVec2;
                            vec2_2        = vec2_3 + asVec2_2;
                            num5         += unit.MaximumForwardUnlimitedSpeed;
                            ++num6;
                        }
                    }
                    for (int index = 0; index < formation.LooseDetachedUnits.Count; ++index)
                    {
                        Agent looseDetachedUnit   = formation.LooseDetachedUnits[index];
                        Vec2 globalPositionOfUnit = formation.GetCurrentGlobalPositionOfUnit(looseDetachedUnit, false);
                        vec3                = looseDetachedUnit.Position;
                        Vec2 asVec2_1       = vec3.AsVec2;
                        vec2_1              = globalPositionOfUnit - asVec2_1;
                        float lengthSquared = vec2_1.LengthSquared;
                        if ((double)lengthSquared < (double)num3)
                        {
                            num4         += lengthSquared;
                            Vec2 vec2_3   = vec2_2;
                            vec3          = looseDetachedUnit.AverageVelocity;
                            Vec2 asVec2_2 = vec3.AsVec2;
                            vec2_2        = vec2_3 + asVec2_2;
                            num5         += looseDetachedUnit.MaximumForwardUnlimitedSpeed;
                            ++num6;
                        }
                    }
                    if (num6 > 0)
                    {
                        Vec2 vec2_3 = vec2_2 * (1f / (float)num6);
                        float x     = num4 / (float)num6;
                        float num2  = num5 / (float)num6;
                        FormationQuerySystem.FormationIntegrityDataGroup integrityDataGroup;
                        integrityDataGroup.AverageVelocityExcludeFarAgents          = vec2_3;
                        integrityDataGroup.DeviationOfPositionsExcludeFarAgents     = MathF.Sqrt(x);
                        integrityDataGroup.AverageMaxUnlimitedSpeedExcludeFarAgents = num2;
                        return(integrityDataGroup);
                    }
                }
                FormationQuerySystem.FormationIntegrityDataGroup integrityDataGroup1;
                integrityDataGroup1.AverageVelocityExcludeFarAgents          = Vec2.Zero;
                integrityDataGroup1.DeviationOfPositionsExcludeFarAgents     = 0.0f;
                integrityDataGroup1.AverageMaxUnlimitedSpeedExcludeFarAgents = 0.0f;
                return(integrityDataGroup1);
            }), 1f);
            this._formationDispersedness = new QueryData <float>((Func <float>)(() =>
            {
                if (formation.CountOfUnits == 0)
                {
                    return(0.0f);
                }
                float num1 = 0.0f;
                int num2   = 0;
                foreach (IFormationUnit allUnit in formation.arrangement.GetAllUnits())
                {
                    Vec2?positionOfUnitOrDefault = formation.arrangement.GetLocalPositionOfUnitOrDefault(allUnit);
                    if (positionOfUnitOrDefault.HasValue)
                    {
                        MatrixFrame m = new MatrixFrame(Mat3.Identity, new Vec3(positionOfUnitOrDefault.Value));
                        MatrixFrame matrixFrame;
                        ref MatrixFrame local = ref matrixFrame;
                        Mat3 rot = new Mat3(new Vec3(formation.Direction.RightVec()), new Vec3(formation.Direction), new Vec3(z: 1f));
                        WorldPosition worldPosition = formation.QuerySystem.MedianPosition;
                        Vec3 navMeshVec3            = worldPosition.GetNavMeshVec3();
                        local = new MatrixFrame(rot, navMeshVec3);
                        MatrixFrame parent = matrixFrame.TransformToParent(m);
                        double num3        = (double)num1;
                        worldPosition      = (allUnit as Agent).GetWorldPosition();
                        double num4        = (double)worldPosition.GetGroundVec3().Distance(parent.origin);
                        num1 = (float)(num3 + num4);
                    }
예제 #8
0
        protected override void CalculateCurrentOrder()
        {
            WorldPosition position = this.formation.QuerySystem.MedianPosition;

            if (this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation == null)
            {
                position.SetVec2(this.formation.QuerySystem.AveragePosition);
            }
            else
            {
                int  num1     = (double)(this.formation.QuerySystem.AverageAllyPosition - this.formation.Team.QuerySystem.AverageEnemyPosition).LengthSquared <= 3600.0 ? 1 : 0;
                bool engaging = this._engaging;
                this._engaging = num1 != 0 || (this._engaging ? (double)this.formation.QuerySystem.UnderRangedAttackRatio <= (double)this.formation.QuerySystem.MakingRangedAttackRatio && (!this.formation.QuerySystem.FastestSignificantlyLargeEnemyFormation.IsCavalryFormation && !this.formation.QuerySystem.FastestSignificantlyLargeEnemyFormation.IsRangedCavalryFormation || (double)(this.formation.QuerySystem.AveragePosition - this.formation.QuerySystem.FastestSignificantlyLargeEnemyFormation.MedianPosition.AsVec2).LengthSquared / ((double)this.formation.QuerySystem.FastestSignificantlyLargeEnemyFormation.MovementSpeed * (double)this.formation.QuerySystem.FastestSignificantlyLargeEnemyFormation.MovementSpeed) >= 16.0) : (double)(this.formation.QuerySystem.AveragePosition - this.formation.QuerySystem.AverageAllyPosition).LengthSquared <= 3600.0);
                if (this._engaging)
                {
                    Vec2 vec2_1 = this.formation.QuerySystem.AveragePosition - this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.AveragePosition;
                    vec2_1 = vec2_1.Normalized();
                    Vec2 vec2_2 = vec2_1.LeftVec();
                    FormationQuerySystem largeEnemyFormation = this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation;
                    float     num2       = (float)(50.0 + ((double)this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.Formation.Width + (double)this.formation.Depth) * 0.5);
                    float     num3       = 0.0f;
                    Formation formation1 = this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.Formation;
                    for (int index1 = 0; index1 < Mission.Current.Teams.Count; ++index1)
                    {
                        Team team = Mission.Current.Teams[index1];
                        if (team.IsEnemyOf(this.formation.Team))
                        {
                            for (int index2 = 0; index2 < team.FormationsIncludingSpecialAndEmpty.Count; ++index2)
                            {
                                Formation formation2 = team.FormationsIncludingSpecialAndEmpty[index2];
                                if (formation2.CountOfUnits > 0 && formation2.QuerySystem != largeEnemyFormation)
                                {
                                    Vec2  v    = formation2.QuerySystem.AveragePosition - largeEnemyFormation.AveragePosition;
                                    float num4 = v.Normalize();
                                    if ((double)vec2_2.DotProduct(v) > 0.800000011920929 && (double)num4 < (double)num2 && (double)num4 > (double)num3)
                                    {
                                        num3       = num4;
                                        formation1 = formation2;
                                    }
                                }
                            }
                        }
                    }
                    if (((double)this.formation.QuerySystem.RangedCavalryUnitRatio <= 0.949999988079071 ? 0 : (this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.Formation == formation1 ? 1 : 0)) == 0)
                    {
                        bool  flag   = formation1.QuerySystem.IsCavalryFormation || formation1.QuerySystem.IsRangedCavalryFormation;
                        float radius = Math.Min((flag ? 35f : 20f) + (float)(((double)formation1.Depth + (double)this.formation.Width) * 0.5), this.formation.QuerySystem.MissileRange - this.formation.Width * 0.5f);
                        BehaviorMountedSkirmish.Ellipse ellipse = new BehaviorMountedSkirmish.Ellipse(formation1.QuerySystem.MedianPosition.AsVec2, radius, (float)((double)formation1.Width * 0.5 * (flag ? 1.5 : 1.0)), formation1.Direction);
                        position.SetVec2(ellipse.GetTargetPos(this.formation.QuerySystem.AveragePosition, 20f));
                    }
                    else
                    {
                        this.CurrentOrder = MovementOrder.MovementOrderCharge;
                        return;
                    }
                }
                else
                {
                    position = new WorldPosition(Mission.Current.Scene, new Vec3(this.formation.QuerySystem.AverageAllyPosition, this.formation.Team.QuerySystem.MedianPosition.GetNavMeshZ() + 100f));
                }
            }
            this.CurrentOrder = MovementOrder.MovementOrderMove(position);
        }
        protected override float GetAiWeight()
        {
            FormationQuerySystem querySystem = this.formation.QuerySystem;

            return(this.formation.AI.ActiveBehavior == null ? 0.0f : MBMath.Lerp(0.1f, 1.2f, MBMath.ClampFloat((float)((double)this.formation.AI.ActiveBehavior.BehaviorCoherence * ((double)querySystem.FormationIntegrityData.DeviationOfPositionsExcludeFarAgents + 1.0) / ((double)querySystem.IdealAverageDisplacement + 1.0)), 0.0f, 3f) / 3f));
        }
        protected override void CalculateCurrentOrder()
        {
            if (this.formation.QuerySystem.ClosestEnemyFormation == null)
            {
                this.CurrentOrder = MovementOrder.MovementOrderCharge;
            }
            else
            {
                BehaviorTacticalCharge.ChargeState chargeState = this.CheckAndChangeState();
                if (chargeState != this._chargeState)
                {
                    this._chargeState = chargeState;
                    switch (this._chargeState)
                    {
                    case BehaviorTacticalCharge.ChargeState.Undetermined:
                        this.CurrentOrder = MovementOrder.MovementOrderCharge;
                        break;

                    case BehaviorTacticalCharge.ChargeState.Charging:
                        this._lastTarget = this.formation.QuerySystem.ClosestEnemyFormation;
                        if (this.formation.QuerySystem.IsCavalryFormation || this.formation.QuerySystem.IsRangedCavalryFormation)
                        {
                            this._initialChargeDirection    = this._lastTarget.MedianPosition.AsVec2 - this.formation.QuerySystem.AveragePosition;
                            this._desiredChargeStopDistance = MBMath.ClampFloat(this._initialChargeDirection.Normalize(), 20f, 50f);
                            break;
                        }
                        break;

                    case BehaviorTacticalCharge.ChargeState.ChargingPast:
                        this._chargingPastTimer = new Timer(MBCommon.GetTime(MBCommon.TimeType.Mission), 5f);
                        break;

                    case BehaviorTacticalCharge.ChargeState.Reforming:
                        this._reformTimer = new Timer(MBCommon.GetTime(MBCommon.TimeType.Mission), 2f);
                        break;

                    case BehaviorTacticalCharge.ChargeState.Bracing:
                        this._bracePosition = this.formation.QuerySystem.AveragePosition + (this.formation.QuerySystem.Team.MedianTargetFormationPosition.AsVec2 - this.formation.QuerySystem.AveragePosition).Normalized() * 5f;
                        break;
                    }
                }
                switch (this._chargeState)
                {
                case BehaviorTacticalCharge.ChargeState.Undetermined:
                    if (this.formation.QuerySystem.ClosestEnemyFormation != null && (this.formation.QuerySystem.IsCavalryFormation || this.formation.QuerySystem.IsRangedCavalryFormation))
                    {
                        this.CurrentOrder = MovementOrder.MovementOrderMove(this.formation.QuerySystem.ClosestEnemyFormation.MedianPosition);
                    }
                    else
                    {
                        this.CurrentOrder = MovementOrder.MovementOrderCharge;
                    }
                    this.CurrentFacingOrder = FacingOrder.FacingOrderLookAtEnemy;
                    break;

                case BehaviorTacticalCharge.ChargeState.Charging:
                    if (!this.formation.QuerySystem.IsCavalryFormation && !this.formation.QuerySystem.IsRangedCavalryFormation)
                    {
                        this.CurrentOrder       = MovementOrder.MovementOrderMove(this.formation.QuerySystem.ClosestEnemyFormation.MedianPosition);
                        this.CurrentFacingOrder = FacingOrder.FacingOrderLookAtEnemy;
                        break;
                    }
                    Vec2          direction1      = (this._lastTarget.MedianPosition.AsVec2 - this.formation.QuerySystem.AveragePosition).Normalized();
                    WorldPosition medianPosition1 = this._lastTarget.MedianPosition;
                    Vec2          vec2            = medianPosition1.AsVec2 + direction1 * this._desiredChargeStopDistance;
                    medianPosition1.SetVec2(vec2);
                    this.CurrentOrder       = MovementOrder.MovementOrderMove(medianPosition1);
                    this.CurrentFacingOrder = FacingOrder.FacingOrderLookAtDirection(direction1);
                    break;

                case BehaviorTacticalCharge.ChargeState.ChargingPast:
                    Vec2          averagePosition = this.formation.QuerySystem.AveragePosition;
                    WorldPosition medianPosition2 = this._lastTarget.MedianPosition;
                    Vec2          asVec2          = medianPosition2.AsVec2;
                    Vec2          direction2      = averagePosition - asVec2;
                    if ((double)direction2.Normalize() <= 20.0)
                    {
                        Vec2 initialChargeDirection = this._initialChargeDirection;
                    }
                    this._lastReformDestination = this._lastTarget.MedianPosition;
                    medianPosition2             = this._lastTarget.MedianPosition;
                    this._lastReformDestination.SetVec2(medianPosition2.AsVec2 + direction2 * this._desiredChargeStopDistance);
                    this.CurrentOrder       = MovementOrder.MovementOrderMove(this._lastReformDestination);
                    this.CurrentFacingOrder = FacingOrder.FacingOrderLookAtDirection(direction2);
                    break;

                case BehaviorTacticalCharge.ChargeState.Reforming:
                    this.CurrentOrder       = MovementOrder.MovementOrderMove(this._lastReformDestination);
                    this.CurrentFacingOrder = FacingOrder.FacingOrderLookAtEnemy;
                    break;

                case BehaviorTacticalCharge.ChargeState.Bracing:
                    WorldPosition medianPosition3 = this.formation.QuerySystem.MedianPosition;
                    medianPosition3.SetVec2(this._bracePosition);
                    this.CurrentOrder = MovementOrder.MovementOrderMove(medianPosition3);
                    break;
                }
            }
        }