1 #region Copyright & License Information
2 /*
3  * Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
4  * This file is part of OpenRA, which is free software. It is made
5  * available to you under the terms of the GNU General Public License
6  * as published by the Free Software Foundation, either version 3 of
7  * the License, or (at your option) any later version. For more
8  * information, see COPYING.
9  */
10 #endregion
11 
12 using System.Collections.Generic;
13 using OpenRA.Primitives;
14 using OpenRA.Traits;
15 
16 namespace OpenRA.Mods.Common.Orders
17 {
18 	public abstract class UnitOrderTargeter : IOrderTargeter
19 	{
20 		readonly string cursor;
21 		readonly bool targetEnemyUnits, targetAllyUnits;
22 
UnitOrderTargeter(string order, int priority, string cursor, bool targetEnemyUnits, bool targetAllyUnits)23 		public UnitOrderTargeter(string order, int priority, string cursor, bool targetEnemyUnits, bool targetAllyUnits)
24 		{
25 			OrderID = order;
26 			OrderPriority = priority;
27 			this.cursor = cursor;
28 			this.targetEnemyUnits = targetEnemyUnits;
29 			this.targetAllyUnits = targetAllyUnits;
30 		}
31 
32 		public string OrderID { get; private set; }
33 		public int OrderPriority { get; private set; }
34 		public bool? ForceAttack = null;
TargetOverridesSelection(Actor self, Target target, List<Actor> actorsAt, CPos xy, TargetModifiers modifiers)35 		public bool TargetOverridesSelection(Actor self, Target target, List<Actor> actorsAt, CPos xy, TargetModifiers modifiers) { return true; }
36 
CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)37 		public abstract bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor);
CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)38 		public abstract bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor);
39 
CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)40 		public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
41 		{
42 			var type = target.Type;
43 			if (type != TargetType.Actor && type != TargetType.FrozenActor)
44 				return false;
45 
46 			cursor = this.cursor;
47 			IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue);
48 
49 			if (ForceAttack != null && modifiers.HasModifier(TargetModifiers.ForceAttack) != ForceAttack)
50 				return false;
51 
52 			var owner = type == TargetType.FrozenActor ? target.FrozenActor.Owner : target.Actor.Owner;
53 			var playerRelationship = self.Owner.Stances[owner];
54 
55 			if (!modifiers.HasModifier(TargetModifiers.ForceAttack) && playerRelationship == Stance.Ally && !targetAllyUnits)
56 				return false;
57 
58 			if (!modifiers.HasModifier(TargetModifiers.ForceAttack) && playerRelationship == Stance.Enemy && !targetEnemyUnits)
59 				return false;
60 
61 			return type == TargetType.FrozenActor ?
62 				CanTargetFrozenActor(self, target.FrozenActor, modifiers, ref cursor) :
63 				CanTargetActor(self, target.Actor, modifiers, ref cursor);
64 		}
65 
66 		public virtual bool IsQueued { get; protected set; }
67 	}
68 
69 	public class TargetTypeOrderTargeter : UnitOrderTargeter
70 	{
71 		readonly BitSet<TargetableType> targetTypes;
72 
TargetTypeOrderTargeter(BitSet<TargetableType> targetTypes, string order, int priority, string cursor, bool targetEnemyUnits, bool targetAllyUnits)73 		public TargetTypeOrderTargeter(BitSet<TargetableType> targetTypes, string order, int priority, string cursor, bool targetEnemyUnits, bool targetAllyUnits)
74 			: base(order, priority, cursor, targetEnemyUnits, targetAllyUnits)
75 		{
76 			this.targetTypes = targetTypes;
77 		}
78 
CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)79 		public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
80 		{
81 			return targetTypes.Overlaps(target.GetEnabledTargetTypes());
82 		}
83 
CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)84 		public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)
85 		{
86 			return target.TargetTypes.Overlaps(targetTypes);
87 		}
88 	}
89 }
90