diff --git a/OpenRA.Mods.RA/Effects/Rank.cs b/OpenRA.Mods.RA/Effects/Rank.cs new file mode 100644 index 0000000000..654da3a5dc --- /dev/null +++ b/OpenRA.Mods.RA/Effects/Rank.cs @@ -0,0 +1,68 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 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.Collections.Generic; +using OpenRA.Effects; +using OpenRA.Graphics; +using OpenRA.Mods.RA.Buildings; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA.Effects +{ + class Rank : IEffect + { + Actor self; + Animation anim = new Animation("rank"); + GainsExperience xp; + + public Rank(Actor self) + { + this.self = self; + xp = self.Trait(); + + anim.PlayRepeating("rank"); + anim.PlayFetchIndex("rank", () => xp.Level - 1); + } + + public void Tick(World world) + { + if (self.Destroyed) + world.AddFrameEndTask(w => w.Remove(this)); + else + anim.Tick(); + } + + public IEnumerable Render(WorldRenderer wr) + { + if (!self.IsInWorld) + yield break; + + if (self.Destroyed) + yield break; + + if (xp.Level < 1) + yield break; + + if (!self.Owner.IsAlliedWith(self.World.RenderPlayer)) + yield break; + + if (wr.world.FogObscures(self)) + yield break; + + var pos = wr.ScreenPxPosition(self.CenterPosition); + var bounds = self.Bounds.Value; + bounds.Offset(pos.X, pos.Y); + + var offset = (int)(6 / wr.Viewport.Zoom); + var effectPos = wr.Position(new int2(bounds.Right - offset, bounds.Bottom - offset)); + yield return new SpriteRenderable(anim.Image, effectPos, WVec.Zero, 0, wr.Palette("effect"), 1f / wr.Viewport.Zoom, true); + } + } +} diff --git a/OpenRA.Mods.RA/GainsExperience.cs b/OpenRA.Mods.RA/GainsExperience.cs index 01bb9f4ad8..fa0a3fd1a7 100644 --- a/OpenRA.Mods.RA/GainsExperience.cs +++ b/OpenRA.Mods.RA/GainsExperience.cs @@ -10,11 +10,11 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.FileFormats; using OpenRA.GameRules; using OpenRA.Graphics; using OpenRA.Mods.RA.Effects; using OpenRA.Traits; -using OpenRA.FileFormats; namespace OpenRA.Mods.RA { @@ -28,102 +28,74 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new GainsExperience(init, this); } } - public class GainsExperience : IFirepowerModifier, ISpeedModifier, IDamageModifier, IRenderModifier, ISync + public class GainsExperience : IFirepowerModifier, ISpeedModifier, IDamageModifier, ISync { readonly Actor self; - readonly int[] Levels; - readonly GainsExperienceInfo Info; - readonly Animation RankAnim; + readonly int[] levels; + readonly GainsExperienceInfo info; public GainsExperience(ActorInitializer init, GainsExperienceInfo info) { self = init.self; - this.Info = info; + this.info = info; var cost = self.Info.Traits.Get().Cost; - Levels = Info.CostThreshold.Select(t => (int)(t * cost)).ToArray(); - RankAnim = new Animation("rank"); - RankAnim.PlayFetchIndex("rank", () => Level - 1); + levels = info.CostThreshold.Select(t => (int)(t * cost)).ToArray(); if (init.Contains()) { - Experience = init.Get(); + experience = init.Get(); - while (Level < Levels.Length && Experience >= Levels[Level]) + while (Level < levels.Length && experience >= levels[Level]) Level++; } } - [Sync] int Experience = 0; + [Sync] int experience = 0; [Sync] public int Level { get; private set; } - int MaxLevel { get { return Levels.Length; } } + int MaxLevel { get { return levels.Length; } } public bool CanGainLevel { get { return Level < MaxLevel; } } public void GiveOneLevel() { if (Level < MaxLevel) - GiveExperience(Levels[Level] - Experience); + GiveExperience(levels[Level] - experience); } public void GiveLevels(int numLevels) { - for( var i = 0; i < numLevels; i++ ) + for (var i = 0; i < numLevels; i++) GiveOneLevel(); } public void GiveExperience(int amount) { - Experience += amount; + experience += amount; - while (Level < MaxLevel && Experience >= Levels[Level]) + while (Level < MaxLevel && experience >= levels[Level]) { Level++; + Sound.PlayNotification(self.Owner, "Sounds", "LevelUp", self.Owner.Country.Race); self.World.AddFrameEndTask(w => w.Add(new CrateEffect(self, "levelup"))); + if (Level == 1) + self.World.AddFrameEndTask(w => w.Add(new Rank(self))); } } public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { - return Level > 0 ? 1 / Info.ArmorModifier[Level - 1] : 1; + return Level > 0 ? 1 / info.ArmorModifier[Level - 1] : 1; } public float GetFirepowerModifier() { - return Level > 0 ? Info.FirepowerModifier[Level - 1] : 1; + return Level > 0 ? info.FirepowerModifier[Level - 1] : 1; } public decimal GetSpeedModifier() { - return Level > 0 ? Info.SpeedModifier[Level - 1] : 1m; - } - - public IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r) - { - // TODO: Make this consistent with everything else that adds animations to RenderSimple. - if (self.Owner.IsAlliedWith(self.World.RenderPlayer) && Level > 0) - return InnerModifyRender(self, wr, r); - else - return r; - } - - IEnumerable InnerModifyRender(Actor self, WorldRenderer wr, IEnumerable r) - { - foreach (var rs in r) - yield return rs; - - RankAnim.Tick(); // HACK - - if (self.World.FogObscures(self)) - yield break; - - var pos = wr.ScreenPxPosition(self.CenterPosition); - var bounds = self.Bounds.Value; - bounds.Offset(pos.X, pos.Y); - - var offset = (int)(6 / wr.Viewport.Zoom); - var effectPos = wr.Position(new int2(bounds.Right - offset, bounds.Bottom - offset)); - yield return new SpriteRenderable(RankAnim.Image, effectPos, WVec.Zero, 0, wr.Palette("effect"), 1f / wr.Viewport.Zoom, true); + return Level > 0 ? info.SpeedModifier[Level - 1] : 1m; } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index c627a2aef8..fa190426fe 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -472,6 +472,7 @@ +