#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.Linq; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [RequireExplicitImplementation] public interface IBlocksProjectiles { WDist BlockingHeight { get; } } [Desc("This actor blocks bullets and missiles with 'Blockable' property.")] public class BlocksProjectilesInfo : UpgradableTraitInfo { public readonly WDist Height = WDist.FromCells(1); public override object Create(ActorInitializer init) { return new BlocksProjectiles(init.Self, this); } } public class BlocksProjectiles : UpgradableTrait, IBlocksProjectiles { public BlocksProjectiles(Actor self, BlocksProjectilesInfo info) : base(info) { } WDist IBlocksProjectiles.BlockingHeight { get { return Info.Height; } } public static bool AnyBlockingActorAt(World world, WPos pos) { var dat = world.Map.DistanceAboveTerrain(pos); return world.ActorMap.GetActorsAt(world.Map.CellContaining(pos)) .Any(a => a.TraitsImplementing() .Where(t => t.BlockingHeight > dat) .Any(Exts.IsTraitEnabled)); } public static bool AnyBlockingActorsBetween(World world, WPos start, WPos end, WDist width, WDist overscan, out WPos hit) { var actors = world.FindActorsOnLine(start, end, width, overscan); var length = (end - start).Length; foreach (var a in actors) { var blockers = a.TraitsImplementing() .Where(Exts.IsTraitEnabled).ToList(); if (!blockers.Any()) continue; var hitPos = WorldExtensions.MinimumPointLineProjection(start, end, a.CenterPosition); var dat = world.Map.DistanceAboveTerrain(hitPos); if ((hitPos - start).Length < length && blockers.Any(t => t.BlockingHeight > dat)) { hit = hitPos; return true; } } hit = WPos.Zero; return false; } } }