|
14 | 14 | using System.Collections.Generic;
|
15 | 15 | using System.Linq;
|
16 | 16 | using OpenRA.Mods.Common.Traits.BotModules.Squads;
|
| 17 | +using OpenRA.Primitives; |
17 | 18 | using OpenRA.Support;
|
18 | 19 | using OpenRA.Traits;
|
19 | 20 |
|
@@ -74,6 +75,9 @@ public class SquadManagerBotModuleInfo : ConditionalTraitInfo
|
74 | 75 | [Desc("Radius in cells that protecting squads should scan for enemies around their position.")]
|
75 | 76 | public readonly int ProtectionScanRadius = 8;
|
76 | 77 |
|
| 78 | + [Desc("Enemy target types to never target.")] |
| 79 | + public readonly BitSet<TargetableType> IgnoredEnemyTargetTypes = default(BitSet<TargetableType>); |
| 80 | + |
77 | 81 | public override object Create(ActorInitializer init) { return new SquadManagerBotModule(init.Self, this); }
|
78 | 82 | }
|
79 | 83 |
|
@@ -119,11 +123,14 @@ public SquadManagerBotModule(Actor self, SquadManagerBotModuleInfo info)
|
119 | 123 | unitCannotBeOrdered = a => a == null || a.Owner != Player || a.IsDead || !a.IsInWorld;
|
120 | 124 | }
|
121 | 125 |
|
122 |
| - public bool IsEnemyUnit(Actor a) |
| 126 | + // Use for proactive targeting. |
| 127 | + public bool IsPreferredEnemyUnit(Actor a) |
123 | 128 | {
|
124 |
| - return a != null && !a.IsDead && Player.Stances[a.Owner] == Stance.Enemy |
125 |
| - && !a.Info.HasTraitInfo<HuskInfo>() |
126 |
| - && !a.GetEnabledTargetTypes().IsEmpty; |
| 129 | + if (a == null || a.IsDead || Player.Stances[a.Owner] != Stance.Enemy || a.Info.HasTraitInfo<HuskInfo>()) |
| 130 | + return false; |
| 131 | + |
| 132 | + var targetTypes = a.GetEnabledTargetTypes(); |
| 133 | + return !targetTypes.IsEmpty && !targetTypes.Overlaps(Info.IgnoredEnemyTargetTypes); |
127 | 134 | }
|
128 | 135 |
|
129 | 136 | public bool IsNotHiddenUnit(Actor a)
|
@@ -175,13 +182,13 @@ void IBotTick.BotTick(IBot bot)
|
175 | 182 |
|
176 | 183 | internal Actor FindClosestEnemy(WPos pos)
|
177 | 184 | {
|
178 |
| - var units = World.Actors.Where(IsEnemyUnit); |
| 185 | + var units = World.Actors.Where(IsPreferredEnemyUnit); |
179 | 186 | return units.Where(IsNotHiddenUnit).ClosestTo(pos) ?? units.ClosestTo(pos);
|
180 | 187 | }
|
181 | 188 |
|
182 | 189 | internal Actor FindClosestEnemy(WPos pos, WDist radius)
|
183 | 190 | {
|
184 |
| - return World.FindActorsInCircle(pos, radius).Where(a => IsEnemyUnit(a) && IsNotHiddenUnit(a)).ClosestTo(pos); |
| 191 | + return World.FindActorsInCircle(pos, radius).Where(a => IsPreferredEnemyUnit(a) && IsNotHiddenUnit(a)).ClosestTo(pos); |
185 | 192 | }
|
186 | 193 |
|
187 | 194 | void CleanSquads()
|
@@ -311,7 +318,7 @@ void TryToRushAttack(IBot bot)
|
311 | 318 | {
|
312 | 319 | // Don't rush enemy aircraft!
|
313 | 320 | var enemies = World.FindActorsInCircle(b.CenterPosition, WDist.FromCells(Info.RushAttackScanRadius))
|
314 |
| - .Where(unit => IsEnemyUnit(unit) && unit.Info.HasTraitInfo<AttackBaseInfo>() && !unit.Info.HasTraitInfo<AircraftInfo>() && !Info.NavalUnitsTypes.Contains(unit.Info.Name)).ToList(); |
| 321 | + .Where(unit => IsPreferredEnemyUnit(unit) && unit.Info.HasTraitInfo<AttackBaseInfo>() && !unit.Info.HasTraitInfo<AircraftInfo>() && !Info.NavalUnitsTypes.Contains(unit.Info.Name)).ToList(); |
315 | 322 |
|
316 | 323 | if (AttackOrFleeFuzzy.Rush.CanAttack(ownUnits, enemies))
|
317 | 324 | {
|
@@ -357,7 +364,7 @@ void IBotPositionsUpdated.UpdatedDefenseCenter(CPos newLocation) { }
|
357 | 364 |
|
358 | 365 | void IBotRespondToAttack.RespondToAttack(IBot bot, Actor self, AttackInfo e)
|
359 | 366 | {
|
360 |
| - if (!IsEnemyUnit(e.Attacker)) |
| 367 | + if (!IsPreferredEnemyUnit(e.Attacker)) |
361 | 368 | return;
|
362 | 369 |
|
363 | 370 | // Protected priority assets, MCVs, harvesters and buildings
|
|
0 commit comments