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); }
private static float GetPositionMultiplierOfFormation( Formation formation, IEnumerable <ICastleKeyPosition> referencePositions) { ICastleKeyPosition closestCastlePosition; float betweenPositions = ThreatSeeker.GetMinimumDistanceBetweenPositions(formation.GetMedianAgent(false, false, formation.GetAveragePositionOfUnits(false, false)).Position, referencePositions, out closestCastlePosition); bool flag = closestCastlePosition.AttackerSiegeWeapon != null && closestCastlePosition.AttackerSiegeWeapon.HasCompletedAction(); return(formation.IsRanged() ? (float)(((double)betweenPositions >= 20.0 ? ((double)betweenPositions >= 35.0 ? 0.600000023841858 : 0.800000011920929) : 1.0) + (flag ? 0.200000002980232 : 0.0)) : (float)(((double)betweenPositions >= 15.0 ? ((double)betweenPositions >= 40.0 ? 0.119999997317791 : 0.150000005960464) : 0.200000002980232) * (flag ? 7.5 : 1.0))); }