added units.ini (and campaignUnits.ini), and IniFile got support for load/merging multiple files.
- Rules can now handle map-specific rules changes
- units.ini replaces {buildings,units,infantry}.txt (or will replace; sidebar still uses them)
- Added support for loading map-placed units/structures - try scg11eb.ini
- added FCOM
This commit is contained in:
@@ -10,65 +10,94 @@ namespace OpenRa.FileFormats
|
|||||||
public class IniFile
|
public class IniFile
|
||||||
{
|
{
|
||||||
Dictionary<string, IniSection> sections = new Dictionary<string, IniSection>();
|
Dictionary<string, IniSection> sections = new Dictionary<string, IniSection>();
|
||||||
IniSection currentSection;
|
|
||||||
|
|
||||||
public IniFile( Stream s )
|
public IniFile( Stream s )
|
||||||
|
{
|
||||||
|
Load( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IniFile( params Stream[] streams )
|
||||||
|
{
|
||||||
|
foreach( var s in streams )
|
||||||
|
Load( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load( Stream s )
|
||||||
{
|
{
|
||||||
StreamReader reader = new StreamReader( s );
|
StreamReader reader = new StreamReader( s );
|
||||||
|
IniSection currentSection = null;
|
||||||
|
|
||||||
while( !reader.EndOfStream )
|
while( !reader.EndOfStream )
|
||||||
{
|
{
|
||||||
string line = reader.ReadLine();
|
string line = reader.ReadLine();
|
||||||
|
|
||||||
if (line.Length == 0) continue;
|
if( line.Length == 0 ) continue;
|
||||||
|
|
||||||
switch (line[0])
|
switch( line[ 0 ] )
|
||||||
{
|
{
|
||||||
case ';': break;
|
case ';': break;
|
||||||
case '[': ProcessSection(line); break;
|
case '[': currentSection = ProcessSection( line ); break;
|
||||||
default: ProcessEntry(line); break;
|
default: ProcessEntry( line, currentSection ); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Regex sectionPattern = new Regex( @"^\[([^]]*)\]" );
|
Regex sectionPattern = new Regex( @"^\[([^]]*)\]" );
|
||||||
Regex entryPattern = new Regex( @"([^=;]+)=([^;]*)" );
|
|
||||||
|
|
||||||
bool ProcessSection( string line )
|
IniSection ProcessSection( string line )
|
||||||
{
|
{
|
||||||
Match m = sectionPattern.Match( line );
|
Match m = sectionPattern.Match( line );
|
||||||
if( m == null || !m.Success )
|
if( m == null || !m.Success )
|
||||||
return false;
|
return null;
|
||||||
|
string sectionName = m.Groups[ 1 ].Value.ToLowerInvariant();
|
||||||
|
|
||||||
string sectionName = m.Groups[ 1 ].Value;
|
IniSection ret;
|
||||||
currentSection = new IniSection( sectionName );
|
if( !sections.TryGetValue( sectionName, out ret ) )
|
||||||
sections.Add( sectionName, currentSection );
|
sections.Add( sectionName, ret = new IniSection( sectionName ) );
|
||||||
|
return ret;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProcessEntry( string line )
|
bool ProcessEntry( string line, IniSection currentSection )
|
||||||
{
|
{
|
||||||
int comment = line.IndexOf(';');
|
int comment = line.IndexOf( ';' );
|
||||||
if (comment >= 0)
|
if( comment >= 0 )
|
||||||
line = line.Substring(0, comment);
|
line = line.Substring( 0, comment );
|
||||||
|
|
||||||
int eq = line.IndexOf('=');
|
line = line.Trim();
|
||||||
if (eq < 0)
|
if( line.Length == 0 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (currentSection == null)
|
var key = line;
|
||||||
throw new InvalidOperationException("No current INI section");
|
var value = "";
|
||||||
|
int eq = line.IndexOf( '=' );
|
||||||
|
if( eq >= 0 )
|
||||||
|
{
|
||||||
|
key = line.Substring( 0, eq );
|
||||||
|
value = line.Substring( eq + 1, line.Length - eq - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
currentSection.Add(line.Substring(0, eq),
|
if( currentSection == null )
|
||||||
line.Substring(eq + 1, line.Length - eq - 1));
|
throw new InvalidOperationException( "No current INI section" );
|
||||||
|
|
||||||
|
if( !currentSection.Contains( key ) )
|
||||||
|
currentSection.Add( key, value );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IniSection GetSection( string s )
|
public IniSection GetSection( string s )
|
||||||
|
{
|
||||||
|
return GetSection( s, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IniSection GetSection( string s, bool allowFail )
|
||||||
{
|
{
|
||||||
IniSection section;
|
IniSection section;
|
||||||
sections.TryGetValue( s, out section );
|
if( sections.TryGetValue( s.ToLowerInvariant(), out section ) )
|
||||||
return section;
|
return section;
|
||||||
|
|
||||||
|
if( allowFail )
|
||||||
|
return new IniSection( s );
|
||||||
|
throw new InvalidOperationException( "Section does not exist in map or rules: " + s );
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IniSection> Sections { get { return sections.Values; } }
|
public IEnumerable<IniSection> Sections { get { return sections.Values; } }
|
||||||
@@ -89,6 +118,11 @@ namespace OpenRa.FileFormats
|
|||||||
values[key] = value;
|
values[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Contains( string key )
|
||||||
|
{
|
||||||
|
return values.ContainsKey( key );
|
||||||
|
}
|
||||||
|
|
||||||
public string GetValue( string key, string defaultValue )
|
public string GetValue( string key, string defaultValue )
|
||||||
{
|
{
|
||||||
string s;
|
string s;
|
||||||
|
|||||||
@@ -117,6 +117,10 @@ namespace OpenRa.Game
|
|||||||
traits.Add(new Traits.RenderBuildingOre(this));
|
traits.Add(new Traits.RenderBuildingOre(this));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "fcom":
|
||||||
|
traits.Add( new Traits.Building( this ) );
|
||||||
|
traits.Add( new Traits.RenderBuilding( this ) );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException( "Actor traits for " + name );
|
throw new NotImplementedException( "Actor traits for " + name );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,12 +34,13 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
public Game(string mapName, Renderer renderer, int2 clientSize)
|
public Game(string mapName, Renderer renderer, int2 clientSize)
|
||||||
{
|
{
|
||||||
Rules.LoadRules();
|
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.Soviet));
|
||||||
|
|
||||||
map = new Map(new IniFile(FileSystem.Open(mapName)));
|
var mapFile = new IniFile( FileSystem.Open( mapName ) );
|
||||||
|
map = new Map( mapFile );
|
||||||
FileSystem.Mount(new Package(map.Theater + ".mix"));
|
FileSystem.Mount(new Package(map.Theater + ".mix"));
|
||||||
|
|
||||||
viewport = new Viewport(clientSize, map.Size, renderer);
|
viewport = new Viewport(clientSize, map.Size, renderer);
|
||||||
@@ -51,6 +52,9 @@ namespace OpenRa.Game
|
|||||||
foreach( TreeReference treeReference in map.Trees )
|
foreach( TreeReference treeReference in map.Trees )
|
||||||
world.Add( new Actor( treeReference, treeCache, map.Offset ) );
|
world.Add( new Actor( treeReference, treeCache, map.Offset ) );
|
||||||
|
|
||||||
|
LoadMapBuildings( mapFile );
|
||||||
|
LoadMapUnits( mapFile );
|
||||||
|
|
||||||
LocalPlayerBuildings = new BuildingInfluenceMap(world, LocalPlayer);
|
LocalPlayerBuildings = new BuildingInfluenceMap(world, LocalPlayer);
|
||||||
|
|
||||||
pathFinder = new PathFinder(map, terrain.tileSet, LocalPlayerBuildings);
|
pathFinder = new PathFinder(map, terrain.tileSet, LocalPlayerBuildings);
|
||||||
@@ -66,6 +70,28 @@ namespace OpenRa.Game
|
|||||||
PlaySound("intro.aud", false);
|
PlaySound("intro.aud", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoadMapBuildings( IniFile mapfile )
|
||||||
|
{
|
||||||
|
foreach( var s in mapfile.GetSection( "STRUCTURES", true ) )
|
||||||
|
{
|
||||||
|
//num=owner,type,health,location,facing,trigger,unknown,shouldRepair
|
||||||
|
var parts = s.Value.ToLowerInvariant().Split( ',' );
|
||||||
|
var loc = int.Parse( parts[ 3 ] );
|
||||||
|
world.Add( new Actor( parts[ 1 ], new int2( loc % 128 - map.Offset.X, loc / 128-map.Offset.Y ), players[ 0 ] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadMapUnits( IniFile mapfile )
|
||||||
|
{
|
||||||
|
foreach( var s in mapfile.GetSection( "UNITS", true ) )
|
||||||
|
{
|
||||||
|
//num=owner,type,health,location,facing,action,trigger
|
||||||
|
var parts = s.Value.ToLowerInvariant().Split( ',' );
|
||||||
|
var loc = int.Parse( parts[ 3 ] );
|
||||||
|
world.Add( new Actor( parts[ 1 ], new int2( loc % 128 - map.Offset.X, loc / 128 - map.Offset.Y ), players[ 0 ] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
readonly Cache<string, ISoundSource> sounds;
|
readonly Cache<string, ISoundSource> sounds;
|
||||||
|
|
||||||
ISoundSource LoadSound(string filename)
|
ISoundSource LoadSound(string filename)
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ namespace OpenRa.Game.GameRules
|
|||||||
{
|
{
|
||||||
readonly Dictionary<string, T> infos = new Dictionary<string, T>();
|
readonly Dictionary<string, T> infos = new Dictionary<string, T>();
|
||||||
|
|
||||||
public InfoLoader(IniFile rules, params Pair<string, Func<string,T>>[] srcs)
|
public InfoLoader(params Pair<string, Func<string,T>>[] srcs)
|
||||||
{
|
{
|
||||||
foreach (var src in srcs)
|
foreach (var src in srcs)
|
||||||
foreach (var s in Util.ReadAllLines(FileSystem.Open(src.First)))
|
foreach (var s in Rules.AllRules.GetSection(src.First))
|
||||||
{
|
{
|
||||||
var name = s.Split(',')[0];
|
var name = s.Key.ToLowerInvariant();
|
||||||
var t = src.Second(name.ToLowerInvariant());
|
var t = src.Second(name);
|
||||||
FieldLoader.Load(t, rules.GetSection(name));
|
FieldLoader.Load(t, Rules.AllRules.GetSection(name));
|
||||||
infos[name.ToLowerInvariant()] = t;
|
infos[name] = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,5 +28,10 @@ namespace OpenRa.Game.GameRules
|
|||||||
{
|
{
|
||||||
get { return infos[name.ToLowerInvariant()]; }
|
get { return infos[name.ToLowerInvariant()]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
|
||||||
|
{
|
||||||
|
return infos.GetEnumerator();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,29 +9,35 @@ namespace OpenRa.Game
|
|||||||
{
|
{
|
||||||
static class Rules
|
static class Rules
|
||||||
{
|
{
|
||||||
|
public static IniFile AllRules;
|
||||||
public static InfoLoader<UnitInfo> UnitInfo;
|
public static InfoLoader<UnitInfo> UnitInfo;
|
||||||
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 Footprint Footprint;
|
public static Footprint Footprint;
|
||||||
|
|
||||||
// TODO: load rules from the map, where appropriate.
|
public static void LoadRules( string mapFileName )
|
||||||
public static void LoadRules()
|
|
||||||
{
|
{
|
||||||
var rulesIni = new IniFile(FileSystem.Open("rules.ini"));
|
AllRules = new IniFile(
|
||||||
|
FileSystem.Open( mapFileName ),
|
||||||
|
FileSystem.Open( "rules.ini" ),
|
||||||
|
FileSystem.Open( "units.ini" ),
|
||||||
|
FileSystem.Open( "campaignUnits.ini" ) );
|
||||||
|
|
||||||
UnitInfo = new InfoLoader<UnitInfo>(rulesIni,
|
UnitInfo = new InfoLoader<UnitInfo>(
|
||||||
Pair.New<string,Func<string,UnitInfo>>( "buildings.txt", s => new UnitInfo.BuildingInfo(s)),
|
Pair.New<string,Func<string,UnitInfo>>( "BuildingTypes", s => new UnitInfo.BuildingInfo(s)),
|
||||||
Pair.New<string, Func<string,UnitInfo>>("infantry.txt", s => new UnitInfo.InfantryInfo(s)),
|
Pair.New<string,Func<string,UnitInfo>>( "InfantryTypes", s => new UnitInfo.InfantryInfo(s)),
|
||||||
Pair.New<string,Func<string,UnitInfo>>( "vehicles.txt", s => new UnitInfo.VehicleInfo(s)));
|
Pair.New<string,Func<string,UnitInfo>>( "VehicleTypes", s => new UnitInfo.VehicleInfo(s)),
|
||||||
|
Pair.New<string,Func<string,UnitInfo>>( "ShipTypes", s => new UnitInfo.VehicleInfo(s)),
|
||||||
|
Pair.New<string,Func<string,UnitInfo>>( "PlaneTypes", s => new UnitInfo.VehicleInfo(s)));
|
||||||
|
|
||||||
WeaponInfo = new InfoLoader<WeaponInfo>(rulesIni,
|
WeaponInfo = new InfoLoader<WeaponInfo>(
|
||||||
Pair.New<string,Func<string,WeaponInfo>>("weapons.txt", _ => new WeaponInfo()));
|
Pair.New<string,Func<string,WeaponInfo>>("WeaponTypes", _ => new WeaponInfo()));
|
||||||
WarheadInfo = new InfoLoader<WarheadInfo>(rulesIni,
|
WarheadInfo = new InfoLoader<WarheadInfo>(
|
||||||
Pair.New<string,Func<string,WarheadInfo>>("warheads.txt", _ => new WarheadInfo()));
|
Pair.New<string,Func<string,WarheadInfo>>("WarheadTypes", _ => new WarheadInfo()));
|
||||||
|
|
||||||
ProjectileInfo = new InfoLoader<ProjectileInfo>(rulesIni,
|
ProjectileInfo = new InfoLoader<ProjectileInfo>(
|
||||||
Pair.New<string, Func<string, ProjectileInfo>>("projectiles.txt", _ => new ProjectileInfo()));
|
Pair.New<string, Func<string, ProjectileInfo>>("ProjectileTypes", _ => new ProjectileInfo()));
|
||||||
|
|
||||||
Footprint = new Footprint(FileSystem.Open("footprint.txt"));
|
Footprint = new Footprint(FileSystem.Open("footprint.txt"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ namespace OpenRa.Game
|
|||||||
string key = line.Substring(0, line.IndexOf(','));
|
string key = line.Substring(0, line.IndexOf(','));
|
||||||
int secondComma = line.IndexOf(',', line.IndexOf(',') + 1);
|
int secondComma = line.IndexOf(',', line.IndexOf(',') + 1);
|
||||||
string group = line.Substring(secondComma + 1, line.Length - secondComma - 1);
|
string group = line.Substring(secondComma + 1, line.Length - secondComma - 1);
|
||||||
sprites.Add( key, SpriteSheetBuilder.LoadSprite( key + "icon", ".shp" ) );
|
|
||||||
|
if( Rules.UnitInfo[ key ].TechLevel != -1 )
|
||||||
|
sprites.Add( key, SpriteSheetBuilder.LoadSprite( key + "icon", ".shp" ) );
|
||||||
itemGroups.Add(key, group);
|
itemGroups.Add(key, group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ namespace OpenRa.TechTree
|
|||||||
|
|
||||||
static Tuple<string[],string[]> ParsePrerequisites(string prerequisites, string tag)
|
static Tuple<string[],string[]> ParsePrerequisites(string prerequisites, string tag)
|
||||||
{
|
{
|
||||||
Debug.WriteLine( tag );
|
|
||||||
List<string> allied = new List<string>(prerequisites.ToLowerInvariant().Split(
|
List<string> allied = new List<string>(prerequisites.ToLowerInvariant().Split(
|
||||||
new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
|
new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
|
||||||
|
|
||||||
|
|||||||
@@ -1,106 +1,103 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using OpenRa.FileFormats;
|
using OpenRa.FileFormats;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRa.Game;
|
using OpenRa.Game;
|
||||||
|
|
||||||
namespace OpenRa.TechTree
|
namespace OpenRa.TechTree
|
||||||
{
|
{
|
||||||
public class TechTree
|
public class TechTree
|
||||||
{
|
{
|
||||||
Dictionary<string, Item> objects = new Dictionary<string, Item>();
|
Dictionary<string, Item> objects = new Dictionary<string, Item>();
|
||||||
public ICollection<string> built = new List<string>();
|
public ICollection<string> built = new List<string>();
|
||||||
|
|
||||||
Race currentRace = Race.None;
|
Race currentRace = Race.None;
|
||||||
|
|
||||||
public Race CurrentRace
|
public Race CurrentRace
|
||||||
{
|
{
|
||||||
get { return currentRace; }
|
get { return currentRace; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
currentRace = value;
|
currentRace = value;
|
||||||
CheckAll();
|
CheckAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TechTree()
|
public TechTree()
|
||||||
{
|
{
|
||||||
LoadRules();
|
LoadRules();
|
||||||
CheckAll();
|
CheckAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Tuple<string, string, bool>> Lines(string filename, bool param)
|
IEnumerable<Tuple<string, string, bool>> Lines(string filename, bool param)
|
||||||
{
|
{
|
||||||
Regex pattern = new Regex(@"^(\w+),([\w ]+),(\w+)$");
|
Regex pattern = new Regex(@"^(\w+),([\w ]+),(\w+)$");
|
||||||
foreach (string s in File.ReadAllLines("../../../../" + filename))
|
foreach (string s in File.ReadAllLines("../../../../" + filename))
|
||||||
{
|
{
|
||||||
Match m = pattern.Match(s);
|
Match m = pattern.Match(s);
|
||||||
if (m == null || !m.Success)
|
if (m == null || !m.Success)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
yield return new Tuple<string, string, bool>(
|
yield return new Tuple<string, string, bool>(
|
||||||
m.Groups[1].Value, m.Groups[2].Value, param);
|
m.Groups[1].Value, m.Groups[2].Value, param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadRules()
|
void LoadRules()
|
||||||
{
|
{
|
||||||
IEnumerable<Tuple<string, string, bool>> definitions =
|
var allBuildings = Rules.AllRules.GetSection( "BuildingTypes" ).Select( x => x.Key.ToLowerInvariant() ).ToList();
|
||||||
Lines("buildings.txt", true)
|
|
||||||
.Concat( Lines( "vehicles.txt", false ) )
|
foreach( var unit in Rules.UnitInfo )
|
||||||
.Concat( Lines( "infantry.txt", false ) );
|
objects.Add( unit.Key, new Item( unit.Key, unit.Value, allBuildings.Contains( unit.Key ) ) );
|
||||||
|
}
|
||||||
foreach (Tuple<string, string, bool> p in definitions)
|
|
||||||
objects.Add(p.a.ToLowerInvariant(), new Item(p.a.ToLowerInvariant(), Rules.UnitInfo[p.a.ToLowerInvariant()], p.c));
|
public bool Build(string key, bool force)
|
||||||
}
|
{
|
||||||
|
if( string.IsNullOrEmpty( key ) ) return false;
|
||||||
public bool Build(string key, bool force)
|
key = key.ToLowerInvariant();
|
||||||
{
|
Item b = objects[ key ];
|
||||||
if( string.IsNullOrEmpty( key ) ) return false;
|
if (!force && !b.CanBuild) return false;
|
||||||
key = key.ToLowerInvariant();
|
built.Add(key);
|
||||||
Item b = objects[ key ];
|
CheckAll();
|
||||||
if (!force && !b.CanBuild) return false;
|
return true;
|
||||||
built.Add(key);
|
}
|
||||||
CheckAll();
|
|
||||||
return true;
|
public bool Build(string key)
|
||||||
}
|
{
|
||||||
|
return Build(key, false);
|
||||||
public bool Build(string key)
|
}
|
||||||
{
|
|
||||||
return Build(key, false);
|
public bool Unbuild(string key)
|
||||||
}
|
{
|
||||||
|
key = key.ToLowerInvariant();
|
||||||
public bool Unbuild(string key)
|
Item b = objects[key];
|
||||||
{
|
if (!built.Contains(key)) return false;
|
||||||
key = key.ToLowerInvariant();
|
built.Remove(key);
|
||||||
Item b = objects[key];
|
CheckAll();
|
||||||
if (!built.Contains(key)) return false;
|
return true;
|
||||||
built.Remove(key);
|
}
|
||||||
CheckAll();
|
|
||||||
return true;
|
void CheckAll()
|
||||||
}
|
{
|
||||||
|
foreach (Item unit in objects.Values)
|
||||||
void CheckAll()
|
unit.CheckPrerequisites(built, currentRace);
|
||||||
{
|
|
||||||
foreach (Item unit in objects.Values)
|
BuildableItemsChanged();
|
||||||
unit.CheckPrerequisites(built, currentRace);
|
}
|
||||||
|
|
||||||
BuildableItemsChanged();
|
public IEnumerable<Item> BuildableItems
|
||||||
}
|
{
|
||||||
|
get
|
||||||
public IEnumerable<Item> BuildableItems
|
{
|
||||||
{
|
foreach (Item b in objects.Values)
|
||||||
get
|
if (b.CanBuild)
|
||||||
{
|
yield return b;
|
||||||
foreach (Item b in objects.Values)
|
}
|
||||||
if (b.CanBuild)
|
}
|
||||||
yield return b;
|
|
||||||
}
|
public event Action BuildableItemsChanged = () => { };
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public event Action BuildableItemsChanged = () => { };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -34,3 +34,5 @@ WEAF,Fake War Factory,building
|
|||||||
SYRF,Fake Shipyard,building
|
SYRF,Fake Shipyard,building
|
||||||
SPEF,Fake Sub Pen,building
|
SPEF,Fake Sub Pen,building
|
||||||
DOMF,Fake Radar Dome,building
|
DOMF,Fake Radar Dome,building
|
||||||
|
FCOM,Forward Command Post,building
|
||||||
|
|
||||||
|
|||||||
6
campaignUnits.ini
Executable file
6
campaignUnits.ini
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
[BuildingTypes]
|
||||||
|
FCOM
|
||||||
|
|
||||||
|
[FCOM]
|
||||||
|
Description=Forward Command Post
|
||||||
|
|
||||||
@@ -30,6 +30,13 @@
|
|||||||
|
|
||||||
<sequences>
|
<sequences>
|
||||||
|
|
||||||
|
<!-- forward command post (campaign specific building) -->
|
||||||
|
<unit name="fcom">
|
||||||
|
<sequence name="idle" start="0"/>
|
||||||
|
<sequence name="damaged-idle" start="1"/>
|
||||||
|
<sequence name="make" start="0"/>
|
||||||
|
</unit>
|
||||||
|
|
||||||
<!-- construction yard -->
|
<!-- construction yard -->
|
||||||
<unit name="fact">
|
<unit name="fact">
|
||||||
<sequence name="idle" start="0"/>
|
<sequence name="idle" start="0"/>
|
||||||
|
|||||||
320
units.ini
Executable file
320
units.ini
Executable file
@@ -0,0 +1,320 @@
|
|||||||
|
[VehicleTypes]
|
||||||
|
V2RL
|
||||||
|
1TNK
|
||||||
|
2TNK
|
||||||
|
3TNK
|
||||||
|
4TNK
|
||||||
|
MRJ
|
||||||
|
MGG
|
||||||
|
ARTY
|
||||||
|
HARV
|
||||||
|
MCV
|
||||||
|
JEEP
|
||||||
|
APC
|
||||||
|
MNLY
|
||||||
|
|
||||||
|
[V2RL]
|
||||||
|
Description=V2 Rocket
|
||||||
|
[1TNK]
|
||||||
|
Description=Light Tank
|
||||||
|
[2TNK]
|
||||||
|
Description=Medium Tank
|
||||||
|
[3TNK]
|
||||||
|
Description=Heavy Tank
|
||||||
|
[4TNK]
|
||||||
|
Description=Mammoth Tank
|
||||||
|
[MRJ]
|
||||||
|
Description=Radar Jammer
|
||||||
|
[MGG]
|
||||||
|
Description=Mobile Gap Generator
|
||||||
|
[ARTY]
|
||||||
|
Description=Artillery
|
||||||
|
[HARV]
|
||||||
|
Description=Ore Truck
|
||||||
|
[MCV]
|
||||||
|
Description=Mobile Construction Vehicle
|
||||||
|
[JEEP]
|
||||||
|
Description=Ranger
|
||||||
|
[APC]
|
||||||
|
Description=Armored Personnel Carrier
|
||||||
|
[MNLY]
|
||||||
|
Description=Minelayer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[ShipTypes]
|
||||||
|
SS
|
||||||
|
DD
|
||||||
|
CA
|
||||||
|
LST
|
||||||
|
PT
|
||||||
|
|
||||||
|
[SS]
|
||||||
|
Description=Submarine
|
||||||
|
[DD]
|
||||||
|
Description=Destroyer
|
||||||
|
[CA]
|
||||||
|
Description=Cruiser
|
||||||
|
[LST]
|
||||||
|
Description=Transport
|
||||||
|
[PT]
|
||||||
|
Description=Gunboat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[PlaneTypes]
|
||||||
|
MIG
|
||||||
|
YAK
|
||||||
|
TRAN
|
||||||
|
HELI
|
||||||
|
HIND
|
||||||
|
; TODO:
|
||||||
|
; U2 (spyplane)
|
||||||
|
; BADR (paratrooper/paradrop plane)
|
||||||
|
|
||||||
|
[MIG]
|
||||||
|
Description=Mig Attack Plane
|
||||||
|
[YAK]
|
||||||
|
Description=Yak Attack Plane
|
||||||
|
[TRAN]
|
||||||
|
Description=Transport Helicopter
|
||||||
|
[HELI]
|
||||||
|
Description=Longbow
|
||||||
|
[HIND]
|
||||||
|
Description=Hind
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[BuildingTypes]
|
||||||
|
IRON
|
||||||
|
ATEK
|
||||||
|
PDOX
|
||||||
|
WEAP
|
||||||
|
SYRD
|
||||||
|
SPEN
|
||||||
|
PBOX
|
||||||
|
HBOX
|
||||||
|
TSLA
|
||||||
|
GUN
|
||||||
|
AGUN
|
||||||
|
FTUR
|
||||||
|
FACT
|
||||||
|
PROC
|
||||||
|
SILO
|
||||||
|
HPAD
|
||||||
|
DOME
|
||||||
|
GAP
|
||||||
|
SAM
|
||||||
|
MSLO
|
||||||
|
AFLD
|
||||||
|
POWR
|
||||||
|
APWR
|
||||||
|
STEK
|
||||||
|
BARR
|
||||||
|
TENT
|
||||||
|
KENN
|
||||||
|
FIX
|
||||||
|
SBAG
|
||||||
|
BRIK
|
||||||
|
FENC
|
||||||
|
FACF
|
||||||
|
WEAF
|
||||||
|
SYRF
|
||||||
|
SPEF
|
||||||
|
DOMF
|
||||||
|
; TODO? : campaign-specific stuff - FCOM, civilian buildings, etc
|
||||||
|
|
||||||
|
[IRON]
|
||||||
|
Description=Iron Curtain
|
||||||
|
[ATEK]
|
||||||
|
Description=Allied Tech Center
|
||||||
|
[PDOX]
|
||||||
|
Description=Chronosphere
|
||||||
|
[WEAP]
|
||||||
|
Description=War Factory
|
||||||
|
[SYRD]
|
||||||
|
Description=Shipyard
|
||||||
|
[SPEN]
|
||||||
|
Description=Sub Pen
|
||||||
|
[PBOX]
|
||||||
|
Description=Pillbox
|
||||||
|
[HBOX]
|
||||||
|
Description=Camo Pillbox
|
||||||
|
[TSLA]
|
||||||
|
Description=Tesla Coil
|
||||||
|
[GUN]
|
||||||
|
Description=Turret
|
||||||
|
[AGUN]
|
||||||
|
Description=AA Gun
|
||||||
|
[FTUR]
|
||||||
|
Description=Flame Turret
|
||||||
|
[FACT]
|
||||||
|
Description=Construction Yard
|
||||||
|
[PROC]
|
||||||
|
Description=Ore Refinery
|
||||||
|
[SILO]
|
||||||
|
Description=Silo
|
||||||
|
[HPAD]
|
||||||
|
Description=Helipad
|
||||||
|
[DOME]
|
||||||
|
Description=Radar Dome
|
||||||
|
[GAP]
|
||||||
|
Description=Gap Generator
|
||||||
|
[SAM]
|
||||||
|
Description=SAM Site
|
||||||
|
[MSLO]
|
||||||
|
Description=Missile Silo
|
||||||
|
[AFLD]
|
||||||
|
Description=Airstrip
|
||||||
|
[POWR]
|
||||||
|
Description=Power Plant
|
||||||
|
[APWR]
|
||||||
|
Description=Advanced Power Plant
|
||||||
|
[STEK]
|
||||||
|
Description=Soviet Tech Center
|
||||||
|
[BARR]
|
||||||
|
Description=Soviet Barracks
|
||||||
|
[TENT]
|
||||||
|
Description=Allied Barracks
|
||||||
|
[KENN]
|
||||||
|
Description=Kennel
|
||||||
|
[FIX]
|
||||||
|
Description=Service Depot
|
||||||
|
[SBAG]
|
||||||
|
Description=Sandbags
|
||||||
|
[BRIK]
|
||||||
|
Description=Concrete Wall
|
||||||
|
[FENC]
|
||||||
|
Description=Wire Fence
|
||||||
|
[FACF]
|
||||||
|
Description=Fake Construction Yard
|
||||||
|
[WEAF]
|
||||||
|
Description=Fake War Factory
|
||||||
|
[SYRF]
|
||||||
|
Description=Fake Shipyard
|
||||||
|
[SPEF]
|
||||||
|
Description=Fake Sub Pen
|
||||||
|
[DOMF]
|
||||||
|
Description=Fake Radar Dome
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[InfantryTypes]
|
||||||
|
DOG
|
||||||
|
E1
|
||||||
|
E2
|
||||||
|
E3
|
||||||
|
E4
|
||||||
|
E6
|
||||||
|
SPY
|
||||||
|
THF
|
||||||
|
E7
|
||||||
|
MEDI
|
||||||
|
|
||||||
|
[DOG]
|
||||||
|
Description=Attack Dog
|
||||||
|
[E1]
|
||||||
|
Description=Rifle Infantry
|
||||||
|
[E2]
|
||||||
|
Description=Grenadier
|
||||||
|
[E3]
|
||||||
|
Description=Rocket Soldier
|
||||||
|
[E4]
|
||||||
|
Description=Flamethrower
|
||||||
|
[E6]
|
||||||
|
Description=Engineer
|
||||||
|
[SPY]
|
||||||
|
Description=Spy
|
||||||
|
[THF]
|
||||||
|
Description=Thief
|
||||||
|
[E7]
|
||||||
|
Description=Tanya
|
||||||
|
[MEDI]
|
||||||
|
Description=Medic
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[WeaponTypes]
|
||||||
|
Colt45
|
||||||
|
ZSU-23
|
||||||
|
Vulcan
|
||||||
|
Maverick
|
||||||
|
Camera
|
||||||
|
FireballLauncher
|
||||||
|
Flamer
|
||||||
|
Sniper
|
||||||
|
ChainGun
|
||||||
|
Pistol
|
||||||
|
M1Carbine
|
||||||
|
Dragon
|
||||||
|
Hellfire
|
||||||
|
Grenade
|
||||||
|
75mm
|
||||||
|
90mm
|
||||||
|
105mm
|
||||||
|
120mm
|
||||||
|
TurretGun
|
||||||
|
MammothTusk
|
||||||
|
155mm
|
||||||
|
M60mg
|
||||||
|
Napalm
|
||||||
|
TeslaZap
|
||||||
|
Nike
|
||||||
|
RedEye
|
||||||
|
8Inch
|
||||||
|
Stinger
|
||||||
|
TorpTube
|
||||||
|
2Inch
|
||||||
|
DepthCharge
|
||||||
|
ParaBomb
|
||||||
|
DogJaw
|
||||||
|
Heal
|
||||||
|
SCUD
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[ProjectileTypes]
|
||||||
|
Invisible
|
||||||
|
LeapDog
|
||||||
|
Cannon
|
||||||
|
Ack
|
||||||
|
Torpedo
|
||||||
|
FROG
|
||||||
|
HeatSeeker
|
||||||
|
LaserGuided
|
||||||
|
AAMissile
|
||||||
|
Lobbed
|
||||||
|
Catapult
|
||||||
|
Bomblet
|
||||||
|
Ballistic
|
||||||
|
Parachute
|
||||||
|
GPSSatellite
|
||||||
|
NukeUp
|
||||||
|
NukeDown
|
||||||
|
Fireball
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[WarheadTypes]
|
||||||
|
SA
|
||||||
|
HE
|
||||||
|
AP
|
||||||
|
Fire
|
||||||
|
HollowPoint
|
||||||
|
Super
|
||||||
|
Organic
|
||||||
|
Nuke
|
||||||
Reference in New Issue
Block a user