diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 324674b94b..29f8b91081 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -388,6 +388,7 @@
+
diff --git a/OpenRA.Mods.Common/Traits/GivesExperience.cs b/OpenRA.Mods.Common/Traits/GivesExperience.cs
index c08d066387..14573f1d28 100644
--- a/OpenRA.Mods.Common/Traits/GivesExperience.cs
+++ b/OpenRA.Mods.Common/Traits/GivesExperience.cs
@@ -22,6 +22,12 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Stance the attacking player needs to receive the experience.")]
public readonly Stance ValidStances = Stance.Neutral | Stance.Enemy;
+ [Desc("Percentage of the `Experience` value that is being granted to the killing actor.")]
+ public readonly int ActorExperienceModifier = 10000;
+
+ [Desc("Percentage of the `Experience` value that is being granted to the player owning the killing actor.")]
+ public readonly int PlayerExperienceModifier = 0;
+
public object Create(ActorInitializer init) { return new GivesExperience(init.Self, this); }
}
@@ -44,14 +50,17 @@ namespace OpenRA.Mods.Common.Traits
var valued = self.Info.TraitInfoOrDefault();
- // Default experience is 100 times our value
var exp = info.Experience >= 0
? info.Experience
- : valued != null ? valued.Cost * 100 : 0;
+ : valued != null ? valued.Cost : 0;
var killer = e.Attacker.TraitOrDefault();
if (killer != null)
- killer.GiveExperience(exp);
+ killer.GiveExperience(Util.ApplyPercentageModifiers(exp, new[] { info.ActorExperienceModifier }));
+
+ var attackerExp = e.Attacker.Owner.PlayerActor.TraitOrDefault();
+ if (attackerExp != null)
+ attackerExp.GiveExperience(Util.ApplyPercentageModifiers(exp, new[] { info.PlayerExperienceModifier }));
}
}
}
diff --git a/OpenRA.Mods.Common/Traits/Player/PlayerExperience.cs b/OpenRA.Mods.Common/Traits/Player/PlayerExperience.cs
new file mode 100644
index 0000000000..a632787f26
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/Player/PlayerExperience.cs
@@ -0,0 +1,35 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2016 The OpenRA Developers (see AUTHORS)
+ * This file is part of OpenRA, which is free software. It is made
+ * available to you under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. For more
+ * information, see COPYING.
+ */
+#endregion
+
+using System;
+using System.Linq;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Traits
+{
+ [Desc("This trait can be used to track player experience based on units killed with the `GivesExperience` trait.",
+ "It can also be used as a point score system in scripted maps, for example.",
+ "Attach this to the player actor.")]
+ public class PlayerExperienceInfo : ITraitInfo
+ {
+ public object Create(ActorInitializer init) { return new PlayerExperience(); }
+ }
+
+ public class PlayerExperience : ISync
+ {
+ [Sync] public int Experience { get; private set; }
+
+ public void GiveExperience(int num)
+ {
+ Experience += num;
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs b/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs
index b0b8a35023..ab6aa46eca 100644
--- a/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs
+++ b/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs
@@ -23,6 +23,7 @@ namespace OpenRA.Mods.Common.Traits
public class PlayerStatistics : ITick, IResolveOrder, INotifyCreated
{
PlayerResources resources;
+ PlayerExperience experience;
public int OrderCount;
@@ -34,6 +35,14 @@ namespace OpenRA.Mods.Common.Traits
}
}
+ public int Experience
+ {
+ get
+ {
+ return experience != null ? experience.Experience : 0;
+ }
+ }
+
public Queue EarnedSamples = new Queue(100);
int earnedAtBeginningOfMinute;
@@ -51,6 +60,7 @@ namespace OpenRA.Mods.Common.Traits
void INotifyCreated.Created(Actor self)
{
resources = self.TraitOrDefault();
+ experience = self.TraitOrDefault();
}
void UpdateEarnedThisMinute()