Merge pull request #11364 from pchote/lobby-trait-options
Unhardcode the lobby options backend.
This commit is contained in:
@@ -173,6 +173,17 @@ namespace OpenRA.Network
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class LobbyOptionState
|
||||||
|
{
|
||||||
|
public bool Locked;
|
||||||
|
public string Value;
|
||||||
|
public string PreferredValue;
|
||||||
|
|
||||||
|
public LobbyOptionState() { }
|
||||||
|
|
||||||
|
public bool Enabled { get { return Value == "True"; } }
|
||||||
|
}
|
||||||
|
|
||||||
public class Global
|
public class Global
|
||||||
{
|
{
|
||||||
public string ServerName;
|
public string ServerName;
|
||||||
@@ -180,32 +191,52 @@ namespace OpenRA.Network
|
|||||||
public int Timestep = 40;
|
public int Timestep = 40;
|
||||||
public int OrderLatency = 3; // net tick frames (x 120 = ms)
|
public int OrderLatency = 3; // net tick frames (x 120 = ms)
|
||||||
public int RandomSeed = 0;
|
public int RandomSeed = 0;
|
||||||
public bool AllowCheats = false;
|
|
||||||
public bool AllowSpectators = true;
|
public bool AllowSpectators = true;
|
||||||
public bool Dedicated;
|
|
||||||
public string Difficulty;
|
public string Difficulty;
|
||||||
public bool Crates = true;
|
|
||||||
public bool Creeps = true;
|
|
||||||
public bool Shroud = true;
|
|
||||||
public bool Fog = true;
|
|
||||||
public bool AllyBuildRadius = true;
|
|
||||||
public int StartingCash = 5000;
|
|
||||||
public string TechLevel;
|
|
||||||
public string StartingUnitsClass;
|
|
||||||
public string GameSpeedType = "default";
|
public string GameSpeedType = "default";
|
||||||
public bool ShortGame = true;
|
|
||||||
public bool AllowVersionMismatch;
|
public bool AllowVersionMismatch;
|
||||||
public string GameUid;
|
public string GameUid;
|
||||||
public bool DisableSingleplayer;
|
public bool DisableSingleplayer;
|
||||||
|
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
public Dictionary<string, LobbyOptionState> LobbyOptions = new Dictionary<string, LobbyOptionState>();
|
||||||
|
|
||||||
public static Global Deserialize(MiniYaml data)
|
public static Global Deserialize(MiniYaml data)
|
||||||
{
|
{
|
||||||
return FieldLoader.Load<Global>(data);
|
var gs = FieldLoader.Load<Global>(data);
|
||||||
|
|
||||||
|
var optionsNode = data.Nodes.FirstOrDefault(n => n.Key == "Options");
|
||||||
|
if (optionsNode != null)
|
||||||
|
foreach (var n in optionsNode.Value.Nodes)
|
||||||
|
gs.LobbyOptions[n.Key] = FieldLoader.Load<LobbyOptionState>(n.Value);
|
||||||
|
|
||||||
|
return gs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MiniYamlNode Serialize()
|
public MiniYamlNode Serialize()
|
||||||
{
|
{
|
||||||
return new MiniYamlNode("GlobalSettings", FieldSaver.Save(this));
|
var data = new MiniYamlNode("GlobalSettings", FieldSaver.Save(this));
|
||||||
|
var options = LobbyOptions.Select(kv => new MiniYamlNode(kv.Key, FieldSaver.Save(kv.Value))).ToList();
|
||||||
|
data.Value.Nodes.Add(new MiniYamlNode("Options", new MiniYaml(null, options)));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OptionOrDefault(string id, bool def)
|
||||||
|
{
|
||||||
|
LobbyOptionState option;
|
||||||
|
if (LobbyOptions.TryGetValue(id, out option))
|
||||||
|
return option.Enabled;
|
||||||
|
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OptionOrDefault(string id, string def)
|
||||||
|
{
|
||||||
|
LobbyOptionState option;
|
||||||
|
if (LobbyOptions.TryGetValue(id, out option))
|
||||||
|
return option.Value;
|
||||||
|
|
||||||
|
return def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,6 @@ namespace OpenRA.Server
|
|||||||
RandomSeed = randomSeed,
|
RandomSeed = randomSeed,
|
||||||
Map = settings.Map,
|
Map = settings.Map,
|
||||||
ServerName = settings.Name,
|
ServerName = settings.Name,
|
||||||
Dedicated = dedicated,
|
|
||||||
DisableSingleplayer = settings.DisableSinglePlayer,
|
DisableSingleplayer = settings.DisableSinglePlayer,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,10 +9,12 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
[Desc("Attach this to the player actor.")]
|
[Desc("Attach this to the player actor.")]
|
||||||
public class DeveloperModeInfo : ITraitInfo
|
public class DeveloperModeInfo : ITraitInfo, ILobbyOptions
|
||||||
{
|
{
|
||||||
[Desc("Default value of the developer mode checkbox in the lobby.")]
|
[Desc("Default value of the developer mode checkbox in the lobby.")]
|
||||||
public bool Enabled = false;
|
public bool Enabled = false;
|
||||||
@@ -56,6 +58,11 @@ namespace OpenRA.Traits
|
|||||||
[Desc("Enable the actor tags overlay by default.")]
|
[Desc("Enable the actor tags overlay by default.")]
|
||||||
public bool ShowActorTags;
|
public bool ShowActorTags;
|
||||||
|
|
||||||
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
|
||||||
|
{
|
||||||
|
yield return new LobbyBooleanOption("cheats", "Debug Menu", Enabled, Locked);
|
||||||
|
}
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new DeveloperMode(this); }
|
public object Create(ActorInitializer init) { return new DeveloperMode(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +113,8 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
{
|
{
|
||||||
Enabled = self.World.LobbyInfo.GlobalSettings.AllowCheats || self.World.LobbyInfo.IsSinglePlayer;
|
Enabled = self.World.LobbyInfo.IsSinglePlayer || self.World.LobbyInfo.GlobalSettings
|
||||||
|
.OptionOrDefault("cheats", info.Enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResolveOrder(Actor self, Order order)
|
public void ResolveOrder(Actor self, Order order)
|
||||||
|
|||||||
@@ -10,11 +10,12 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
public class PlayerResourcesInfo : ITraitInfo
|
public class PlayerResourcesInfo : ITraitInfo, ILobbyOptions
|
||||||
{
|
{
|
||||||
[Desc("Starting cash options that are available in the lobby options.")]
|
[Desc("Starting cash options that are available in the lobby options.")]
|
||||||
public readonly int[] SelectableCash = { 2500, 5000, 10000, 20000 };
|
public readonly int[] SelectableCash = { 2500, 5000, 10000, 20000 };
|
||||||
@@ -31,6 +32,14 @@ namespace OpenRA.Traits
|
|||||||
[Desc("Delay (in ticks) during which warnings will be muted.")]
|
[Desc("Delay (in ticks) during which warnings will be muted.")]
|
||||||
public readonly int InsufficientFundsNotificationDelay = 750;
|
public readonly int InsufficientFundsNotificationDelay = 750;
|
||||||
|
|
||||||
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
|
||||||
|
{
|
||||||
|
var startingCash = SelectableCash.ToDictionary(c => c.ToString(), c => "$" + c.ToString());
|
||||||
|
|
||||||
|
if (startingCash.Any())
|
||||||
|
yield return new LobbyOption("startingcash", "Starting Cash", new ReadOnlyDictionary<string, string>(startingCash), DefaultCash.ToString(), DefaultCashLocked);
|
||||||
|
}
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new PlayerResources(init.Self, this); }
|
public object Create(ActorInitializer init) { return new PlayerResources(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +55,11 @@ namespace OpenRA.Traits
|
|||||||
this.info = info;
|
this.info = info;
|
||||||
owner = self.Owner;
|
owner = self.Owner;
|
||||||
|
|
||||||
Cash = self.World.LobbyInfo.GlobalSettings.StartingCash;
|
var startingCash = self.World.LobbyInfo.GlobalSettings
|
||||||
|
.OptionOrDefault("startingcash", info.DefaultCash.ToString());
|
||||||
|
|
||||||
|
if (!int.TryParse(startingCash, out Cash))
|
||||||
|
Cash = info.DefaultCash;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Sync] public int Cash;
|
[Sync] public int Cash;
|
||||||
|
|||||||
@@ -412,4 +412,50 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public interface IRulesetLoaded<TInfo> { void RulesetLoaded(Ruleset rules, TInfo info); }
|
public interface IRulesetLoaded<TInfo> { void RulesetLoaded(Ruleset rules, TInfo info); }
|
||||||
public interface IRulesetLoaded : IRulesetLoaded<ActorInfo>, ITraitInfoInterface { }
|
public interface IRulesetLoaded : IRulesetLoaded<ActorInfo>, ITraitInfoInterface { }
|
||||||
|
|
||||||
|
[RequireExplicitImplementation]
|
||||||
|
public interface ILobbyOptions : ITraitInfoInterface
|
||||||
|
{
|
||||||
|
IEnumerable<LobbyOption> LobbyOptions(Ruleset rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LobbyOption
|
||||||
|
{
|
||||||
|
public readonly string Id;
|
||||||
|
public readonly string Name;
|
||||||
|
public readonly IReadOnlyDictionary<string, string> Values;
|
||||||
|
public readonly string DefaultValue;
|
||||||
|
public readonly bool Locked;
|
||||||
|
|
||||||
|
public LobbyOption(string id, string name, IReadOnlyDictionary<string, string> values, string defaultValue, bool locked)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Name = name;
|
||||||
|
Values = values;
|
||||||
|
DefaultValue = defaultValue;
|
||||||
|
Locked = locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string ValueChangedMessage(string playerName, string newValue)
|
||||||
|
{
|
||||||
|
return playerName + " changed " + Name + " to " + Values[newValue] + ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LobbyBooleanOption : LobbyOption
|
||||||
|
{
|
||||||
|
static readonly Dictionary<string, string> BoolValues = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ true.ToString(), "enabled" },
|
||||||
|
{ false.ToString(), "disabled" }
|
||||||
|
};
|
||||||
|
|
||||||
|
public LobbyBooleanOption(string id, string name, bool defaultValue, bool locked)
|
||||||
|
: base(id, name, new ReadOnlyDictionary<string, string>(BoolValues), defaultValue.ToString(), locked) { }
|
||||||
|
|
||||||
|
public override string ValueChangedMessage(string playerName, string newValue)
|
||||||
|
{
|
||||||
|
return playerName + " " + BoolValues[newValue] + " " + Name + ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.Network;
|
||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
[Desc("Required for shroud and fog visibility checks. Add this to the player actor.")]
|
[Desc("Required for shroud and fog visibility checks. Add this to the player actor.")]
|
||||||
public class ShroudInfo : ITraitInfo
|
public class ShroudInfo : ITraitInfo, ILobbyOptions
|
||||||
{
|
{
|
||||||
[Desc("Default value of the fog checkbox in the lobby.")]
|
[Desc("Default value of the fog checkbox in the lobby.")]
|
||||||
public bool FogEnabled = true;
|
public bool FogEnabled = true;
|
||||||
@@ -30,7 +31,13 @@ namespace OpenRA.Traits
|
|||||||
[Desc("Prevent the explore map enabled state from being changed in the lobby.")]
|
[Desc("Prevent the explore map enabled state from being changed in the lobby.")]
|
||||||
public bool ExploredMapLocked = false;
|
public bool ExploredMapLocked = false;
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new Shroud(init.Self); }
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
|
||||||
|
{
|
||||||
|
yield return new LobbyBooleanOption("explored", "Explored Map", ExploredMapEnabled, ExploredMapLocked);
|
||||||
|
yield return new LobbyBooleanOption("fog", "Fog of War", FogEnabled, FogLocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new Shroud(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Shroud : ISync, INotifyCreated
|
public class Shroud : ISync, INotifyCreated
|
||||||
@@ -38,6 +45,7 @@ namespace OpenRA.Traits
|
|||||||
public event Action<IEnumerable<PPos>> CellsChanged;
|
public event Action<IEnumerable<PPos>> CellsChanged;
|
||||||
|
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
|
readonly ShroudInfo info;
|
||||||
readonly Map map;
|
readonly Map map;
|
||||||
|
|
||||||
readonly CellLayer<short> visibleCount;
|
readonly CellLayer<short> visibleCount;
|
||||||
@@ -72,9 +80,10 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public int Hash { get; private set; }
|
public int Hash { get; private set; }
|
||||||
|
|
||||||
public Shroud(Actor self)
|
public Shroud(Actor self, ShroudInfo info)
|
||||||
{
|
{
|
||||||
this.self = self;
|
this.self = self;
|
||||||
|
this.info = info;
|
||||||
map = self.World.Map;
|
map = self.World.Map;
|
||||||
|
|
||||||
visibleCount = new CellLayer<short>(map);
|
visibleCount = new CellLayer<short>(map);
|
||||||
@@ -84,9 +93,11 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
{
|
{
|
||||||
fogEnabled = self.World.LobbyInfo.GlobalSettings.Fog;
|
var gs = self.World.LobbyInfo.GlobalSettings;
|
||||||
var shroudEnabled = self.World.LobbyInfo.GlobalSettings.Shroud;
|
fogEnabled = gs.OptionOrDefault("fog", info.FogEnabled);
|
||||||
if (!shroudEnabled)
|
|
||||||
|
var exploreMap = gs.OptionOrDefault("explored", info.ExploredMapEnabled);
|
||||||
|
if (exploreMap)
|
||||||
self.World.AddFrameEndTask(w => ExploreAll());
|
self.World.AddFrameEndTask(w => ExploreAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -424,74 +424,43 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ "allowcheats",
|
{ "option",
|
||||||
s =>
|
s =>
|
||||||
{
|
{
|
||||||
if (!client.IsAdmin)
|
if (!client.IsAdmin)
|
||||||
{
|
{
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
server.SendOrderTo(conn, "Message", "Only the host can change the configuration.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var devMode = server.Map.Rules.Actors["player"].TraitInfo<DeveloperModeInfo>();
|
var options = server.Map.Rules.Actors["player"].TraitInfos<ILobbyOptions>()
|
||||||
if (devMode.Locked)
|
.Concat(server.Map.Rules.Actors["world"].TraitInfos<ILobbyOptions>())
|
||||||
|
.SelectMany(t => t.LobbyOptions(server.Map.Rules))
|
||||||
|
.ToDictionary(o => o.Id, o => o);
|
||||||
|
|
||||||
|
var split = s.Split(' ');
|
||||||
|
LobbyOption option;
|
||||||
|
if (split.Length < 2 || !options.TryGetValue(split[0], out option) ||
|
||||||
|
!option.Values.ContainsKey(split[1]))
|
||||||
{
|
{
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled cheat configuration.");
|
server.SendOrderTo(conn, "Message", "Invalid configuration command.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllowCheats);
|
if (option.Locked)
|
||||||
|
{
|
||||||
|
server.SendOrderTo(conn, "Message", "{0} cannot be changed.".F(option.Name));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var oo = server.LobbyInfo.GlobalSettings.LobbyOptions[option.Id];
|
||||||
|
if (oo.Value == split[1])
|
||||||
|
return true;
|
||||||
|
|
||||||
|
oo.Value = oo.PreferredValue = split[1];
|
||||||
|
|
||||||
server.SyncLobbyGlobalSettings();
|
server.SyncLobbyGlobalSettings();
|
||||||
server.SendMessage("{0} {1} the Debug Menu."
|
server.SendMessage(option.ValueChangedMessage(client.Name, split[1]));
|
||||||
.F(client.Name, server.LobbyInfo.GlobalSettings.AllowCheats ? "enabled" : "disabled"));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "shroud",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var shroud = server.Map.Rules.Actors["player"].TraitInfo<ShroudInfo>();
|
|
||||||
if (shroud.ExploredMapLocked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled shroud configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Shroud);
|
|
||||||
server.SyncLobbyGlobalSettings();
|
|
||||||
server.SendMessage("{0} {1} Explored map."
|
|
||||||
.F(client.Name, server.LobbyInfo.GlobalSettings.Shroud ? "disabled" : "enabled"));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "fog",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var shroud = server.Map.Rules.Actors["player"].TraitInfo<ShroudInfo>();
|
|
||||||
if (shroud.FogLocked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled fog configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Fog);
|
|
||||||
server.SyncLobbyGlobalSettings();
|
|
||||||
server.SendMessage("{0} {1} Fog of War."
|
|
||||||
.F(client.Name, server.LobbyInfo.GlobalSettings.Fog ? "enabled" : "disabled"));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -537,78 +506,6 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ "crates",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var crateSpawner = server.Map.Rules.Actors["world"].TraitInfoOrDefault<CrateSpawnerInfo>();
|
|
||||||
if (crateSpawner == null || crateSpawner.Locked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled crate configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Crates);
|
|
||||||
server.SyncLobbyGlobalSettings();
|
|
||||||
server.SendMessage("{0} {1} Crates."
|
|
||||||
.F(client.Name, server.LobbyInfo.GlobalSettings.Crates ? "enabled" : "disabled"));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "creeps",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapCreeps = server.Map.Rules.Actors["world"].TraitInfoOrDefault<MapCreepsInfo>();
|
|
||||||
if (mapCreeps == null || mapCreeps.Locked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled Creeps spawning configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool.TryParse(s, out server.LobbyInfo.GlobalSettings.Creeps);
|
|
||||||
server.SyncLobbyGlobalSettings();
|
|
||||||
server.SendMessage("{0} {1} Creeps spawning."
|
|
||||||
.F(client.Name, server.LobbyInfo.GlobalSettings.Creeps ? "enabled" : "disabled"));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "allybuildradius",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapBuildRadius = server.Map.Rules.Actors["world"].TraitInfoOrDefault<MapBuildRadiusInfo>();
|
|
||||||
if (mapBuildRadius == null || mapBuildRadius.AllyBuildRadiusLocked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled ally build radius configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool.TryParse(s, out server.LobbyInfo.GlobalSettings.AllyBuildRadius);
|
|
||||||
server.SyncLobbyGlobalSettings();
|
|
||||||
server.SendMessage("{0} {1} Build off Allies' ConYards."
|
|
||||||
.F(client.Name, server.LobbyInfo.GlobalSettings.AllyBuildRadius ? "enabled" : "disabled"));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "difficulty",
|
{ "difficulty",
|
||||||
s =>
|
s =>
|
||||||
{
|
{
|
||||||
@@ -642,110 +539,6 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ "startingunits",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var startingUnits = server.Map.Rules.Actors["world"].TraitInfoOrDefault<SpawnMPUnitsInfo>();
|
|
||||||
if (startingUnits == null || startingUnits.Locked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled start unit configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var startUnitsInfo = server.Map.Rules.Actors["world"].TraitInfos<MPStartUnitsInfo>();
|
|
||||||
var selectedClass = startUnitsInfo.Where(u => u.Class == s).FirstOrDefault();
|
|
||||||
if (selectedClass == null)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Invalid starting units option selected: {0}".F(s));
|
|
||||||
server.SendOrderTo(conn, "Message", "Supported values: {0}".F(startUnitsInfo.Select(su => su.ClassName).JoinWith(", ")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.StartingUnitsClass == selectedClass.Class)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
server.LobbyInfo.GlobalSettings.StartingUnitsClass = selectedClass.Class;
|
|
||||||
server.SyncLobbyGlobalSettings();
|
|
||||||
server.SendMessage("{0} changed Starting Units to {1}.".F(client.Name, selectedClass.ClassName));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "startingcash",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var playerResources = server.Map.Rules.Actors["player"].TraitInfo<PlayerResourcesInfo>();
|
|
||||||
if (playerResources.DefaultCashLocked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled cash configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var startingCashOptions = playerResources.SelectableCash;
|
|
||||||
var requestedCash = Exts.ParseIntegerInvariant(s);
|
|
||||||
if (!startingCashOptions.Contains(requestedCash))
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Invalid starting cash value selected: {0}".F(s));
|
|
||||||
server.SendOrderTo(conn, "Message", "Supported values: {0}".F(startingCashOptions.JoinWith(", ")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.StartingCash == requestedCash)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
server.LobbyInfo.GlobalSettings.StartingCash = requestedCash;
|
|
||||||
server.SyncLobbyGlobalSettings();
|
|
||||||
server.SendMessage("{0} changed Starting Cash to ${1}.".F(client.Name, requestedCash));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "techlevel",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (server.LobbyInfo.GlobalSettings.TechLevel == s)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapOptions = server.Map.Rules.Actors["world"].TraitInfo<MapOptionsInfo>();
|
|
||||||
if (mapOptions.TechLevelLocked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled Tech configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var techlevels = server.Map.Rules.Actors["player"].TraitInfos<ProvidesTechPrerequisiteInfo>().Select(t => t.Name);
|
|
||||||
if (!techlevels.Contains(s))
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Invalid tech level selected: {0}".F(s));
|
|
||||||
server.SendOrderTo(conn, "Message", "Supported values: {0}".F(techlevels.JoinWith(", ")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
server.LobbyInfo.GlobalSettings.TechLevel = s;
|
|
||||||
server.SyncLobbyInfo();
|
|
||||||
server.SendMessage("{0} changed Tech Level to {1}.".F(client.Name, s));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "gamespeed",
|
{ "gamespeed",
|
||||||
s =>
|
s =>
|
||||||
{
|
{
|
||||||
@@ -975,30 +768,6 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ "shortgame",
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
if (!client.IsAdmin)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapOptions = server.Map.Rules.Actors["world"].TraitInfo<MapOptionsInfo>();
|
|
||||||
if (mapOptions.ShortGameLocked)
|
|
||||||
{
|
|
||||||
server.SendOrderTo(conn, "Message", "Map has disabled short game configuration.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool.TryParse(s, out server.LobbyInfo.GlobalSettings.ShortGame);
|
|
||||||
server.SyncLobbyGlobalSettings();
|
|
||||||
server.SendMessage("{0} {1} Short Game."
|
|
||||||
.F(client.Name, server.LobbyInfo.GlobalSettings.ShortGame ? "enabled" : "disabled"));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "sync_lobby",
|
{ "sync_lobby",
|
||||||
s =>
|
s =>
|
||||||
{
|
{
|
||||||
@@ -1067,32 +836,36 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
|
|
||||||
public static void LoadMapSettings(Session.Global gs, Ruleset rules)
|
public static void LoadMapSettings(Session.Global gs, Ruleset rules)
|
||||||
{
|
{
|
||||||
var devMode = rules.Actors["player"].TraitInfo<DeveloperModeInfo>();
|
var options = rules.Actors["player"].TraitInfos<ILobbyOptions>()
|
||||||
gs.AllowCheats = devMode.Enabled;
|
.Concat(rules.Actors["world"].TraitInfos<ILobbyOptions>())
|
||||||
|
.SelectMany(t => t.LobbyOptions(rules));
|
||||||
|
|
||||||
var crateSpawner = rules.Actors["world"].TraitInfoOrDefault<CrateSpawnerInfo>();
|
foreach (var o in options)
|
||||||
gs.Crates = crateSpawner != null && crateSpawner.Enabled;
|
{
|
||||||
|
var value = o.DefaultValue;
|
||||||
|
var preferredValue = o.DefaultValue;
|
||||||
|
Session.LobbyOptionState state;
|
||||||
|
if (gs.LobbyOptions.TryGetValue(o.Id, out state))
|
||||||
|
{
|
||||||
|
// Propagate old state on map change
|
||||||
|
if (!o.Locked)
|
||||||
|
{
|
||||||
|
if (o.Values.Keys.Contains(state.PreferredValue))
|
||||||
|
value = state.PreferredValue;
|
||||||
|
else if (o.Values.Keys.Contains(state.Value))
|
||||||
|
value = state.Value;
|
||||||
|
}
|
||||||
|
|
||||||
var shroud = rules.Actors["player"].TraitInfo<ShroudInfo>();
|
preferredValue = state.PreferredValue;
|
||||||
gs.Fog = shroud.FogEnabled;
|
}
|
||||||
gs.Shroud = !shroud.ExploredMapEnabled;
|
else
|
||||||
|
state = new Session.LobbyOptionState();
|
||||||
|
|
||||||
var resources = rules.Actors["player"].TraitInfo<PlayerResourcesInfo>();
|
state.Locked = o.Locked;
|
||||||
gs.StartingCash = resources.DefaultCash;
|
state.Value = value;
|
||||||
|
state.PreferredValue = preferredValue;
|
||||||
var startingUnits = rules.Actors["world"].TraitInfoOrDefault<SpawnMPUnitsInfo>();
|
gs.LobbyOptions[o.Id] = state;
|
||||||
gs.StartingUnitsClass = startingUnits == null ? "none" : startingUnits.StartingUnitsClass;
|
}
|
||||||
|
|
||||||
var mapBuildRadius = rules.Actors["world"].TraitInfoOrDefault<MapBuildRadiusInfo>();
|
|
||||||
gs.AllyBuildRadius = mapBuildRadius != null && mapBuildRadius.AllyBuildRadiusEnabled;
|
|
||||||
|
|
||||||
var mapCreeps = rules.Actors["world"].TraitInfoOrDefault<MapCreepsInfo>();
|
|
||||||
gs.Creeps = mapCreeps != null && mapCreeps.Enabled;
|
|
||||||
|
|
||||||
var mapOptions = rules.Actors["world"].TraitInfo<MapOptionsInfo>();
|
|
||||||
gs.ShortGame = mapOptions.ShortGameEnabled;
|
|
||||||
gs.TechLevel = mapOptions.TechLevel;
|
|
||||||
gs.Difficulty = mapOptions.Difficulty ?? mapOptions.Difficulties.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HSLColor SanitizePlayerColor(S server, HSLColor askedColor, int playerIndex, Connection connectionToEcho = null)
|
static HSLColor SanitizePlayerColor(S server, HSLColor askedColor, int playerIndex, Connection connectionToEcho = null)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using System.Linq;
|
|||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Network;
|
using OpenRA.Network;
|
||||||
using OpenRA.Server;
|
using OpenRA.Server;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Server
|
namespace OpenRA.Mods.Common.Server
|
||||||
{
|
{
|
||||||
@@ -26,40 +27,17 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
var defaults = new Session.Global();
|
var defaults = new Session.Global();
|
||||||
LobbyCommands.LoadMapSettings(defaults, server.Map.Rules);
|
LobbyCommands.LoadMapSettings(defaults, server.Map.Rules);
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.AllowCheats != defaults.AllowCheats)
|
var options = server.Map.Rules.Actors["player"].TraitInfos<ILobbyOptions>()
|
||||||
server.SendOrderTo(conn, "Message", "Allow Cheats: {0}".F(server.LobbyInfo.GlobalSettings.AllowCheats));
|
.Concat(server.Map.Rules.Actors["world"].TraitInfos<ILobbyOptions>())
|
||||||
|
.SelectMany(t => t.LobbyOptions(server.Map.Rules))
|
||||||
|
.ToDictionary(o => o.Id, o => o);
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.Shroud != defaults.Shroud)
|
foreach (var kv in server.LobbyInfo.GlobalSettings.LobbyOptions)
|
||||||
server.SendOrderTo(conn, "Message", "Explored map: {0}".F(!server.LobbyInfo.GlobalSettings.Shroud));
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.Fog != defaults.Fog)
|
|
||||||
server.SendOrderTo(conn, "Message", "Fog of war: {0}".F(server.LobbyInfo.GlobalSettings.Fog));
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.Crates != defaults.Crates)
|
|
||||||
server.SendOrderTo(conn, "Message", "Crates Appear: {0}".F(server.LobbyInfo.GlobalSettings.Crates));
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.Creeps != defaults.Creeps)
|
|
||||||
server.SendOrderTo(conn, "Message", "Creeps Spawn: {0}".F(server.LobbyInfo.GlobalSettings.Creeps));
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.AllyBuildRadius != defaults.AllyBuildRadius)
|
|
||||||
server.SendOrderTo(conn, "Message", "Build off Ally ConYards: {0}".F(server.LobbyInfo.GlobalSettings.AllyBuildRadius));
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.StartingUnitsClass != defaults.StartingUnitsClass)
|
|
||||||
{
|
{
|
||||||
var startUnitsInfo = server.Map.Rules.Actors["world"].TraitInfos<MPStartUnitsInfo>();
|
Session.LobbyOptionState def;
|
||||||
var selectedClass = startUnitsInfo.Where(u => u.Class == server.LobbyInfo.GlobalSettings.StartingUnitsClass).Select(u => u.ClassName).FirstOrDefault();
|
if (!defaults.LobbyOptions.TryGetValue(kv.Key, out def) || kv.Value.Value != def.Value)
|
||||||
var className = selectedClass != null ? selectedClass : server.LobbyInfo.GlobalSettings.StartingUnitsClass;
|
server.SendOrderTo(conn, "Message", options[kv.Key].Name + ": " + kv.Value.Value);
|
||||||
server.SendOrderTo(conn, "Message", "Starting Units: {0}".F(className));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.StartingCash != defaults.StartingCash)
|
|
||||||
server.SendOrderTo(conn, "Message", "Starting Cash: ${0}".F(server.LobbyInfo.GlobalSettings.StartingCash));
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.TechLevel != defaults.TechLevel)
|
|
||||||
server.SendOrderTo(conn, "Message", "Tech Level: {0}".F(server.LobbyInfo.GlobalSettings.TechLevel));
|
|
||||||
|
|
||||||
if (server.LobbyInfo.GlobalSettings.ShortGame != defaults.ShortGame)
|
|
||||||
server.SendOrderTo(conn, "Message", "Short Game: {0}".F(server.LobbyInfo.GlobalSettings.ShortGame));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
var map = init.World.Map;
|
var map = init.World.Map;
|
||||||
|
|
||||||
// Explore map-placed actors if the "Explore Map" option is enabled
|
// Explore map-placed actors if the "Explore Map" option is enabled
|
||||||
var exploredMap = !init.World.LobbyInfo.GlobalSettings.Shroud;
|
var shroudInfo = init.World.Map.Rules.Actors["player"].TraitInfo<ShroudInfo>();
|
||||||
|
var exploredMap = init.World.LobbyInfo.GlobalSettings.OptionOrDefault("explored", shroudInfo.ExploredMapEnabled);
|
||||||
startsRevealed = exploredMap && init.Contains<SpawnedByMapInit>() && !init.Contains<HiddenUnderFogInit>();
|
startsRevealed = exploredMap && init.Contains<SpawnedByMapInit>() && !init.Contains<HiddenUnderFogInit>();
|
||||||
var footprintCells = FootprintUtils.FrozenUnderFogTiles(init.Self).ToList();
|
var footprintCells = FootprintUtils.FrozenUnderFogTiles(init.Self).ToList();
|
||||||
footprint = footprintCells.SelectMany(c => map.ProjectedCellsCovering(c.ToMPos(map))).ToArray();
|
footprint = footprintCells.SelectMany(c => map.ProjectedCellsCovering(c.ToMPos(map))).ToArray();
|
||||||
|
|||||||
@@ -15,7 +15,14 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
public class ProvidesTechPrerequisiteInfo : ITechTreePrerequisiteInfo
|
public class ProvidesTechPrerequisiteInfo : ITechTreePrerequisiteInfo
|
||||||
{
|
{
|
||||||
|
[Desc("Internal id for this tech level.")]
|
||||||
|
public readonly string Id;
|
||||||
|
|
||||||
|
[Translate]
|
||||||
|
[Desc("Name shown in the lobby options.")]
|
||||||
public readonly string Name;
|
public readonly string Name;
|
||||||
|
|
||||||
|
[Desc("Prerequisites to grant when this tech level is active.")]
|
||||||
public readonly string[] Prerequisites = { };
|
public readonly string[] Prerequisites = { };
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new ProvidesTechPrerequisite(this, init); }
|
public object Create(ActorInitializer init) { return new ProvidesTechPrerequisite(this, init); }
|
||||||
@@ -23,8 +30,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public class ProvidesTechPrerequisite : ITechTreePrerequisite
|
public class ProvidesTechPrerequisite : ITechTreePrerequisite
|
||||||
{
|
{
|
||||||
ProvidesTechPrerequisiteInfo info;
|
readonly ProvidesTechPrerequisiteInfo info;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
static readonly string[] NoPrerequisites = new string[0];
|
static readonly string[] NoPrerequisites = new string[0];
|
||||||
|
|
||||||
public string Name { get { return info.Name; } }
|
public string Name { get { return info.Name; } }
|
||||||
@@ -40,7 +48,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public ProvidesTechPrerequisite(ProvidesTechPrerequisiteInfo info, ActorInitializer init)
|
public ProvidesTechPrerequisite(ProvidesTechPrerequisiteInfo info, ActorInitializer init)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
enabled = info.Name == init.World.LobbyInfo.GlobalSettings.TechLevel;
|
var mapOptions = init.World.WorldActor.TraitOrDefault<MapOptions>();
|
||||||
|
enabled = mapOptions != null && mapOptions.TechLevel == info.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,13 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Mods.Common.Activities;
|
using OpenRA.Mods.Common.Activities;
|
||||||
|
using OpenRA.Network;
|
||||||
using OpenRA.Primitives;
|
using OpenRA.Primitives;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
public class CrateSpawnerInfo : ITraitInfo
|
public class CrateSpawnerInfo : ITraitInfo, ILobbyOptions
|
||||||
{
|
{
|
||||||
[Desc("Default value of the crates checkbox in the lobby.")]
|
[Desc("Default value of the crates checkbox in the lobby.")]
|
||||||
public readonly bool Enabled = true;
|
public readonly bool Enabled = true;
|
||||||
@@ -64,27 +65,39 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("Spawn and remove the plane this far outside the map.")]
|
[Desc("Spawn and remove the plane this far outside the map.")]
|
||||||
public readonly WDist Cordon = new WDist(5120);
|
public readonly WDist Cordon = new WDist(5120);
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new CrateSpawner(this, init.Self); }
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
|
||||||
|
{
|
||||||
|
yield return new LobbyBooleanOption("crates", "Crates", Enabled, Locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new CrateSpawner(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CrateSpawner : ITick
|
public class CrateSpawner : ITick, INotifyCreated
|
||||||
{
|
{
|
||||||
readonly CrateSpawnerInfo info;
|
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
int crates = 0;
|
readonly CrateSpawnerInfo info;
|
||||||
int ticks = 0;
|
bool enabled;
|
||||||
|
int crates;
|
||||||
|
int ticks;
|
||||||
|
|
||||||
public CrateSpawner(CrateSpawnerInfo info, Actor self)
|
public CrateSpawner(Actor self, CrateSpawnerInfo info)
|
||||||
{
|
{
|
||||||
this.info = info;
|
|
||||||
this.self = self;
|
this.self = self;
|
||||||
|
this.info = info;
|
||||||
|
|
||||||
ticks = info.InitialSpawnDelay;
|
ticks = info.InitialSpawnDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void INotifyCreated.Created(Actor self)
|
||||||
|
{
|
||||||
|
enabled = self.World.LobbyInfo.GlobalSettings
|
||||||
|
.OptionOrDefault("crates", info.Enabled);
|
||||||
|
}
|
||||||
|
|
||||||
public void Tick(Actor self)
|
public void Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (!self.World.LobbyInfo.GlobalSettings.Crates)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (--ticks <= 0)
|
if (--ticks <= 0)
|
||||||
|
|||||||
@@ -15,22 +15,36 @@ using OpenRA.Traits;
|
|||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Controls the build radius checkboxes in the lobby options.")]
|
[Desc("Controls the build radius checkboxes in the lobby options.")]
|
||||||
public class MapBuildRadiusInfo : TraitInfo<MapBuildRadius>
|
public class MapBuildRadiusInfo : ITraitInfo, ILobbyOptions
|
||||||
{
|
{
|
||||||
[Desc("Default value of the ally build radius checkbox in the lobby.")]
|
[Desc("Default value of the ally build radius checkbox in the lobby.")]
|
||||||
public readonly bool AllyBuildRadiusEnabled = true;
|
public readonly bool AllyBuildRadiusEnabled = true;
|
||||||
|
|
||||||
[Desc("Prevent the ally build radius state from being changed in the lobby.")]
|
[Desc("Prevent the ally build radius state from being changed in the lobby.")]
|
||||||
public readonly bool AllyBuildRadiusLocked = false;
|
public readonly bool AllyBuildRadiusLocked = false;
|
||||||
|
|
||||||
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
|
||||||
|
{
|
||||||
|
yield return new LobbyBooleanOption("allybuild", "Build off Allies' ConYards", AllyBuildRadiusEnabled, AllyBuildRadiusLocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new MapBuildRadius(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MapBuildRadius : INotifyCreated
|
public class MapBuildRadius : INotifyCreated
|
||||||
{
|
{
|
||||||
|
readonly MapBuildRadiusInfo info;
|
||||||
public bool AllyBuildRadiusEnabled { get; private set; }
|
public bool AllyBuildRadiusEnabled { get; private set; }
|
||||||
|
|
||||||
|
public MapBuildRadius(MapBuildRadiusInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
{
|
{
|
||||||
AllyBuildRadiusEnabled = self.World.LobbyInfo.GlobalSettings.AllyBuildRadius;
|
AllyBuildRadiusEnabled = self.World.LobbyInfo.GlobalSettings
|
||||||
|
.OptionOrDefault("allybuild", info.AllyBuildRadiusEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,22 +15,36 @@ using OpenRA.Traits;
|
|||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Controls the 'Creeps' checkbox in the lobby options.")]
|
[Desc("Controls the 'Creeps' checkbox in the lobby options.")]
|
||||||
public class MapCreepsInfo : TraitInfo<MapCreeps>
|
public class MapCreepsInfo : ITraitInfo, ILobbyOptions
|
||||||
{
|
{
|
||||||
[Desc("Default value of the creeps checkbox in the lobby.")]
|
[Desc("Default value of the creeps checkbox in the lobby.")]
|
||||||
public readonly bool Enabled = true;
|
public readonly bool Enabled = true;
|
||||||
|
|
||||||
[Desc("Prevent the creeps state from being changed in the lobby.")]
|
[Desc("Prevent the creeps state from being changed in the lobby.")]
|
||||||
public readonly bool Locked = false;
|
public readonly bool Locked = false;
|
||||||
|
|
||||||
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
|
||||||
|
{
|
||||||
|
yield return new LobbyBooleanOption("creeps", "Worms", Enabled, Locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new MapCreeps(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MapCreeps : INotifyCreated
|
public class MapCreeps : INotifyCreated
|
||||||
{
|
{
|
||||||
|
readonly MapCreepsInfo info;
|
||||||
public bool Enabled { get; private set; }
|
public bool Enabled { get; private set; }
|
||||||
|
|
||||||
|
public MapCreeps(MapCreepsInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
{
|
{
|
||||||
Enabled = self.World.LobbyInfo.GlobalSettings.Creeps;
|
Enabled = self.World.LobbyInfo.GlobalSettings
|
||||||
|
.OptionOrDefault("creeps", info.Enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,13 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Controls the map difficulty, tech level, and short game lobby options.")]
|
[Desc("Controls the map difficulty, tech level, and short game lobby options.")]
|
||||||
public class MapOptionsInfo : TraitInfo<MapOptions>
|
public class MapOptionsInfo : ITraitInfo, ILobbyOptions
|
||||||
{
|
{
|
||||||
[Desc("Default value of the short game checkbox in the lobby.")]
|
[Desc("Default value of the short game checkbox in the lobby.")]
|
||||||
public readonly bool ShortGameEnabled = true;
|
public readonly bool ShortGameEnabled = true;
|
||||||
@@ -24,7 +25,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public readonly bool ShortGameLocked = false;
|
public readonly bool ShortGameLocked = false;
|
||||||
|
|
||||||
[Desc("Default tech level.")]
|
[Desc("Default tech level.")]
|
||||||
public readonly string TechLevel = "Unrestricted";
|
public readonly string TechLevel = "unrestricted";
|
||||||
|
|
||||||
[Desc("Prevent the tech level from being changed in the lobby.")]
|
[Desc("Prevent the tech level from being changed in the lobby.")]
|
||||||
public readonly bool TechLevelLocked = false;
|
public readonly bool TechLevelLocked = false;
|
||||||
@@ -37,15 +38,42 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
[Desc("Prevent the difficulty from being changed in the lobby.")]
|
[Desc("Prevent the difficulty from being changed in the lobby.")]
|
||||||
public readonly bool DifficultyLocked = false;
|
public readonly bool DifficultyLocked = false;
|
||||||
|
|
||||||
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
|
||||||
|
{
|
||||||
|
yield return new LobbyBooleanOption("shortgame", "Short Game", ShortGameEnabled, ShortGameLocked);
|
||||||
|
|
||||||
|
var techLevels = rules.Actors["player"].TraitInfos<ProvidesTechPrerequisiteInfo>()
|
||||||
|
.ToDictionary(t => t.Id, t => t.Name);
|
||||||
|
|
||||||
|
if (techLevels.Any())
|
||||||
|
yield return new LobbyOption("techlevel", "Tech Level",
|
||||||
|
new ReadOnlyDictionary<string, string>(techLevels),
|
||||||
|
TechLevel, TechLevelLocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new MapOptions(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MapOptions : INotifyCreated
|
public class MapOptions : INotifyCreated
|
||||||
{
|
{
|
||||||
|
readonly MapOptionsInfo info;
|
||||||
|
|
||||||
public bool ShortGame { get; private set; }
|
public bool ShortGame { get; private set; }
|
||||||
|
public string TechLevel { get; private set; }
|
||||||
|
|
||||||
|
public MapOptions(MapOptionsInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
{
|
{
|
||||||
ShortGame = self.World.LobbyInfo.GlobalSettings.ShortGame;
|
ShortGame = self.World.LobbyInfo.GlobalSettings
|
||||||
|
.OptionOrDefault("shortgame", info.ShortGameEnabled);
|
||||||
|
|
||||||
|
TechLevel = self.World.LobbyInfo.GlobalSettings
|
||||||
|
.OptionOrDefault("techlevel", info.TechLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Primitives;
|
using OpenRA.Primitives;
|
||||||
@@ -18,25 +19,48 @@ using OpenRA.Traits;
|
|||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Spawn base actor at the spawnpoint and support units in an annulus around the base actor. Both are defined at MPStartUnits. Attach this to the world actor.")]
|
[Desc("Spawn base actor at the spawnpoint and support units in an annulus around the base actor. Both are defined at MPStartUnits. Attach this to the world actor.")]
|
||||||
public class SpawnMPUnitsInfo : TraitInfo<SpawnMPUnits>, Requires<MPStartLocationsInfo>, Requires<MPStartUnitsInfo>
|
public class SpawnMPUnitsInfo : ITraitInfo, Requires<MPStartLocationsInfo>, Requires<MPStartUnitsInfo>, ILobbyOptions
|
||||||
{
|
{
|
||||||
public readonly string StartingUnitsClass = "none";
|
public readonly string StartingUnitsClass = "none";
|
||||||
|
|
||||||
[Desc("Prevent the starting units option from being changed in the lobby.")]
|
[Desc("Prevent the starting units option from being changed in the lobby.")]
|
||||||
public bool Locked = false;
|
public bool Locked = false;
|
||||||
|
|
||||||
|
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
|
||||||
|
{
|
||||||
|
var startingUnits = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
// Duplicate classes are defined for different race variants
|
||||||
|
foreach (var t in rules.Actors["world"].TraitInfos<MPStartUnitsInfo>())
|
||||||
|
startingUnits[t.Class] = t.ClassName;
|
||||||
|
|
||||||
|
if (startingUnits.Any())
|
||||||
|
yield return new LobbyOption("startingunits", "Starting Units", new ReadOnlyDictionary<string, string>(startingUnits), StartingUnitsClass, Locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new SpawnMPUnits(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SpawnMPUnits : IWorldLoaded
|
public class SpawnMPUnits : IWorldLoaded
|
||||||
{
|
{
|
||||||
|
readonly SpawnMPUnitsInfo info;
|
||||||
|
|
||||||
|
public SpawnMPUnits(SpawnMPUnitsInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
public void WorldLoaded(World world, WorldRenderer wr)
|
public void WorldLoaded(World world, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
foreach (var s in world.WorldActor.Trait<MPStartLocations>().Start)
|
foreach (var s in world.WorldActor.Trait<MPStartLocations>().Start)
|
||||||
SpawnUnitsForPlayer(world, s.Key, s.Value);
|
SpawnUnitsForPlayer(world, s.Key, s.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SpawnUnitsForPlayer(World w, Player p, CPos sp)
|
void SpawnUnitsForPlayer(World w, Player p, CPos sp)
|
||||||
{
|
{
|
||||||
var spawnClass = p.PlayerReference.StartingUnitsClass ?? w.LobbyInfo.GlobalSettings.StartingUnitsClass;
|
var spawnClass = p.PlayerReference.StartingUnitsClass ?? w.LobbyInfo.GlobalSettings
|
||||||
|
.OptionOrDefault("startingunits", info.StartingUnitsClass);
|
||||||
|
|
||||||
var unitGroup = w.Map.Rules.Actors["world"].TraitInfos<MPStartUnitsInfo>()
|
var unitGroup = w.Map.Rules.Actors["world"].TraitInfos<MPStartUnitsInfo>()
|
||||||
.Where(g => g.Class == spawnClass && g.Factions != null && g.Factions.Contains(p.Faction.InternalName))
|
.Where(g => g.Class == spawnClass && g.Factions != null && g.Factions.Contains(p.Faction.InternalName))
|
||||||
.RandomOrDefault(w.SharedRandom);
|
.RandomOrDefault(w.SharedRandom);
|
||||||
|
|||||||
@@ -123,6 +123,13 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (engineVersion < 20160604 && node.Key.StartsWith("ProvidesTechPrerequisite"))
|
||||||
|
{
|
||||||
|
var name = node.Value.Nodes.First(n => n.Key == "Name");
|
||||||
|
var id = name.Value.Value.ToLowerInvariant().Replace(" ", "");
|
||||||
|
node.Value.Nodes.Add(new MiniYamlNode("Id", id));
|
||||||
|
}
|
||||||
|
|
||||||
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
|
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,12 +75,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Debug/Cheats tab
|
// Debug/Cheats tab
|
||||||
if (lp != null && world.LobbyInfo.GlobalSettings.AllowCheats)
|
// Can't use DeveloperMode.Enabled because there is a hardcoded hack to *always*
|
||||||
|
// enable developer mode for singleplayer games, but we only want to show the button
|
||||||
|
// if it has been explicitly enabled
|
||||||
|
var def = world.Map.Rules.Actors["player"].TraitInfo<DeveloperModeInfo>().Enabled;
|
||||||
|
var developerEnabled = world.LobbyInfo.GlobalSettings.OptionOrDefault("cheats", def);
|
||||||
|
if (lp != null && developerEnabled)
|
||||||
{
|
{
|
||||||
numTabs++;
|
numTabs++;
|
||||||
var debugTabButton = widget.Get<ButtonWidget>(string.Concat("BUTTON", numTabs.ToString()));
|
var debugTabButton = widget.Get<ButtonWidget>(string.Concat("BUTTON", numTabs.ToString()));
|
||||||
debugTabButton.Text = "Debug";
|
debugTabButton.Text = "Debug";
|
||||||
debugTabButton.IsVisible = () => lp != null && world.LobbyInfo.GlobalSettings.AllowCheats && numTabs > 1 && !hasError;
|
debugTabButton.IsVisible = () => lp != null && numTabs > 1 && !hasError;
|
||||||
debugTabButton.IsDisabled = () => world.IsGameOver;
|
debugTabButton.IsDisabled = () => world.IsGameOver;
|
||||||
debugTabButton.OnClick = () => activePanel = IngameInfoPanel.Debug;
|
debugTabButton.OnClick = () => activePanel = IngameInfoPanel.Debug;
|
||||||
debugTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Debug;
|
debugTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Debug;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Traits;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
@@ -67,7 +68,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var debug = widget.GetOrNull<MenuButtonWidget>("DEBUG_BUTTON");
|
var debug = widget.GetOrNull<MenuButtonWidget>("DEBUG_BUTTON");
|
||||||
if (debug != null)
|
if (debug != null)
|
||||||
{
|
{
|
||||||
debug.IsVisible = () => world.LobbyInfo.GlobalSettings.AllowCheats;
|
// Can't use DeveloperMode.Enabled because there is a hardcoded hack to *always*
|
||||||
|
// enable developer mode for singleplayer games, but we only want to show the button
|
||||||
|
// if it has been explicitly enabled
|
||||||
|
var def = world.Map.Rules.Actors["player"].TraitInfo<DeveloperModeInfo>().Enabled;
|
||||||
|
var enabled = world.LobbyInfo.GlobalSettings.OptionOrDefault("cheats", def);
|
||||||
|
debug.IsVisible = () => enabled;
|
||||||
debug.IsDisabled = () => disableSystemButtons;
|
debug.IsDisabled = () => disableSystemButtons;
|
||||||
debug.OnClick = () => OpenMenuPanel(debug, new WidgetArgs()
|
debug.OnClick = () => OpenMenuPanel(debug, new WidgetArgs()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -336,73 +336,91 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
forceStartBin.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => panel = PanelType.Players;
|
forceStartBin.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => panel = PanelType.Players;
|
||||||
|
|
||||||
// Options panel
|
// Options panel
|
||||||
var allowCheats = optionsBin.GetOrNull<CheckboxWidget>("ALLOWCHEATS_CHECKBOX");
|
var optionCheckboxes = new Dictionary<string, string>()
|
||||||
if (allowCheats != null)
|
|
||||||
{
|
{
|
||||||
var cheatsLocked = new CachedTransform<MapPreview, bool>(
|
{ "EXPLORED_MAP_CHECKBOX", "explored" },
|
||||||
map => map.Rules.Actors["player"].TraitInfo<DeveloperModeInfo>().Locked);
|
{ "CRATES_CHECKBOX", "crates" },
|
||||||
|
{ "SHORTGAME_CHECKBOX", "shortgame" },
|
||||||
|
{ "FOG_CHECKBOX", "fog" },
|
||||||
|
{ "ALLYBUILDRADIUS_CHECKBOX", "allybuild" },
|
||||||
|
{ "ALLOWCHEATS_CHECKBOX", "cheats" },
|
||||||
|
{ "CREEPS_CHECKBOX", "creeps" },
|
||||||
|
};
|
||||||
|
|
||||||
allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats;
|
foreach (var kv in optionCheckboxes)
|
||||||
allowCheats.IsDisabled = () => configurationDisabled() || cheatsLocked.Update(Map);
|
|
||||||
allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command(
|
|
||||||
"allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var crates = optionsBin.GetOrNull<CheckboxWidget>("CRATES_CHECKBOX");
|
|
||||||
if (crates != null)
|
|
||||||
{
|
{
|
||||||
var cratesLocked = new CachedTransform<MapPreview, bool>(map =>
|
var checkbox = optionsBin.GetOrNull<CheckboxWidget>(kv.Key);
|
||||||
|
if (checkbox != null)
|
||||||
{
|
{
|
||||||
var crateSpawner = map.Rules.Actors["world"].TraitInfoOrDefault<CrateSpawnerInfo>();
|
var option = new CachedTransform<Session.Global, Session.LobbyOptionState>(
|
||||||
return crateSpawner == null || crateSpawner.Locked;
|
gs => gs.LobbyOptions[kv.Value]);
|
||||||
});
|
|
||||||
|
|
||||||
crates.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Crates;
|
checkbox.IsChecked = () => option.Update(orderManager.LobbyInfo.GlobalSettings).Enabled;
|
||||||
crates.IsDisabled = () => configurationDisabled() || cratesLocked.Update(Map);
|
checkbox.IsDisabled = () => configurationDisabled() ||
|
||||||
crates.OnClick = () => orderManager.IssueOrder(Order.Command(
|
option.Update(orderManager.LobbyInfo.GlobalSettings).Locked;
|
||||||
"crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates)));
|
checkbox.OnClick = () => orderManager.IssueOrder(Order.Command(
|
||||||
|
"option {0} {1}".F(kv.Value, !option.Update(orderManager.LobbyInfo.GlobalSettings).Enabled)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var creeps = optionsBin.GetOrNull<CheckboxWidget>("CREEPS_CHECKBOX");
|
var optionDropdowns = new Dictionary<string, string>()
|
||||||
if (creeps != null)
|
|
||||||
{
|
{
|
||||||
var creepsLocked = new CachedTransform<MapPreview, bool>(map =>
|
{ "TECHLEVEL", "techlevel" },
|
||||||
|
{ "STARTINGUNITS", "startingunits" },
|
||||||
|
{ "STARTINGCASH", "startingcash" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var allOptions = new CachedTransform<MapPreview, LobbyOption[]>(
|
||||||
|
map => map.Rules.Actors["player"].TraitInfos<ILobbyOptions>()
|
||||||
|
.Concat(map.Rules.Actors["world"].TraitInfos<ILobbyOptions>())
|
||||||
|
.SelectMany(t => t.LobbyOptions(map.Rules))
|
||||||
|
.ToArray());
|
||||||
|
|
||||||
|
foreach (var kv in optionDropdowns)
|
||||||
|
{
|
||||||
|
var dropdown = optionsBin.GetOrNull<DropDownButtonWidget>(kv.Key + "_DROPDOWNBUTTON");
|
||||||
|
if (dropdown != null)
|
||||||
{
|
{
|
||||||
var mapCreeps = map.Rules.Actors["world"].TraitInfoOrDefault<MapCreepsInfo>();
|
var optionValue = new CachedTransform<Session.Global, Session.LobbyOptionState>(
|
||||||
return mapCreeps == null || mapCreeps.Locked;
|
gs => gs.LobbyOptions[kv.Value]);
|
||||||
});
|
|
||||||
|
|
||||||
creeps.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Creeps;
|
var option = new CachedTransform<MapPreview, LobbyOption>(
|
||||||
creeps.IsDisabled = () => configurationDisabled() || creepsLocked.Update(Map);
|
map => allOptions.Update(map).FirstOrDefault(o => o.Id == kv.Value));
|
||||||
creeps.OnClick = () => orderManager.IssueOrder(Order.Command(
|
|
||||||
"creeps {0}".F(!orderManager.LobbyInfo.GlobalSettings.Creeps)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var allybuildradius = optionsBin.GetOrNull<CheckboxWidget>("ALLYBUILDRADIUS_CHECKBOX");
|
var getOptionLabel = new CachedTransform<string, string>(id =>
|
||||||
if (allybuildradius != null)
|
{
|
||||||
{
|
string value;
|
||||||
var allyBuildRadiusLocked = new CachedTransform<MapPreview, bool>(map =>
|
if (id == null || !option.Update(Map).Values.TryGetValue(id, out value))
|
||||||
{
|
return "Not Available";
|
||||||
var mapBuildRadius = map.Rules.Actors["world"].TraitInfoOrDefault<MapBuildRadiusInfo>();
|
|
||||||
return mapBuildRadius == null || mapBuildRadius.AllyBuildRadiusLocked;
|
|
||||||
});
|
|
||||||
|
|
||||||
allybuildradius.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius;
|
return value;
|
||||||
allybuildradius.IsDisabled = () => configurationDisabled() || allyBuildRadiusLocked.Update(Map);
|
});
|
||||||
allybuildradius.OnClick = () => orderManager.IssueOrder(Order.Command(
|
|
||||||
"allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var shortGame = optionsBin.GetOrNull<CheckboxWidget>("SHORTGAME_CHECKBOX");
|
dropdown.GetText = () => getOptionLabel.Update(optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value);
|
||||||
if (shortGame != null)
|
dropdown.IsVisible = () => option.Update(Map) != null;
|
||||||
{
|
dropdown.IsDisabled = () => configurationDisabled() ||
|
||||||
var shortGameLocked = new CachedTransform<MapPreview, bool>(
|
optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Locked;
|
||||||
map => map.Rules.Actors["world"].TraitInfo<MapOptionsInfo>().ShortGameLocked);
|
|
||||||
|
|
||||||
shortGame.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.ShortGame;
|
dropdown.OnMouseDown = _ =>
|
||||||
shortGame.IsDisabled = () => configurationDisabled() || shortGameLocked.Update(Map);
|
{
|
||||||
shortGame.OnClick = () => orderManager.IssueOrder(Order.Command(
|
Func<KeyValuePair<string, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (c, template) =>
|
||||||
"shortgame {0}".F(!orderManager.LobbyInfo.GlobalSettings.ShortGame)));
|
{
|
||||||
|
Func<bool> isSelected = () => optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value == c.Key;
|
||||||
|
Action onClick = () => orderManager.IssueOrder(Order.Command("option {0} {1}".F(kv.Value, c.Key)));
|
||||||
|
|
||||||
|
var item = ScrollItemWidget.Setup(template, isSelected, onClick);
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => c.Value;
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
var options = option.Update(Map).Values;
|
||||||
|
dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
var label = optionsBin.GetOrNull(kv.Key + "_DESC");
|
||||||
|
if (label != null)
|
||||||
|
label.IsVisible = () => option.Update(Map) != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var difficulty = optionsBin.GetOrNull<DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");
|
var difficulty = optionsBin.GetOrNull<DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");
|
||||||
@@ -434,116 +452,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
optionsBin.Get<LabelWidget>("DIFFICULTY_DESC").IsVisible = difficulty.IsVisible;
|
optionsBin.Get<LabelWidget>("DIFFICULTY_DESC").IsVisible = difficulty.IsVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
var startingUnits = optionsBin.GetOrNull<DropDownButtonWidget>("STARTINGUNITS_DROPDOWNBUTTON");
|
|
||||||
if (startingUnits != null)
|
|
||||||
{
|
|
||||||
var startUnitsInfos = new CachedTransform<MapPreview, IEnumerable<MPStartUnitsInfo>>(
|
|
||||||
map => map.Rules.Actors["world"].TraitInfos<MPStartUnitsInfo>());
|
|
||||||
|
|
||||||
var startUnitsLocked = new CachedTransform<MapPreview, bool>(map =>
|
|
||||||
{
|
|
||||||
var spawnUnitsInfo = map.Rules.Actors["world"].TraitInfoOrDefault<SpawnMPUnitsInfo>();
|
|
||||||
return spawnUnitsInfo == null || spawnUnitsInfo.Locked;
|
|
||||||
});
|
|
||||||
|
|
||||||
Func<string, string> className = c =>
|
|
||||||
{
|
|
||||||
var selectedClass = startUnitsInfos.Update(Map).Where(s => s.Class == c).Select(u => u.ClassName).FirstOrDefault();
|
|
||||||
return selectedClass != null ? selectedClass : c;
|
|
||||||
};
|
|
||||||
|
|
||||||
startingUnits.IsDisabled = () => configurationDisabled() || startUnitsLocked.Update(Map);
|
|
||||||
startingUnits.GetText = () => !Map.RulesLoaded || startUnitsLocked.Update(Map) ?
|
|
||||||
"Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass);
|
|
||||||
startingUnits.OnMouseDown = _ =>
|
|
||||||
{
|
|
||||||
var classes = startUnitsInfos.Update(Map).Select(a => a.Class).Distinct();
|
|
||||||
var options = classes.Select(c => new DropDownOption
|
|
||||||
{
|
|
||||||
Title = className(c),
|
|
||||||
IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass == c,
|
|
||||||
OnClick = () => orderManager.IssueOrder(Order.Command("startingunits {0}".F(c)))
|
|
||||||
});
|
|
||||||
|
|
||||||
Func<DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
|
||||||
{
|
|
||||||
var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
|
|
||||||
item.Get<LabelWidget>("LABEL").GetText = () => option.Title;
|
|
||||||
return item;
|
|
||||||
};
|
|
||||||
|
|
||||||
startingUnits.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
|
|
||||||
};
|
|
||||||
|
|
||||||
optionsBin.Get<LabelWidget>("STARTINGUNITS_DESC").IsVisible = startingUnits.IsVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
var startingCash = optionsBin.GetOrNull<DropDownButtonWidget>("STARTINGCASH_DROPDOWNBUTTON");
|
|
||||||
if (startingCash != null)
|
|
||||||
{
|
|
||||||
var playerResources = new CachedTransform<MapPreview, PlayerResourcesInfo>(
|
|
||||||
map => map.Rules.Actors["player"].TraitInfo<PlayerResourcesInfo>());
|
|
||||||
|
|
||||||
startingCash.IsDisabled = () => configurationDisabled() || playerResources.Update(Map).DefaultCashLocked;
|
|
||||||
startingCash.GetText = () => !Map.RulesLoaded || playerResources.Update(Map).DefaultCashLocked ?
|
|
||||||
"Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
|
|
||||||
startingCash.OnMouseDown = _ =>
|
|
||||||
{
|
|
||||||
var options = playerResources.Update(Map).SelectableCash.Select(c => new DropDownOption
|
|
||||||
{
|
|
||||||
Title = "${0}".F(c),
|
|
||||||
IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingCash == c,
|
|
||||||
OnClick = () => orderManager.IssueOrder(Order.Command("startingcash {0}".F(c)))
|
|
||||||
});
|
|
||||||
|
|
||||||
Func<DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
|
||||||
{
|
|
||||||
var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
|
|
||||||
item.Get<LabelWidget>("LABEL").GetText = () => option.Title;
|
|
||||||
return item;
|
|
||||||
};
|
|
||||||
|
|
||||||
startingCash.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var techLevel = optionsBin.GetOrNull<DropDownButtonWidget>("TECHLEVEL_DROPDOWNBUTTON");
|
|
||||||
if (techLevel != null)
|
|
||||||
{
|
|
||||||
var mapOptions = new CachedTransform<MapPreview, MapOptionsInfo>(
|
|
||||||
map => map.Rules.Actors["world"].TraitInfo<MapOptionsInfo>());
|
|
||||||
|
|
||||||
var techLevels = new CachedTransform<MapPreview, List<ProvidesTechPrerequisiteInfo>>(
|
|
||||||
map => map.Rules.Actors["player"].TraitInfos<ProvidesTechPrerequisiteInfo>().ToList());
|
|
||||||
|
|
||||||
techLevel.IsVisible = () => Map.RulesLoaded && techLevels.Update(Map).Any();
|
|
||||||
var techLevelDescription = optionsBin.GetOrNull<LabelWidget>("TECHLEVEL_DESC");
|
|
||||||
if (techLevelDescription != null)
|
|
||||||
techLevelDescription.IsVisible = techLevel.IsVisible;
|
|
||||||
|
|
||||||
techLevel.IsDisabled = () => configurationDisabled() || mapOptions.Update(Map).TechLevelLocked;
|
|
||||||
techLevel.GetText = () => !Map.RulesLoaded || mapOptions.Update(Map).TechLevelLocked ?
|
|
||||||
"Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel);
|
|
||||||
techLevel.OnMouseDown = _ =>
|
|
||||||
{
|
|
||||||
var options = techLevels.Update(Map).Select(c => new DropDownOption
|
|
||||||
{
|
|
||||||
Title = "{0}".F(c.Name),
|
|
||||||
IsSelected = () => orderManager.LobbyInfo.GlobalSettings.TechLevel == c.Name,
|
|
||||||
OnClick = () => orderManager.IssueOrder(Order.Command("techlevel {0}".F(c.Name)))
|
|
||||||
});
|
|
||||||
|
|
||||||
Func<DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
|
||||||
{
|
|
||||||
var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
|
|
||||||
item.Get<LabelWidget>("LABEL").GetText = () => option.Title;
|
|
||||||
return item;
|
|
||||||
};
|
|
||||||
|
|
||||||
techLevel.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var gameSpeed = optionsBin.GetOrNull<DropDownButtonWidget>("GAMESPEED_DROPDOWNBUTTON");
|
var gameSpeed = optionsBin.GetOrNull<DropDownButtonWidget>("GAMESPEED_DROPDOWNBUTTON");
|
||||||
if (gameSpeed != null)
|
if (gameSpeed != null)
|
||||||
{
|
{
|
||||||
@@ -582,30 +490,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var exploredMap = optionsBin.GetOrNull<CheckboxWidget>("EXPLORED_MAP_CHECKBOX");
|
|
||||||
if (exploredMap != null)
|
|
||||||
{
|
|
||||||
var exploredMapLocked = new CachedTransform<MapPreview, bool>(
|
|
||||||
map => map.Rules.Actors["player"].TraitInfo<ShroudInfo>().ExploredMapLocked);
|
|
||||||
|
|
||||||
exploredMap.IsChecked = () => !orderManager.LobbyInfo.GlobalSettings.Shroud;
|
|
||||||
exploredMap.IsDisabled = () => configurationDisabled() || exploredMapLocked.Update(Map);
|
|
||||||
exploredMap.OnClick = () => orderManager.IssueOrder(Order.Command(
|
|
||||||
"shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var enableFog = optionsBin.GetOrNull<CheckboxWidget>("FOG_CHECKBOX");
|
|
||||||
if (enableFog != null)
|
|
||||||
{
|
|
||||||
var fogLocked = new CachedTransform<MapPreview, bool>(
|
|
||||||
map => map.Rules.Actors["player"].TraitInfo<ShroudInfo>().FogLocked);
|
|
||||||
|
|
||||||
enableFog.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Fog;
|
|
||||||
enableFog.IsDisabled = () => configurationDisabled() || fogLocked.Update(Map);
|
|
||||||
enableFog.OnClick = () => orderManager.IssueOrder(Order.Command(
|
|
||||||
"fog {0}".F(!orderManager.LobbyInfo.GlobalSettings.Fog)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var disconnectButton = lobby.Get<ButtonWidget>("DISCONNECT_BUTTON");
|
var disconnectButton = lobby.Get<ButtonWidget>("DISCONNECT_BUTTON");
|
||||||
disconnectButton.OnClick = () => { Ui.CloseWindow(); onExit(); };
|
disconnectButton.OnClick = () => { Ui.CloseWindow(); onExit(); };
|
||||||
|
|
||||||
|
|||||||
@@ -19,14 +19,18 @@ Player:
|
|||||||
ProvidesTechPrerequisite@low:
|
ProvidesTechPrerequisite@low:
|
||||||
Name: Low
|
Name: Low
|
||||||
Prerequisites: techlevel.low
|
Prerequisites: techlevel.low
|
||||||
|
Id: low
|
||||||
ProvidesTechPrerequisite@medium:
|
ProvidesTechPrerequisite@medium:
|
||||||
Name: Medium
|
Name: Medium
|
||||||
Prerequisites: techlevel.low, techlevel.medium
|
Prerequisites: techlevel.low, techlevel.medium
|
||||||
|
Id: medium
|
||||||
ProvidesTechPrerequisite@nosuper:
|
ProvidesTechPrerequisite@nosuper:
|
||||||
Name: No Powers
|
Name: No Powers
|
||||||
Prerequisites: techlevel.low, techlevel.medium, techlevel.high
|
Prerequisites: techlevel.low, techlevel.medium, techlevel.high
|
||||||
|
Id: nopowers
|
||||||
ProvidesTechPrerequisite@all:
|
ProvidesTechPrerequisite@all:
|
||||||
Name: Unrestricted
|
Name: Unrestricted
|
||||||
Prerequisites: techlevel.low, techlevel.medium, techlevel.high, techlevel.superweapons
|
Prerequisites: techlevel.low, techlevel.medium, techlevel.high, techlevel.superweapons
|
||||||
|
Id: unrestricted
|
||||||
GlobalUpgradeManager:
|
GlobalUpgradeManager:
|
||||||
ResourceStorageWarning:
|
ResourceStorageWarning:
|
||||||
|
|||||||
@@ -73,15 +73,19 @@ Player:
|
|||||||
ProvidesTechPrerequisite@low:
|
ProvidesTechPrerequisite@low:
|
||||||
Name: Low
|
Name: Low
|
||||||
Prerequisites: techlevel.low
|
Prerequisites: techlevel.low
|
||||||
|
Id: low
|
||||||
ProvidesTechPrerequisite@medium:
|
ProvidesTechPrerequisite@medium:
|
||||||
Name: Medium
|
Name: Medium
|
||||||
Prerequisites: techlevel.low, techlevel.medium
|
Prerequisites: techlevel.low, techlevel.medium
|
||||||
|
Id: medium
|
||||||
ProvidesTechPrerequisite@nosuper:
|
ProvidesTechPrerequisite@nosuper:
|
||||||
Name: No Powers
|
Name: No Powers
|
||||||
Prerequisites: techlevel.low, techlevel.medium, techlevel.high
|
Prerequisites: techlevel.low, techlevel.medium, techlevel.high
|
||||||
|
Id: nopowers
|
||||||
ProvidesTechPrerequisite@all:
|
ProvidesTechPrerequisite@all:
|
||||||
Name: Unrestricted
|
Name: Unrestricted
|
||||||
Prerequisites: techlevel.low, techlevel.medium, techlevel.high, techlevel.superweapons
|
Prerequisites: techlevel.low, techlevel.medium, techlevel.high, techlevel.superweapons
|
||||||
|
Id: unrestricted
|
||||||
EnemyWatcher:
|
EnemyWatcher:
|
||||||
HarvesterInsurance:
|
HarvesterInsurance:
|
||||||
GlobalUpgradeManager:
|
GlobalUpgradeManager:
|
||||||
|
|||||||
@@ -55,18 +55,23 @@ Player:
|
|||||||
ProvidesTechPrerequisite@infonly:
|
ProvidesTechPrerequisite@infonly:
|
||||||
Name: Infantry Only
|
Name: Infantry Only
|
||||||
Prerequisites: techlevel.infonly
|
Prerequisites: techlevel.infonly
|
||||||
|
Id: infantryonly
|
||||||
ProvidesTechPrerequisite@low:
|
ProvidesTechPrerequisite@low:
|
||||||
Name: Low
|
Name: Low
|
||||||
Prerequisites: techlevel.infonly, techlevel.low
|
Prerequisites: techlevel.infonly, techlevel.low
|
||||||
|
Id: low
|
||||||
ProvidesTechPrerequisite@medium:
|
ProvidesTechPrerequisite@medium:
|
||||||
Name: Medium
|
Name: Medium
|
||||||
Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium
|
Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium
|
||||||
|
Id: medium
|
||||||
ProvidesTechPrerequisite@high:
|
ProvidesTechPrerequisite@high:
|
||||||
Name: No Superweapons
|
Name: No Superweapons
|
||||||
Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium, techlevel.high
|
Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium, techlevel.high
|
||||||
|
Id: nosuperweapons
|
||||||
ProvidesTechPrerequisite@unrestricted:
|
ProvidesTechPrerequisite@unrestricted:
|
||||||
Name: Unrestricted
|
Name: Unrestricted
|
||||||
Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium, techlevel.high, techlevel.unrestricted
|
Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium, techlevel.high, techlevel.unrestricted
|
||||||
|
Id: unrestricted
|
||||||
GlobalUpgradeManager:
|
GlobalUpgradeManager:
|
||||||
EnemyWatcher:
|
EnemyWatcher:
|
||||||
VeteranProductionIconOverlay:
|
VeteranProductionIconOverlay:
|
||||||
|
|||||||
Reference in New Issue
Block a user