#region Copyright & License Information /* * Copyright 2007-2015 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. For more information, * see COPYING. */ #endregion using System; using System.Collections.Generic; using OpenRA.Mods.Common.Effects; using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("This actor's experience increases when it has killed a GivesExperience actor.")] public class GainsExperienceInfo : ITraitInfo, Requires, Requires { [FieldLoader.Require] [Desc("Upgrades to grant at each level.", "Key is the XP requirements for each level as a percentage of our own value.", "Value is a list of the upgrade types to grant")] public readonly Dictionary Upgrades = null; [Desc("Palette for the level up sprite.")] [PaletteReference] public readonly string LevelUpPalette = "effect"; [Desc("Should the level-up animation be suppressed when actor is created?")] public readonly bool SuppressLevelupAnimation = true; public object Create(ActorInitializer init) { return new GainsExperience(init, this); } } public class GainsExperience : ISync, IResolveOrder { readonly Actor self; readonly GainsExperienceInfo info; readonly UpgradeManager um; readonly List> nextLevel = new List>(); // Stored as a percentage of our value [Sync] int experience = 0; [Sync] public int Level { get; private set; } public readonly int MaxLevel; public GainsExperience(ActorInitializer init, GainsExperienceInfo info) { self = init.Self; this.info = info; MaxLevel = info.Upgrades.Count; var cost = self.Info.TraitInfo().Cost; foreach (var kv in info.Upgrades) nextLevel.Add(Pair.New(kv.Key * cost, kv.Value)); if (init.Contains()) GiveExperience(init.Get(), info.SuppressLevelupAnimation); um = self.Trait(); } public bool CanGainLevel { get { return Level < MaxLevel; } } public void GiveLevels(int numLevels, bool silent = false) { var newLevel = Math.Min(Level + numLevels, MaxLevel); GiveExperience(nextLevel[newLevel - 1].First - experience, silent); } public void GiveExperience(int amount, bool silent = false) { experience += amount; while (Level < MaxLevel && experience >= nextLevel[Level].First) { var upgrades = nextLevel[Level].Second; Level++; foreach (var u in upgrades) um.GrantUpgrade(self, u, this); if (!silent) { Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "LevelUp", self.Owner.Faction.InternalName); self.World.AddFrameEndTask(w => w.Add(new CrateEffect(self, "levelup", info.LevelUpPalette))); } } } public void ResolveOrder(Actor self, Order order) { if (!self.World.AllowDevCommands) return; if (order.OrderString == "DevLevelUp") { if ((int)order.ExtraData > 0) GiveLevels((int)order.ExtraData); else GiveLevels(1); } } } class ExperienceInit : IActorInit { [FieldFromYamlKey] readonly int value; public ExperienceInit() { } public ExperienceInit(int init) { value = init; } public int Value(World world) { return value; } } }