public override void OnMissionTick(float dt) { if (!this.CheckTimer(dt)) { return; } if (this._checkState == SallyOutEndLogic.EndConditionCheckState.Deactive) { foreach (Team team in this.Mission.Teams.Where <Team>((Func <Team, bool>)(t => t.Side == BattleSideEnum.Defender))) { foreach (Formation formation in team.FormationsIncludingSpecial) { if (!TeamAISiegeComponent.IsFormationInsideCastle(formation, true, 0.1f)) { this._checkState = SallyOutEndLogic.EndConditionCheckState.Active; return; } } } } else { if (this._checkState != SallyOutEndLogic.EndConditionCheckState.Idle) { return; } this._checkState = SallyOutEndLogic.EndConditionCheckState.Active; } }
private void CheckAndChangeState() { this.Formations.Where <Formation>((Func <Formation, bool>)(f => TeamAISiegeComponent.IsFormationInsideCastle(f, true))); if (!this.MustRetreatToCastle() || this._isRetreatingToKeep) { return; } this._isRetreatingToKeep = true; this.StartRetreatToKeep(); }
public IEnumerable <Formation> GetAttackerFormationsInsideWalls() { IEnumerable <Formation> formations = this.Mission.AttackerTeam.FormationsIncludingSpecial; if (this.Mission.AttackerAllyTeam != null) { formations = formations.Concat <Formation>(this.Mission.AttackerAllyTeam.FormationsIncludingSpecial); } return(formations.Where <Formation>((Func <Formation, bool>)(af => TeamAISiegeComponent.IsFormationInsideCastle(af, true)))); }
private static float GetTargetValueOfFormation( Formation formation, IEnumerable <ICastleKeyPosition> referencePositions) { float num = (float)formation.CountOfUnits * 3f; if (TeamAISiegeComponent.IsFormationInsideCastle(formation, true)) { num *= 3f; } return(num * ThreatSeeker.GetPositionMultiplierOfFormation(formation, referencePositions) * (MBMath.ClampFloat(formation.QuerySystem.LocalAllyPower / (formation.QuerySystem.LocalEnemyPower + 0.01f), 0.0f, 5f) / 5f)); }
private BehaviorAssaultWalls.BehaviorState CheckAndChangeState() { switch (this._behaviourState) { case BehaviorAssaultWalls.BehaviorState.Deciding: if (!this._isGateLane && this._wallSegment == null) { return(BehaviorAssaultWalls.BehaviorState.Charging); } return(this._isGateLane ? BehaviorAssaultWalls.BehaviorState.AttackEntity : BehaviorAssaultWalls.BehaviorState.ClimbWall); case BehaviorAssaultWalls.BehaviorState.ClimbWall: if (this._wallSegment == null) { return(BehaviorAssaultWalls.BehaviorState.Charging); } bool flag = false; if (this.behaviorSide < FormationAI.BehaviorSide.BehaviorSideNotSet) { SiegeLane siegeLane = TeamAISiegeComponent.SiegeLanes[(int)this.behaviorSide]; flag = siegeLane.IsUnderAttack() && !siegeLane.IsDefended(); } return(flag | (double)this.formation.QuerySystem.MedianPosition.GetNavMeshVec3().DistanceSquared(this._wallSegment.MiddleFrame.Origin.GetNavMeshVec3()) < (double)this.formation.Depth * (double)this.formation.Depth ? BehaviorAssaultWalls.BehaviorState.TakeControl : BehaviorAssaultWalls.BehaviorState.ClimbWall); case BehaviorAssaultWalls.BehaviorState.AttackEntity: return(this._teamAISiegeComponent.OuterGate.IsGateOpen && this._teamAISiegeComponent.InnerGate.IsGateOpen ? BehaviorAssaultWalls.BehaviorState.Charging : BehaviorAssaultWalls.BehaviorState.AttackEntity); case BehaviorAssaultWalls.BehaviorState.TakeControl: if (this.formation.QuerySystem.ClosestEnemyFormation == null) { return(BehaviorAssaultWalls.BehaviorState.Deciding); } if (TeamAISiegeComponent.SiegeLanes.FirstOrDefault <SiegeLane>((Func <SiegeLane, bool>)(sl => sl.LaneSide == this.behaviorSide)).IsDefended()) { return(BehaviorAssaultWalls.BehaviorState.TakeControl); } return(!this._teamAISiegeComponent.OuterGate.IsGateOpen || !this._teamAISiegeComponent.InnerGate.IsGateOpen ? BehaviorAssaultWalls.BehaviorState.MoveToGate : BehaviorAssaultWalls.BehaviorState.Charging); case BehaviorAssaultWalls.BehaviorState.MoveToGate: return(this._teamAISiegeComponent.OuterGate.IsGateOpen && this._teamAISiegeComponent.InnerGate.IsGateOpen ? BehaviorAssaultWalls.BehaviorState.Charging : BehaviorAssaultWalls.BehaviorState.MoveToGate); case BehaviorAssaultWalls.BehaviorState.Charging: if (!TeamAISiegeComponent.IsFormationInsideCastle(this.formation, true)) { return(BehaviorAssaultWalls.BehaviorState.Deciding); } return(this.formation.QuerySystem.ClosestEnemyFormation == null ? BehaviorAssaultWalls.BehaviorState.Stop : BehaviorAssaultWalls.BehaviorState.Charging); default: return(this.formation.QuerySystem.ClosestEnemyFormation != null ? BehaviorAssaultWalls.BehaviorState.Deciding : BehaviorAssaultWalls.BehaviorState.Stop); } }
private void CheckAndChangeState() { this.Formations.Where <Formation>((Func <Formation, bool>)(f => TeamAISiegeComponent.IsFormationInsideCastle(f, true))); if (this._tacticState == TacticBreachWalls.TacticState.Retreating) { return; } if (this.ShouldRetreat((IEnumerable <SiegeLane>) this.DetermineCurrentLanes(), this.Formations.Count <Formation>((Func <Formation, bool>)(f => TeamAISiegeComponent.IsFormationInsideCastle(f, true))))) { this._tacticState = TacticBreachWalls.TacticState.Retreating; this.StartTacticalRetreat(); this.IsTacticReapplyNeeded = false; } else { TacticBreachWalls.TacticState tacticState = TacticBreachWalls.TacticState.TotalAttack; if (this._tacticState != TacticBreachWalls.TacticState.TotalAttack) { double num1 = (double)Math.Max((float)this._meleeFormations.Sum <Formation>((Func <Formation, int>)(mf => mf.CountOfUnits)), 1f); float num2 = Math.Max((float)this._rangedFormations.Sum <Formation>((Func <Formation, int>)(rf => rf.CountOfUnits)), 1f); float num3 = (float)num1 + num2; float num4 = num3 - (float)this.Formations.Sum <Formation>((Func <Formation, int>)(f => f.CountOfUnitsWithoutDetachedOnes)); tacticState = num1 / (double)num2 <= 0.5 || (double)num4 / (double)num3 >= 0.200000002980232 ? TacticBreachWalls.TacticState.TotalAttack : TacticBreachWalls.TacticState.AssaultUnderRangedCover; } if (tacticState == this._tacticState) { return; } if (tacticState != TacticBreachWalls.TacticState.AssaultUnderRangedCover) { if (tacticState != TacticBreachWalls.TacticState.TotalAttack) { return; } this._tacticState = TacticBreachWalls.TacticState.TotalAttack; this.ManageFormationCounts(); this.AllInAssault(); this.IsTacticReapplyNeeded = false; } else { this._tacticState = TacticBreachWalls.TacticState.AssaultUnderRangedCover; this.ManageFormationCounts(); this.WellRoundedAssault(); this.IsTacticReapplyNeeded = false; } } }
public bool IsCastleBreached() { IEnumerable <Formation> formations = this.Mission.AttackerTeam.FormationsIncludingSpecial; if (this.Mission.AttackerAllyTeam != null) { formations = formations.Concat <Formation>(this.Mission.AttackerAllyTeam.FormationsIncludingSpecial); } float num1 = (float)formations.Count <Formation>() * 0.7f; int num2 = 0; foreach (Formation formation in formations) { if (TeamAISiegeComponent.IsFormationInsideCastle(formation, true)) { ++num2; } if ((double)num2 >= (double)num1) { return(true); } } return(false); }
public override bool MissionEnded(ref MissionResult missionResult) { if (this.IsSallyOutOver) { missionResult = MissionResult.CreateSuccessful((IMission)this.Mission); return(true); } if (this._checkState != SallyOutEndLogic.EndConditionCheckState.Active) { return(false); } foreach (Team team in (ReadOnlyCollection <Team>) this.Mission.Teams) { switch (team.Side) { case BattleSideEnum.Defender: if (team.FormationsIncludingSpecial.Any <Formation>() && team.Formations.Any <Formation>((Func <Formation, bool>)(f => !TeamAISiegeComponent.IsFormationInsideCastle(f, false, 0.9f)))) { this._checkState = SallyOutEndLogic.EndConditionCheckState.Idle; return(false); } continue; case BattleSideEnum.Attacker: if (TeamAISiegeComponent.IsFormationGroupInsideCastle(team.FormationsIncludingSpecial, false, 0.1f)) { this._checkState = SallyOutEndLogic.EndConditionCheckState.Idle; return(false); } continue; default: continue; } } this.IsSallyOutOver = true; missionResult = MissionResult.CreateSuccessful((IMission)this.Mission); return(true); }
private void DetermineMostImportantInvadingEnemyFormation() { IEnumerable <Formation> source = this.formation.QuerySystem.Team.EnemyTeams.SelectMany <TeamQuerySystem, Formation>((Func <TeamQuerySystem, IEnumerable <Formation> >)(et => et.Team.Formations)).Where <Formation>((Func <Formation, bool>)(f => TeamAISiegeComponent.IsFormationInsideCastle(f, true))); if (source.Any <Formation>()) { this._targetEnemyFormation = source.MaxBy <Formation, float>((Func <Formation, float>)(efi => efi.QuerySystem.FormationPower)); } else { this._targetEnemyFormation = (Formation)null; } }
private void ResetOrderPositions() { this.behaviorSide = this.formation.AI.Side; this._innerGate = (CastleGate)null; this._outerGate = (CastleGate)null; this._laddersOnThisSide.Clear(); int num1 = Mission.Current.ActiveMissionObjects.FindAllWithType <CastleGate>().Any <CastleGate>((Func <CastleGate, bool>)(cg => cg.DefenseSide == this.behaviorSide && cg.GameEntity.HasTag("outer_gate"))) ? 1 : 0; this._isDefendingWideGap = false; WorldFrame worldFrame1; WorldFrame worldFrame2; if (num1 != 0) { CastleGate outerGate = this._teamAISiegeDefender.OuterGate; this._innerGate = this._teamAISiegeDefender.InnerGate; this._outerGate = this._teamAISiegeDefender.OuterGate; worldFrame1 = outerGate.MiddleFrame; worldFrame2 = outerGate.DefenseWaitFrame; this._tacticalMiddlePos = outerGate.MiddlePosition; this._tacticalWaitPos = outerGate.WaitPosition; this._isDefendingWideGap = false; } else { WallSegment wallSegment = Mission.Current.ActiveMissionObjects.FindAllWithType <WallSegment>().Where <WallSegment>((Func <WallSegment, bool>)(ws => ws.DefenseSide == this.behaviorSide && ws.IsBreachedWall)).FirstOrDefault <WallSegment>(); if (wallSegment != null) { worldFrame1 = wallSegment.MiddleFrame; worldFrame2 = wallSegment.DefenseWaitFrame; this._tacticalMiddlePos = wallSegment.MiddlePosition; this._tacticalWaitPos = wallSegment.WaitPosition; this._isDefendingWideGap = false; } else { IEnumerable <SiegeWeapon> source = Mission.Current.ActiveMissionObjects.FindAllWithType <SiegeWeapon>().Where <SiegeWeapon>((Func <SiegeWeapon, bool>)(sw => { if (!(sw is IPrimarySiegeWeapon) || (sw as IPrimarySiegeWeapon).WeaponSide != this.behaviorSide) { return(false); } return(!sw.IsDestroyed || (sw as IPrimarySiegeWeapon).HasCompletedAction()); })); if (!source.Any <SiegeWeapon>()) { worldFrame1 = WorldFrame.Invalid; worldFrame2 = WorldFrame.Invalid; this._tacticalMiddlePos = (TacticalPosition)null; this._tacticalWaitPos = (TacticalPosition)null; } else { this._laddersOnThisSide = source.Where <SiegeWeapon>((Func <SiegeWeapon, bool>)(aw => aw is SiegeLadder)).Select <SiegeWeapon, SiegeLadder>((Func <SiegeWeapon, SiegeLadder>)(aw => aw as SiegeLadder)).ToList <SiegeLadder>(); ICastleKeyPosition targetCastlePosition = (source.FirstOrDefault <SiegeWeapon>() as IPrimarySiegeWeapon).TargetCastlePosition as ICastleKeyPosition; worldFrame1 = targetCastlePosition.MiddleFrame; worldFrame2 = targetCastlePosition.DefenseWaitFrame; this._tacticalMiddlePos = targetCastlePosition.MiddlePosition; this._tacticalWaitPos = targetCastlePosition.WaitPosition; } } } if (this._tacticalMiddlePos != null) { this._readyOrder = MovementOrder.MovementOrderMove(this._tacticalMiddlePos.Position); this._readyFacingOrder = FacingOrder.FacingOrderLookAtDirection(this._tacticalMiddlePos.Direction); } else if (worldFrame1.Origin.IsValid) { double num2 = (double)worldFrame1.Rotation.f.Normalize(); this._readyOrder = MovementOrder.MovementOrderMove(worldFrame1.Origin); this._readyFacingOrder = FacingOrder.FacingOrderLookAtDirection(worldFrame1.Rotation.f.AsVec2); } else { this._readyOrder = MovementOrder.MovementOrderStop; this._readyFacingOrder = FacingOrder.FacingOrderLookAtEnemy; } if (this._tacticalWaitPos != null) { this._waitOrder = MovementOrder.MovementOrderMove(this._tacticalWaitPos.Position); this._waitFacingOrder = FacingOrder.FacingOrderLookAtDirection(this._tacticalWaitPos.Direction); } else if (worldFrame2.Origin.IsValid) { double num2 = (double)worldFrame2.Rotation.f.Normalize(); this._waitOrder = MovementOrder.MovementOrderMove(worldFrame2.Origin); this._waitFacingOrder = FacingOrder.FacingOrderLookAtDirection(worldFrame2.Rotation.f.AsVec2); } else { this._waitOrder = MovementOrder.MovementOrderStop; this._waitFacingOrder = FacingOrder.FacingOrderLookAtEnemy; } this.CurrentOrder = this._behaviourState == BehaviorDefendCastleKeyPosition.BehaviourState.Ready ? this._readyOrder : this._waitOrder; this.CurrentFacingOrder = this.formation.QuerySystem.ClosestEnemyFormation == null || !TeamAISiegeComponent.IsFormationInsideCastle(this.formation.QuerySystem.ClosestEnemyFormation.Formation, true) ? (this._behaviourState == BehaviorDefendCastleKeyPosition.BehaviourState.Ready ? this._readyFacingOrder : this._waitFacingOrder) : FacingOrder.FacingOrderLookAtEnemy; }
protected override void CalculateCurrentOrder() { base.CalculateCurrentOrder(); this.CurrentOrder = this._behaviourState == BehaviorDefendCastleKeyPosition.BehaviourState.Ready ? this._readyOrder : this._waitOrder; this.CurrentFacingOrder = this.formation.QuerySystem.ClosestEnemyFormation == null || !TeamAISiegeComponent.IsFormationInsideCastle(this.formation.QuerySystem.ClosestEnemyFormation.Formation, true) ? (this._behaviourState == BehaviorDefendCastleKeyPosition.BehaviourState.Ready ? this._readyFacingOrder : this._waitFacingOrder) : FacingOrder.FacingOrderLookAtEnemy; }
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); } } } } }
private void CheckAndChangeState() { switch (this._state) { case TacticSallyOutHitAndRun.TacticState.HeadingOutFromCastle: if (!this._cavalryFormations.All <Formation>((Func <Formation, bool>)(cf => !TeamAISiegeComponent.IsFormationInsideCastle(cf, false)))) { break; } this._state = TacticSallyOutHitAndRun.TacticState.DestroyingSiegeWeapons; this.DestroySiegeWeapons(); break; case TacticSallyOutHitAndRun.TacticState.DestroyingSiegeWeapons: if (!this._destructibleEnemySiegeWeapons.All <SiegeWeapon>((Func <SiegeWeapon, bool>)(desw => desw.IsDestroyed)) && !this._cavalryFormations.All <Formation>((Func <Formation, bool>)(cf => { if (!(cf.AI.ActiveBehavior is BehaviorDestroySiegeWeapons) || cf.MovementOrder == (object)MovementOrder.MovementOrderRetreat) { return(true); } if ((cf.AI.ActiveBehavior as BehaviorDestroySiegeWeapons).LastTargetWeapon == null) { return(false); } Vec3 globalPosition = (cf.AI.ActiveBehavior as BehaviorDestroySiegeWeapons).LastTargetWeapon.GameEntity.GlobalPosition; return((double)this.team.QuerySystem.GetLocalEnemyPower(globalPosition.AsVec2) > (double)this.team.QuerySystem.GetLocalAllyPower(globalPosition.AsVec2) + (double)cf.QuerySystem.FormationPower); }))) { break; } this._state = TacticSallyOutHitAndRun.TacticState.CavalryRetreating; this.CavalryRetreat(); break; case TacticSallyOutHitAndRun.TacticState.CavalryRetreating: if (!this._cavalryFormations.IsEmpty <Formation>() && !TeamAISiegeComponent.IsFormationGroupInsideCastle((IEnumerable <Formation>) this._cavalryFormations, false)) { break; } this._state = TacticSallyOutHitAndRun.TacticState.InfantryRetreating; this.InfantryRetreat(); break; } }