diff --git a/OpenRa.Game/BuildingInfluenceMap.cs b/OpenRa.Game/BuildingInfluenceMap.cs index 18efbe568f..c8360e7d75 100644 --- a/OpenRa.Game/BuildingInfluenceMap.cs +++ b/OpenRa.Game/BuildingInfluenceMap.cs @@ -20,14 +20,14 @@ namespace OpenRa.Game void AddInfluence(Actor a) { - foreach (var t in Footprint.UnpathableTiles(a.unitInfo.Name, a.Location)) + foreach (var t in Footprint.UnpathableTiles(a.unitInfo, a.Location)) if (IsValid(t)) influence[t.X, t.Y] = a; } void RemoveInfluence(Actor a) { - foreach (var t in Footprint.UnpathableTiles(a.unitInfo.Name, a.Location)) + foreach (var t in Footprint.UnpathableTiles(a.unitInfo, a.Location)) if (IsValid(t)) influence[t.X, t.Y] = null; } diff --git a/OpenRa.Game/GameRules/FieldLoader.cs b/OpenRa.Game/GameRules/FieldLoader.cs index 2822ec7c83..361d13999e 100755 --- a/OpenRa.Game/GameRules/FieldLoader.cs +++ b/OpenRa.Game/GameRules/FieldLoader.cs @@ -39,10 +39,15 @@ namespace OpenRa.Game.GameRules var parts = x.Split( new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries ); var ret = Array.CreateInstance( fieldType.GetElementType(), parts.Length ); - for (int i = 0; i < parts.Length; i++) + for( int i = 0 ; i < parts.Length ; i++ ) ret.SetValue( GetValue( fieldType.GetElementType(), parts[ i ].Trim() ), i ); return ret; } + else if( fieldType == typeof( int2 ) ) + { + var parts = x.Split( new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries ); + return new int2( int.Parse( parts[ 0 ] ), int.Parse( parts[ 1 ] ) ); + } else throw new InvalidOperationException( "FieldLoader: don't know how to load field of type " + fieldType.ToString() ); } diff --git a/OpenRa.Game/GameRules/Footprint.cs b/OpenRa.Game/GameRules/Footprint.cs index bd8bf2d0ca..a6efcc35db 100644 --- a/OpenRa.Game/GameRules/Footprint.cs +++ b/OpenRa.Game/GameRules/Footprint.cs @@ -7,74 +7,57 @@ using OpenRa.Game.Graphics; namespace OpenRa.Game.GameRules { - class Footprint + static class Footprint { - Dictionary buildingFootprints; - - public string[] GetFootprint(string name) + public static IEnumerable Tiles( UnitInfo unitInfo, int2 position ) { - string[] val; - if (!buildingFootprints.TryGetValue(name, out val)) - buildingFootprints.TryGetValue("*", out val); - return val; - } + var buildingInfo = unitInfo as UnitInfo.BuildingInfo; + var dim = buildingInfo.Dimensions; - public Footprint(Stream s) - { - var lines = Util.ReadAllLines(s).Where(a => !a.StartsWith("#")); - - Func words = - b => b.Split( new[] { ' ', '\t' }, - StringSplitOptions.RemoveEmptyEntries ); - - var buildings = lines - .Select(a => a.Split(':')) - .SelectMany(a => words(a[1]) - .Select( b => new { Name=b, Pat=words(a[0]) } )); - - buildingFootprints = buildings - .ToDictionary(a => a.Name, a => a.Pat); - } - - public static IEnumerable Tiles(string name, int2 position) - { - var footprint = Rules.Footprint.GetFootprint(name); - var j = 0; - - int maxWidth = 0; - foreach (var row in footprint) - if (row.Length > maxWidth) - maxWidth = row.Length; - - foreach (var row in footprint) + var footprint = buildingInfo.Footprint.ToCharArray().Where( x => !char.IsWhiteSpace( x ) ); + if( buildingInfo.Bib ) { - var i = 0; - foreach (var c in row) + dim.Y += 1; + footprint = footprint.Concat( new char[ dim.X ] ); + } + foreach( var tile in TilesWhere( unitInfo.Name, dim, footprint.ToArray(), a => a != '_' ) ) + yield return tile + position - AdjustForBuildingSize( buildingInfo ); + } + + public static IEnumerable UnpathableTiles( UnitInfo unitInfo, int2 position ) + { + var buildingInfo = unitInfo as UnitInfo.BuildingInfo; + + var footprint = buildingInfo.Footprint.ToCharArray().Where( x => !char.IsWhiteSpace( x ) ).ToArray(); + foreach( var tile in TilesWhere( unitInfo.Name, buildingInfo.Dimensions, footprint, a => a == 'x' ) ) + yield return tile + position; + } + + static IEnumerable TilesWhere( string name, int2 dim, char[] footprint, Func cond ) + { + if( footprint.Length != dim.X * dim.Y ) + throw new InvalidOperationException( "Invalid footprint for " + name ); + int index = 0; + for( int y = 0 ; y < dim.Y ; y++ ) + { + for( int x = 0 ; x < dim.X ; x++ ) { - if (c != '_') - yield return position + new int2(i, j) - new int2(maxWidth / 2, footprint.Length / 2); - ++i; + if( cond( footprint[ index ] ) ) + yield return new int2( x, y ); + ++index; } - ++j; } } - public static IEnumerable UnpathableTiles( string name, int2 position ) + public static int2 AdjustForBuildingSize( string name ) { - var footprint = Rules.Footprint.GetFootprint( name ); - var j = 0; + return AdjustForBuildingSize( Rules.UnitInfo[ name ] as UnitInfo.BuildingInfo ); + } - foreach( var row in footprint ) - { - var i = 0; - foreach( var c in row ) - { - if( c == 'x' ) - yield return position + new int2( i, j ); - ++i; - } - ++j; - } + public static int2 AdjustForBuildingSize( UnitInfo.BuildingInfo unitInfo ) + { + var dim = unitInfo.Dimensions; + return new int2( dim.X / 2, ( dim.Y + 1 ) / 2 ); } } } diff --git a/OpenRa.Game/GameRules/Rules.cs b/OpenRa.Game/GameRules/Rules.cs index fce75ff64c..bb36ee500f 100755 --- a/OpenRa.Game/GameRules/Rules.cs +++ b/OpenRa.Game/GameRules/Rules.cs @@ -14,7 +14,6 @@ namespace OpenRa.Game public static InfoLoader WeaponInfo; public static InfoLoader WarheadInfo; public static InfoLoader ProjectileInfo; - public static Footprint Footprint; public static void LoadRules( string mapFileName ) { @@ -38,8 +37,6 @@ namespace OpenRa.Game ProjectileInfo = new InfoLoader( Pair.New>("ProjectileTypes", _ => new ProjectileInfo())); - - Footprint = new Footprint(FileSystem.Open("footprint.txt")); } } } diff --git a/OpenRa.Game/GameRules/UnitInfo.cs b/OpenRa.Game/GameRules/UnitInfo.cs index 7da2ac2480..0527f6e510 100755 --- a/OpenRa.Game/GameRules/UnitInfo.cs +++ b/OpenRa.Game/GameRules/UnitInfo.cs @@ -58,7 +58,6 @@ namespace OpenRa.Game.GameRules public class InfantryInfo : MobileInfo { - public readonly bool C4 = false; public readonly bool FraidyCat = false; public readonly bool Infiltrate = false; @@ -78,6 +77,9 @@ namespace OpenRa.Game.GameRules public class BuildingInfo : UnitInfo { + public readonly int2 Dimensions = new int2( 1, 1 ); + public readonly string Footprint = "x"; + public readonly bool BaseNormal = true; public readonly int Adjacent = 1; public readonly bool Bib = false; diff --git a/OpenRa.Game/Graphics/Viewport.cs b/OpenRa.Game/Graphics/Viewport.cs index c7749d80d2..cfdab6df88 100644 --- a/OpenRa.Game/Graphics/Viewport.cs +++ b/OpenRa.Game/Graphics/Viewport.cs @@ -24,13 +24,15 @@ namespace OpenRa.Game.Graphics public void Scroll(float2 delta) { - scrollPosition = (scrollPosition + delta).Constrain(float2.Zero, mapSize); + scrollPosition = ( scrollPosition + delta ).Constrain( float2.Zero, mapSize ); } public Viewport(float2 size, float2 mapSize, Renderer renderer) { this.size = size; this.mapSize = Game.CellSize * mapSize - size + new float2(128, 0); + if( this.mapSize.X < 0 ) this.mapSize.X = 0; + if( this.mapSize.Y < 0 ) this.mapSize.Y = 0; this.renderer = renderer; cursorRenderer = new SpriteRenderer(renderer, true); } diff --git a/OpenRa.Game/PlaceBuilding.cs b/OpenRa.Game/PlaceBuilding.cs index 65ca5511a4..2f93642c06 100644 --- a/OpenRa.Game/PlaceBuilding.cs +++ b/OpenRa.Game/PlaceBuilding.cs @@ -20,7 +20,7 @@ namespace OpenRa.Game public IEnumerable Order(int2 xy) { // todo: check that space is free - if (Footprint.Tiles(Name, xy).Any(t => !Game.IsCellBuildable(t, UnitMovementType.Wheel))) + if (Footprint.Tiles(Rules.UnitInfo[Name], xy).Any(t => !Game.IsCellBuildable(t, UnitMovementType.Wheel))) yield break; yield return new PlaceBuildingOrder(this, xy); diff --git a/OpenRa.Game/PlaceBuildingOrder.cs b/OpenRa.Game/PlaceBuildingOrder.cs index d45c2c8c7a..433e661913 100644 --- a/OpenRa.Game/PlaceBuildingOrder.cs +++ b/OpenRa.Game/PlaceBuildingOrder.cs @@ -10,41 +10,34 @@ namespace OpenRa.Game PlaceBuilding building; int2 xy; - public PlaceBuildingOrder(PlaceBuilding building, int2 xy) + public PlaceBuildingOrder( PlaceBuilding building, int2 xy ) { this.building = building; this.xy = xy; } - public override void Apply(bool leftMouseButton) + public override void Apply( bool leftMouseButton ) { - if (leftMouseButton) + if( leftMouseButton ) { - Game.world.AddFrameEndTask(_ => + Game.world.AddFrameEndTask( _ => { - Log.Write("Player \"{0}\" builds {1}", building.Owner.PlayerName, building.Name); + Log.Write( "Player \"{0}\" builds {1}", building.Owner.PlayerName, building.Name ); //Adjust placement for cursor to be in middle - var footprint = Rules.Footprint.GetFootprint(building.Name); - int maxWidth = 0; - foreach (var row in footprint) - if (row.Length > maxWidth) - maxWidth = row.Length; - - Game.world.Add(new Actor(building.Name, - xy - new int2(maxWidth / 2, footprint.Length / 2), building.Owner)); + Game.world.Add( new Actor( building.Name, xy - GameRules.Footprint.AdjustForBuildingSize( building.Name ), building.Owner ) ); Game.controller.orderGenerator = null; Game.worldRenderer.uiOverlay.KillOverlay(); - }); + } ); } else { - Game.world.AddFrameEndTask(_ => + Game.world.AddFrameEndTask( _ => { Game.controller.orderGenerator = null; Game.worldRenderer.uiOverlay.KillOverlay(); - }); + } ); } } } diff --git a/OpenRa.Game/Sidebar.cs b/OpenRa.Game/Sidebar.cs index e984426e82..02916ef578 100644 --- a/OpenRa.Game/Sidebar.cs +++ b/OpenRa.Game/Sidebar.cs @@ -1,176 +1,176 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; -using OpenRa.FileFormats; -using OpenRa.Game.Graphics; -using OpenRa.TechTree; -using System.Linq; - -namespace OpenRa.Game -{ - using GRegion = OpenRa.Game.Graphics.Region; - - class Sidebar - { - TechTree.TechTree techTree; - - SpriteRenderer spriteRenderer, clockRenderer; - Sprite blank; - readonly GRegion region; - - public GRegion Region { get { return region; } } - public float Width { get { return spriteWidth * 2; } } - - Dictionary sprites = new Dictionary(); - const int spriteWidth = 64, spriteHeight = 48; - - static string[] groups = new string[] { "building", "vehicle", "boat", "infantry", "plane" }; - - Dictionary itemGroups = new Dictionary(); //item->group - Dictionary clockAnimations = new Dictionary(); //group->clockAnimation - Dictionary selectedItems = new Dictionary(); //group->selectedItem - - List items = new List(); - - public Sidebar( Renderer renderer ) - { - this.techTree = Game.LocalPlayer.TechTree; - this.techTree.BuildableItemsChanged += PopulateItemList; - region = GRegion.Create(Game.viewport, DockStyle.Right, 128, Paint, MouseHandler); - Game.viewport.AddRegion( region ); - spriteRenderer = new SpriteRenderer(renderer, false); - clockRenderer = new SpriteRenderer(renderer, true); - - LoadSprites( "BuildingTypes", "building" ); - LoadSprites( "VehicleTypes", "vehicle" ); - LoadSprites( "InfantryTypes", "infantry" ); - LoadSprites( "ShipTypes", "boat" ); - LoadSprites( "PlaneTypes", "plane" ); - - foreach (string s in groups) - { - clockAnimations.Add(s, new Animation("clock")); - clockAnimations[s].PlayRepeating("idle"); - selectedItems.Add(s, null); - } - - blank = SheetBuilder.Add(new Size((int)spriteWidth, (int)spriteHeight), 16); - } - - public void Build(SidebarItem item) - { - if (item != null) - Game.controller.orderGenerator = new PlaceBuilding(Game.LocalPlayer, - item.techTreeItem.tag.ToLowerInvariant()); - } - - void LoadSprites( string category, string group ) - { - foreach( var u in Rules.AllRules.GetSection( category ) ) - { - var unit = Rules.UnitInfo[ u.Key ]; - - if( unit.TechLevel != -1 ) - sprites.Add( unit.Name, SpriteSheetBuilder.LoadSprite( unit.Name + "icon", ".shp" ) ); - itemGroups.Add( unit.Name, group ); - } - } - - void DrawSprite(Sprite s, ref float2 p) - { - spriteRenderer.DrawSprite(s, p, 0); - p.Y += spriteHeight; - } - - void Fill(float height, float2 p) - { - while (p.Y < height) - DrawSprite(blank, ref p); - } - - int buildPos = 0; - int unitPos = 0; - - void PopulateItemList() - { - buildPos = 0; unitPos = 0; - - items.Clear(); - - foreach (Item i in techTree.BuildableItems) - { - Sprite sprite; - if (!sprites.TryGetValue(i.tag, out sprite)) continue; - - items.Add(new SidebarItem(sprite, i, i.IsStructure ? buildPos : unitPos)); - - if (i.IsStructure) - buildPos += spriteHeight; - else - unitPos += spriteHeight; - } - - foreach (string g in groups) selectedItems[g] = null; - } - - void Paint() - { - foreach (SidebarItem i in items) - i.Paint(spriteRenderer, region.Location); - - Fill(region.Size.Y + region.Location.Y, new float2(region.Location.X, buildPos + region.Location.Y)); - Fill(region.Size.Y + region.Location.Y, new float2(region.Location.X + spriteWidth, unitPos + region.Location.Y)); - - spriteRenderer.Flush(); - - foreach (var kvp in selectedItems) - { - if (kvp.Value != null) - { - clockRenderer.DrawSprite(clockAnimations[kvp.Key].Image, region.Location.ToFloat2() + kvp.Value.location, 0); - clockAnimations[kvp.Key].Tick(1); - } - } - - clockRenderer.Flush(); - } - - public SidebarItem GetItem(float2 point) - { - foreach (SidebarItem i in items) - if (i.Clicked(point)) - return i; - - return null; - } - - void MouseHandler(MouseInput mi) - { - if (mi.Button == MouseButtons.Left && mi.Event == MouseInputEvent.Down) - { - var point = mi.Location.ToFloat2(); - var item = GetItem(point); - if (item != null) - { - string group = itemGroups[item.techTreeItem.tag]; - if (selectedItems[group] == null) - { - selectedItems[group] = item; - Build(item); - } - } - } - else if( mi.Button == MouseButtons.Right && mi.Event == MouseInputEvent.Down ) - { - var point = mi.Location.ToFloat2(); - var item = GetItem(point); - if( item != null ) - { - string group = itemGroups[ item.techTreeItem.tag ]; - selectedItems[ group ] = null; - } - } - } - } -} +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using OpenRa.FileFormats; +using OpenRa.Game.Graphics; +using OpenRa.TechTree; +using System.Linq; + +namespace OpenRa.Game +{ + using GRegion = OpenRa.Game.Graphics.Region; + + class Sidebar + { + TechTree.TechTree techTree; + + SpriteRenderer spriteRenderer, clockRenderer; + Sprite blank; + readonly GRegion region; + + public GRegion Region { get { return region; } } + public float Width { get { return spriteWidth * 2; } } + + Dictionary sprites = new Dictionary(); + const int spriteWidth = 64, spriteHeight = 48; + + static string[] groups = new string[] { "building", "vehicle", "boat", "infantry", "plane" }; + + Dictionary itemGroups = new Dictionary(); //item->group + Dictionary clockAnimations = new Dictionary(); //group->clockAnimation + Dictionary selectedItems = new Dictionary(); //group->selectedItem + + List items = new List(); + + public Sidebar( Renderer renderer ) + { + this.techTree = Game.LocalPlayer.TechTree; + this.techTree.BuildableItemsChanged += PopulateItemList; + region = GRegion.Create(Game.viewport, DockStyle.Right, 128, Paint, MouseHandler); + Game.viewport.AddRegion( region ); + spriteRenderer = new SpriteRenderer(renderer, false); + clockRenderer = new SpriteRenderer(renderer, true); + + LoadSprites( "BuildingTypes", "building" ); + LoadSprites( "VehicleTypes", "vehicle" ); + LoadSprites( "InfantryTypes", "infantry" ); + LoadSprites( "ShipTypes", "boat" ); + LoadSprites( "PlaneTypes", "plane" ); + + foreach (string s in groups) + { + clockAnimations.Add(s, new Animation("clock")); + clockAnimations[s].PlayRepeating("idle"); + selectedItems.Add(s, null); + } + + blank = SheetBuilder.Add(new Size((int)spriteWidth, (int)spriteHeight), 16); + } + + public void Build(SidebarItem item) + { + if (item != null) + Game.controller.orderGenerator = new PlaceBuilding(Game.LocalPlayer, + item.techTreeItem.tag.ToLowerInvariant()); + } + + void LoadSprites( string category, string group ) + { + foreach( var u in Rules.AllRules.GetSection( category ) ) + { + var unit = Rules.UnitInfo[ u.Key ]; + + if( unit.TechLevel != -1 ) + sprites.Add( unit.Name, SpriteSheetBuilder.LoadSprite( unit.Name + "icon", ".shp" ) ); + itemGroups.Add( unit.Name, group ); + } + } + + void DrawSprite(Sprite s, ref float2 p) + { + spriteRenderer.DrawSprite(s, p, 0); + p.Y += spriteHeight; + } + + void Fill(float height, float2 p) + { + while (p.Y < height) + DrawSprite(blank, ref p); + } + + int buildPos = 0; + int unitPos = 0; + + void PopulateItemList() + { + buildPos = 0; unitPos = 0; + + items.Clear(); + + foreach (Item i in techTree.BuildableItems) + { + Sprite sprite; + if (!sprites.TryGetValue(i.tag, out sprite)) continue; + + items.Add(new SidebarItem(sprite, i, i.IsStructure ? buildPos : unitPos)); + + if (i.IsStructure) + buildPos += spriteHeight; + else + unitPos += spriteHeight; + } + + foreach (string g in groups) selectedItems[g] = null; + } + + void Paint() + { + foreach (SidebarItem i in items) + i.Paint(spriteRenderer, region.Location); + + Fill(region.Size.Y + region.Location.Y, new float2(region.Location.X, buildPos + region.Location.Y)); + Fill(region.Size.Y + region.Location.Y, new float2(region.Location.X + spriteWidth, unitPos + region.Location.Y)); + + spriteRenderer.Flush(); + + foreach (var kvp in selectedItems) + { + if (kvp.Value != null) + { + clockRenderer.DrawSprite(clockAnimations[kvp.Key].Image, region.Location.ToFloat2() + kvp.Value.location, 0); + clockAnimations[kvp.Key].Tick(1); + } + } + + clockRenderer.Flush(); + } + + public SidebarItem GetItem(float2 point) + { + foreach (SidebarItem i in items) + if (i.Clicked(point)) + return i; + + return null; + } + + void MouseHandler(MouseInput mi) + { + if (mi.Button == MouseButtons.Left && mi.Event == MouseInputEvent.Down) + { + var point = mi.Location.ToFloat2(); + var item = GetItem(point); + if (item != null) + { + string group = itemGroups[item.techTreeItem.tag]; + if (selectedItems[group] == null) + { + selectedItems[group] = item; + Build(item); + } + } + } + else if( mi.Button == MouseButtons.Right && mi.Event == MouseInputEvent.Down ) + { + var point = mi.Location.ToFloat2(); + var item = GetItem(point); + if( item != null ) + { + string group = itemGroups[ item.techTreeItem.tag ]; + selectedItems[ group ] = null; + } + } + } + } +} diff --git a/OpenRa.Game/Traits/RenderBuilding.cs b/OpenRa.Game/Traits/RenderBuilding.cs index 1ea4e56654..5b78491745 100644 --- a/OpenRa.Game/Traits/RenderBuilding.cs +++ b/OpenRa.Game/Traits/RenderBuilding.cs @@ -21,14 +21,13 @@ namespace OpenRa.Game.Traits anim.PlayThen("make", () => anim.PlayRepeating("idle")); // at this point, we already know where we are, so we can safely place the bib in the smudge - if (((UnitInfo.BuildingInfo)self.unitInfo).Bib) + var buildingInfo = (UnitInfo.BuildingInfo)self.unitInfo; + if (buildingInfo.Bib) { - var fp = Rules.Footprint.GetFootprint(self.unitInfo.Name); - var bibOffset = fp.Length - 2; - var size = fp.First().Length; + var size = buildingInfo.Dimensions.X; + var bibOffset = buildingInfo.Dimensions.Y - 1; var startIndex = (size == 2) ? SmallBibStart : LargeBibStart; - for (int i = 0; i < 2 * size; i++) { var p = self.Location + Game.map.Offset + new int2(i % size, i / size + bibOffset); diff --git a/OpenRa.Game/UiOverlay.cs b/OpenRa.Game/UiOverlay.cs index ff626b9124..f66150ca67 100644 --- a/OpenRa.Game/UiOverlay.cs +++ b/OpenRa.Game/UiOverlay.cs @@ -1,61 +1,61 @@ -using System.Drawing; -using OpenRa.Game.Graphics; -using System; -using OpenRa.Game.GameRules; - -namespace OpenRa.Game -{ - class UiOverlay - { - SpriteRenderer spriteRenderer; - Sprite buildOk; - Sprite buildBlocked; - - public UiOverlay(SpriteRenderer spriteRenderer) - { - this.spriteRenderer = spriteRenderer; - - buildOk = SynthesizeTile(0x80); - buildBlocked = SynthesizeTile(0xe6); - } - - static Sprite SynthesizeTile(byte paletteIndex) - { - byte[] data = new byte[Game.CellSize * Game.CellSize]; - - for (int i = 0; i < Game.CellSize; i++) - for (int j = 0; j < Game.CellSize; j++) - data[i * Game.CellSize + j] = ((i + j) % 4 < 2) ? (byte)0 : paletteIndex; - - return SheetBuilder.Add( data, new Size(Game.CellSize,Game.CellSize) ); - } - - public void Draw() - { - if (!hasOverlay) +using System.Drawing; +using OpenRa.Game.Graphics; +using System; +using OpenRa.Game.GameRules; + +namespace OpenRa.Game +{ + class UiOverlay + { + SpriteRenderer spriteRenderer; + Sprite buildOk; + Sprite buildBlocked; + + public UiOverlay(SpriteRenderer spriteRenderer) + { + this.spriteRenderer = spriteRenderer; + + buildOk = SynthesizeTile(0x80); + buildBlocked = SynthesizeTile(0xe6); + } + + static Sprite SynthesizeTile(byte paletteIndex) + { + byte[] data = new byte[Game.CellSize * Game.CellSize]; + + for (int i = 0; i < Game.CellSize; i++) + for (int j = 0; j < Game.CellSize; j++) + data[i * Game.CellSize + j] = ((i + j) % 4 < 2) ? (byte)0 : paletteIndex; + + return SheetBuilder.Add( data, new Size(Game.CellSize,Game.CellSize) ); + } + + public void Draw() + { + if (!hasOverlay) return; - foreach (var t in Footprint.Tiles(name,position)) - spriteRenderer.DrawSprite(Game.IsCellBuildable(t, UnitMovementType.Wheel) - ? buildOk : buildBlocked, Game.CellSize * t, 0); - - spriteRenderer.Flush(); - } - - bool hasOverlay; - int2 position; - string name; - - public void KillOverlay() - { - hasOverlay = false; - } - - public void SetCurrentOverlay(int2 cell, string name) - { - hasOverlay = true; - position = cell; - this.name = name; - } - } -} + foreach( var t in Footprint.Tiles( Rules.UnitInfo[ name ], position ) ) + spriteRenderer.DrawSprite( Game.IsCellBuildable( t, UnitMovementType.Wheel ) + ? buildOk : buildBlocked, Game.CellSize * t, 0 ); + + spriteRenderer.Flush(); + } + + bool hasOverlay; + int2 position; + string name; + + public void KillOverlay() + { + hasOverlay = false; + } + + public void SetCurrentOverlay(int2 cell, string name) + { + hasOverlay = true; + position = cell; + this.name = name; + } + } +} diff --git a/campaignUnits.ini b/campaignUnits.ini index 18e879edf1..64ae191618 100755 --- a/campaignUnits.ini +++ b/campaignUnits.ini @@ -1,6 +1,178 @@ [BuildingTypes] FCOM +V01 +V02 +V03 +V04 +V05 +V06 +V07 +V08 +V09 +V10 +V11 +V12 +V13 +V14 +V15 +V16 +V17 +V18 +V19 +V20 +V21 +V22 +V23 +V24 +V25 +V26 +V27 +V28 +V29 +V30 +V31 +V32 +V33 +V34 +V35 +V36 +V37 +BARL +BRL3 +MISS [FCOM] Description=Forward Command Post Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx + +[V01] +Traits=Building, RenderBuilding +Image=FCOM +[V02] +Traits=Building, RenderBuilding +Image=FCOM +[V03] +Traits=Building, RenderBuilding +Image=FCOM +[V04] +Traits=Building, RenderBuilding +Image=FCOM +[V05] +Traits=Building, RenderBuilding +Image=FCOM +[V06] +Traits=Building, RenderBuilding +Image=FCOM +[V07] +Traits=Building, RenderBuilding +Image=FCOM +[V08] +Traits=Building, RenderBuilding +Image=FCOM +[V09] +Traits=Building, RenderBuilding +Image=FCOM +[V10] +Traits=Building, RenderBuilding +Image=FCOM +[V11] +Traits=Building, RenderBuilding +Image=FCOM +[V12] +Traits=Building, RenderBuilding +Image=FCOM +[V13] +Traits=Building, RenderBuilding +Image=FCOM +[V14] +Traits=Building, RenderBuilding +Image=FCOM +[V15] +Traits=Building, RenderBuilding +Image=FCOM +[V16] +Traits=Building, RenderBuilding +Image=FCOM +[V17] +Traits=Building, RenderBuilding +Image=FCOM +[V18] +Traits=Building, RenderBuilding +Image=FCOM +[V19] +Traits=Building, RenderBuilding +Image=FCOM +[V20] +Traits=Building, RenderBuilding +Image=FCOM +[V21] +Traits=Building, RenderBuilding +Image=FCOM +[V22] +Traits=Building, RenderBuilding +Image=FCOM +[V23] +Traits=Building, RenderBuilding +Image=FCOM +[V24] +Traits=Building, RenderBuilding +Image=FCOM +[V25] +Traits=Building, RenderBuilding +Image=FCOM +[V26] +Traits=Building, RenderBuilding +Image=FCOM +[V27] +Traits=Building, RenderBuilding +Image=FCOM +[V28] +Traits=Building, RenderBuilding +Image=FCOM +[V29] +Traits=Building, RenderBuilding +Image=FCOM +[V30] +Traits=Building, RenderBuilding +Image=FCOM +[V31] +Traits=Building, RenderBuilding +Image=FCOM +[V32] +Traits=Building, RenderBuilding +Image=FCOM +[V33] +Traits=Building, RenderBuilding +Image=FCOM +[V34] +Traits=Building, RenderBuilding +Image=FCOM +[V35] +Traits=Building, RenderBuilding +Image=FCOM +[V36] +Traits=Building, RenderBuilding +Image=FCOM +[V37] +Traits=Building, RenderBuilding +Image=FCOM +[BARL] +Traits=Building, RenderBuilding +Image=FCOM +[BRL3] +Traits=Building, RenderBuilding +Image=FCOM +[MISS] +Traits=Building, RenderBuilding +Image=FCOM + + + + +[VehicleTypes] +TRUK + +[TRUK] +Traits=Mobile, RenderUnit \ No newline at end of file diff --git a/footprint.txt b/footprint.txt deleted file mode 100644 index fde12f7d16..0000000000 --- a/footprint.txt +++ /dev/null @@ -1,18 +0,0 @@ -# -# Building footprints -# - -# default is indicated by * - -x : ftur sbag brik fenc gun pbox hbox silo gap kenn * -_ x : tsla agun -xx xx == : powr dome barr tent domf hpad atek -xxx xxx === : weap weaf stek -___ xxx xxx === : apwr -xxx xxx xxx === : fact facf -xxx xxx xxx : syrf syrd spen spef -xx : sam mslo -_x_ xxx x== === : proc -xxx xxx : afld -_x_ xxx _x_ : fix -xx xx : iron diff --git a/rules.ini b/rules.ini index 790c53a82c..e98a31e19f 100644 --- a/rules.ini +++ b/rules.ini @@ -1721,7 +1721,7 @@ Strength=1 Points=1 Armor=none Cost=75 -Repariable=false +Repairable=false Adjacent=1 Sight=0 @@ -1731,7 +1731,7 @@ Strength=1 Points=1 Armor=wood Cost=25 -Repariable=false +Repairable=false Adjacent=1 Sight=0 @@ -1739,7 +1739,7 @@ Sight=0 [WOOD] Strength=1 Points=1 -Repariable=false +Repairable=false Adjacent=1 Sight=0 @@ -1850,224 +1850,224 @@ BaseNormal=no Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false Capturable=true [V02] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V03] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V04] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V05] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V06] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V07] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V08] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V09] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V10] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V11] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V12] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V13] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V14] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V15] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V16] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V17] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V18] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V19] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V20] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V21] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V22] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V23] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V24] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V25] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V26] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V27] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V28] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V29] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V30] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V31] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V32] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V33] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V34] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V35] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V36] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false [V37] Strength=400 Points=5 Armor=wood -Repariable=false +Repairable=false ; ******* Weapon Statistics ******* diff --git a/sequences.xml b/sequences.xml index 713e2819e5..960ef59a0f 100644 --- a/sequences.xml +++ b/sequences.xml @@ -169,6 +169,13 @@ + + + + + + + @@ -204,6 +211,13 @@ + + + + + + + diff --git a/units.ini b/units.ini index 871fc63b94..e437132e5f 100755 --- a/units.ini +++ b/units.ini @@ -18,16 +18,16 @@ Description=V2 Rocket Traits=Mobile, RenderUnit [1TNK] Description=Light Tank -Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted +Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted [2TNK] Description=Medium Tank -Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted +Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted [3TNK] Description=Heavy Tank -Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted +Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted [4TNK] Description=Mammoth Tank -Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted +Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted [MRJ] Description=Radar Jammer Traits=Mobile, Turreted, RenderUnitTurreted ; temporary. It's not a turret, it's a spinney-thing @@ -45,7 +45,7 @@ Description=Mobile Construction Vehicle Traits=Mobile, McvDeploy, RenderUnit [JEEP] Description=Ranger -Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted +Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted [APC] Description=Armored Personnel Carrier Traits=Mobile, RenderUnit @@ -143,105 +143,178 @@ SPEF DOMF ; TODO? : campaign-specific stuff - FCOM, civilian buildings, etc + +; `Dimensions` is the size of a box that will include the whole building, excluding bib. +; ("bib-ness" can be altered in rules.ini; we can't expect people to change this, too) +; `Footprint` is the pathability and buildability of each cell occupied by the building +; _ : Not occupied by the building (e.g: the holes in the refinery and the service depot) +; x : Solid. cannot be walked on or built on. +; = : Occupied by a building, but can be walked on normally. (e.g: the drop-off point on the refinery) [IRON] Description=Iron Curtain Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx [ATEK] Description=Allied Tech Center Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx [PDOX] Description=Chronosphere Traits=Building, RenderBuilding +Dimensions=2,1 +Footprint=xx [WEAP] Description=War Factory Traits=Building, RenderWarFactory +Dimensions=3,2 +Footprint=xxx xxx [SYRD] Description=Shipyard Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=xxx xxx xxx [SPEN] Description=Sub Pen Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=xxx xxx xxx [PBOX] Description=Pillbox Traits=Building, RenderBuilding +Dimensions=1,1 +Footprint=x [HBOX] Description=Camo Pillbox Traits=Building, RenderBuilding +Dimensions=1,1 +Footprint=x [TSLA] Description=Tesla Coil Traits=Building, RenderBuilding +Dimensions=1,2 +Footprint=_ x [GUN] Description=Turret Traits=Building, Turreted, RenderBuildingTurreted +Dimensions=1,1 +Footprint=x [AGUN] Description=AA Gun Traits=Building, Turreted, RenderBuildingTurreted +Dimensions=1,2 +Footprint=_ x [FTUR] Description=Flame Turret Traits=Building, RenderBuilding +Dimensions=1,1 +Footprint=x [FACT] Description=Construction Yard Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=xxx xxx xxx [PROC] Description=Ore Refinery Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=_x_ xxx x== [SILO] Description=Silo Traits=Building, RenderBuildingOre +Dimensions=1,1 +Footprint=x [HPAD] Description=Helipad Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx [DOME] Description=Radar Dome Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx [GAP] Description=Gap Generator Traits=Building, RenderBuilding +Dimensions=1,2 +Footprint=_ x [SAM] Description=SAM Site Traits=Building, Turreted, RenderBuildingTurreted +Dimensions=2,1 +Footprint=xx [MSLO] Description=Missile Silo Traits=Building, RenderBuilding +Dimensions=2,1 +Footprint=xx [AFLD] Description=Airstrip Traits=Building, RenderBuilding +Dimensions=3,2 +Footprint=xxx xxx [POWR] Description=Power Plant Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx [APWR] Description=Advanced Power Plant Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=___ xxx xxx [STEK] Description=Soviet Tech Center Traits=Building, RenderBuilding +Dimensions=3,2 +Footprint=xxx xxx [BARR] Description=Soviet Barracks Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx [TENT] Description=Allied Barracks Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx [KENN] Description=Kennel Traits=Building, RenderBuilding +Dimensions=1,1 +Footprint=x [FIX] Description=Service Depot Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=_x_ xxx _x_ [FACF] Description=Fake Construction Yard Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=xxx xxx xxx [WEAF] Description=Fake War Factory Traits=Building, RenderWarFactory +Dimensions=3,2 +Footprint=xxx xxx [SYRF] Description=Fake Shipyard Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=xxx xxx xxx [SPEF] Description=Fake Sub Pen Traits=Building, RenderBuilding +Dimensions=3,3 +Footprint=xxx xxx xxx [DOMF] Description=Fake Radar Dome Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx ;[SBAG] ;Description=Sandbags ;[BRIK]