#region Copyright & License Information /* * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. * This file is part of OpenRA. * * OpenRA is free software: you can redistribute it and/or modify * it 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. * * OpenRA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenRA. If not, see . */ #endregion using System.Collections.Generic; using System.Linq; using OpenRA.GameRules; using OpenRA.Traits; namespace OpenRA.Traits { public class MobileAirInfo : MobileInfo { public readonly int CruiseAltitude = 20; public readonly float InstabilityMagnitude = 2.0f; public readonly int InstabilityTicks = 5; public readonly bool LandWhenIdle = true; public override object Create(ActorInitializer init) { return new MobileAir(init, this); } } public class MobileAir : Mobile, ITick, IOccupyAir { MobileAirInfo Info; public MobileAir (ActorInitializer init, MobileAirInfo info) : base(init, info) { Info = info; } public override void AddInfluence() { self.World.WorldActor.traits.Get().Add( self, this ); } public override void RemoveInfluence() { self.World.WorldActor.traits.Get().Remove( self, this ); } public override bool CanEnterCell(int2 p, Actor ignoreBuilding, bool checkTransientActors) { if (!checkTransientActors) return true; return self.World.WorldActor.traits.Get().GetUnitsAt(p).Count() == 0; } public override float MovementCostForCell(Actor self, int2 cell) { if (!self.World.Map.IsInMap(cell.X,cell.Y)) return float.PositiveInfinity; return self.World.WorldActor.traits.WithInterface().Aggregate(1f, (a, x) => a * x.GetCost(cell,self)); } public override float MovementSpeedForCell(Actor self, int2 cell) { var unitInfo = self.Info.Traits.GetOrDefault(); if( unitInfo == null || !self.World.Map.IsInMap(cell.X,cell.Y)) return 0f; var modifier = self.traits .WithInterface() .Select(t => t.GetSpeedModifier()) .Product(); return unitInfo.Speed * modifier; } public override IEnumerable OccupiedCells() { // Todo: do the right thing when landed return new int2[] {}; } public IEnumerable OccupiedAirCells() { return (fromCell == toCell) ? new[] { fromCell } : CanEnterCell(toCell) ? new[] { toCell } : new[] { fromCell, toCell }; } int offsetTicks = 0; public void Tick(Actor self) { var unit = self.traits.Get(); //if (unit.Altitude <= 0) // return; if (unit.Altitude < Info.CruiseAltitude) unit.Altitude++; if (--offsetTicks <= 0) { self.CenterLocation += Info.InstabilityMagnitude * self.World.SharedRandom.Gauss2D(5); unit.Altitude += (int)(Info.InstabilityMagnitude * self.World.SharedRandom.Gauss1D(5)); offsetTicks = Info.InstabilityTicks; } } } }