1 #region Copyright & License Information 2 /* 3 * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) 4 * This file is part of OpenRA, which is free software. It is made 5 * available to you under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, either version 3 of 7 * the License, or (at your option) any later version. For more 8 * information, see COPYING. 9 */ 10 #endregion 11 12 using System.Linq; 13 using Eluant; 14 using OpenRA.Mods.Common.Traits; 15 using OpenRA.Scripting; 16 17 namespace OpenRA.Mods.Common.Scripting 18 { 19 [ScriptGlobal("Map")] 20 public class MapGlobal : ScriptGlobal 21 { 22 readonly SpawnMapActors sma; 23 readonly World world; 24 MapGlobal(ScriptContext context)25 public MapGlobal(ScriptContext context) 26 : base(context) 27 { 28 sma = context.World.WorldActor.Trait<SpawnMapActors>(); 29 world = context.World; 30 31 // Register map actors as globals (yuck!) 32 foreach (var kv in sma.Actors) 33 context.RegisterMapActor(kv.Key, kv.Value); 34 } 35 36 [Desc("Returns a table of all actors within the requested region, filtered using the specified function.")] ActorsInCircle(WPos location, WDist radius, LuaFunction filter = null)37 public Actor[] ActorsInCircle(WPos location, WDist radius, LuaFunction filter = null) 38 { 39 var actors = Context.World.FindActorsInCircle(location, radius); 40 return FilteredObjects(actors, filter).ToArray(); 41 } 42 43 [Desc("Returns a table of all actors within the requested rectangle, filtered using the specified function.")] ActorsInBox(WPos topLeft, WPos bottomRight, LuaFunction filter = null)44 public Actor[] ActorsInBox(WPos topLeft, WPos bottomRight, LuaFunction filter = null) 45 { 46 var actors = Context.World.ActorMap.ActorsInBox(topLeft, bottomRight); 47 return FilteredObjects(actors, filter).ToArray(); 48 } 49 50 [Desc("Returns the location of the top-left corner of the map (assuming zero terrain height).")] 51 public WPos TopLeft 52 { 53 get 54 { 55 // HACK: This api method abuses the coordinate system, and should be removed 56 // in favour of proper actor queries. See #8549. 57 return Context.World.Map.ProjectedTopLeft; 58 } 59 } 60 61 [Desc("Returns the location of the bottom-right corner of the map (assuming zero terrain height).")] 62 public WPos BottomRight 63 { 64 get 65 { 66 // HACK: This api method abuses the coordinate system, and should be removed 67 // in favour of proper actor queries. See #8549. 68 return Context.World.Map.ProjectedBottomRight; 69 } 70 } 71 72 [Desc("Returns a random cell inside the visible region of the map.")] RandomCell()73 public CPos RandomCell() 74 { 75 return Context.World.Map.ChooseRandomCell(Context.World.SharedRandom); 76 } 77 78 [Desc("Returns a random cell on the visible border of the map.")] RandomEdgeCell()79 public CPos RandomEdgeCell() 80 { 81 return Context.World.Map.ChooseRandomEdgeCell(Context.World.SharedRandom); 82 } 83 84 [Desc("Returns the closest cell on the visible border of the map from the given cell.")] ClosestEdgeCell(CPos givenCell)85 public CPos ClosestEdgeCell(CPos givenCell) 86 { 87 return Context.World.Map.ChooseClosestEdgeCell(givenCell); 88 } 89 90 [Desc("Returns the first cell on the visible border of the map from the given cell,", 91 "matching the filter function called as function(CPos cell).")] ClosestMatchingEdgeCell(CPos givenCell, LuaFunction filter)92 public CPos ClosestMatchingEdgeCell(CPos givenCell, LuaFunction filter) 93 { 94 return FilteredObjects(Context.World.Map.AllEdgeCells.OrderBy(c => (givenCell - c).Length), filter).FirstOrDefault(); 95 } 96 97 [Desc("Returns the center of a cell in world coordinates.")] CenterOfCell(CPos cell)98 public WPos CenterOfCell(CPos cell) 99 { 100 return Context.World.Map.CenterOfCell(cell); 101 } 102 103 [Desc("Returns the type of the terrain at the target cell.")] TerrainType(CPos cell)104 public string TerrainType(CPos cell) 105 { 106 return Context.World.Map.GetTerrainInfo(cell).Type; 107 } 108 109 [Desc("Returns true if there is only one human player.")] 110 public bool IsSinglePlayer { get { return Context.World.LobbyInfo.NonBotPlayers.Count() == 1; } } 111 112 [Desc("Returns the value of a `ScriptLobbyDropdown` selected in the game lobby.")] LobbyOption(string id)113 public LuaValue LobbyOption(string id) 114 { 115 var option = Context.World.WorldActor.TraitsImplementing<ScriptLobbyDropdown>() 116 .FirstOrDefault(sld => sld.Info.ID == id); 117 118 if (option == null) 119 throw new YamlException("A ScriptLobbyDropdown with ID `" + id + "` was not found."); 120 121 return option.Value; 122 } 123 124 [Desc("Returns a table of all the actors that were specified in the map file.")] 125 public Actor[] NamedActors { get { return sma.Actors.Values.ToArray(); } } 126 127 [Desc("Returns the actor that was specified with a given name in " + 128 "the map file (or nil, if the actor is dead or not found).")] NamedActor(string actorName)129 public Actor NamedActor(string actorName) 130 { 131 Actor ret; 132 133 if (!sma.Actors.TryGetValue(actorName, out ret)) 134 return null; 135 136 if (ret.Disposed) 137 return null; 138 139 return ret; 140 } 141 142 [Desc("Returns true if actor was originally specified in the map file.")] IsNamedActor(Actor actor)143 public bool IsNamedActor(Actor actor) 144 { 145 return actor.ActorID <= sma.LastMapActorID && actor.ActorID > sma.LastMapActorID - sma.Actors.Count; 146 } 147 148 [Desc("Returns a table of all actors tagged with the given string.")] ActorsWithTag(string tag)149 public Actor[] ActorsWithTag(string tag) 150 { 151 return Context.World.ActorsHavingTrait<ScriptTags>(t => t.HasTag(tag)).ToArray(); 152 } 153 154 [Desc("Returns a table of all the actors that are currently on the map/in the world.")] 155 public Actor[] ActorsInWorld { get { return world.Actors.ToArray(); } } 156 } 157 } 158