Upgrades to House handling

* Added code to filter out special houses (e.g. "None") by HouseTypeFlag rather than using hardcoded exceptions.
* Added code to fix the PlayerSettings control scrolling past the first selected alliance.
* Alliances mask now uses specific list for alliance-houses, which is filtered and sorted to potentially include special houses.
* PropertyTracker now has a function to retrieve data inside it in the requested type.
* Houses are now always saved with their own house name in their alliances list.
* Sole Survivor maps with all multi-Houses enabled will now have all those beyond Multi4 disabled on map load, to limit needlessly expanding the ini.
This commit is contained in:
Nyerguds 2023-12-10 17:01:11 +01:00
parent c52f39d3d1
commit 93e70f5dc7
15 changed files with 336 additions and 192 deletions

View File

@ -43,6 +43,7 @@ namespace MobiusEditor.Controls
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.playerControlLbl = new System.Windows.Forms.Label();
this.iqNud = new MobiusEditor.Controls.EnhNumericUpDown();
this.techLevelNud = new MobiusEditor.Controls.EnhNumericUpDown();
this.maxVesselsNud = new MobiusEditor.Controls.EnhNumericUpDown();
@ -61,7 +62,6 @@ namespace MobiusEditor.Controls
this.maxUnitsNud = new MobiusEditor.Controls.EnhNumericUpDown();
this.label5 = new System.Windows.Forms.Label();
this.playersListBox = new System.Windows.Forms.ListBox();
this.playerControlLbl = new System.Windows.Forms.Label();
this.playerControlCheckBox = new System.Windows.Forms.CheckBox();
this.tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.iqNud)).BeginInit();
@ -116,6 +116,15 @@ namespace MobiusEditor.Controls
this.tableLayoutPanel1.Size = new System.Drawing.Size(329, 372);
this.tableLayoutPanel1.TabIndex = 2;
//
// playerControlLbl
//
this.playerControlLbl.AutoSize = true;
this.playerControlLbl.Location = new System.Drawing.Point(3, 209);
this.playerControlLbl.Name = "playerControlLbl";
this.playerControlLbl.Size = new System.Drawing.Size(72, 13);
this.playerControlLbl.TabIndex = 27;
this.playerControlLbl.Text = "Player Control";
//
// iqNud
//
this.iqNud.Dock = System.Windows.Forms.DockStyle.Fill;
@ -307,15 +316,7 @@ namespace MobiusEditor.Controls
this.playersListBox.SelectionMode = System.Windows.Forms.SelectionMode.MultiSimple;
this.playersListBox.Size = new System.Drawing.Size(100, 134);
this.playersListBox.TabIndex = 18;
//
// playerControlLbl
//
this.playerControlLbl.AutoSize = true;
this.playerControlLbl.Location = new System.Drawing.Point(3, 209);
this.playerControlLbl.Name = "playerControlLbl";
this.playerControlLbl.Size = new System.Drawing.Size(72, 13);
this.playerControlLbl.TabIndex = 27;
this.playerControlLbl.Text = "Player Control";
this.playersListBox.Resize += new System.EventHandler(this.playersListBox_Resize);
//
// playerControlCheckBox
//

View File

@ -17,7 +17,6 @@ using MobiusEditor.Model;
using MobiusEditor.Utility;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
@ -26,18 +25,16 @@ namespace MobiusEditor.Controls
public partial class PlayerSettings : UserControl
{
private readonly PropertyTracker<House> houseSettingsTracker;
private readonly dynamic house;
IGamePlugin plugin;
private bool initDone = false;
public PlayerSettings(IGamePlugin plugin, PropertyTracker<House> houseSettingsTracker)
{
this.plugin = plugin;
this.houseSettingsTracker = houseSettingsTracker;
house = houseSettingsTracker;
InitializeComponent();
edgeComboBox.Items.Clear();
edgeComboBox.Items.AddRange(Globals.MapEdges.ToArray());
creditsNud.DataBindings.Add("Value", houseSettingsTracker, "Credits");
maxBuildingsNud.DataBindings.Add("Value", houseSettingsTracker, "MaxBuilding");
maxUnitsNud.DataBindings.Add("Value", houseSettingsTracker, "MaxUnit");
@ -61,27 +58,66 @@ namespace MobiusEditor.Controls
playerControlCheckBox.DataBindings.Add("Checked", houseSettingsTracker, "PlayerControl");
break;
}
}
/// <summary>
/// Call this after the control is added, to ensure all resize and selecting weirdness is complete.
/// </summary>
public void InitAlliances()
{
playersListBox.BeginUpdate();
playersListBox.SelectedIndexChanged -= playersListBox_SelectedIndexChanged;
playersListBox.Items.Clear();
playersListBox.Items.AddRange(plugin.Map.Houses.Select(h => h.Type.Name).ToArray());
var selectedIndices = new List<int>();
foreach (var id in house.Allies)
ListItem<int>[] housesArray = plugin.Map.HousesForAlliances.Select(h => new ListItem<int>(h.Type.ID, h.Type.Name)).ToArray();
playersListBox.Items.AddRange(housesArray);
if (houseSettingsTracker.TryGetMember("Allies", out AlliesMask mask))
{
playersListBox.SetSelected(id, true);
foreach (var id in mask)
{
int index = ListItem.GetIndexInList(id, housesArray);
if (index != -1)
{
playersListBox.SetSelected(index, true);
}
}
}
initDone = true;
playersListBox_Resize(playersListBox, new EventArgs());
playersListBox.EndUpdate();
playersListBox.SelectedIndexChanged += playersListBox_SelectedIndexChanged;
}
private void playersListBox_SelectedIndexChanged(object sender, EventArgs e)
{
var allies = 0;
foreach (int selectedIndex in playersListBox.SelectedIndices)
foreach (ListItem<int> selectedItem in playersListBox.SelectedItems)
{
allies |= 1 << selectedIndex;
allies |= 1 << selectedItem.Value;
}
house.Allies = new AlliesMask(allies);
houseSettingsTracker.TrySetMember("Allies", new AlliesMask(allies));
}
private void playersListBox_Resize(Object sender, EventArgs e)
{
if (!initDone)
return;
int min = -1;
int max = -1;
foreach (int index in playersListBox.SelectedIndices)
{
min = min == -1 ? index : Math.Min(min, index);
max = max == -1 ? index : Math.Max(max, index);
}
if (min == -1 || max == -1)
{
playersListBox.TopIndex = 0;
return;
}
int diff = max - min + 1;
int items = (playersListBox.ClientRectangle.Height + (playersListBox.ItemHeight - 1)) / playersListBox.ItemHeight;
int itemDiff = (items - diff) / 2;
playersListBox.TopIndex = Math.Max(0, min - itemDiff);
playersListBox.Invalidate();
}
}
}

View File

@ -90,7 +90,7 @@ namespace MobiusEditor.Dialogs
{
if (e.PropertyName == "SoloMission")
{
if (basicSettingsTracker.TryGetMember("SoloMission", out object result) && (result is bool solo))
if (basicSettingsTracker.TryGetMember("SoloMission", out bool solo))
{
ResetSettingsTree(solo);
}
@ -187,6 +187,8 @@ namespace MobiusEditor.Dialogs
PlayerSettings playerPanel = new PlayerSettings(plugin, houseSettingsTrackers[player]);
settingsPanel.Controls.Add(playerPanel);
playerPanel.Dock = DockStyle.Fill;
// Needs special init because the alliances listbox's selection doesn't play nice when resizing as part of the docking.
playerPanel.InitAlliances();
}
break;
}

View File

@ -1722,11 +1722,13 @@ namespace MobiusEditor
if (loadInfo.Plugin == null || (loadInfo.Plugin != null && !loadInfo.MapLoaded))
{
// Attempted to load file, loading went OK, but map was not loaded.
#if NOT DEBUG
if (loadInfo.FileName != null && loadInfo.Plugin != null && !loadInfo.MapLoaded)
{
var fileInfo = new FileInfo(loadInfo.FileName);
mru.Remove(fileInfo);
}
#endif
// In case of actual error, remove label.
SimpleMultiThreading.RemoveBusyLabel(this);
MessageBox.Show(string.Format("Error loading {0}: {1}", loadInfo.FileName ?? "new map", String.Join("\n", errors)), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

View File

@ -101,19 +101,16 @@ namespace MobiusEditor.Model
{
return null;
}
var map = (context as MapContext).Map;
var alliesMask = (AlliesMask)value;
var allies = new List<string>(map.Houses.Length);
Map map = (context as MapContext).Map;
AlliesMask alliesMask = (AlliesMask)value;
List<string> allies = new List<string>(map.HousesForAlliances.Length);
foreach (var id in alliesMask)
{
if (map.Houses.Where(h => h.Type.Equals((sbyte)id)).FirstOrDefault() is House house)
if (map.HousesForAlliances.Where(h => h.Type.Equals((sbyte)id)).FirstOrDefault() is House house)
{
allies.Add(house.Type.Name);
}
}
return string.Join(",", allies);
}
@ -123,14 +120,12 @@ namespace MobiusEditor.Model
{
return null;
}
var map = (context as MapContext).Instance as Map;
var alliesMask = new AlliesMask(0);
var allies = (value as string).Split(',');
Map map = (context as MapContext).Instance as Map;
AlliesMask alliesMask = new AlliesMask(0);
string[] allies = (value as string).Split(',');
foreach (var ally in allies)
{
if (map.Houses.Where(h => h.Type.Equals(ally)).FirstOrDefault() is House house)
if (map.HousesForAlliances.Where(h => h.Type.Equals(ally)).FirstOrDefault() is House house)
{
alliesMask.Set(house.Type.ID);
}

View File

@ -18,6 +18,19 @@ using System.Linq;
namespace MobiusEditor.Model
{
[Flags]
public enum HouseTypeFlag
{
/// <summary>No flags set.</summary>
None /**/ = 0,
/// <summary>Is a special House, not used for normal lists.</summary>
Special /**/ = 1 << 1,
/// <summary>Is used for alliances.</summary>
ForAlliances /**/ = 1 << 2,
/// <summary>Special empty House, used if the plugin does not assign any House to unbuilt structures.</summary>
BaseHouse /**/ = 1 << 3,
}
public class HouseType
{
public int ID { get; private set; }
@ -30,34 +43,47 @@ namespace MobiusEditor.Model
public WaypointFlag MultiplayIdentifier { get; private set; }
public HouseTypeFlag Flags { get; private set; }
public IDictionary<string, string> OverrideTeamColors { get; private set; }
public HouseType(int id, string name, WaypointFlag multiplayIdentifier, string unitTeamColor, string buildingTeamColor, params (string type, string teamColor)[] overrideTeamColors)
public HouseType(int id, string name, WaypointFlag multiplayIdentifier, HouseTypeFlag flags, string unitTeamColor, string buildingTeamColor, params (string type, string teamColor)[] overrideTeamColors)
{
ID = id;
Name = name;
MultiplayIdentifier = multiplayIdentifier;
UnitTeamColor = unitTeamColor;
BuildingTeamColor = buildingTeamColor;
OverrideTeamColors = overrideTeamColors.ToDictionary(x => x.type, x => x.teamColor);
this.ID = id;
this.Name = name;
this.MultiplayIdentifier = multiplayIdentifier;
this.Flags = flags;
this.UnitTeamColor = unitTeamColor;
this.BuildingTeamColor = buildingTeamColor;
this.OverrideTeamColors = overrideTeamColors.ToDictionary(x => x.type, x => x.teamColor);
}
public HouseType(int id, string name, string unitTeamColor, string buildingTeamColor, params (string type, string teamColor)[] overrideTeamColors)
:this(id, name, WaypointFlag.None, unitTeamColor, buildingTeamColor, overrideTeamColors)
:this(id, name, WaypointFlag.None, HouseTypeFlag.ForAlliances, unitTeamColor, buildingTeamColor, overrideTeamColors)
{
}
public HouseType(int id, string name, HouseTypeFlag flags, string teamColor)
: this(id, name, WaypointFlag.None, flags, teamColor, teamColor)
{
}
public HouseType(int id, string name, string teamColor)
: this(id, name, WaypointFlag.None, teamColor, teamColor)
: this(id, name, WaypointFlag.None, HouseTypeFlag.ForAlliances, teamColor, teamColor)
{
}
public HouseType(int id, string name)
: this(id, name, WaypointFlag.None, null, null)
: this(id, name, WaypointFlag.None, HouseTypeFlag.ForAlliances, null, null)
{
}
public HouseType(int id, string name, WaypointFlag multiplayIdentifier, string teamColor)
: this(id, name, multiplayIdentifier, teamColor, teamColor)
: this(id, name, multiplayIdentifier, HouseTypeFlag.ForAlliances, teamColor, teamColor)
{
}
public HouseType(int id, string name, WaypointFlag multiplayIdentifier, HouseTypeFlag flags, string teamColor)
: this(id, name, multiplayIdentifier, flags, teamColor, teamColor)
{
}

View File

@ -256,7 +256,7 @@ namespace MobiusEditor.Model
public readonly HouseType[] HouseTypes;
public readonly HouseType[] HouseTypesIncludingNone;
public readonly HouseType[] HouseTypesIncludingSpecials;
public ITeamColor[] FlagColors { get; set; }
@ -398,8 +398,9 @@ namespace MobiusEditor.Model
public readonly List<TeamType> TeamTypes;
public House[] Houses;
public House[] HousesIncludingNone;
public House[] HousesIncludingSpecials;
public House[] HousesForAlliances;
public House HouseNone;
public string MovieEmpty;
public readonly List<string> MovieTypes;
@ -480,8 +481,8 @@ namespace MobiusEditor.Model
this.MapSection = new MapSection(cellSize);
this.BasicSection = basicSection;
this.HouseType = houseType;
this.HouseTypesIncludingNone = houseTypes.ToArray();
this.HouseTypes = this.HouseTypesIncludingNone.Where(h => h.ID >= 0).ToArray();
this.HouseTypesIncludingSpecials = houseTypes.ToArray();
this.HouseTypes = this.HouseTypesIncludingSpecials.Where(h => (h.Flags & HouseTypeFlag.Special) == 0).ToArray();
this.FlagColors = flagColors == null ? new ITeamColor[8] : flagColors;
this.TheaterTypes = new List<TheaterType>(theaterTypes);
this.TemplateTypes = new List<TemplateType>(templateTypes);
@ -535,8 +536,14 @@ namespace MobiusEditor.Model
this.Overlappers = new OverlapperSet<ICellOverlapper>(this.Metrics);
this.triggers = new List<Trigger>();
this.TeamTypes = new List<TeamType>();
this.HousesIncludingNone = this.HouseTypesIncludingNone.Select(t => { House h = (House)Activator.CreateInstance(this.HouseType, t); h.SetDefault(); return h; }).ToArray();
this.Houses = this.HousesIncludingNone.Where(h => h.Type.ID >= 0).ToArray();
this.HousesIncludingSpecials = this.HouseTypesIncludingSpecials.Select(t => { House h = (House)Activator.CreateInstance(this.HouseType, t); h.SetDefault(); return h; }).ToArray();
this.Houses = this.HousesIncludingSpecials.Where(h => (h.Type.Flags & (HouseTypeFlag.Special)) == 0).ToArray();
// Build houses list for allies. Special houses not shown in the normal houses lists (e.g. 'Allies' and 'Soviet') are put first.
List<House> housesAlly = this.HousesIncludingSpecials.Where(h => (h.Type.Flags & (HouseTypeFlag.ForAlliances)) != 0).ToList();
List<House> housesAllySpecial = housesAlly.Where(h => (h.Type.Flags & (HouseTypeFlag.Special)) != 0).OrderBy(h => h.Type.ID).ToList();
List<House> housesAllyNormal = housesAlly.Where(h => (h.Type.Flags & (HouseTypeFlag.Special)) == 0).OrderBy(h => h.Type.ID).ToList();
this.HousesForAlliances = housesAllySpecial.Concat(housesAllyNormal).ToArray();
this.HouseNone = this.HousesIncludingSpecials.Where(h => (h.Type.Flags & (HouseTypeFlag.BaseHouse)) != 0).FirstOrDefault();
Waypoint[] wp = waypoints.ToArray();
this.Waypoints = new Waypoint[wp.Length];
for (int i = 0; i < wp.Length; ++i)
@ -618,12 +625,12 @@ namespace MobiusEditor.Model
DirectionType infDir = this.UnitDirectionTypes.Where(d => d.Facing == FacingType.South).First();
foreach (InfantryType infantryType in this.AllInfantryTypes)
{
infantryType.Init(this.HouseTypesIncludingNone.Where(h => h.Equals(infantryType.OwnerHouse)).FirstOrDefault(), infDir);
infantryType.Init(this.HouseTypesIncludingSpecials.Where(h => h.Equals(infantryType.OwnerHouse)).FirstOrDefault(), infDir);
}
DirectionType unitDir = this.UnitDirectionTypes.Where(d => d.Facing == FacingType.SouthWest).First();
foreach (UnitType unitType in this.AllUnitTypes)
{
unitType.Init(gameInfo, this.HouseTypesIncludingNone.Where(h => h.Equals(unitType.OwnerHouse)).FirstOrDefault(), unitDir);
unitType.Init(gameInfo, this.HouseTypesIncludingSpecials.Where(h => h.Equals(unitType.OwnerHouse)).FirstOrDefault(), unitDir);
}
// Required for initialising air unit names for teamtypes if DisableAirUnits is true.
foreach (ITechnoType techno in this.AllTeamTechnoTypes)
@ -634,7 +641,7 @@ namespace MobiusEditor.Model
// No restriction. All get attempted and dummies are all filled in.
foreach (BuildingType buildingType in this.BuildingTypes)
{
buildingType.Init(gameInfo, this.HouseTypesIncludingNone.Where(h => h.Equals(buildingType.OwnerHouse)).FirstOrDefault(), bldDir);
buildingType.Init(gameInfo, this.HouseTypesIncludingSpecials.Where(h => h.Equals(buildingType.OwnerHouse)).FirstOrDefault(), bldDir);
}
}
catch (Exception ex)
@ -1482,18 +1489,15 @@ namespace MobiusEditor.Model
public HouseType GetBaseHouse(GameInfo gameInfo)
{
House noneHouse = this.HousesIncludingNone.Where(h => h.Type.ID < 0).FirstOrDefault();
if (noneHouse != null)
if (this.HouseNone != null)
{
return noneHouse.Type;
}
else
{
String oppos = gameInfo.GetClassicOpposingPlayer(this.BasicSection.Player);
return this.HouseTypes.Where(h => h.Equals(this.BasicSection.BasePlayer)).FirstOrDefault()
?? this.HouseTypes.Where(h => h.Equals(oppos)).FirstOrDefault()
?? this.HouseTypes.First();
return this.HouseNone.Type;
}
String oppos = gameInfo.GetClassicOpposingPlayer(this.BasicSection.Player);
return this.HouseTypes.Where(h => h.Equals(this.BasicSection.BasePlayer)).FirstOrDefault()
?? this.HouseTypes.Where(h => h.Equals(oppos)).FirstOrDefault()
?? this.HouseTypes.First();
}
private void RemoveBibs(Building building)
@ -1533,7 +1537,7 @@ namespace MobiusEditor.Model
}
// This is a shallow clone; the map is new, but the placed contents all still reference the original objects.
// These shallow copies are used for map preview during editing, where dummy objects can be added without any issue.
Map map = new Map(this.BasicSection, this.Theater, this.Metrics.Size, this.HouseType, this.HouseTypesIncludingNone,
Map map = new Map(this.BasicSection, this.Theater, this.Metrics.Size, this.HouseType, this.HouseTypesIncludingSpecials,
this.FlagColors, this.TheaterTypes, this.TemplateTypes, this.TerrainTypes, this.OverlayTypes, this.SmudgeTypes,
this.EventTypes, this.CellEventTypes, this.UnitEventTypes, this.BuildingEventTypes, this.TerrainEventTypes,
this.ActionTypes, this.CellActionTypes, this.UnitActionTypes, this.BuildingActionTypes, this.TerrainActionTypes,
@ -1545,7 +1549,7 @@ namespace MobiusEditor.Model
TopLeft = TopLeft,
Size = Size,
// Allows functions to check whether they are being applied on the real map or the preview map.
ForPreview = ForPreview
ForPreview = forPreview
};
map.BeginUpdate();
this.MapSection.CopyTo(map.MapSection);

View File

@ -107,7 +107,7 @@ namespace MobiusEditor.Model
public Bitmap Thumbnail { get; set; }
public UnitType(int id, string name, string textId, string ownerHouse, FrameUsage bodyFrameUsage, FrameUsage turrFrameUsage, string turret, string turret2, int turrOffset, int turrY, UnitTypeFlag flags) //bool hasTurret, bool isFixedWing, bool isArmed, bool isHarvester)
public UnitType(int id, string name, string textId, string ownerHouse, FrameUsage bodyFrameUsage, FrameUsage turrFrameUsage, string turret, string turret2, int turrOffset, int turrY, UnitTypeFlag flags)
{
this.ID = id;
this.Name = name;

View File

@ -519,7 +519,7 @@ namespace MobiusEditor.RedAlert
BasicSection basicSection = new BasicSection();
basicSection.SetDefault();
IEnumerable<HouseType> houseTypes = HouseTypes.GetTypes();
basicSection.Player = houseTypes.First().Name;
basicSection.Player = houseTypes.Where(ht => (ht.Flags & HouseTypeFlag.Special) == HouseTypeFlag.None).First().Name;
basicSection.BasePlayer = HouseTypes.GetBasePlayer(basicSection.Player);
string[] cellEventTypes =
{
@ -3319,15 +3319,30 @@ namespace MobiusEditor.RedAlert
waypointsSection[i.ToString()] = waypoint.Cell.Value.ToString();
}
}
foreach (House house in Map.Houses)
foreach (Model.House house in Map.Houses.Where(h => (h.Type.Flags & HouseTypeFlag.Special) == 0).OrderBy(h => h.Type.ID))
{
if (house.Type.ID < 0)
{
continue;
}
House gameHouse = (House)house;
bool enabled = house.Enabled;
INITools.FillAndReAdd(ini, gameHouse.Type.Name, gameHouse, new MapContext(Map, false), enabled);
string name = gameHouse.Type.Name;
INISection houseSection = INITools.FillAndReAdd(ini, gameHouse.Type.Name, gameHouse, new MapContext(Map, false), enabled);
// Current house is not in its own alliances list. Fix that.
if (houseSection != null && !gameHouse.Allies.Contains(gameHouse.Type.ID))
{
HashSet<String> allies = (houseSection.TryGetValue("Allies") ?? String.Empty)
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Distinct(StringComparer.InvariantCultureIgnoreCase)
.ToHashSet(StringComparer.InvariantCultureIgnoreCase);
if (!allies.Contains(name))
{
allies.Add(name);
List<string> alliesBuild = new List<string>();
foreach (Model.House houseAll in Map.HousesForAlliances.Where(h => allies.Contains(h.Type.Name)))
{
alliesBuild.Add(houseAll.Type.Name);
}
houseSection["Allies"] = String.Join(",", alliesBuild.ToArray());
}
}
}
SaveIniBriefing(ini);
using (MemoryStream stream = new MemoryStream())
@ -4120,7 +4135,7 @@ namespace MobiusEditor.RedAlert
{
Map.BasicSection.BasePlayer = HouseTypes.GetBasePlayer(Map.BasicSection.Player);
}
HouseType rebuildHouse = Map.HouseTypesIncludingNone.Where(h => h.Name == Map.BasicSection.BasePlayer).FirstOrDefault();
HouseType rebuildHouse = Map.HouseTypes.Where(h => h.Name == Map.BasicSection.BasePlayer).FirstOrDefault();
housesWithProd.Add(rebuildHouse.Name);
return housesWithProd;
}
@ -4656,7 +4671,7 @@ namespace MobiusEditor.RedAlert
// Updating BasePlayer will trigger PropertyChanged and re-call this function, so no need to continue here.
return;
}
HouseType basePlayer = Map.HouseTypesIncludingNone.Where(h => h.Equals(Map.BasicSection.BasePlayer)).FirstOrDefault() ?? Map.HouseTypes.First();
HouseType basePlayer = Map.HouseTypesIncludingSpecials.Where(h => h.Equals(Map.BasicSection.BasePlayer)).FirstOrDefault() ?? Map.HouseTypes.First();
foreach (var (_, building) in Map.Buildings.OfType<Building>())
{
if (!building.IsPrebuilt)

View File

@ -41,6 +41,9 @@ namespace MobiusEditor.RedAlert
public static readonly HouseType Multi6 = new HouseType(17, "Multi6", Waypoint.GetFlagForMpId(5), "MULTI7"); // purple; fixed to match actual game.
public static readonly HouseType Multi7 = new HouseType(18, "Multi7", Waypoint.GetFlagForMpId(6), "MULTI6"); // blue; fixed to match actual game.
public static readonly HouseType Multi8 = new HouseType(19, "Multi8", Waypoint.GetFlagForMpId(7), "MULTI8"); // pink
// Special group houses; these can be set in house alliances.
public static readonly HouseType Allies = new HouseType(20, "Allies", HouseTypeFlag.ForAlliances | HouseTypeFlag.Special, "GREECE");
public static readonly HouseType Soviet = new HouseType(21, "Soviet", HouseTypeFlag.ForAlliances | HouseTypeFlag.Special, "USSR");
private static readonly HouseType[] Types;
@ -64,7 +67,7 @@ namespace MobiusEditor.RedAlert
public static string GetClassicOpposingPlayer(string player)
{
return (USSR.Equals(player) || Ukraine.Equals(player) || Bad.Equals(player)) ? Greece.Name : USSR.Name;
return (Soviet.Equals(player) || USSR.Equals(player) || Ukraine.Equals(player) || Bad.Equals(player)) ? Greece.Name : USSR.Name;
}
}
}

View File

@ -76,7 +76,6 @@ namespace MobiusEditor.SoleSurvivor
Waypoint[] waypoints = crateWaypoints.Concat(teamWaypoints).Concat(generalWaypoints).Concat(specialWaypoints).ToArray();
TiberianDawn.BasicSection basicSection = new TiberianDawn.BasicSection();
basicSection.SetDefault();
List<HouseType> houseTypes = HouseTypes.GetTypes().ToList();
basicSection.Player = HouseTypes.Admin.Name;
// Irrelevant for Sole. Rebuilding options will be disabled in the editor.
basicSection.BasePlayer = HouseTypes.GetBasePlayer(basicSection.Player);
@ -121,7 +120,7 @@ namespace MobiusEditor.SoleSurvivor
ExplorerComparer sorter = new ExplorerComparer();
movies.Sort(sorter);
Size mapSize = !megaMap ? Constants.MaxSize : Constants.MaxSizeMega;
Map = new Map(basicSection, null, mapSize, typeof(TiberianDawn.House), houseTypes,
Map = new Map(basicSection, null, mapSize, typeof(TiberianDawn.House), HouseTypes.GetTypes(),
null, TheaterTypes.GetTypes(), TemplateTypes.GetTypes(),
TerrainTypes.GetTypes(), OverlayTypes.GetTypes(), SmudgeTypes.GetTypes(Globals.ConvertCraters),
EventTypes.GetTypes(), cellEventTypes, unitEventTypes, structureEventTypes, terrainEventTypes,
@ -155,6 +154,26 @@ namespace MobiusEditor.SoleSurvivor
protected override List<string> LoadINI(INI ini, bool forceSoloMission, ref bool modified)
{
List<string> errors = LoadINI(ini, forceSoloMission, true, ref modified);
// Cleanup of all multi houses in ini. The "overflow houses" are the ones beyond Multi4. They aren't put
// in the alliances list due to the fact alliances are handled as bit flags and thus can't go beyond 32.
List<Model.House> overflowHouses = Map.Houses.Where(h => (h.Type.Flags & HouseTypeFlag.ForAlliances) == 0).ToList();
bool allEnabled = true;
If all of them are enabled this indicates a default map with its default houses spam, so clean it up.
foreach (Model.House house in overflowHouses)
{
if (!house.Enabled)
{
allEnabled = false;
break;
}
}
if (allEnabled)
{
foreach (Model.House house in overflowHouses)
{
house.Enabled = false;
}
}
INISection cratesIniSection = extraSections.Extract("Crates");
if (cratesIniSection != null)
{

View File

@ -38,102 +38,102 @@ namespace MobiusEditor.SoleSurvivor
public static readonly HouseType Multi2 /**/ = new HouseType(11, "Multi2", Waypoint.GetFlagForMpId(1), "MULTI5"); // Orange
public static readonly HouseType Multi3 /**/ = new HouseType(12, "Multi3", Waypoint.GetFlagForMpId(2), "MULTI4"); // Green
public static readonly HouseType Multi4 /**/ = new HouseType(13, "Multi4", Waypoint.GetFlagForMpId(3), "MULTI6"); // Teal (originally gray)
public static readonly HouseType Multi5 /**/ = new HouseType(14, "Multi5", Waypoint.GetFlagForMpId(4), "MULTI1"); // Yellow
public static readonly HouseType Multi6 /**/ = new HouseType(15, "Multi6", Waypoint.GetFlagForMpId(5), "MULTI3"); // Red
public static readonly HouseType Multi7 /**/ = new HouseType(16, "Multi7", Waypoint.GetFlagForMpId(6), "MULTI3"); // Red
public static readonly HouseType Multi8 /**/ = new HouseType(17, "Multi8", Waypoint.GetFlagForMpId(7), "MULTI3"); // Red
public static readonly HouseType Multi9 /**/ = new HouseType(18, "Multi9", "MULTI3"); // Red
public static readonly HouseType Multi10 /**/ = new HouseType(19, "Multi10", "MULTI3"); // Red
public static readonly HouseType Multi11 /**/ = new HouseType(20, "Multi11", "MULTI3"); // Red
public static readonly HouseType Multi12 /**/ = new HouseType(21, "Multi12", "MULTI3"); // Red
public static readonly HouseType Multi13 /**/ = new HouseType(22, "Multi13", "MULTI3"); // Red
public static readonly HouseType Multi14 /**/ = new HouseType(23, "Multi14", "MULTI3"); // Red
public static readonly HouseType Multi15 /**/ = new HouseType(24, "Multi15", "MULTI3"); // Red
public static readonly HouseType Multi16 /**/ = new HouseType(25, "Multi16", "MULTI3"); // Red
public static readonly HouseType Multi17 /**/ = new HouseType(26, "Multi17", "MULTI3"); // Red
public static readonly HouseType Multi18 /**/ = new HouseType(27, "Multi18", "MULTI3"); // Red
public static readonly HouseType Multi19 /**/ = new HouseType(28, "Multi19", "MULTI3"); // Red
public static readonly HouseType Multi20 /**/ = new HouseType(29, "Multi20", "MULTI3"); // Red
public static readonly HouseType Multi21 /**/ = new HouseType(30, "Multi21", "MULTI3"); // Red
public static readonly HouseType Multi22 /**/ = new HouseType(31, "Multi22", "MULTI3"); // Red
public static readonly HouseType Multi23 /**/ = new HouseType(32, "Multi23", "MULTI3"); // Red
public static readonly HouseType Multi24 /**/ = new HouseType(33, "Multi24", "MULTI3"); // Red
public static readonly HouseType Multi25 /**/ = new HouseType(34, "Multi25", "MULTI3"); // Red
public static readonly HouseType Multi26 /**/ = new HouseType(35, "Multi26", "MULTI3"); // Red
public static readonly HouseType Multi27 /**/ = new HouseType(36, "Multi27", "MULTI3"); // Red
public static readonly HouseType Multi28 /**/ = new HouseType(37, "Multi28", "MULTI3"); // Red
public static readonly HouseType Multi29 /**/ = new HouseType(38, "Multi29", "MULTI3"); // Red
public static readonly HouseType Multi30 /**/ = new HouseType(39, "Multi30", "MULTI3"); // Red
public static readonly HouseType Multi31 /**/ = new HouseType(40, "Multi31", "MULTI3"); // Red
public static readonly HouseType Multi32 /**/ = new HouseType(41, "Multi32", "MULTI3"); // Red
public static readonly HouseType Multi33 /**/ = new HouseType(42, "Multi33", "MULTI3"); // Red
public static readonly HouseType Multi34 /**/ = new HouseType(43, "Multi34", "MULTI3"); // Red
public static readonly HouseType Multi35 /**/ = new HouseType(44, "Multi35", "MULTI3"); // Red
public static readonly HouseType Multi36 /**/ = new HouseType(45, "Multi36", "MULTI3"); // Red
public static readonly HouseType Multi37 /**/ = new HouseType(46, "Multi37", "MULTI3"); // Red
public static readonly HouseType Multi38 /**/ = new HouseType(47, "Multi38", "MULTI3"); // Red
public static readonly HouseType Multi39 /**/ = new HouseType(48, "Multi39", "MULTI3"); // Red
public static readonly HouseType Multi40 /**/ = new HouseType(49, "Multi40", "MULTI3"); // Red
public static readonly HouseType Multi41 /**/ = new HouseType(50, "Multi41", "MULTI3"); // Red
public static readonly HouseType Multi42 /**/ = new HouseType(51, "Multi42", "MULTI3"); // Red
public static readonly HouseType Multi43 /**/ = new HouseType(52, "Multi43", "MULTI3"); // Red
public static readonly HouseType Multi44 /**/ = new HouseType(53, "Multi44", "MULTI3"); // Red
public static readonly HouseType Multi45 /**/ = new HouseType(54, "Multi45", "MULTI3"); // Red
public static readonly HouseType Multi46 /**/ = new HouseType(55, "Multi46", "MULTI3"); // Red
public static readonly HouseType Multi47 /**/ = new HouseType(56, "Multi47", "MULTI3"); // Red
public static readonly HouseType Multi48 /**/ = new HouseType(57, "Multi48", "MULTI3"); // Red
public static readonly HouseType Multi49 /**/ = new HouseType(58, "Multi49", "MULTI3"); // Red
public static readonly HouseType Multi50 /**/ = new HouseType(59, "Multi50", "MULTI3"); // Red
public static readonly HouseType Multi51 /**/ = new HouseType(60, "Multi51", "MULTI3"); // Red
public static readonly HouseType Multi52 /**/ = new HouseType(61, "Multi52", "MULTI3"); // Red
public static readonly HouseType Multi53 /**/ = new HouseType(62, "Multi53", "MULTI3"); // Red
public static readonly HouseType Multi54 /**/ = new HouseType(63, "Multi54", "MULTI3"); // Red
public static readonly HouseType Multi55 /**/ = new HouseType(64, "Multi55", "MULTI3"); // Red
public static readonly HouseType Multi56 /**/ = new HouseType(65, "Multi56", "MULTI3"); // Red
public static readonly HouseType Multi57 /**/ = new HouseType(66, "Multi57", "MULTI3"); // Red
public static readonly HouseType Multi58 /**/ = new HouseType(67, "Multi58", "MULTI3"); // Red
public static readonly HouseType Multi59 /**/ = new HouseType(68, "Multi59", "MULTI3"); // Red
public static readonly HouseType Multi60 /**/ = new HouseType(69, "Multi60", "MULTI3"); // Red
public static readonly HouseType Multi61 /**/ = new HouseType(70, "Multi61", "MULTI3"); // Red
public static readonly HouseType Multi62 /**/ = new HouseType(71, "Multi62", "MULTI3"); // Red
public static readonly HouseType Multi63 /**/ = new HouseType(72, "Multi63", "MULTI3"); // Red
public static readonly HouseType Multi64 /**/ = new HouseType(73, "Multi64", "MULTI3"); // Red
public static readonly HouseType Multi65 /**/ = new HouseType(74, "Multi65", "MULTI3"); // Red
public static readonly HouseType Multi66 /**/ = new HouseType(75, "Multi66", "MULTI3"); // Red
public static readonly HouseType Multi67 /**/ = new HouseType(76, "Multi67", "MULTI3"); // Red
public static readonly HouseType Multi68 /**/ = new HouseType(77, "Multi68", "MULTI3"); // Red
public static readonly HouseType Multi69 /**/ = new HouseType(78, "Multi69", "MULTI3"); // Red
public static readonly HouseType Multi70 /**/ = new HouseType(79, "Multi70", "MULTI3"); // Red
public static readonly HouseType Multi71 /**/ = new HouseType(80, "Multi71", "MULTI3"); // Red
public static readonly HouseType Multi72 /**/ = new HouseType(81, "Multi72", "MULTI3"); // Red
public static readonly HouseType Multi73 /**/ = new HouseType(82, "Multi73", "MULTI3"); // Red
public static readonly HouseType Multi74 /**/ = new HouseType(83, "Multi74", "MULTI3"); // Red
public static readonly HouseType Multi75 /**/ = new HouseType(84, "Multi75", "MULTI3"); // Red
public static readonly HouseType Multi76 /**/ = new HouseType(85, "Multi76", "MULTI3"); // Red
public static readonly HouseType Multi77 /**/ = new HouseType(86, "Multi77", "MULTI3"); // Red
public static readonly HouseType Multi78 /**/ = new HouseType(87, "Multi78", "MULTI3"); // Red
public static readonly HouseType Multi79 /**/ = new HouseType(88, "Multi79", "MULTI3"); // Red
public static readonly HouseType Multi80 /**/ = new HouseType(89, "Multi80", "MULTI3"); // Red
public static readonly HouseType Multi81 /**/ = new HouseType(90, "Multi81", "MULTI3"); // Red
public static readonly HouseType Multi82 /**/ = new HouseType(91, "Multi82", "MULTI3"); // Red
public static readonly HouseType Multi83 /**/ = new HouseType(92, "Multi83", "MULTI3"); // Red
public static readonly HouseType Multi84 /**/ = new HouseType(93, "Multi84", "MULTI3"); // Red
public static readonly HouseType Multi85 /**/ = new HouseType(94, "Multi85", "MULTI3"); // Red
public static readonly HouseType Multi86 /**/ = new HouseType(95, "Multi86", "MULTI3"); // Red
public static readonly HouseType Multi87 /**/ = new HouseType(96, "Multi87", "MULTI3"); // Red
public static readonly HouseType Multi88 /**/ = new HouseType(97, "Multi88", "MULTI3"); // Red
public static readonly HouseType Multi89 /**/ = new HouseType(98, "Multi89", "MULTI3"); // Red
public static readonly HouseType Multi90 /**/ = new HouseType(99, "Multi90", "MULTI3"); // Red
public static readonly HouseType Multi91 /**/ = new HouseType(100, "Multi91", "MULTI3"); // Red
public static readonly HouseType Multi92 /**/ = new HouseType(101, "Multi92", "MULTI3"); // Red
public static readonly HouseType Multi93 /**/ = new HouseType(102, "Multi93", "MULTI3"); // Red
public static readonly HouseType Multi94 /**/ = new HouseType(103, "Multi94", "MULTI3"); // Red
public static readonly HouseType Multi95 /**/ = new HouseType(104, "Multi95", "MULTI3"); // Red
public static readonly HouseType Multi96 /**/ = new HouseType(105, "Multi96", "MULTI3"); // Red
public static readonly HouseType Multi97 /**/ = new HouseType(106, "Multi97", "MULTI3"); // Red
public static readonly HouseType Multi98 /**/ = new HouseType(107, "Multi98", "MULTI3"); // Red
public static readonly HouseType Multi99 /**/ = new HouseType(108, "Multi99", "MULTI3"); // Red
public static readonly HouseType Multi100 /**/ = new HouseType(109, "Multi100", "MULTI3"); // Red
public static readonly HouseType Multi5 /**/ = new HouseType(14, "Multi5", Waypoint.GetFlagForMpId(4), HouseTypeFlag.None, "MULTI1"); // Yellow
public static readonly HouseType Multi6 /**/ = new HouseType(15, "Multi6", Waypoint.GetFlagForMpId(5), HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi7 /**/ = new HouseType(16, "Multi7", Waypoint.GetFlagForMpId(6), HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi8 /**/ = new HouseType(17, "Multi8", Waypoint.GetFlagForMpId(7), HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi9 /**/ = new HouseType(18, "Multi9", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi10 /**/ = new HouseType(19, "Multi10", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi11 /**/ = new HouseType(20, "Multi11", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi12 /**/ = new HouseType(21, "Multi12", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi13 /**/ = new HouseType(22, "Multi13", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi14 /**/ = new HouseType(23, "Multi14", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi15 /**/ = new HouseType(24, "Multi15", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi16 /**/ = new HouseType(25, "Multi16", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi17 /**/ = new HouseType(26, "Multi17", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi18 /**/ = new HouseType(27, "Multi18", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi19 /**/ = new HouseType(28, "Multi19", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi20 /**/ = new HouseType(29, "Multi20", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi21 /**/ = new HouseType(30, "Multi21", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi22 /**/ = new HouseType(31, "Multi22", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi23 /**/ = new HouseType(32, "Multi23", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi24 /**/ = new HouseType(33, "Multi24", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi25 /**/ = new HouseType(34, "Multi25", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi26 /**/ = new HouseType(35, "Multi26", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi27 /**/ = new HouseType(36, "Multi27", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi28 /**/ = new HouseType(37, "Multi28", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi29 /**/ = new HouseType(38, "Multi29", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi30 /**/ = new HouseType(39, "Multi30", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi31 /**/ = new HouseType(40, "Multi31", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi32 /**/ = new HouseType(41, "Multi32", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi33 /**/ = new HouseType(42, "Multi33", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi34 /**/ = new HouseType(43, "Multi34", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi35 /**/ = new HouseType(44, "Multi35", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi36 /**/ = new HouseType(45, "Multi36", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi37 /**/ = new HouseType(46, "Multi37", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi38 /**/ = new HouseType(47, "Multi38", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi39 /**/ = new HouseType(48, "Multi39", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi40 /**/ = new HouseType(49, "Multi40", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi41 /**/ = new HouseType(50, "Multi41", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi42 /**/ = new HouseType(51, "Multi42", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi43 /**/ = new HouseType(52, "Multi43", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi44 /**/ = new HouseType(53, "Multi44", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi45 /**/ = new HouseType(54, "Multi45", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi46 /**/ = new HouseType(55, "Multi46", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi47 /**/ = new HouseType(56, "Multi47", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi48 /**/ = new HouseType(57, "Multi48", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi49 /**/ = new HouseType(58, "Multi49", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi50 /**/ = new HouseType(59, "Multi50", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi51 /**/ = new HouseType(60, "Multi51", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi52 /**/ = new HouseType(61, "Multi52", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi53 /**/ = new HouseType(62, "Multi53", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi54 /**/ = new HouseType(63, "Multi54", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi55 /**/ = new HouseType(64, "Multi55", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi56 /**/ = new HouseType(65, "Multi56", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi57 /**/ = new HouseType(66, "Multi57", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi58 /**/ = new HouseType(67, "Multi58", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi59 /**/ = new HouseType(68, "Multi59", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi60 /**/ = new HouseType(69, "Multi60", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi61 /**/ = new HouseType(70, "Multi61", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi62 /**/ = new HouseType(71, "Multi62", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi63 /**/ = new HouseType(72, "Multi63", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi64 /**/ = new HouseType(73, "Multi64", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi65 /**/ = new HouseType(74, "Multi65", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi66 /**/ = new HouseType(75, "Multi66", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi67 /**/ = new HouseType(76, "Multi67", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi68 /**/ = new HouseType(77, "Multi68", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi69 /**/ = new HouseType(78, "Multi69", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi70 /**/ = new HouseType(79, "Multi70", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi71 /**/ = new HouseType(80, "Multi71", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi72 /**/ = new HouseType(81, "Multi72", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi73 /**/ = new HouseType(82, "Multi73", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi74 /**/ = new HouseType(83, "Multi74", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi75 /**/ = new HouseType(84, "Multi75", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi76 /**/ = new HouseType(85, "Multi76", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi77 /**/ = new HouseType(86, "Multi77", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi78 /**/ = new HouseType(87, "Multi78", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi79 /**/ = new HouseType(88, "Multi79", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi80 /**/ = new HouseType(89, "Multi80", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi81 /**/ = new HouseType(90, "Multi81", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi82 /**/ = new HouseType(91, "Multi82", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi83 /**/ = new HouseType(92, "Multi83", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi84 /**/ = new HouseType(93, "Multi84", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi85 /**/ = new HouseType(94, "Multi85", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi86 /**/ = new HouseType(95, "Multi86", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi87 /**/ = new HouseType(96, "Multi87", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi88 /**/ = new HouseType(97, "Multi88", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi89 /**/ = new HouseType(98, "Multi89", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi90 /**/ = new HouseType(99, "Multi90", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi91 /**/ = new HouseType(100, "Multi91", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi92 /**/ = new HouseType(101, "Multi92", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi93 /**/ = new HouseType(102, "Multi93", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi94 /**/ = new HouseType(103, "Multi94", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi95 /**/ = new HouseType(104, "Multi95", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi96 /**/ = new HouseType(105, "Multi96", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi97 /**/ = new HouseType(106, "Multi97", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi98 /**/ = new HouseType(107, "Multi98", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi99 /**/ = new HouseType(108, "Multi99", HouseTypeFlag.None, "MULTI3"); // Red
public static readonly HouseType Multi100 /**/ = new HouseType(109, "Multi100", HouseTypeFlag.None, "MULTI3"); // Red
private static readonly HouseType[] Types;

View File

@ -434,7 +434,7 @@ namespace MobiusEditor.TiberianDawn
basicSection.SetDefault();
IEnumerable<HouseType> houseTypes = HouseTypes.GetTypes();
basicSection.Player = houseTypes.Where(h => h.ID > -1).First().Name;
basicSection.BasePlayer = HouseTypes.GetBasePlayer(basicSection.Player);
basicSection.BasePlayer = HouseTypes.None.Name;
string[] cellEventTypes = new[]
{
EventTypes.EVENT_PLAYER_ENTERED,
@ -1613,8 +1613,9 @@ namespace MobiusEditor.TiberianDawn
modified = true;
newBld.House = defHouse;
}
if (Map.Buildings.Add(cell, newBld))
if (Map.Buildings.CanAdd(cell, newBld) && Map.Technos.CanAdd(cell, newBld, newBld.Type.BaseOccupyMask))
{
Map.Buildings.Add(cell, newBld);
if (!caseTrigs.ContainsKey(tokens[5]))
{
errors.Add(string.Format("Structure '{0}' on cell {1} links to unknown trigger '{2}'; clearing trigger.", buildingType.Name, cell, tokens[5]));
@ -1735,10 +1736,14 @@ namespace MobiusEditor.TiberianDawn
BasePriority = curPriorityVal,
IsPrebuilt = false
};
if (!Map.Buildings.Add(location, toRebuild))
if (!Map.Buildings.CanAdd(location, toRebuild) || !Map.Technos.CanAdd(location, toRebuild, toRebuild.Type.BaseOccupyMask))
{
Map.CheckBuildingBlockingCell(cell, buildingType, errors, ref modified, key);
}
else
{
Map.Buildings.Add(location, toRebuild);
}
}
curPriorityVal++;
}
@ -2713,13 +2718,29 @@ namespace MobiusEditor.TiberianDawn
protected IEnumerable<INISection> SaveIniHouses(INI ini)
{
List<INISection> houseSections = new List<INISection>();
foreach (Model.House house in Map.Houses.Where(h => h.Type.ID >= 0).OrderBy(h => h.Type.ID))
foreach (Model.House house in Map.Houses.Where(h => (h.Type.Flags & HouseTypeFlag.Special) == 0).OrderBy(h => h.Type.ID))
{
House gameHouse = (House)house;
bool enabled = house.Enabled;
INISection houseSection = INITools.FillAndReAdd(ini, gameHouse.Type.Name, gameHouse, new MapContext(Map, false), enabled);
if (houseSection != null)
string name = gameHouse.Type.Name;
INISection houseSection = INITools.FillAndReAdd(ini, name, gameHouse, new MapContext(Map, false), enabled);
// Current house is not in its own alliances list. Fix that.
if (houseSection != null && !gameHouse.Allies.Contains(gameHouse.Type.ID))
{
HashSet<String> allies = (houseSection.TryGetValue("Allies") ?? String.Empty)
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Distinct(StringComparer.InvariantCultureIgnoreCase)
.ToHashSet(StringComparer.InvariantCultureIgnoreCase);
if (!allies.Contains(name))
{
allies.Add(name);
List<string> alliesBuild = new List<string>();
foreach (HouseType houseAll in Map.HouseTypesIncludingSpecials.Where(h => allies.Contains(h.Name)))
{
alliesBuild.Add(houseAll.Name);
}
houseSection["Allies"] = String.Join(",", alliesBuild.ToArray());
}
houseSections.Add(houseSection);
}
}
@ -3521,8 +3542,13 @@ namespace MobiusEditor.TiberianDawn
protected void UpdateBasePlayerHouse()
{
Map.BasicSection.BasePlayer = HouseTypes.GetBasePlayer(Map.BasicSection.Player);
HouseType basePlayer = Map.HouseTypesIncludingNone.Where(h => h.Equals(Map.BasicSection.BasePlayer)).FirstOrDefault() ?? Map.HouseTypes.First();
HouseType basePlayer = Map.HouseNone?.Type ?? Map.HouseTypes.FirstOrDefault();
if (basePlayer == null)
{
return;
}
// Unused in TD, but whatever.
Map.BasicSection.BasePlayer = basePlayer.Name;
// Not really needed now BasePlayer House is always "None", but whatever.
foreach (var (_, building) in Map.Buildings.OfType<Building>())
{

View File

@ -22,7 +22,7 @@ namespace MobiusEditor.TiberianDawn
public static class HouseTypes
{
/// <summary>Special House added for buildings without owner; those in the rebuild list that are not on the map.</summary>
public static readonly HouseType None = new HouseType(-1, House.None, "NONE");
public static readonly HouseType None = new HouseType(-1, House.None, HouseTypeFlag.BaseHouse | HouseTypeFlag.Special, "NONE");
// Normal Houses
public static readonly HouseType Good = new HouseType(0, "GoodGuy", "GOOD");
public static readonly HouseType Bad = new HouseType(1, "BadGuy", "BAD_UNIT", "BAD_STRUCTURE", ("harv", "BAD_STRUCTURE"), ("mcv", "BAD_STRUCTURE"));

View File

@ -143,7 +143,6 @@ namespace MobiusEditor.Utility
return true;
}
public bool TryGetMember(string memberName, out object result)
{
if (!trackableProperties.TryGetValue(memberName, out PropertyInfo property))
@ -151,7 +150,6 @@ namespace MobiusEditor.Utility
result = null;
return false;
}
if (!propertyValues.TryGetValue(memberName, out result))
{
result = property.GetValue(Object);
@ -159,6 +157,23 @@ namespace MobiusEditor.Utility
return true;
}
public bool TryGetMember<U>(string memberName, out U result)
{
result = default;
if (!trackableProperties.TryGetValue(memberName, out PropertyInfo property) || !typeof(U).IsAssignableFrom(property.PropertyType))
{
return false;
}
Object value;
if (propertyValues.TryGetValue(memberName, out value))
{
result = (U)value;
return true;
}
result = (U)property.GetValue(Object);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (!trackableProperties.TryGetValue(binder.Name, out PropertyInfo property))