Killed that fail TechTree, and added a new one to Rules.
This commit is contained in:
@@ -1,15 +1,14 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using OpenRa.FileFormats;
|
|
||||||
using OpenRa.Game.Graphics;
|
|
||||||
using OpenRa.TechTree;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using IrrKlang;
|
|
||||||
using IjwFramework.Collections;
|
using IjwFramework.Collections;
|
||||||
using System;
|
|
||||||
using IjwFramework.Types;
|
using IjwFramework.Types;
|
||||||
using OpenRa.Game.Traits;
|
using IrrKlang;
|
||||||
|
using OpenRa.FileFormats;
|
||||||
using OpenRa.Game.GameRules;
|
using OpenRa.Game.GameRules;
|
||||||
|
using OpenRa.Game.Graphics;
|
||||||
|
using OpenRa.Game.Traits;
|
||||||
|
|
||||||
namespace OpenRa.Game
|
namespace OpenRa.Game
|
||||||
{
|
{
|
||||||
@@ -44,7 +43,7 @@ namespace OpenRa.Game
|
|||||||
Rules.LoadRules(mapName);
|
Rules.LoadRules(mapName);
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
players.Add(i, new Player(i, string.Format("Multi{0}", i), Race.Soviet));
|
players.Add(i, new Player(i, string.Format("Multi{0}", i), Race.Allies));
|
||||||
|
|
||||||
localPlayerIndex = localPlayer;
|
localPlayerIndex = localPlayer;
|
||||||
|
|
||||||
@@ -223,7 +222,7 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
public static void BuildUnit(Player player, string name)
|
public static void BuildUnit(Player player, string name)
|
||||||
{
|
{
|
||||||
var producerTypes = Rules.UnitInfo[name].BuiltAt;
|
var producerTypes = Rules.TechTree.UnitBuiltAt( Rules.UnitInfo[ name ] );
|
||||||
var producer = world.Actors
|
var producer = world.Actors
|
||||||
.FirstOrDefault(a => a.unitInfo != null
|
.FirstOrDefault(a => a.unitInfo != null
|
||||||
&& producerTypes.Contains(a.unitInfo.Name) && a.Owner == player);
|
&& producerTypes.Contains(a.unitInfo.Name) && a.Owner == player);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace OpenRa.Game.GameRules
|
|||||||
return x;
|
return x;
|
||||||
|
|
||||||
else if (fieldType.IsEnum)
|
else if (fieldType.IsEnum)
|
||||||
return Enum.Parse(fieldType, x);
|
return Enum.Parse(fieldType, x, true);
|
||||||
|
|
||||||
else if (fieldType == typeof(bool))
|
else if (fieldType == typeof(bool))
|
||||||
return ParseYesNo(x);
|
return ParseYesNo(x);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace OpenRa.Game
|
|||||||
public static InfoLoader<WeaponInfo> WeaponInfo;
|
public static InfoLoader<WeaponInfo> WeaponInfo;
|
||||||
public static InfoLoader<WarheadInfo> WarheadInfo;
|
public static InfoLoader<WarheadInfo> WarheadInfo;
|
||||||
public static InfoLoader<ProjectileInfo> ProjectileInfo;
|
public static InfoLoader<ProjectileInfo> ProjectileInfo;
|
||||||
|
public static TechTree TechTree;
|
||||||
|
|
||||||
public static void LoadRules( string mapFileName )
|
public static void LoadRules( string mapFileName )
|
||||||
{
|
{
|
||||||
@@ -52,6 +53,8 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
ProjectileInfo = new InfoLoader<ProjectileInfo>(
|
ProjectileInfo = new InfoLoader<ProjectileInfo>(
|
||||||
Pair.New<string, Func<string, ProjectileInfo>>("Projectile", _ => new ProjectileInfo()));
|
Pair.New<string, Func<string, ProjectileInfo>>("Projectile", _ => new ProjectileInfo()));
|
||||||
|
|
||||||
|
TechTree = new TechTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadCategories( params string[] types )
|
static void LoadCategories( params string[] types )
|
||||||
|
|||||||
65
OpenRa.Game/GameRules/TechTree.cs
Executable file
65
OpenRa.Game/GameRules/TechTree.cs
Executable file
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using IjwFramework.Collections;
|
||||||
|
|
||||||
|
namespace OpenRa.Game.GameRules
|
||||||
|
{
|
||||||
|
class TechTree
|
||||||
|
{
|
||||||
|
readonly Cache<string, List<UnitInfo.BuildingInfo>> producesIndex = new Cache<string, List<UnitInfo.BuildingInfo>>( x => new List<UnitInfo.BuildingInfo>() );
|
||||||
|
|
||||||
|
public TechTree()
|
||||||
|
{
|
||||||
|
foreach( var b in Rules.Categories[ "Building" ] )
|
||||||
|
{
|
||||||
|
var info = (UnitInfo.BuildingInfo)Rules.UnitInfo[ b ];
|
||||||
|
foreach( var p in info.Produces )
|
||||||
|
producesIndex[ p ].Add( info );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cache<string, List<Actor>> GatherBuildings( Player player )
|
||||||
|
{
|
||||||
|
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
|
||||||
|
foreach( var b in Game.world.Actors.Where( x => x.Owner == player && Rules.UnitCategory[ x.unitInfo.Name ] == "Building" ) )
|
||||||
|
ret[ b.unitInfo.Name ].Add( b );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanBuild( UnitInfo unit, Player player, Cache<string, List<Actor>> playerBuildings )
|
||||||
|
{
|
||||||
|
if( unit.TechLevel == -1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( !unit.Owner.Any( x => x == player.Race ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach( var p in unit.Prerequisite )
|
||||||
|
if( playerBuildings[ p ].Count == 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( producesIndex[ Rules.UnitCategory[ unit.Name ] ].All( x => playerBuildings[ x.Name ].Count == 0 ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> BuildableItems( Player player, params string[] categories )
|
||||||
|
{
|
||||||
|
var playerBuildings = GatherBuildings( player );
|
||||||
|
foreach( var unit in categories.SelectMany( x => Rules.Categories[ x ] ).Select( x => Rules.UnitInfo[ x ] ) )
|
||||||
|
if( CanBuild( unit, player, playerBuildings ) )
|
||||||
|
yield return unit.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> UnitBuiltAt( UnitInfo info )
|
||||||
|
{
|
||||||
|
if( info.BuiltAt.Length != 0 )
|
||||||
|
return info.BuiltAt;
|
||||||
|
else
|
||||||
|
return producesIndex[ Rules.UnitCategory[ info.Name ] ].Select( x => x.Name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ namespace OpenRa.Game.GameRules
|
|||||||
public readonly int GuardRange = -1; // -1 = use weapon's range
|
public readonly int GuardRange = -1; // -1 = use weapon's range
|
||||||
public readonly string Image = null; // sprite-set to use when rendering
|
public readonly string Image = null; // sprite-set to use when rendering
|
||||||
public readonly bool Invisible = false;
|
public readonly bool Invisible = false;
|
||||||
public readonly string[] Owner = { "allies", "soviet" };
|
public readonly Race[] Owner = { Race.Allies, Race.Soviet };
|
||||||
public readonly int Points = 0;
|
public readonly int Points = 0;
|
||||||
public readonly string[] Prerequisite = { };
|
public readonly string[] Prerequisite = { };
|
||||||
public readonly string Primary = null;
|
public readonly string Primary = null;
|
||||||
@@ -81,6 +81,7 @@ namespace OpenRa.Game.GameRules
|
|||||||
{
|
{
|
||||||
public readonly int2 Dimensions = new int2( 1, 1 );
|
public readonly int2 Dimensions = new int2( 1, 1 );
|
||||||
public readonly string Footprint = "x";
|
public readonly string Footprint = "x";
|
||||||
|
public readonly string[] Produces = { };
|
||||||
|
|
||||||
public readonly bool BaseNormal = true;
|
public readonly bool BaseNormal = true;
|
||||||
public readonly int Adjacent = 1;
|
public readonly int Adjacent = 1;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using System.Drawing;
|
|||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using OpenRa.FileFormats;
|
using OpenRa.FileFormats;
|
||||||
using OpenRa.Game.Graphics;
|
using OpenRa.Game.Graphics;
|
||||||
using OpenRa.TechTree;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace OpenRa.Game
|
namespace OpenRa.Game
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="GameRules\TechTree.cs" />
|
||||||
<Compile Include="OrderManager.cs" />
|
<Compile Include="OrderManager.cs" />
|
||||||
<Compile Include="Traits\Activities\DeployMcv.cs" />
|
<Compile Include="Traits\Activities\DeployMcv.cs" />
|
||||||
<Compile Include="Actor.cs" />
|
<Compile Include="Actor.cs" />
|
||||||
@@ -99,7 +100,6 @@
|
|||||||
<Compile Include="BuildingInfluenceMap.cs" />
|
<Compile Include="BuildingInfluenceMap.cs" />
|
||||||
<Compile Include="IOrderGenerator.cs" />
|
<Compile Include="IOrderGenerator.cs" />
|
||||||
<Compile Include="PlaceBuilding.cs" />
|
<Compile Include="PlaceBuilding.cs" />
|
||||||
<Compile Include="TechTree\Item.cs" />
|
|
||||||
<Compile Include="Player.cs" />
|
<Compile Include="Player.cs" />
|
||||||
<Compile Include="Race.cs" />
|
<Compile Include="Race.cs" />
|
||||||
<Compile Include="Support\SharedResources.cs" />
|
<Compile Include="Support\SharedResources.cs" />
|
||||||
@@ -124,7 +124,6 @@
|
|||||||
<Compile Include="Graphics\Sprite.cs" />
|
<Compile Include="Graphics\Sprite.cs" />
|
||||||
<Compile Include="Graphics\SpriteRenderer.cs" />
|
<Compile Include="Graphics\SpriteRenderer.cs" />
|
||||||
<Compile Include="Graphics\SpriteSheetBuilder.cs" />
|
<Compile Include="Graphics\SpriteSheetBuilder.cs" />
|
||||||
<Compile Include="TechTree\TechTree.cs" />
|
|
||||||
<Compile Include="TerrainCosts.cs" />
|
<Compile Include="TerrainCosts.cs" />
|
||||||
<Compile Include="Graphics\TerrainRenderer.cs" />
|
<Compile Include="Graphics\TerrainRenderer.cs" />
|
||||||
<Compile Include="Graphics\TreeCache.cs" />
|
<Compile Include="Graphics\TreeCache.cs" />
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ namespace OpenRa.Game
|
|||||||
public int Palette;
|
public int Palette;
|
||||||
public int Kills;
|
public int Kills;
|
||||||
public string PlayerName;
|
public string PlayerName;
|
||||||
public TechTree.TechTree TechTree = new OpenRa.TechTree.TechTree();
|
public Race Race;
|
||||||
|
|
||||||
public Player( int palette, string playerName, OpenRa.TechTree.Race race )
|
public Player( int palette, string playerName, Race race )
|
||||||
{
|
{
|
||||||
this.Palette = palette;
|
this.Palette = palette;
|
||||||
this.PlayerName = playerName;
|
this.PlayerName = playerName;
|
||||||
TechTree.CurrentRace = race;
|
this.Race = race;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetSiloFullness()
|
public float GetSiloFullness()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace OpenRa.TechTree
|
namespace OpenRa.Game
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum Race
|
public enum Race
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using System.Drawing;
|
|||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using OpenRa.FileFormats;
|
using OpenRa.FileFormats;
|
||||||
using OpenRa.Game.Graphics;
|
using OpenRa.Game.Graphics;
|
||||||
using OpenRa.TechTree;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace OpenRa.Game
|
namespace OpenRa.Game
|
||||||
@@ -34,7 +33,6 @@ namespace OpenRa.Game
|
|||||||
public Sidebar( Renderer renderer, Player player )
|
public Sidebar( Renderer renderer, Player player )
|
||||||
{
|
{
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.player.TechTree.BuildableItemsChanged += PopulateItemList;
|
|
||||||
region = GRegion.Create(Game.viewport, DockStyle.Right, 128, Paint, MouseHandler);
|
region = GRegion.Create(Game.viewport, DockStyle.Right, 128, Paint, MouseHandler);
|
||||||
Game.viewport.AddRegion( region );
|
Game.viewport.AddRegion( region );
|
||||||
spriteRenderer = new SpriteRenderer(renderer, false);
|
spriteRenderer = new SpriteRenderer(renderer, false);
|
||||||
@@ -68,11 +66,11 @@ namespace OpenRa.Game
|
|||||||
{
|
{
|
||||||
if (item == null) return;
|
if (item == null) return;
|
||||||
|
|
||||||
if (item.techTreeItem.IsStructure)
|
if (item.IsStructure)
|
||||||
Game.controller.orderGenerator = new PlaceBuilding(player,
|
Game.controller.orderGenerator = new PlaceBuilding(player,
|
||||||
item.techTreeItem.tag.ToLowerInvariant());
|
item.Tag.ToLowerInvariant());
|
||||||
else
|
else
|
||||||
Game.controller.AddOrder(Order.BuildUnit(player, item.techTreeItem.tag.ToLowerInvariant()));
|
Game.controller.AddOrder(Order.BuildUnit(player, item.Tag.ToLowerInvariant()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadSprites( string group )
|
void LoadSprites( string group )
|
||||||
@@ -107,17 +105,20 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
items.Clear();
|
items.Clear();
|
||||||
|
|
||||||
foreach (Item i in player.TechTree.BuildableItems)
|
foreach (var i in Rules.TechTree.BuildableItems(player, "Building"))
|
||||||
{
|
{
|
||||||
Sprite sprite;
|
Sprite sprite;
|
||||||
if (!sprites.TryGetValue(i.tag, out sprite)) continue;
|
if (!sprites.TryGetValue(i, out sprite)) continue;
|
||||||
|
items.Add(new SidebarItem(sprite, i, true, buildPos));
|
||||||
|
buildPos += spriteHeight;
|
||||||
|
}
|
||||||
|
|
||||||
items.Add(new SidebarItem(sprite, i, i.IsStructure ? buildPos : unitPos));
|
foreach( var i in Rules.TechTree.BuildableItems( player, "Vehicle", "Infantry", "Ship", "Plane" ) )
|
||||||
|
{
|
||||||
if (i.IsStructure)
|
Sprite sprite;
|
||||||
buildPos += spriteHeight;
|
if( !sprites.TryGetValue( i, out sprite ) ) continue;
|
||||||
else
|
items.Add( new SidebarItem( sprite, i, false, unitPos ) );
|
||||||
unitPos += spriteHeight;
|
unitPos += spriteHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach( string g in groups ) player.CancelProduction( g );
|
foreach( string g in groups ) player.CancelProduction( g );
|
||||||
@@ -125,11 +126,12 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
void Paint()
|
void Paint()
|
||||||
{
|
{
|
||||||
|
PopulateItemList();
|
||||||
foreach( SidebarItem i in items )
|
foreach( SidebarItem i in items )
|
||||||
{
|
{
|
||||||
var group = Rules.UnitCategory[ i.techTreeItem.tag ];
|
var group = Rules.UnitCategory[ i.Tag ];
|
||||||
var producing = player.Producing( group );
|
var producing = player.Producing( group );
|
||||||
if( producing != null && producing.Item == i.techTreeItem.tag )
|
if( producing != null && producing.Item == i.Tag )
|
||||||
{
|
{
|
||||||
clockAnimations[ group ].Tick();
|
clockAnimations[ group ].Tick();
|
||||||
clockRenderer.DrawSprite( clockAnimations[ group ].Image, region.Location.ToFloat2() + i.location, 0 );
|
clockRenderer.DrawSprite( clockAnimations[ group ].Image, region.Location.ToFloat2() + i.location, 0 );
|
||||||
@@ -155,30 +157,22 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
void MouseHandler(MouseInput mi)
|
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 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( mi.Button == MouseButtons.Left && mi.Event == MouseInputEvent.Down )
|
||||||
{
|
{
|
||||||
var point = mi.Location.ToFloat2();
|
string group = Rules.UnitCategory[ item.Tag ];
|
||||||
var item = GetItem(point);
|
|
||||||
if (item != null)
|
|
||||||
{
|
|
||||||
string group = Rules.UnitCategory[ item.techTreeItem.tag ];
|
|
||||||
if (player.Producing(group) == null)
|
if (player.Producing(group) == null)
|
||||||
{
|
{
|
||||||
player.BeginProduction( group, new ProductionItem( item.techTreeItem.tag, 25, 0 ) );
|
player.BeginProduction( group, new ProductionItem( item.Tag, 25, 0 ) );
|
||||||
Build(item);
|
Build(item);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if( mi.Button == MouseButtons.Right && mi.Event == MouseInputEvent.Down )
|
else if( mi.Button == MouseButtons.Right && mi.Event == MouseInputEvent.Down )
|
||||||
{
|
player.CancelProduction( Rules.UnitCategory[ item.Tag ] );
|
||||||
var point = mi.Location.ToFloat2();
|
|
||||||
var item = GetItem(point);
|
|
||||||
if( item != null )
|
|
||||||
{
|
|
||||||
string group = Rules.UnitCategory[ item.techTreeItem.tag ];
|
|
||||||
player.CancelProduction( group );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
using OpenRa.Game.Graphics;
|
using OpenRa.Game.Graphics;
|
||||||
using OpenRa.TechTree;
|
|
||||||
|
|
||||||
namespace OpenRa.Game
|
namespace OpenRa.Game
|
||||||
{
|
{
|
||||||
class SidebarItem
|
class SidebarItem
|
||||||
{
|
{
|
||||||
public readonly Item techTreeItem;
|
|
||||||
public readonly float2 location;
|
public readonly float2 location;
|
||||||
|
public readonly string Tag;
|
||||||
|
public readonly bool IsStructure;
|
||||||
readonly Sprite sprite;
|
readonly Sprite sprite;
|
||||||
|
|
||||||
public SidebarItem(Sprite s, Item item, int y)
|
public SidebarItem(Sprite s, string tag, bool isStructure, int y)
|
||||||
{
|
{
|
||||||
this.techTreeItem = item;
|
|
||||||
this.sprite = s;
|
this.sprite = s;
|
||||||
location = new float2(item.IsStructure ? 0 : 64, y);
|
this.Tag = tag;
|
||||||
|
this.IsStructure = isStructure;
|
||||||
|
location = new float2(isStructure ? 0 : 64, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Clicked(float2 p)
|
public bool Clicked(float2 p)
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using OpenRa.FileFormats;
|
|
||||||
using OpenRa.Game.GameRules;
|
|
||||||
using IjwFramework.Types;
|
|
||||||
using OpenRa.Game;
|
|
||||||
|
|
||||||
namespace OpenRa.TechTree
|
|
||||||
{
|
|
||||||
public class Item
|
|
||||||
{
|
|
||||||
readonly bool isStructure;
|
|
||||||
|
|
||||||
public bool IsStructure { get { return isStructure; } }
|
|
||||||
|
|
||||||
public Item(string tag, UnitInfo unitInfo, bool isStructure)
|
|
||||||
{
|
|
||||||
this.tag = tag;
|
|
||||||
this.friendlyName = unitInfo.Description;
|
|
||||||
this.isStructure = isStructure;
|
|
||||||
|
|
||||||
owner = ParseOwner(unitInfo.Owner, unitInfo.DoubleOwned);
|
|
||||||
techLevel = unitInfo.TechLevel;
|
|
||||||
var pre = ParsePrerequisites(unitInfo.Prerequisite, tag);
|
|
||||||
alliedPrerequisites = pre.a;
|
|
||||||
sovietPrerequisites = pre.b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Race ParseOwner(string[] owners, bool doubleOwned)
|
|
||||||
{
|
|
||||||
if (doubleOwned)
|
|
||||||
return Race.Allies | Race.Soviet;
|
|
||||||
|
|
||||||
Race race = Race.None;
|
|
||||||
|
|
||||||
foreach (string s in owners)
|
|
||||||
race |= Enum<Race>.Parse(s);
|
|
||||||
|
|
||||||
return race;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Tuple<string[],string[]> ParsePrerequisites(string[] prerequisites, string tag)
|
|
||||||
{
|
|
||||||
var allied = prerequisites.Select( x => x.ToLowerInvariant() ).ToList();
|
|
||||||
var soviet = new List<string>(allied);
|
|
||||||
|
|
||||||
if (allied.Remove("stek")) allied.Add("atek");
|
|
||||||
if (soviet.Remove("atek")) soviet.Add("stek");
|
|
||||||
if (soviet.Remove("tent")) soviet.Add("barr");
|
|
||||||
if (allied.Remove("barr")) allied.Add("tent");
|
|
||||||
|
|
||||||
if( Rules.UnitCategory[ tag ] == "Infantry" )
|
|
||||||
{
|
|
||||||
if( !allied.Contains( "tent" ) ) allied.Add( "tent" );
|
|
||||||
if( !soviet.Contains( "barr" ) ) soviet.Add( "barr" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag == "lst")
|
|
||||||
{
|
|
||||||
if (!soviet.Contains("spen")) soviet.Add("spen");
|
|
||||||
if (!allied.Contains("syrd")) allied.Add("syrd");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Tuple<string[], string[]>(
|
|
||||||
allied.ToArray(), soviet.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly string tag, friendlyName;
|
|
||||||
readonly int techLevel;
|
|
||||||
readonly Race owner;
|
|
||||||
readonly string[] alliedPrerequisites, sovietPrerequisites;
|
|
||||||
|
|
||||||
bool ShouldMakeBuildable(IEnumerable<string> buildings, string[] racePrerequisites)
|
|
||||||
{
|
|
||||||
if (techLevel < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (racePrerequisites.Length == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return racePrerequisites.Except(buildings).Count() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShouldMakeUnbuildable(IEnumerable<string> buildings, string[] racePrerequisites)
|
|
||||||
{
|
|
||||||
if (racePrerequisites.Length == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return racePrerequisites.Except(buildings).Count() == racePrerequisites.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckForBoth(IEnumerable<string> buildings)
|
|
||||||
{
|
|
||||||
if (CanBuild && (ShouldMakeUnbuildable(buildings, alliedPrerequisites)
|
|
||||||
&& ShouldMakeUnbuildable(buildings, sovietPrerequisites)))
|
|
||||||
CanBuild = false;
|
|
||||||
|
|
||||||
else if (!CanBuild && (ShouldMakeBuildable(buildings, alliedPrerequisites)
|
|
||||||
|| ShouldMakeBuildable(buildings, sovietPrerequisites)))
|
|
||||||
CanBuild = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CheckPrerequisites(IEnumerable<string> buildings, Race currentRace)
|
|
||||||
{
|
|
||||||
if (currentRace == Race.None || currentRace == (Race.Allies | Race.Soviet))
|
|
||||||
CheckForBoth(buildings);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string[] racePrerequisites = (currentRace == Race.Allies) ? alliedPrerequisites : sovietPrerequisites;
|
|
||||||
|
|
||||||
if ((CanBuild && ShouldMakeUnbuildable(buildings, racePrerequisites)) || !((owner & currentRace) == currentRace))
|
|
||||||
CanBuild = false;
|
|
||||||
else if (!CanBuild && ShouldMakeBuildable(buildings, racePrerequisites))
|
|
||||||
CanBuild = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanBuild { get; private set; }
|
|
||||||
public string Tooltip { get { return string.Format("{0} ({1})\n{2}", friendlyName, tag, owner); } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using OpenRa.FileFormats;
|
|
||||||
using System.Linq;
|
|
||||||
using OpenRa.Game;
|
|
||||||
|
|
||||||
namespace OpenRa.TechTree
|
|
||||||
{
|
|
||||||
public class TechTree
|
|
||||||
{
|
|
||||||
Dictionary<string, Item> objects = new Dictionary<string, Item>();
|
|
||||||
public ICollection<string> built = new List<string>();
|
|
||||||
|
|
||||||
Race currentRace = Race.None;
|
|
||||||
|
|
||||||
public Race CurrentRace
|
|
||||||
{
|
|
||||||
get { return currentRace; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
currentRace = value;
|
|
||||||
CheckAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TechTree()
|
|
||||||
{
|
|
||||||
LoadRules();
|
|
||||||
CheckAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadRules()
|
|
||||||
{
|
|
||||||
foreach( var unit in Rules.UnitInfo )
|
|
||||||
objects.Add( unit.Key, new Item( unit.Key, unit.Value, Rules.UnitCategory[ unit.Key ] == "Building" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Build(string key, bool force)
|
|
||||||
{
|
|
||||||
if( string.IsNullOrEmpty( key ) ) return false;
|
|
||||||
key = key.ToLowerInvariant();
|
|
||||||
Item b = objects[ key ];
|
|
||||||
if (!force && !b.CanBuild) return false;
|
|
||||||
built.Add(key);
|
|
||||||
CheckAll();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Build(string key) { return Build(key, false); }
|
|
||||||
|
|
||||||
public bool Unbuild(string key)
|
|
||||||
{
|
|
||||||
key = key.ToLowerInvariant();
|
|
||||||
Item b = objects[key];
|
|
||||||
if (!built.Contains(key)) return false;
|
|
||||||
built.Remove(key);
|
|
||||||
CheckAll();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckAll()
|
|
||||||
{
|
|
||||||
foreach (Item unit in objects.Values)
|
|
||||||
unit.CheckPrerequisites(built, currentRace);
|
|
||||||
|
|
||||||
BuildableItemsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Item> BuildableItems { get { return objects.Values.Where(b => b.CanBuild); } }
|
|
||||||
public event Action BuildableItemsChanged = () => { };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,10 +15,8 @@ namespace OpenRa.Game.Traits
|
|||||||
public void Tick(Actor self)
|
public void Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (first && self.Owner == Game.LocalPlayer)
|
if (first && self.Owner == Game.LocalPlayer)
|
||||||
{
|
|
||||||
self.Owner.TechTree.Build(self.unitInfo.Name, true);
|
|
||||||
self.CenterLocation = Game.CellSize * (float2)self.Location + 0.5f * self.SelectedSize;
|
self.CenterLocation = Game.CellSize * (float2)self.Location + 0.5f * self.SelectedSize;
|
||||||
}
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- openra/sequences.xml
|
<!-- openra/sequences.xml
|
||||||
|
|
||||||
this file describes animation sequences for structures and units.
|
this file describes animation sequences for structures and units.
|
||||||
@@ -361,7 +361,7 @@
|
|||||||
<sequence name="attack" start="21" length="8" x="12" y="12" />
|
<sequence name="attack" start="21" length="8" x="12" y="12" />
|
||||||
<sequence name="move-minimap" start="29" length="6" />
|
<sequence name="move-minimap" start="29" length="6" />
|
||||||
<sequence name="repair" start="35" length="24" />
|
<sequence name="repair" start="35" length="24" />
|
||||||
<sequence name="deploy" start="59" length="9" x="12" y="12"/>
|
<sequence name="deploy" start="59" length="9" x="12" y="12" />
|
||||||
<sequence name="sell" start="68" length="12" />
|
<sequence name="sell" start="68" length="12" />
|
||||||
<sequence name="default-minimap" start="80" length="1" />
|
<sequence name="default-minimap" start="80" length="1" />
|
||||||
<sequence name="ability" start="82" length="8" />
|
<sequence name="ability" start="82" length="8" />
|
||||||
@@ -465,4 +465,7 @@
|
|||||||
<sequence name="5" start="0" length="22" src="veh-hit2" />
|
<sequence name="5" start="0" length="22" src="veh-hit2" />
|
||||||
<sequence name="6" start="0" length="27" src="atomsfx" />
|
<sequence name="6" start="0" length="27" src="atomsfx" />
|
||||||
</unit>
|
</unit>
|
||||||
</sequences>
|
<unit name="lst">
|
||||||
|
<sequence name="idle" start="0" length="1" />
|
||||||
|
</unit>
|
||||||
|
</sequences>
|
||||||
|
|||||||
26
units.ini
26
units.ini
@@ -16,55 +16,42 @@ MNLY
|
|||||||
[V2RL]
|
[V2RL]
|
||||||
Description=V2 Rocket
|
Description=V2 Rocket
|
||||||
Traits=Mobile, RenderUnit
|
Traits=Mobile, RenderUnit
|
||||||
BuiltAt=weap
|
|
||||||
[1TNK]
|
[1TNK]
|
||||||
Description=Light Tank
|
Description=Light Tank
|
||||||
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
||||||
BuiltAt=weap
|
|
||||||
[2TNK]
|
[2TNK]
|
||||||
Description=Medium Tank
|
Description=Medium Tank
|
||||||
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
||||||
BuiltAt=weap
|
|
||||||
[3TNK]
|
[3TNK]
|
||||||
Description=Heavy Tank
|
Description=Heavy Tank
|
||||||
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
||||||
BuiltAt=weap
|
|
||||||
[4TNK]
|
[4TNK]
|
||||||
Description=Mammoth Tank
|
Description=Mammoth Tank
|
||||||
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
||||||
BuiltAt=weap
|
|
||||||
[MRJ]
|
[MRJ]
|
||||||
Description=Radar Jammer
|
Description=Radar Jammer
|
||||||
Traits=Mobile, Turreted, RenderUnitTurreted ; temporary. It's not a turret, it's a spinney-thing
|
Traits=Mobile, Turreted, RenderUnitTurreted ; temporary. It's not a turret, it's a spinney-thing
|
||||||
BuiltAt=weap
|
|
||||||
[MGG]
|
[MGG]
|
||||||
Description=Mobile Gap Generator
|
Description=Mobile Gap Generator
|
||||||
Traits=Mobile, Turreted, RenderUnitTurreted ; temporary. It's not a turret, it's a spinney-thing
|
Traits=Mobile, Turreted, RenderUnitTurreted ; temporary. It's not a turret, it's a spinney-thing
|
||||||
BuiltAt=weap
|
|
||||||
[ARTY]
|
[ARTY]
|
||||||
Description=Artillery
|
Description=Artillery
|
||||||
Traits=Mobile, RenderUnit
|
Traits=Mobile, RenderUnit
|
||||||
BuiltAt=weap
|
|
||||||
[HARV]
|
[HARV]
|
||||||
Description=Ore Truck
|
Description=Ore Truck
|
||||||
Traits=Mobile, RenderUnit
|
Traits=Mobile, RenderUnit
|
||||||
BuiltAt=weap
|
|
||||||
[MCV]
|
[MCV]
|
||||||
Description=Mobile Construction Vehicle
|
Description=Mobile Construction Vehicle
|
||||||
Traits=Mobile, McvDeploy, RenderUnit
|
Traits=Mobile, McvDeploy, RenderUnit
|
||||||
BuiltAt=weap
|
|
||||||
[JEEP]
|
[JEEP]
|
||||||
Description=Ranger
|
Description=Ranger
|
||||||
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
Traits=Mobile, Turreted, AttackTurreted, RenderUnitTurreted
|
||||||
BuiltAt=weap
|
|
||||||
[APC]
|
[APC]
|
||||||
Description=Armored Personnel Carrier
|
Description=Armored Personnel Carrier
|
||||||
Traits=Mobile, RenderUnit
|
Traits=Mobile, RenderUnit
|
||||||
BuiltAt=weap
|
|
||||||
[MNLY]
|
[MNLY]
|
||||||
Description=Minelayer
|
Description=Minelayer
|
||||||
Traits=Mobile, RenderUnit
|
Traits=Mobile, RenderUnit
|
||||||
BuiltAt=weap
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -95,7 +82,6 @@ Traits=Mobile, RenderUnit
|
|||||||
[LST]
|
[LST]
|
||||||
Description=Transport
|
Description=Transport
|
||||||
WaterBound=yes
|
WaterBound=yes
|
||||||
BuiltAt=syrd,spen
|
|
||||||
Traits=Mobile, RenderUnit
|
Traits=Mobile, RenderUnit
|
||||||
[PT]
|
[PT]
|
||||||
Description=Gunboat
|
Description=Gunboat
|
||||||
@@ -178,6 +164,7 @@ DOMF
|
|||||||
; _ : Not occupied by the building (e.g: the holes in the refinery and the service depot)
|
; _ : 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.
|
; 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)
|
; = : Occupied by a building, but can be walked on normally. (e.g: the drop-off point on the refinery)
|
||||||
|
; `Produces` is a category of objects that this building can produce.
|
||||||
[IRON]
|
[IRON]
|
||||||
Description=Iron Curtain
|
Description=Iron Curtain
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
@@ -198,16 +185,19 @@ Description=War Factory
|
|||||||
Traits=Building, RenderWarFactory
|
Traits=Building, RenderWarFactory
|
||||||
Dimensions=3,2
|
Dimensions=3,2
|
||||||
Footprint=xxx xxx
|
Footprint=xxx xxx
|
||||||
|
Produces=Vehicle
|
||||||
[SYRD]
|
[SYRD]
|
||||||
Description=Shipyard
|
Description=Shipyard
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
Dimensions=3,3
|
Dimensions=3,3
|
||||||
Footprint=xxx xxx xxx
|
Footprint=xxx xxx xxx
|
||||||
|
Produces=Ship
|
||||||
[SPEN]
|
[SPEN]
|
||||||
Description=Sub Pen
|
Description=Sub Pen
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
Dimensions=3,3
|
Dimensions=3,3
|
||||||
Footprint=xxx xxx xxx
|
Footprint=xxx xxx xxx
|
||||||
|
Produces=Ship
|
||||||
[PBOX]
|
[PBOX]
|
||||||
Description=Pillbox
|
Description=Pillbox
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
@@ -243,6 +233,7 @@ Description=Construction Yard
|
|||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
Dimensions=3,3
|
Dimensions=3,3
|
||||||
Footprint=xxx xxx xxx
|
Footprint=xxx xxx xxx
|
||||||
|
Produces=Building
|
||||||
[PROC]
|
[PROC]
|
||||||
Description=Ore Refinery
|
Description=Ore Refinery
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
@@ -258,6 +249,7 @@ Description=Helipad
|
|||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
Dimensions=2,2
|
Dimensions=2,2
|
||||||
Footprint=xx xx
|
Footprint=xx xx
|
||||||
|
Produces=Plane
|
||||||
[DOME]
|
[DOME]
|
||||||
Description=Radar Dome
|
Description=Radar Dome
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
@@ -283,6 +275,7 @@ Description=Airstrip
|
|||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
Dimensions=3,2
|
Dimensions=3,2
|
||||||
Footprint=xxx xxx
|
Footprint=xxx xxx
|
||||||
|
Produces=Plane
|
||||||
[POWR]
|
[POWR]
|
||||||
Description=Power Plant
|
Description=Power Plant
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
@@ -303,11 +296,13 @@ Description=Soviet Barracks
|
|||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
Dimensions=2,2
|
Dimensions=2,2
|
||||||
Footprint=xx xx
|
Footprint=xx xx
|
||||||
|
Produces=Infantry
|
||||||
[TENT]
|
[TENT]
|
||||||
Description=Allied Barracks
|
Description=Allied Barracks
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
Dimensions=2,2
|
Dimensions=2,2
|
||||||
Footprint=xx xx
|
Footprint=xx xx
|
||||||
|
Produces=Infantry
|
||||||
[KENN]
|
[KENN]
|
||||||
Description=Kennel
|
Description=Kennel
|
||||||
Traits=Building, RenderBuilding
|
Traits=Building, RenderBuilding
|
||||||
@@ -368,6 +363,7 @@ MEDI
|
|||||||
|
|
||||||
[DOG]
|
[DOG]
|
||||||
Description=Attack Dog
|
Description=Attack Dog
|
||||||
|
BuiltAt=KENN
|
||||||
[E1]
|
[E1]
|
||||||
Description=Rifle Infantry
|
Description=Rifle Infantry
|
||||||
[E2]
|
[E2]
|
||||||
@@ -467,4 +463,4 @@ Organic
|
|||||||
Nuke
|
Nuke
|
||||||
|
|
||||||
[HE]
|
[HE]
|
||||||
ImpactSound=kaboom25
|
ImpactSound=kaboom25
|
||||||
|
|||||||
Reference in New Issue
Block a user