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.Mods.Common.Activities; 14 using OpenRA.Mods.Common.Orders; 15 using OpenRA.Primitives; 16 using OpenRA.Traits; 17 18 namespace OpenRA.Mods.Common.Traits 19 { 20 [Desc("This actor can grant experience levels equal to it's own current level via entering to other actors with the `AcceptsDeliveredExperience` trait.")] 21 class DeliversExperienceInfo : ITraitInfo, Requires<GainsExperienceInfo> 22 { 23 [Desc("The amount of experience the donating player receives.")] 24 public readonly int PlayerExperience = 0; 25 26 [Desc("Identifier checked against AcceptsDeliveredExperience.ValidTypes. Only needed if the latter is not empty.")] 27 public readonly string Type = null; 28 29 [VoiceReference] 30 public readonly string Voice = "Action"; 31 Create(ActorInitializer init)32 public object Create(ActorInitializer init) { return new DeliversExperience(init, this); } 33 } 34 35 class DeliversExperience : IIssueOrder, IResolveOrder, IOrderVoice 36 { 37 readonly DeliversExperienceInfo info; 38 readonly Actor self; 39 readonly GainsExperience gainsExperience; 40 DeliversExperience(ActorInitializer init, DeliversExperienceInfo info)41 public DeliversExperience(ActorInitializer init, DeliversExperienceInfo info) 42 { 43 this.info = info; 44 self = init.Self; 45 gainsExperience = self.Trait<GainsExperience>(); 46 } 47 48 public IEnumerable<IOrderTargeter> Orders 49 { 50 get 51 { 52 if (gainsExperience.Level != 0) 53 yield return new DeliversExperienceOrderTargeter(); 54 } 55 } 56 IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)57 public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) 58 { 59 if (order.OrderID != "DeliverExperience") 60 return null; 61 62 return new Order(order.OrderID, self, target, queued); 63 } 64 VoicePhraseForOrder(Actor self, Order order)65 public string VoicePhraseForOrder(Actor self, Order order) 66 { 67 if (order.OrderString != "DeliverExperience") 68 return null; 69 70 return info.Voice; 71 } 72 ResolveOrder(Actor self, Order order)73 public void ResolveOrder(Actor self, Order order) 74 { 75 if (order.OrderString != "DeliverExperience") 76 return; 77 78 if (order.Target.Type == TargetType.Actor) 79 { 80 var targetGainsExperience = order.Target.Actor.Trait<GainsExperience>(); 81 if (targetGainsExperience.Level == targetGainsExperience.MaxLevel) 82 return; 83 } 84 else if (order.Target.Type != TargetType.FrozenActor) 85 return; 86 87 self.QueueActivity(order.Queued, new DonateExperience(self, order.Target, gainsExperience.Level, info.PlayerExperience)); 88 self.ShowTargetLines(); 89 } 90 91 public class DeliversExperienceOrderTargeter : UnitOrderTargeter 92 { DeliversExperienceOrderTargeter()93 public DeliversExperienceOrderTargeter() 94 : base("DeliverExperience", 5, "enter", true, true) { } 95 CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)96 public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) 97 { 98 if (target == self) 99 return false; 100 101 var type = self.Info.TraitInfo<DeliversExperienceInfo>().Type; 102 var targetInfo = target.Info.TraitInfoOrDefault<AcceptsDeliveredExperienceInfo>(); 103 var targetGainsExperience = target.TraitOrDefault<GainsExperience>(); 104 105 if (targetGainsExperience == null || targetInfo == null) 106 return false; 107 108 if (targetGainsExperience.Level == targetGainsExperience.MaxLevel) 109 return false; 110 111 return targetInfo.ValidStances.HasStance(target.Owner.Stances[self.Owner]) 112 && (targetInfo.ValidTypes.Count == 0 113 || (!string.IsNullOrEmpty(type) && targetInfo.ValidTypes.Contains(type))); 114 } 115 CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)116 public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) 117 { 118 if (target.Actor == null || target.Actor == self) 119 return false; 120 121 var type = self.Info.TraitInfo<DeliversExperienceInfo>().Type; 122 var targetInfo = target.Info.TraitInfoOrDefault<AcceptsDeliveredExperienceInfo>(); 123 var targetGainsExperience = target.Actor.TraitOrDefault<GainsExperience>(); 124 125 if (targetGainsExperience == null || targetInfo == null) 126 return false; 127 128 if (targetGainsExperience.Level == targetGainsExperience.MaxLevel) 129 return false; 130 131 return targetInfo.ValidStances.HasStance(target.Owner.Stances[self.Owner]) 132 && (targetInfo.ValidTypes.Count == 0 133 || (!string.IsNullOrEmpty(type) && targetInfo.ValidTypes.Contains(type))); 134 } 135 } 136 } 137 } 138