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:
Bob
2009-10-20 17:16:45 +13:00
parent a59265a661
commit 6dec94d00e
12 changed files with 564 additions and 156 deletions

View File

@@ -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 );
}

View File

@@ -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)

View File

@@ -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();
}
}
}

View File

@@ -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"));
}

View File

@@ -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);
}
}

View File

@@ -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));

View File

@@ -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 = () => { };
}
}