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:
@@ -117,6 +117,10 @@ namespace OpenRa.Game
|
||||
traits.Add(new Traits.RenderBuildingOre(this));
|
||||
break;
|
||||
|
||||
case "fcom":
|
||||
traits.Add( new Traits.Building( this ) );
|
||||
traits.Add( new Traits.RenderBuilding( this ) );
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException( "Actor traits for " + name );
|
||||
}
|
||||
|
||||
@@ -34,12 +34,13 @@ namespace OpenRa.Game
|
||||
|
||||
public Game(string mapName, Renderer renderer, int2 clientSize)
|
||||
{
|
||||
Rules.LoadRules();
|
||||
Rules.LoadRules( mapName );
|
||||
|
||||
for( int i = 0 ; i < 8 ; i++ )
|
||||
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"));
|
||||
|
||||
viewport = new Viewport(clientSize, map.Size, renderer);
|
||||
@@ -51,6 +52,9 @@ namespace OpenRa.Game
|
||||
foreach( TreeReference treeReference in map.Trees )
|
||||
world.Add( new Actor( treeReference, treeCache, map.Offset ) );
|
||||
|
||||
LoadMapBuildings( mapFile );
|
||||
LoadMapUnits( mapFile );
|
||||
|
||||
LocalPlayerBuildings = new BuildingInfluenceMap(world, LocalPlayer);
|
||||
|
||||
pathFinder = new PathFinder(map, terrain.tileSet, LocalPlayerBuildings);
|
||||
@@ -66,6 +70,28 @@ namespace OpenRa.Game
|
||||
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;
|
||||
|
||||
ISoundSource LoadSound(string filename)
|
||||
|
||||
@@ -12,15 +12,15 @@ namespace OpenRa.Game.GameRules
|
||||
{
|
||||
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 s in Util.ReadAllLines(FileSystem.Open(src.First)))
|
||||
foreach (var s in Rules.AllRules.GetSection(src.First))
|
||||
{
|
||||
var name = s.Split(',')[0];
|
||||
var t = src.Second(name.ToLowerInvariant());
|
||||
FieldLoader.Load(t, rules.GetSection(name));
|
||||
infos[name.ToLowerInvariant()] = t;
|
||||
var name = s.Key.ToLowerInvariant();
|
||||
var t = src.Second(name);
|
||||
FieldLoader.Load(t, Rules.AllRules.GetSection(name));
|
||||
infos[name] = t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,5 +28,10 @@ namespace OpenRa.Game.GameRules
|
||||
{
|
||||
get { return infos[name.ToLowerInvariant()]; }
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
|
||||
{
|
||||
return infos.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,29 +9,35 @@ namespace OpenRa.Game
|
||||
{
|
||||
static class Rules
|
||||
{
|
||||
public static IniFile AllRules;
|
||||
public static InfoLoader<UnitInfo> UnitInfo;
|
||||
public static InfoLoader<WeaponInfo> WeaponInfo;
|
||||
public static InfoLoader<WarheadInfo> WarheadInfo;
|
||||
public static InfoLoader<ProjectileInfo> ProjectileInfo;
|
||||
public static Footprint Footprint;
|
||||
|
||||
// TODO: load rules from the map, where appropriate.
|
||||
public static void LoadRules()
|
||||
public static void LoadRules( string mapFileName )
|
||||
{
|
||||
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,
|
||||
Pair.New<string,Func<string,UnitInfo>>( "buildings.txt", s => new UnitInfo.BuildingInfo(s)),
|
||||
Pair.New<string, Func<string,UnitInfo>>("infantry.txt", s => new UnitInfo.InfantryInfo(s)),
|
||||
Pair.New<string,Func<string,UnitInfo>>( "vehicles.txt", s => new UnitInfo.VehicleInfo(s)));
|
||||
UnitInfo = new InfoLoader<UnitInfo>(
|
||||
Pair.New<string,Func<string,UnitInfo>>( "BuildingTypes", s => new UnitInfo.BuildingInfo(s)),
|
||||
Pair.New<string,Func<string,UnitInfo>>( "InfantryTypes", s => new UnitInfo.InfantryInfo(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,
|
||||
Pair.New<string,Func<string,WeaponInfo>>("weapons.txt", _ => new WeaponInfo()));
|
||||
WarheadInfo = new InfoLoader<WarheadInfo>(rulesIni,
|
||||
Pair.New<string,Func<string,WarheadInfo>>("warheads.txt", _ => new WarheadInfo()));
|
||||
WeaponInfo = new InfoLoader<WeaponInfo>(
|
||||
Pair.New<string,Func<string,WeaponInfo>>("WeaponTypes", _ => new WeaponInfo()));
|
||||
WarheadInfo = new InfoLoader<WarheadInfo>(
|
||||
Pair.New<string,Func<string,WarheadInfo>>("WarheadTypes", _ => new WarheadInfo()));
|
||||
|
||||
ProjectileInfo = new InfoLoader<ProjectileInfo>(rulesIni,
|
||||
Pair.New<string, Func<string, ProjectileInfo>>("projectiles.txt", _ => new ProjectileInfo()));
|
||||
ProjectileInfo = new InfoLoader<ProjectileInfo>(
|
||||
Pair.New<string, Func<string, ProjectileInfo>>("ProjectileTypes", _ => new ProjectileInfo()));
|
||||
|
||||
Footprint = new Footprint(FileSystem.Open("footprint.txt"));
|
||||
}
|
||||
|
||||
@@ -72,7 +72,9 @@ namespace OpenRa.Game
|
||||
string key = line.Substring(0, line.IndexOf(','));
|
||||
int secondComma = line.IndexOf(',', line.IndexOf(',') + 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ namespace OpenRa.TechTree
|
||||
|
||||
static Tuple<string[],string[]> ParsePrerequisites(string prerequisites, string tag)
|
||||
{
|
||||
Debug.WriteLine( tag );
|
||||
List<string> allied = new List<string>(prerequisites.ToLowerInvariant().Split(
|
||||
new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
|
||||
|
||||
|
||||
@@ -1,106 +1,103 @@
|
||||
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();
|
||||
}
|
||||
|
||||
IEnumerable<Tuple<string, string, bool>> Lines(string filename, bool param)
|
||||
{
|
||||
Regex pattern = new Regex(@"^(\w+),([\w ]+),(\w+)$");
|
||||
foreach (string s in File.ReadAllLines("../../../../" + filename))
|
||||
{
|
||||
Match m = pattern.Match(s);
|
||||
if (m == null || !m.Success)
|
||||
continue;
|
||||
|
||||
yield return new Tuple<string, string, bool>(
|
||||
m.Groups[1].Value, m.Groups[2].Value, param);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadRules()
|
||||
{
|
||||
IEnumerable<Tuple<string, string, bool>> definitions =
|
||||
Lines("buildings.txt", true)
|
||||
.Concat( Lines( "vehicles.txt", false ) )
|
||||
.Concat( Lines( "infantry.txt", false ) );
|
||||
|
||||
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;
|
||||
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
|
||||
{
|
||||
foreach (Item b in objects.Values)
|
||||
if (b.CanBuild)
|
||||
yield return b;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action BuildableItemsChanged = () => { };
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
IEnumerable<Tuple<string, string, bool>> Lines(string filename, bool param)
|
||||
{
|
||||
Regex pattern = new Regex(@"^(\w+),([\w ]+),(\w+)$");
|
||||
foreach (string s in File.ReadAllLines("../../../../" + filename))
|
||||
{
|
||||
Match m = pattern.Match(s);
|
||||
if (m == null || !m.Success)
|
||||
continue;
|
||||
|
||||
yield return new Tuple<string, string, bool>(
|
||||
m.Groups[1].Value, m.Groups[2].Value, param);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadRules()
|
||||
{
|
||||
var allBuildings = Rules.AllRules.GetSection( "BuildingTypes" ).Select( x => x.Key.ToLowerInvariant() ).ToList();
|
||||
|
||||
foreach( var unit in Rules.UnitInfo )
|
||||
objects.Add( unit.Key, new Item( unit.Key, unit.Value, allBuildings.Contains( unit.Key ) ) );
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
foreach (Item b in objects.Values)
|
||||
if (b.CanBuild)
|
||||
yield return b;
|
||||
}
|
||||
}
|
||||
|
||||
public event Action BuildableItemsChanged = () => { };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user