using System; using System.Linq; using OpenRa.Effects; using OpenRa.GameRules; using OpenRa.Traits.Activities; using OpenRa.Graphics; using System.Collections.Generic; namespace OpenRa.Traits { public class OwnedActorInfo { public readonly int HP = 0; public readonly ArmorType Armor = ArmorType.none; public readonly bool Crewed = false; // replace with trait? public readonly int Sight = 0; public readonly bool WaterBound = false; } public class BuildingInfo : OwnedActorInfo, ITraitInfo { public readonly int Power = 0; public readonly bool BaseNormal = true; public readonly int Adjacent = 2; public readonly bool Bib = false; public readonly bool Capturable = false; public readonly bool Repairable = true; public readonly string Footprint = "x"; public readonly string[] Produces = { }; // does this go somewhere else? public readonly int2 Dimensions = new int2(1, 1); public readonly bool Unsellable = false; public object Create(Actor self) { return new Building(self); } } public class Building : INotifyDamage, IResolveOrder, ITick, IRenderModifier { readonly Actor self; public readonly BuildingInfo Info; [Sync] bool isRepairing = false; public bool Disabled { get { return self.traits.WithInterface().Any(t => t.Disabled); } } public Building(Actor self) { this.self = self; Info = self.Info.Traits.Get(); self.CenterLocation = Game.CellSize * ((float2)self.Location + .5f * (float2)Info.Dimensions); } public int GetPowerUsage() { var modifier = self.traits .WithInterface() .Select(t => t.GetPowerModifier()) .Product(); var maxHP = self.Info.Traits.Get().HP; if (Info.Power > 0) return (int)(modifier*(self.Health * Info.Power) / maxHP); else return (int)(modifier * Info.Power); } public void Damaged(Actor self, AttackInfo e) { if (e.DamageState == DamageState.Dead) Sound.Play("kaboom22.aud"); } public void ResolveOrder(Actor self, Order order) { if (order.OrderString == "Sell") { self.CancelActivity(); self.QueueActivity(new Sell()); } if (order.OrderString == "Repair") { isRepairing = !isRepairing; } } int remainingTicks; public void Tick(Actor self) { if (!isRepairing) return; if (remainingTicks == 0) { var maxHP = self.Info.Traits.Get().HP; var costPerHp = (Rules.General.URepairPercent * self.Info.Traits.Get().Cost) / maxHP; var hpToRepair = Math.Min(Rules.General.URepairStep, maxHP - self.Health); var cost = (int)Math.Ceiling(costPerHp * hpToRepair); if (!self.Owner.TakeCash(cost)) { remainingTicks = 1; return; } self.World.AddFrameEndTask(w => w.Add(new RepairIndicator(self))); self.InflictDamage(self, -hpToRepair, Rules.WarheadInfo["Super"]); if (self.Health == maxHP) { isRepairing = false; return; } remainingTicks = (int)(Rules.General.RepairRate * 60 * 25); } else --remainingTicks; } public IEnumerable ModifyRender(Actor self, IEnumerable r) { foreach (var a in r) { yield return a; if (Disabled) yield return a.WithPalette("disabled"); } } } }