Compare commits
49 Commits
devtest-20
...
release-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65fc9af8b5 | ||
|
|
dc8c8b9fb5 | ||
|
|
968c5b7fba | ||
|
|
086938b812 | ||
|
|
c1bd98626b | ||
|
|
6a50c156dd | ||
|
|
20aca08fa2 | ||
|
|
78929ab311 | ||
|
|
06946b3a10 | ||
|
|
424bf012a7 | ||
|
|
8c173dc870 | ||
|
|
14b286291f | ||
|
|
c4de10a974 | ||
|
|
518bbed9dc | ||
|
|
4236e52c25 | ||
|
|
79fe31530e | ||
|
|
fbb31720c2 | ||
|
|
f8e9692fa6 | ||
|
|
772344ea02 | ||
|
|
ce979a16dc | ||
|
|
6fd99fdd4a | ||
|
|
d0ebe02cbb | ||
|
|
f36c7bbca1 | ||
|
|
5c98973b6d | ||
|
|
115567f67f | ||
|
|
15400cad3b | ||
|
|
cbc33b91a7 | ||
|
|
2d9bb75cbb | ||
|
|
d3be09b60a | ||
|
|
0985e12777 | ||
|
|
510757cb2e | ||
|
|
cccced6709 | ||
|
|
3cf09a7a18 | ||
|
|
ce3df9d859 | ||
|
|
4fd0d047a0 | ||
|
|
de0ccf8769 | ||
|
|
a152e526e5 | ||
|
|
1e3545c6f3 | ||
|
|
3c4f19d855 | ||
|
|
8220f4122a | ||
|
|
f4dc0aa0f4 | ||
|
|
1ebb16e418 | ||
|
|
9395f0c672 | ||
|
|
999b998329 | ||
|
|
a3559d8803 | ||
|
|
9d0d25eca6 | ||
|
|
ced9ff26b5 | ||
|
|
3498ad11dd | ||
|
|
ad03b40635 |
@@ -124,9 +124,9 @@ namespace OpenRA
|
||||
world.AddFrameEndTask(w =>
|
||||
{
|
||||
// Caching this in a AddFrameEndTask, because trait construction order might cause problems if done directly at creation time.
|
||||
// All actors that can move should have IMove, if not it's pretty safe to assume the actor is immobile and
|
||||
// All actors that can move or teleport should have IPositionable, if not it's pretty safe to assume the actor is completely immobile and
|
||||
// all targetable positions can be cached if all ITargetablePositions have no conditional requirements.
|
||||
if (!Info.HasTraitInfo<IMoveInfo>() && targetablePositions.Any() && targetablePositions.All(tp => tp.AlwaysEnabled))
|
||||
if (!Info.HasTraitInfo<IPositionableInfo>() && targetablePositions.Any() && targetablePositions.All(tp => tp.AlwaysEnabled))
|
||||
staticTargetablePositions = targetablePositions.SelectMany(tp => tp.TargetablePositions(this)).ToArray();
|
||||
});
|
||||
|
||||
|
||||
@@ -43,8 +43,19 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
void EnableTLS12OnWindows()
|
||||
{
|
||||
// Enable TLS 1.2 on Windows: .NET 4.7 on Windows 10 only supports obsolete protocols by default
|
||||
// SecurityProtocolType.Tls12 is not defined in the .NET 4.5 reference dlls used by mono,
|
||||
// so we must use the enum's constant value directly
|
||||
if (Platform.CurrentPlatform == PlatformType.Windows)
|
||||
ServicePointManager.SecurityProtocol |= (SecurityProtocolType)3072;
|
||||
}
|
||||
|
||||
public Download(string url, string path, Action<DownloadProgressChangedEventArgs> onProgress, Action<AsyncCompletedEventArgs> onComplete)
|
||||
{
|
||||
EnableTLS12OnWindows();
|
||||
|
||||
lock (syncObject)
|
||||
{
|
||||
wc = new WebClient { Proxy = null };
|
||||
@@ -56,6 +67,8 @@ namespace OpenRA
|
||||
|
||||
public Download(string url, Action<DownloadProgressChangedEventArgs> onProgress, Action<DownloadDataCompletedEventArgs> onComplete)
|
||||
{
|
||||
EnableTLS12OnWindows();
|
||||
|
||||
lock (syncObject)
|
||||
{
|
||||
wc = new WebClient { Proxy = null };
|
||||
|
||||
@@ -258,6 +258,10 @@ namespace OpenRA
|
||||
|
||||
static void Initialize(Arguments args)
|
||||
{
|
||||
var supportDirArg = args.GetValue("Engine.SupportDir", null);
|
||||
if (supportDirArg != null)
|
||||
Platform.OverrideSupportDir(supportDirArg);
|
||||
|
||||
Console.WriteLine("Platform is {0}", Platform.CurrentPlatform);
|
||||
|
||||
// Load the engine version as early as possible so it can be written to exception logs
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace OpenRA.Network
|
||||
public class GameClient
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly string Fingerprint;
|
||||
public readonly HSLColor Color;
|
||||
public readonly string Faction;
|
||||
public readonly int Team;
|
||||
@@ -33,6 +34,7 @@ namespace OpenRA.Network
|
||||
public GameClient(Session.Client c)
|
||||
{
|
||||
Name = c.Name;
|
||||
Fingerprint = c.Fingerprint;
|
||||
Color = c.Color;
|
||||
Faction = c.Faction;
|
||||
Team = c.Team;
|
||||
@@ -54,7 +56,7 @@ namespace OpenRA.Network
|
||||
"Mod", "Version", "ModTitle", "ModWebsite", "ModIcon32",
|
||||
|
||||
// Current server state
|
||||
"Map", "State", "MaxPlayers", "Protected"
|
||||
"Map", "State", "MaxPlayers", "Protected", "Authentication"
|
||||
};
|
||||
|
||||
public const int ProtocolVersion = 2;
|
||||
@@ -98,6 +100,9 @@ namespace OpenRA.Network
|
||||
/// <summary>Password protected</summary>
|
||||
public readonly bool Protected = false;
|
||||
|
||||
/// <summary>Players must be authenticated with the OpenRA forum</summary>
|
||||
public readonly bool Authentication = false;
|
||||
|
||||
/// <summary>UTC datetime string when the game changed to the Playing state</summary>
|
||||
public readonly string Started = null;
|
||||
|
||||
@@ -222,6 +227,7 @@ namespace OpenRA.Network
|
||||
ModWebsite = manifest.Metadata.Website;
|
||||
ModIcon32 = manifest.Metadata.WebIcon32;
|
||||
Protected = !string.IsNullOrEmpty(server.Settings.Password);
|
||||
Authentication = server.Settings.RequireAuthentication || server.Settings.ProfileIDWhitelist.Any();
|
||||
Clients = server.LobbyInfo.Clients.Select(c => new GameClient(c)).ToArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -76,10 +76,12 @@ namespace OpenRA
|
||||
|
||||
public static Order Deserialize(World world, BinaryReader r)
|
||||
{
|
||||
var magic = r.ReadByte();
|
||||
switch (magic)
|
||||
try
|
||||
{
|
||||
case 0xFF:
|
||||
var magic = r.ReadByte();
|
||||
switch (magic)
|
||||
{
|
||||
case 0xFF:
|
||||
{
|
||||
var order = r.ReadString();
|
||||
var subjectId = r.ReadUInt32();
|
||||
@@ -156,7 +158,7 @@ namespace OpenRA
|
||||
return new Order(order, subject, target, targetString, queued, extraLocation, extraData);
|
||||
}
|
||||
|
||||
case 0xfe:
|
||||
case 0xfe:
|
||||
{
|
||||
var name = r.ReadString();
|
||||
var data = r.ReadString();
|
||||
@@ -164,11 +166,23 @@ namespace OpenRA
|
||||
return new Order(name, null, false) { IsImmediate = true, TargetString = data };
|
||||
}
|
||||
|
||||
default:
|
||||
default:
|
||||
{
|
||||
Log.Write("debug", "Received unknown order with magic {0}", magic);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Write("debug", "Caught exception while processing order");
|
||||
Log.Write("debug", e.ToString());
|
||||
|
||||
// HACK: this can hopefully go away in the future
|
||||
Game.Debug("Ignoring malformed order that would have crashed the game");
|
||||
Game.Debug("Please file a bug report and include the replay from this match");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
<OutputPath>..</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<StartArguments>Game.Mod=ra</StartArguments>
|
||||
@@ -53,7 +52,6 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Optimize>true</Optimize>
|
||||
<StartArguments>Game.Mod=ra</StartArguments>
|
||||
<Commandlineparameters>Game.Mod=ra</Commandlineparameters>
|
||||
|
||||
@@ -71,9 +71,30 @@ namespace OpenRA
|
||||
/// </summary>
|
||||
public static string SupportDir { get { return supportDir.Value; } }
|
||||
static Lazy<string> supportDir = Exts.Lazy(GetSupportDir);
|
||||
static string supportDirOverride;
|
||||
|
||||
/// <summary>
|
||||
/// Specify a custom support directory that already exists on the filesystem.
|
||||
/// MUST be called before Platform.SupportDir is first accessed.
|
||||
/// </summary>
|
||||
public static void OverrideSupportDir(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
throw new DirectoryNotFoundException(path);
|
||||
|
||||
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) &&
|
||||
!path.EndsWith(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal))
|
||||
path += Path.DirectorySeparatorChar;
|
||||
|
||||
supportDirOverride = path;
|
||||
}
|
||||
|
||||
static string GetSupportDir()
|
||||
{
|
||||
// Use the custom override if it has been defined
|
||||
if (supportDirOverride != null)
|
||||
return supportDirOverride;
|
||||
|
||||
// Use a local directory in the game root if it exists (shared with the system support dir)
|
||||
var localSupportDir = Path.Combine(GameDir, "Support");
|
||||
if (Directory.Exists(localSupportDir))
|
||||
|
||||
@@ -475,11 +475,25 @@ namespace OpenRA.Server
|
||||
|
||||
delayedActions.Add(() =>
|
||||
{
|
||||
if (Dedicated && Settings.RequireAuthIDs.Any() &&
|
||||
(profile == null || !Settings.RequireAuthIDs.Contains(profile.ProfileID)))
|
||||
var notAuthenticated = Dedicated && profile == null && (Settings.RequireAuthentication || Settings.ProfileIDWhitelist.Any());
|
||||
var blacklisted = Dedicated && profile != null && Settings.ProfileIDBlacklist.Contains(profile.ProfileID);
|
||||
var notWhitelisted = Dedicated && Settings.ProfileIDWhitelist.Any() &&
|
||||
(profile == null || !Settings.ProfileIDWhitelist.Contains(profile.ProfileID));
|
||||
|
||||
if (notAuthenticated)
|
||||
{
|
||||
Log.Write("server", "Rejected connection from {0}; Not in server whitelist.", newConn.Socket.RemoteEndPoint);
|
||||
SendOrderTo(newConn, "ServerError", "You are not authenticated for this server");
|
||||
Log.Write("server", "Rejected connection from {0}; Not authenticated.", newConn.Socket.RemoteEndPoint);
|
||||
SendOrderTo(newConn, "ServerError", "Server requires players to have an OpenRA forum account");
|
||||
DropClient(newConn);
|
||||
}
|
||||
else if (blacklisted || notWhitelisted)
|
||||
{
|
||||
if (blacklisted)
|
||||
Log.Write("server", "Rejected connection from {0}; In server blacklist.", newConn.Socket.RemoteEndPoint);
|
||||
else
|
||||
Log.Write("server", "Rejected connection from {0}; Not in server whitelist.", newConn.Socket.RemoteEndPoint);
|
||||
|
||||
SendOrderTo(newConn, "ServerError", "You do not have permission to join this server");
|
||||
DropClient(newConn);
|
||||
}
|
||||
else
|
||||
@@ -493,10 +507,10 @@ namespace OpenRA.Server
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Dedicated && Settings.RequireAuthIDs.Any())
|
||||
if (Dedicated && (Settings.RequireAuthentication || Settings.ProfileIDWhitelist.Any()))
|
||||
{
|
||||
Log.Write("server", "Rejected connection from {0}; Not authenticated and whitelist is set.", newConn.Socket.RemoteEndPoint);
|
||||
SendOrderTo(newConn, "ServerError", "You are not authenticated for this server");
|
||||
Log.Write("server", "Rejected connection from {0}; Not authenticated.", newConn.Socket.RemoteEndPoint);
|
||||
SendOrderTo(newConn, "ServerError", "Server requires players to have an OpenRA forum account");
|
||||
DropClient(newConn);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -59,8 +59,14 @@ namespace OpenRA
|
||||
[Desc("Takes a comma separated list of IP addresses that are not allowed to join.")]
|
||||
public string[] Ban = { };
|
||||
|
||||
[Desc("If non-empty, only allow authenticated players with these user IDs to join.")]
|
||||
public int[] RequireAuthIDs = { };
|
||||
[Desc("For dedicated servers only, allow anonymous clients to join.")]
|
||||
public bool RequireAuthentication = false;
|
||||
|
||||
[Desc("For dedicated servers only, if non-empty, only allow authenticated players with these profile IDs to join.")]
|
||||
public int[] ProfileIDWhitelist = { };
|
||||
|
||||
[Desc("For dedicated servers only, if non-empty, always reject players with these user IDs from joining.")]
|
||||
public int[] ProfileIDBlacklist = { };
|
||||
|
||||
[Desc("For dedicated servers only, controls whether a game can be started with just one human player in the lobby.")]
|
||||
public bool EnableSingleplayer = false;
|
||||
@@ -130,6 +136,9 @@ namespace OpenRA
|
||||
[Desc("Disable high resolution DPI scaling on Windows operating systems.")]
|
||||
public bool DisableWindowsDPIScaling = true;
|
||||
|
||||
[Desc("Disable separate OpenGL render thread on Windows operating systems.")]
|
||||
public bool DisableWindowsRenderThread = true;
|
||||
|
||||
public int BatchSize = 8192;
|
||||
public int SheetSize = 2048;
|
||||
|
||||
|
||||
@@ -15,22 +15,25 @@ using OpenRA.Activities;
|
||||
using OpenRA.Mods.Cnc.Traits;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Mods.Common.Traits.Render;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Cnc.Activities
|
||||
{
|
||||
public interface IPreventsTeleport { bool PreventsTeleport(Actor self); }
|
||||
|
||||
public class Teleport : Activity
|
||||
{
|
||||
readonly Actor teleporter;
|
||||
readonly int? maximumDistance;
|
||||
readonly bool killOnFailure;
|
||||
readonly BitSet<DamageType> killDamageTypes;
|
||||
CPos destination;
|
||||
bool killCargo;
|
||||
bool screenFlash;
|
||||
string sound;
|
||||
|
||||
public Teleport(Actor teleporter, CPos destination, int? maximumDistance, bool killCargo, bool screenFlash, string sound)
|
||||
public Teleport(Actor teleporter, CPos destination, int? maximumDistance,
|
||||
bool killCargo, bool screenFlash, string sound, bool interruptable = true,
|
||||
bool killOnFailure = false, BitSet<DamageType> killDamageTypes = default(BitSet<DamageType>))
|
||||
{
|
||||
var max = teleporter.World.Map.Grid.MaximumTileSearchRange;
|
||||
if (maximumDistance > max)
|
||||
@@ -42,21 +45,32 @@ namespace OpenRA.Mods.Cnc.Activities
|
||||
this.killCargo = killCargo;
|
||||
this.screenFlash = screenFlash;
|
||||
this.sound = sound;
|
||||
this.killOnFailure = killOnFailure;
|
||||
this.killDamageTypes = killDamageTypes;
|
||||
|
||||
if (!interruptable)
|
||||
IsInterruptible = false;
|
||||
}
|
||||
|
||||
public override Activity Tick(Actor self)
|
||||
{
|
||||
var pc = self.TraitOrDefault<PortableChrono>();
|
||||
if (teleporter == self && pc != null && !pc.CanTeleport)
|
||||
return NextActivity;
|
||||
{
|
||||
if (killOnFailure)
|
||||
self.Kill(teleporter, killDamageTypes);
|
||||
|
||||
foreach (var condition in self.TraitsImplementing<IPreventsTeleport>())
|
||||
if (condition.PreventsTeleport(self))
|
||||
return NextActivity;
|
||||
return NextActivity;
|
||||
}
|
||||
|
||||
var bestCell = ChooseBestDestinationCell(self, destination);
|
||||
if (bestCell == null)
|
||||
{
|
||||
if (killOnFailure)
|
||||
self.Kill(teleporter, killDamageTypes);
|
||||
|
||||
return NextActivity;
|
||||
}
|
||||
|
||||
destination = bestCell.Value;
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>5</LangVersion>
|
||||
</PropertyGroup>
|
||||
@@ -51,7 +50,6 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -17,9 +17,9 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Cnc.Scripting
|
||||
{
|
||||
[ScriptPropertyGroup("Support Powers")]
|
||||
public class ChronsphereProperties : ScriptActorProperties, Requires<ChronoshiftPowerInfo>
|
||||
public class ChronosphereProperties : ScriptActorProperties, Requires<ChronoshiftPowerInfo>
|
||||
{
|
||||
public ChronsphereProperties(ScriptContext context, Actor self)
|
||||
public ChronosphereProperties(ScriptContext context, Actor self)
|
||||
: base(context, self) { }
|
||||
|
||||
[Desc("Chronoshift a group of actors. A duration of 0 will teleport the actors permanently.")]
|
||||
@@ -37,7 +37,9 @@ namespace OpenRA.Mods.Cnc.Scripting
|
||||
kv.Key.WrappedClrType().Name, kv.Value.WrappedClrType().Name));
|
||||
}
|
||||
|
||||
var cs = actor.TraitOrDefault<Chronoshiftable>();
|
||||
var cs = actor.TraitsImplementing<Chronoshiftable>()
|
||||
.FirstEnabledTraitOrDefault();
|
||||
|
||||
if (cs != null && cs.CanChronoshiftTo(actor, cell))
|
||||
cs.Teleport(actor, cell, duration, killCargo, Self);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.Activities;
|
||||
using OpenRA.Mods.Cnc.Activities;
|
||||
using OpenRA.Mods.Common.Activities;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
@@ -18,12 +20,13 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
[Desc("Can be teleported via Chronoshift power.")]
|
||||
public class ChronoshiftableInfo : ITraitInfo
|
||||
public class ChronoshiftableInfo : ConditionalTraitInfo
|
||||
{
|
||||
[Desc("Should the actor die instead of being teleported?")]
|
||||
public readonly bool ExplodeInstead = false;
|
||||
|
||||
[Desc("Types of damage that this trait causes to self when 'ExplodeInstead' is true. Leave empty for no damage types.")]
|
||||
[Desc("Types of damage that this trait causes to self when 'ExplodeInstead' is true",
|
||||
"or the return-to-origin is blocked. Leave empty for no damage types.")]
|
||||
public readonly BitSet<DamageType> DamageTypes = default(BitSet<DamageType>);
|
||||
|
||||
public readonly string ChronoshiftSound = "chrono2.aud";
|
||||
@@ -34,12 +37,12 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
[Desc("The color the bar of the 'return-to-origin' logic has.")]
|
||||
public readonly Color TimeBarColor = Color.White;
|
||||
|
||||
public object Create(ActorInitializer init) { return new Chronoshiftable(init, this); }
|
||||
public override object Create(ActorInitializer init) { return new Chronoshiftable(init, this); }
|
||||
}
|
||||
|
||||
public class Chronoshiftable : ITick, ISync, ISelectionBar, IDeathActorInitModifier, ITransformActorInitModifier, INotifyCreated
|
||||
public class Chronoshiftable : ConditionalTrait<ChronoshiftableInfo>, ITick, ISync, ISelectionBar,
|
||||
IDeathActorInitModifier, ITransformActorInitModifier, INotifyCreated
|
||||
{
|
||||
readonly ChronoshiftableInfo info;
|
||||
readonly Actor self;
|
||||
Actor chronosphere;
|
||||
bool killCargo;
|
||||
@@ -51,8 +54,8 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
[Sync] public int ReturnTicks = 0;
|
||||
|
||||
public Chronoshiftable(ActorInitializer init, ChronoshiftableInfo info)
|
||||
: base(info)
|
||||
{
|
||||
this.info = info;
|
||||
self = init.Self;
|
||||
|
||||
if (init.Contains<ChronoshiftReturnInit>())
|
||||
@@ -70,14 +73,29 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
|
||||
void ITick.Tick(Actor self)
|
||||
{
|
||||
if (!info.ReturnToOrigin || ReturnTicks <= 0)
|
||||
if (IsTraitDisabled || !Info.ReturnToOrigin || ReturnTicks <= 0)
|
||||
return;
|
||||
|
||||
// Return to original location
|
||||
if (--ReturnTicks == 0)
|
||||
{
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(new Teleport(chronosphere, Origin, null, killCargo, true, info.ChronoshiftSound));
|
||||
|
||||
// The Move activity is not immediately cancelled, which, combined
|
||||
// with Activity.Cancel discarding NextActivity without checking the
|
||||
// IsInterruptable flag, means that a well timed order can cancel the
|
||||
// Teleport activity queued below - an exploit / cheat of the return mechanic.
|
||||
// The Teleport activity queued below is guaranteed to either complete
|
||||
// (force-resetting the actor to the middle of the target cell) or kill
|
||||
// the actor. It is therefore safe to force-erase the Move activity to
|
||||
// work around the cancellation bug.
|
||||
// HACK: this is manipulating private internal actor state
|
||||
if (self.CurrentActivity is Move)
|
||||
typeof(Actor).GetProperty("CurrentActivity").SetValue(self, null);
|
||||
|
||||
// The actor is killed using Info.DamageTypes if the teleport fails
|
||||
self.QueueActivity(new Teleport(chronosphere, Origin, null, true, killCargo, Info.ChronoshiftSound,
|
||||
false, true, Info.DamageTypes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,19 +108,22 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation)
|
||||
{
|
||||
// TODO: Allow enemy units to be chronoshifted into bad terrain to kill them
|
||||
return iPositionable != null && iPositionable.CanEnterCell(targetLocation);
|
||||
return !IsTraitDisabled && iPositionable != null && iPositionable.CanEnterCell(targetLocation);
|
||||
}
|
||||
|
||||
public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere)
|
||||
{
|
||||
if (IsTraitDisabled)
|
||||
return false;
|
||||
|
||||
// Some things appear chronoshiftable, but instead they just die.
|
||||
if (info.ExplodeInstead)
|
||||
if (Info.ExplodeInstead)
|
||||
{
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
// Damage is inflicted by the chronosphere
|
||||
if (!self.Disposed)
|
||||
self.Kill(chronosphere, info.DamageTypes);
|
||||
self.Kill(chronosphere, Info.DamageTypes);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@@ -122,7 +143,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
|
||||
// Set up the teleport
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(new Teleport(chronosphere, targetLocation, null, killCargo, true, info.ChronoshiftSound));
|
||||
self.QueueActivity(new Teleport(chronosphere, targetLocation, null, killCargo, true, Info.ChronoshiftSound));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -130,7 +151,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
// Show the remaining time as a bar
|
||||
float ISelectionBar.GetValue()
|
||||
{
|
||||
if (!info.ReturnToOrigin)
|
||||
if (IsTraitDisabled || !Info.ReturnToOrigin)
|
||||
return 0f;
|
||||
|
||||
// Otherwise an empty bar is rendered all the time
|
||||
@@ -140,12 +161,12 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
return (float)ReturnTicks / duration;
|
||||
}
|
||||
|
||||
Color ISelectionBar.GetColor() { return info.TimeBarColor; }
|
||||
Color ISelectionBar.GetColor() { return Info.TimeBarColor; }
|
||||
bool ISelectionBar.DisplayWhenEmpty { get { return false; } }
|
||||
|
||||
void ModifyActorInit(TypeDictionary init)
|
||||
{
|
||||
if (!info.ReturnToOrigin || ReturnTicks <= 0)
|
||||
if (IsTraitDisabled || !Info.ReturnToOrigin || ReturnTicks <= 0)
|
||||
return;
|
||||
|
||||
init.Add(new ChronoshiftOriginInit(Origin));
|
||||
|
||||
@@ -50,6 +50,10 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
|
||||
[VoiceReference] public readonly string Voice = "Action";
|
||||
|
||||
[GrantedConditionReference]
|
||||
[Desc("The condition to grant to self while deployed.")]
|
||||
public readonly string DeployedCondition = null;
|
||||
|
||||
public WeaponInfo ThumpDamageWeaponInfo { get; private set; }
|
||||
public WeaponInfo DetonationWeaponInfo { get; private set; }
|
||||
|
||||
@@ -75,12 +79,13 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
}
|
||||
}
|
||||
|
||||
class MadTank : IIssueOrder, IResolveOrder, IOrderVoice, ITick, IPreventsTeleport, IIssueDeployOrder
|
||||
class MadTank : INotifyCreated, IIssueOrder, IResolveOrder, IOrderVoice, ITick, IIssueDeployOrder
|
||||
{
|
||||
readonly Actor self;
|
||||
readonly MadTankInfo info;
|
||||
readonly WithFacingSpriteBody wfsb;
|
||||
readonly ScreenShaker screenShaker;
|
||||
ConditionManager conditionManager;
|
||||
bool deployed;
|
||||
int tick;
|
||||
|
||||
@@ -92,6 +97,11 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
screenShaker = self.World.WorldActor.Trait<ScreenShaker>();
|
||||
}
|
||||
|
||||
void INotifyCreated.Created(Actor self)
|
||||
{
|
||||
conditionManager = self.TraitOrDefault<ConditionManager>();
|
||||
}
|
||||
|
||||
void ITick.Tick(Actor self)
|
||||
{
|
||||
if (!deployed)
|
||||
@@ -172,6 +182,9 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
if (deployed)
|
||||
return;
|
||||
|
||||
if (conditionManager != null && !string.IsNullOrEmpty(info.DeployedCondition))
|
||||
conditionManager.GrantCondition(self, info.DeployedCondition);
|
||||
|
||||
self.World.AddFrameEndTask(w => EjectDriver());
|
||||
if (info.ThumpSequence != null)
|
||||
wfsb.PlayCustomAnimationRepeating(self, info.ThumpSequence);
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
|
||||
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
yield break;
|
||||
|
||||
var t = init.Actor.TraitInfos<TurretedInfo>().FirstOrDefault();
|
||||
var wsb = init.Actor.TraitInfos<WithSpriteBodyInfo>().FirstOrDefault();
|
||||
|
||||
|
||||
@@ -65,7 +65,12 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
|
||||
foreach (var target in UnitsInRange(order.ExtraLocation))
|
||||
{
|
||||
var cs = target.Trait<Chronoshiftable>();
|
||||
var cs = target.TraitsImplementing<Chronoshiftable>()
|
||||
.FirstEnabledTraitOrDefault();
|
||||
|
||||
if (cs == null)
|
||||
continue;
|
||||
|
||||
var targetCell = target.Location + (order.TargetLocation - order.ExtraLocation);
|
||||
var cpi = Info as ChronoshiftPowerInfo;
|
||||
|
||||
@@ -82,8 +87,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
foreach (var t in tiles)
|
||||
units.UnionWith(Self.World.ActorMap.GetActorsAt(t));
|
||||
|
||||
return units.Where(a => a.Info.HasTraitInfo<ChronoshiftableInfo>() &&
|
||||
!a.TraitsImplementing<IPreventsTeleport>().Any(condition => condition.PreventsTeleport(a)));
|
||||
return units.Where(a => a.TraitsImplementing<Chronoshiftable>().Any(cs => !cs.IsTraitDisabled));
|
||||
}
|
||||
|
||||
public bool SimilarTerrain(CPos xy, CPos sourceLocation)
|
||||
|
||||
@@ -61,18 +61,15 @@ namespace OpenRA.Mods.Common.AI
|
||||
return path[0];
|
||||
}
|
||||
|
||||
public void Tick(List<Actor> activeUnits)
|
||||
public void Tick(List<Actor> harvesters)
|
||||
{
|
||||
if (resLayer == null || resLayer.IsResourceLayerEmpty)
|
||||
return;
|
||||
|
||||
// Find idle harvesters and give them orders:
|
||||
foreach (var harvester in activeUnits)
|
||||
foreach (var harvester in harvesters)
|
||||
{
|
||||
var harv = harvester.TraitOrDefault<Harvester>();
|
||||
if (harv == null)
|
||||
continue;
|
||||
|
||||
var harv = harvester.Trait<Harvester>();
|
||||
if (!harv.IsEmpty)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -286,6 +286,10 @@ namespace OpenRA.Mods.Common.AI
|
||||
// Units that the ai already knows about. Any unit not on this list needs to be given a role.
|
||||
List<Actor> activeUnits = new List<Actor>();
|
||||
|
||||
// Harvesters are usually listed under ExcludeFromSquads, so they're not included in the activeUnits list, but still needed in AIHarvesterManager.
|
||||
// TODO: Consider adding an explicit UnitsCommonNames.Harvester category.
|
||||
List<Actor> harvesters = new List<Actor>();
|
||||
|
||||
public const int FeedbackTime = 30; // ticks; = a bit over 1s. must be >= netlag.
|
||||
|
||||
public readonly World World;
|
||||
@@ -597,6 +601,7 @@ namespace OpenRA.Mods.Common.AI
|
||||
|
||||
activeUnits.RemoveAll(unitCannotBeOrdered);
|
||||
unitsHangingAroundTheBase.RemoveAll(unitCannotBeOrdered);
|
||||
harvesters.RemoveAll(unitCannotBeOrdered);
|
||||
|
||||
if (--rushTicks <= 0)
|
||||
{
|
||||
@@ -614,8 +619,8 @@ namespace OpenRA.Mods.Common.AI
|
||||
if (--assignRolesTicks <= 0)
|
||||
{
|
||||
assignRolesTicks = Info.AssignRolesInterval;
|
||||
harvManager.Tick(activeUnits);
|
||||
FindNewUnits(self);
|
||||
harvManager.Tick(harvesters);
|
||||
InitializeBase(self, true);
|
||||
}
|
||||
|
||||
@@ -738,11 +743,16 @@ namespace OpenRA.Mods.Common.AI
|
||||
void FindNewUnits(Actor self)
|
||||
{
|
||||
var newUnits = self.World.ActorsHavingTrait<IPositionable>()
|
||||
.Where(a => a.Owner == Player && !Info.UnitsCommonNames.Mcv.Contains(a.Info.Name) &&
|
||||
!Info.UnitsCommonNames.ExcludeFromSquads.Contains(a.Info.Name) && !activeUnits.Contains(a));
|
||||
.Where(a => a.Owner == Player && !activeUnits.Contains(a) && !harvesters.Contains(a));
|
||||
|
||||
foreach (var a in newUnits)
|
||||
{
|
||||
if (a.Info.HasTraitInfo<HarvesterInfo>())
|
||||
harvesters.Add(a);
|
||||
|
||||
if (Info.UnitsCommonNames.Mcv.Contains(a.Info.Name) || Info.UnitsCommonNames.ExcludeFromSquads.Contains(a.Info.Name))
|
||||
continue;
|
||||
|
||||
unitsHangingAroundTheBase.Add(a);
|
||||
|
||||
if (a.Info.HasTraitInfo<AircraftInfo>() && a.Info.HasTraitInfo<AttackBaseInfo>())
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<LangVersion>5</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
@@ -34,7 +33,6 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -74,91 +74,6 @@ namespace OpenRA.Mods.Common.SpriteLoaders
|
||||
{
|
||||
enum Format { XORPrev = 0x20, XORLCW = 0x40, LCW = 0x80 }
|
||||
|
||||
class TrimmedFrame : ISpriteFrame
|
||||
{
|
||||
public Size Size { get; private set; }
|
||||
public Size FrameSize { get; private set; }
|
||||
public float2 Offset { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
public bool DisableExportPadding { get { return false; } }
|
||||
|
||||
public TrimmedFrame(ImageHeader header)
|
||||
{
|
||||
var origData = header.Data;
|
||||
var origSize = header.Size;
|
||||
var top = origSize.Height - 1;
|
||||
var bottom = 0;
|
||||
var left = origSize.Width - 1;
|
||||
var right = 0;
|
||||
|
||||
// Scan frame data to find left-, top-, right-, bottom-most
|
||||
// rows/columns with non-zero pixel data
|
||||
var i = 0;
|
||||
for (var y = 0; y < origSize.Height; y++)
|
||||
{
|
||||
for (var x = 0; x < origSize.Width; x++, i++)
|
||||
{
|
||||
if (origData[i] != 0)
|
||||
{
|
||||
top = Math.Min(y, top);
|
||||
bottom = Math.Max(y, bottom);
|
||||
left = Math.Min(x, left);
|
||||
right = Math.Max(x, right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keep a 1px empty border to work avoid rounding issues in the gpu shader
|
||||
if (left > 0)
|
||||
left -= 1;
|
||||
|
||||
if (top > 0)
|
||||
top -= 1;
|
||||
|
||||
if (right < origSize.Width - 1)
|
||||
right += 1;
|
||||
|
||||
if (bottom < origSize.Height - 1)
|
||||
bottom += 1;
|
||||
|
||||
var trimmedWidth = right - left + 1;
|
||||
var trimmedHeight = bottom - top + 1;
|
||||
|
||||
// Pad the dimensions to an even number to avoid issues with half-integer offsets
|
||||
var widthFudge = trimmedWidth % 2;
|
||||
var heightFudge = trimmedHeight % 2;
|
||||
var destWidth = trimmedWidth + widthFudge;
|
||||
var destHeight = trimmedHeight + heightFudge;
|
||||
|
||||
if (trimmedWidth == origSize.Width && trimmedHeight == origSize.Height)
|
||||
{
|
||||
// Nothing to trim, so copy old data directly
|
||||
Size = header.Size;
|
||||
FrameSize = header.FrameSize;
|
||||
Offset = header.Offset;
|
||||
Data = header.Data;
|
||||
}
|
||||
else if (trimmedWidth > 0 && trimmedHeight > 0)
|
||||
{
|
||||
// Trim frame
|
||||
Data = new byte[destWidth * destHeight];
|
||||
for (var y = 0; y < trimmedHeight; y++)
|
||||
Array.Copy(origData, (y + top) * origSize.Width + left, Data, y * destWidth, trimmedWidth);
|
||||
|
||||
Size = new Size(destWidth, destHeight);
|
||||
FrameSize = origSize;
|
||||
Offset = 0.5f * new float2(
|
||||
left + right + widthFudge - origSize.Width + 1,
|
||||
top + bottom + heightFudge - origSize.Height + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Empty frame
|
||||
Data = new byte[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ImageHeader : ISpriteFrame
|
||||
{
|
||||
public Size Size { get { return reader.Size; } }
|
||||
@@ -217,6 +132,7 @@ namespace OpenRA.Mods.Common.SpriteLoaders
|
||||
|
||||
stream.Position += 4;
|
||||
var headers = new ImageHeader[imageCount];
|
||||
Frames = headers.AsReadOnly();
|
||||
for (var i = 0; i < headers.Length; i++)
|
||||
headers[i] = new ImageHeader(stream, this);
|
||||
|
||||
@@ -238,10 +154,6 @@ namespace OpenRA.Mods.Common.SpriteLoaders
|
||||
|
||||
foreach (var h in headers)
|
||||
Decompress(h);
|
||||
|
||||
Frames = headers.Select(f => (ISpriteFrame)new TrimmedFrame(f))
|
||||
.ToArray()
|
||||
.AsReadOnly();
|
||||
}
|
||||
|
||||
void Decompress(ImageHeader h)
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
: valued != null ? valued.Cost : 0;
|
||||
|
||||
var experienceModifier = self.TraitsImplementing<IGivesExperienceModifier>().Select(x => x.GetGivesExperienceModifier());
|
||||
Util.ApplyPercentageModifiers(exp, experienceModifier);
|
||||
exp = Util.ApplyPercentageModifiers(exp, experienceModifier);
|
||||
|
||||
var killer = e.Attacker.TraitOrDefault<GainsExperience>();
|
||||
if (killer != null)
|
||||
|
||||
@@ -18,7 +18,7 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Spawns remains of a husk actor with the correct facing.")]
|
||||
public class HuskInfo : ITraitInfo, IOccupySpaceInfo, IFacingInfo, IActorPreviewInitInfo
|
||||
public class HuskInfo : ITraitInfo, IPositionableInfo, IFacingInfo, IActorPreviewInitInfo
|
||||
{
|
||||
public readonly HashSet<string> AllowedTerrain = new HashSet<string>();
|
||||
|
||||
@@ -41,6 +41,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
|
||||
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
||||
|
||||
public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||
{
|
||||
// IPositionable*Info*.CanEnterCell is only ever used for things like exiting production facilities,
|
||||
// all places relevant for husks check IPositionable.CanEnterCell instead, so we can safely set this to true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class Husk : IPositionable, IFacing, ISync, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld,
|
||||
|
||||
@@ -44,6 +44,9 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
yield break;
|
||||
|
||||
var anim = new Animation(init.World, image);
|
||||
anim.PlayFetchIndex(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequences.First()), () => 0);
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
yield break;
|
||||
|
||||
var anim = new Animation(init.World, image);
|
||||
var sequence = init.World.Type == WorldType.Editor ? EditorSequence : Sequence;
|
||||
var palette = init.World.Type == WorldType.Editor ? init.WorldRenderer.Palette(EditorPalette) : p;
|
||||
|
||||
@@ -23,6 +23,9 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
yield break;
|
||||
|
||||
var anim = new Animation(init.World, image, init.GetFacing());
|
||||
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence));
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
yield break;
|
||||
|
||||
var anim = new Animation(init.World, image);
|
||||
anim.PlayFetchIndex(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence), () => 0);
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
yield break;
|
||||
|
||||
var anim = new Animation(init.World, image, init.GetFacing());
|
||||
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), StandSequences.First()));
|
||||
yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
yield break;
|
||||
|
||||
var adjacent = 0;
|
||||
|
||||
if (init.Contains<RuntimeNeighbourInit>())
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
public class IngameMenuLogic : ChromeLogic
|
||||
{
|
||||
Widget menu;
|
||||
readonly Widget menu;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public IngameMenuLogic(Widget widget, ModData modData, World world, Action onExit, WorldRenderer worldRenderer, IngameInfoPanel activePanel)
|
||||
@@ -97,7 +97,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var iop = world.WorldActor.TraitsImplementing<IObjectivesPanel>().FirstOrDefault();
|
||||
var exitDelay = iop != null ? iop.ExitDelay : 0;
|
||||
|
||||
if (world.IsReplay || world.LobbyInfo.NonBotClients.Count() == 1)
|
||||
if (!world.LobbyInfo.GlobalSettings.Dedicated && world.LobbyInfo.NonBotClients.Count() == 1)
|
||||
{
|
||||
restartAction = () =>
|
||||
{
|
||||
|
||||
@@ -576,7 +576,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (template == null || template.Id != editablePlayerTemplate.Id)
|
||||
template = editablePlayerTemplate.Clone();
|
||||
|
||||
LobbyUtils.SetupLatencyWidget(template, client, orderManager, client.Bot == null);
|
||||
LobbyUtils.SetupLatencyWidget(template, client, orderManager);
|
||||
|
||||
if (client.Bot != null)
|
||||
LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, worldRenderer, map);
|
||||
@@ -595,7 +595,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (template == null || template.Id != nonEditablePlayerTemplate.Id)
|
||||
template = nonEditablePlayerTemplate.Clone();
|
||||
|
||||
LobbyUtils.SetupLatencyWidget(template, client, orderManager, client.Bot == null);
|
||||
LobbyUtils.SetupLatencyWidget(template, client, orderManager);
|
||||
LobbyUtils.SetupColorWidget(template, slot, client);
|
||||
LobbyUtils.SetupFactionWidget(template, slot, client, factions);
|
||||
|
||||
@@ -646,6 +646,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
if (client.IsAdmin)
|
||||
LobbyUtils.SetupEditableReadyWidget(template, null, client, orderManager, map);
|
||||
else
|
||||
LobbyUtils.HideReadyWidgets(template);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -661,9 +663,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
if (client.IsAdmin)
|
||||
LobbyUtils.SetupReadyWidget(template, null, client);
|
||||
else
|
||||
LobbyUtils.HideReadyWidgets(template);
|
||||
}
|
||||
|
||||
LobbyUtils.SetupLatencyWidget(template, c, orderManager, true);
|
||||
LobbyUtils.SetupLatencyWidget(template, c, orderManager);
|
||||
template.IsVisible = () => true;
|
||||
|
||||
if (idx >= players.Children.Count)
|
||||
|
||||
@@ -296,8 +296,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
return "Poor";
|
||||
}
|
||||
|
||||
public static void SetupLatencyWidget(Widget parent, Session.Client c, OrderManager orderManager, bool visible)
|
||||
public static void SetupLatencyWidget(Widget parent, Session.Client c, OrderManager orderManager)
|
||||
{
|
||||
var visible = c != null && c.Bot == null;
|
||||
var block = parent.GetOrNull("LATENCY");
|
||||
if (block != null)
|
||||
{
|
||||
@@ -309,31 +310,34 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
}
|
||||
|
||||
var tooltip = parent.Get<ClientTooltipRegionWidget>("LATENCY_REGION");
|
||||
tooltip.IsVisible = () => c != null && visible;
|
||||
if (c != null)
|
||||
tooltip.IsVisible = () => visible;
|
||||
if (visible)
|
||||
tooltip.Bind(orderManager, null, c);
|
||||
}
|
||||
|
||||
public static void SetupProfileWidget(Widget parent, Session.Client c, OrderManager orderManager, WorldRenderer worldRenderer)
|
||||
{
|
||||
var visible = c != null && c.Bot == null;
|
||||
var profile = parent.GetOrNull<ImageWidget>("PROFILE");
|
||||
if (profile != null && c.Bot == null)
|
||||
if (profile != null)
|
||||
{
|
||||
var imageName = (c != null && c.IsAdmin ? "admin-" : "player-")
|
||||
+ (c.Fingerprint != null ? "registered" : "anonymous");
|
||||
|
||||
profile.GetImageName = () => imageName;
|
||||
profile.IsVisible = () => true;
|
||||
profile.IsVisible = () => visible;
|
||||
}
|
||||
|
||||
var profileTooltip = parent.GetOrNull<ClientTooltipRegionWidget>("PROFILE_TOOLTIP");
|
||||
if (profileTooltip != null && c.Bot == null)
|
||||
if (profileTooltip != null)
|
||||
{
|
||||
if (c != null && c.Fingerprint != null)
|
||||
profileTooltip.Template = "REGISTERED_PLAYER_TOOLTIP";
|
||||
|
||||
profileTooltip.Bind(orderManager, worldRenderer, c);
|
||||
profileTooltip.IsVisible = () => true;
|
||||
if (visible)
|
||||
profileTooltip.Bind(orderManager, worldRenderer, c);
|
||||
|
||||
profileTooltip.IsVisible = () => visible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,6 +568,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
parent.Get<ImageWidget>("STATUS_IMAGE").IsVisible = () => c.IsReady || c.Bot != null;
|
||||
}
|
||||
|
||||
public static void HideReadyWidgets(Widget parent)
|
||||
{
|
||||
HideChildWidget(parent, "STATUS_CHECKBOX");
|
||||
HideChildWidget(parent, "STATUS_IMAGE");
|
||||
}
|
||||
|
||||
public static void AddPlayerFlagAndName(ScrollItemWidget template, Player player)
|
||||
{
|
||||
var flag = template.Get<ImageWidget>("FLAG");
|
||||
|
||||
@@ -374,11 +374,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (selectedMap.InvalidCustomRules)
|
||||
return;
|
||||
|
||||
var orders = new[] {
|
||||
Order.Command("option gamespeed {0}".F(gameSpeed)),
|
||||
Order.Command("option difficulty {0}".F(difficulty)),
|
||||
Order.Command("state {0}".F(Session.ClientState.Ready))
|
||||
};
|
||||
var orders = new List<Order>();
|
||||
if (difficulty != null)
|
||||
orders.Add(Order.Command("option difficulty {0}".F(difficulty)));
|
||||
|
||||
orders.Add(Order.Command("option gamespeed {0}".F(gameSpeed)));
|
||||
orders.Add(Order.Command("state {0}".F(Session.ClientState.Ready)));
|
||||
|
||||
var missionData = selectedMap.Rules.Actors["world"].TraitInfoOrDefault<MissionDataInfo>();
|
||||
if (missionData != null && missionData.StartVideo != null && modData.DefaultFileSystem.Exists(missionData.StartVideo))
|
||||
|
||||
@@ -153,6 +153,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
messageHeader.IsVisible = () => !profileLoaded;
|
||||
|
||||
var profileWidth = 0;
|
||||
var maxProfileWidth = widget.Bounds.Width;
|
||||
var messageText = "Loading player profile...";
|
||||
var messageWidth = messageFont.Measure(messageText).X + 2 * message.Bounds.Left;
|
||||
|
||||
@@ -199,7 +200,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
Func<int, int> negotiateWidth = badgeWidth =>
|
||||
{
|
||||
profileWidth = Math.Min(Math.Max(badgeWidth, profileWidth), widget.Bounds.Width);
|
||||
profileWidth = Math.Min(Math.Max(badgeWidth, profileWidth), maxProfileWidth);
|
||||
return profileWidth;
|
||||
};
|
||||
|
||||
@@ -219,7 +220,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
}
|
||||
}
|
||||
|
||||
profileWidth = Math.Min(profileWidth, widget.Bounds.Width);
|
||||
profileWidth = Math.Min(profileWidth, maxProfileWidth);
|
||||
header.Bounds.Width = widget.Bounds.Width = badgeContainer.Bounds.Width = profileWidth;
|
||||
widget.Bounds.Height = header.Bounds.Height + badgeContainer.Bounds.Height;
|
||||
|
||||
@@ -267,8 +268,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var badgeTemplate = widget.Get("BADGE_TEMPLATE");
|
||||
widget.RemoveChild(badgeTemplate);
|
||||
|
||||
var width = 0;
|
||||
// Negotiate the label length that the tooltip will allow
|
||||
var maxLabelWidth = 0;
|
||||
var templateIcon = badgeTemplate.Get<SpriteWidget>("ICON");
|
||||
var templateLabel = badgeTemplate.Get<LabelWidget>("LABEL");
|
||||
var templateLabelFont = Game.Renderer.Fonts[templateLabel.Font];
|
||||
foreach (var badge in profile.Badges)
|
||||
maxLabelWidth = Math.Max(maxLabelWidth, templateLabelFont.Measure(badge.Label).X);
|
||||
|
||||
widget.Bounds.Width = negotiateWidth(2 * templateLabel.Bounds.Left - templateIcon.Bounds.Right + maxLabelWidth);
|
||||
|
||||
var badgeOffset = badgeTemplate.Bounds.Y;
|
||||
if (profile.Badges.Any())
|
||||
badgeOffset += 3;
|
||||
|
||||
foreach (var badge in profile.Badges)
|
||||
{
|
||||
var b = badgeTemplate.Clone();
|
||||
@@ -278,11 +291,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var label = b.Get<LabelWidget>("LABEL");
|
||||
var labelFont = Game.Renderer.Fonts[label.Font];
|
||||
|
||||
var labelText = WidgetUtils.TruncateText(badge.Label, label.Bounds.Width, labelFont);
|
||||
var labelText = WidgetUtils.TruncateText(badge.Label, widget.Bounds.Width - label.Bounds.X - icon.Bounds.X, labelFont);
|
||||
label.GetText = () => labelText;
|
||||
|
||||
width = Math.Max(width, label.Bounds.Left + labelFont.Measure(labelText).X + icon.Bounds.X);
|
||||
|
||||
b.Bounds.Y = badgeOffset;
|
||||
widget.AddChild(b);
|
||||
|
||||
@@ -292,7 +303,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (badgeOffset > badgeTemplate.Bounds.Y)
|
||||
badgeOffset += 5;
|
||||
|
||||
widget.Bounds.Width = negotiateWidth(width);
|
||||
widget.Bounds.Height = badgeOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,6 +599,16 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
password.GetImageName = () => canJoin ? "protected" : "protected-disabled";
|
||||
}
|
||||
|
||||
var auth = item.GetOrNull<ImageWidget>("REQUIRES_AUTHENTICATION");
|
||||
if (auth != null)
|
||||
{
|
||||
auth.IsVisible = () => game.Authentication;
|
||||
auth.GetImageName = () => canJoin ? "authentication" : "authentication-disabled";
|
||||
|
||||
if (game.Protected && password != null)
|
||||
auth.Bounds.X -= password.Bounds.Width + 5;
|
||||
}
|
||||
|
||||
var players = item.GetOrNull<LabelWithTooltipWidget>("PLAYERS");
|
||||
if (players != null)
|
||||
{
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
text = RemoveInvalidCharacters(value ?? "");
|
||||
CursorPosition = CursorPosition.Clamp(0, text.Length);
|
||||
ClearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -368,7 +368,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
else if (mi.Event == MouseInputEvent.Move && (isStandardScrolling ||
|
||||
(standardScrollStart.HasValue && ((standardScrollStart.Value - mi.Location).Length > Game.Settings.Game.MouseScrollDeadzone))))
|
||||
{
|
||||
isStandardScrolling = scrollType == MouseScrollType.Standard;
|
||||
isStandardScrolling = true;
|
||||
var d = scrollType == MouseScrollType.Inverted ? -1 : 1;
|
||||
worldRenderer.Viewport.Scroll((Viewport.LastMousePos - mi.Location) * d, false);
|
||||
return true;
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;</DefineConstants>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>5</LangVersion>
|
||||
</PropertyGroup>
|
||||
@@ -52,7 +51,6 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<LangVersion>5</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
@@ -30,7 +29,6 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -187,7 +187,16 @@ namespace OpenRA.Platforms.Default
|
||||
// Run graphics rendering on a dedicated thread.
|
||||
// The calling thread will then have more time to process other tasks, since rendering happens in parallel.
|
||||
// If the calling thread is the main game thread, this means it can run more logic and render ticks.
|
||||
context = new ThreadedGraphicsContext(new Sdl2GraphicsContext(this), batchSize);
|
||||
// This is disabled on Windows because it breaks the ability to minimize/restore the window from the taskbar for reasons that we dont understand.
|
||||
var threadedRenderer = Platform.CurrentPlatform != PlatformType.Windows || !Game.Settings.Graphics.DisableWindowsRenderThread;
|
||||
if (!threadedRenderer)
|
||||
{
|
||||
var ctx = new Sdl2GraphicsContext(this);
|
||||
ctx.InitializeOpenGL();
|
||||
context = ctx;
|
||||
}
|
||||
else
|
||||
context = new ThreadedGraphicsContext(new Sdl2GraphicsContext(this), batchSize);
|
||||
|
||||
SDL.SDL_SetModState(SDL.SDL_Keymod.KMOD_NONE);
|
||||
input = new Sdl2Input();
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>5</LangVersion>
|
||||
@@ -53,7 +52,6 @@
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using OpenRA.Support;
|
||||
@@ -23,6 +22,10 @@ namespace OpenRA.Server
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var arguments = new Arguments(args);
|
||||
var supportDirArg = arguments.GetValue("Engine.SupportDir", null);
|
||||
if (supportDirArg != null)
|
||||
Platform.OverrideSupportDir(supportDirArg);
|
||||
|
||||
Log.AddChannel("debug", "dedicated-debug.log");
|
||||
Log.AddChannel("perf", "dedicated-perf.log");
|
||||
Log.AddChannel("server", "dedicated-server.log");
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<LangVersion>5</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
@@ -29,7 +28,6 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>5</LangVersion>
|
||||
@@ -53,7 +52,6 @@
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
set Name="Dedicated Server"
|
||||
set Mod=ra
|
||||
set ListenPort=1234
|
||||
set ExternalPort=1234
|
||||
set AdvertiseOnline=True
|
||||
set EnableSingleplayer=False
|
||||
set Password=""
|
||||
|
||||
:loop
|
||||
|
||||
OpenRA.Server.exe Game.Mod=%Mod% Server.Name=%Name% Server.ListenPort=%ListenPort% Server.ExternalPort=%ExternalPort% Server.AdvertiseOnline=%AdvertiseOnline% Server.EnableSingleplayer=%EnableSingleplayer% Server.Password=%Password%
|
||||
OpenRA.Server.exe Game.Mod=%Mod% Server.Name=%Name% Server.ListenPort=%ListenPort% Server.AdvertiseOnline=%AdvertiseOnline% Server.EnableSingleplayer=%EnableSingleplayer% Server.Password=%Password%
|
||||
|
||||
goto loop
|
||||
@@ -9,14 +9,13 @@
|
||||
Name="${Name:-"Dedicated Server"}"
|
||||
Mod="${Mod:-"ra"}"
|
||||
ListenPort="${ListenPort:-"1234"}"
|
||||
ExternalPort="${ExternalPort:-"1234"}"
|
||||
AdvertiseOnline="${AdvertiseOnline:-"True"}"
|
||||
EnableSingleplayer="${EnableSingleplayer:-"False"}"
|
||||
Password="${Password:-""}"
|
||||
|
||||
while true; do
|
||||
mono --debug OpenRA.Server.exe Game.Mod=$Mod \
|
||||
Server.Name="$Name" Server.ListenPort=$ListenPort Server.ExternalPort=$ExternalPort \
|
||||
Server.Name="$Name" Server.ListenPort=$ListenPort \
|
||||
Server.AdvertiseOnline=$AdvertiseOnline \
|
||||
Server.EnableSingleplayer=$EnableSingleplayer Server.Password=$Password
|
||||
done
|
||||
|
||||
@@ -449,8 +449,10 @@ lobby-bits: chrome.png
|
||||
colorpicker: 257,33,14,14
|
||||
huepicker: 388,96,7,15
|
||||
kick: 386,115,11,11
|
||||
protected: 403,97,10,13
|
||||
protected-disabled: 403,113,10,13
|
||||
protected: 402,97,12,13
|
||||
protected-disabled: 402,113,12,13
|
||||
authentication: 418,97,12,13
|
||||
authentication-disabled: 418,113,12,13
|
||||
admin-registered: 448,112,16,16
|
||||
admin-anonymous: 464,112,16,16
|
||||
player-registered: 480,112,16,16
|
||||
|
||||
@@ -87,17 +87,26 @@ Container@LOBBY_SERVERS_BIN:
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X: 5
|
||||
Width: 255
|
||||
Width: 245
|
||||
Height: 25
|
||||
Image@PASSWORD_PROTECTED:
|
||||
X: 272
|
||||
Y: 6
|
||||
Width: 8
|
||||
Height: 10
|
||||
Width: 12
|
||||
Height: 13
|
||||
ImageCollection: lobby-bits
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
TooltipTemplate: SIMPLE_TOOLTIP
|
||||
TooltipText: Requires Password
|
||||
Image@REQUIRES_AUTHENTICATION:
|
||||
X: 272
|
||||
Y: 6
|
||||
Width: 12
|
||||
Height: 13
|
||||
ImageCollection: lobby-bits
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
TooltipTemplate: SIMPLE_TOOLTIP
|
||||
TooltipText: Requires OpenRA forum account
|
||||
LabelWithTooltip@PLAYERS:
|
||||
X: 290
|
||||
Width: 85
|
||||
|
||||
@@ -108,17 +108,26 @@ Container@MULTIPLAYER_PANEL:
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X: 5
|
||||
Width: 255
|
||||
Width: 245
|
||||
Height: 25
|
||||
Image@PASSWORD_PROTECTED:
|
||||
X: 272
|
||||
Y: 6
|
||||
Width: 8
|
||||
Height: 10
|
||||
Width: 12
|
||||
Height: 13
|
||||
ImageCollection: lobby-bits
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
TooltipTemplate: SIMPLE_TOOLTIP
|
||||
TooltipText: Requires Password
|
||||
Image@REQUIRES_AUTHENTICATION:
|
||||
X: 272
|
||||
Y: 6
|
||||
Width: 12
|
||||
Height: 13
|
||||
ImageCollection: lobby-bits
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
TooltipTemplate: SIMPLE_TOOLTIP
|
||||
TooltipText: Requires OpenRA forum account
|
||||
LabelWithTooltip@PLAYERS:
|
||||
X: 290
|
||||
Width: 85
|
||||
|
||||
@@ -4,7 +4,6 @@ origin: C&C The Ultimate Collection (Origin version, English)
|
||||
RegistryKey: EA Games\CNC and The Covert Operations
|
||||
RegistryValue: Install Dir
|
||||
IDFiles:
|
||||
CNC95Launcher.exe: 1d711adf09ac08738b2599b3092a1b448169b32a
|
||||
CONQUER.MIX: 833e02a09aae694659eb312d3838367f681d1b30
|
||||
Install:
|
||||
copy: .
|
||||
|
||||
@@ -342,7 +342,7 @@ Actors:
|
||||
Tower2: gtwr
|
||||
Location: 23,21
|
||||
Owner: GDI
|
||||
Radar: hq
|
||||
CommCenter: hq
|
||||
Location: 21,14
|
||||
Owner: GDI
|
||||
Silo1: silo
|
||||
|
||||
@@ -45,16 +45,16 @@ Gdi12Waypoints = { waypoint0, waypoint1, waypoint3, waypoint11, waypoint12 }
|
||||
|
||||
AllWaypoints = { Gdi1Waypoints, Gdi2Waypoints, Gdi3Waypoints, Gdi5Waypoints, Gdi11Waypoints, Gdi12Waypoints }
|
||||
|
||||
PrimaryTargets = { Tower1, Tower2, Radar, Silo1, Silo2, Silo3, Refinery, Barracks, Plant1, Plant2, Yard, Factory }
|
||||
PrimaryTargets = { Tower1, Tower2, CommCenter, Silo1, Silo2, Silo3, Refinery, Barracks, Plant1, Plant2, Yard, Factory }
|
||||
|
||||
GDIStartUnits = { }
|
||||
|
||||
SendGDIAirstrike = function()
|
||||
if not Radar.IsDead and Radar.Owner == enemy then
|
||||
if not CommCenter.IsDead and CommCenter.Owner == enemy then
|
||||
local target = getAirstrikeTarget()
|
||||
|
||||
if target then
|
||||
Radar.SendAirstrike(target, false, Facing.NorthEast + 4)
|
||||
CommCenter.SendAirstrike(target, false, Facing.NorthEast + 4)
|
||||
Trigger.AfterDelay(AirstrikeDelay, SendGDIAirstrike)
|
||||
else
|
||||
Trigger.AfterDelay(AirstrikeDelay/4, SendGDIAirstrike)
|
||||
|
||||
@@ -638,7 +638,7 @@ Actors:
|
||||
Detonator: CRATE.plain
|
||||
Location: 59,43
|
||||
Owner: GDI
|
||||
Radar: hq
|
||||
CommCenter: hq
|
||||
Location: 57,32
|
||||
Owner: GDI
|
||||
Actor187: jeep
|
||||
|
||||
@@ -91,12 +91,12 @@ end
|
||||
Atk3TriggerFunction = function()
|
||||
if not Atk3Switch then
|
||||
Atk3Switch = true
|
||||
if not Radar.IsDead then
|
||||
if not CommCenter.IsDead then
|
||||
local targets = player.GetGroundAttackers()
|
||||
local target = targets[DateTime.GameTime % #targets + 1].CenterPosition
|
||||
|
||||
if target then
|
||||
Radar.SendAirstrike(target, false, Facing.NorthEast + 4)
|
||||
CommCenter.SendAirstrike(target, false, Facing.NorthEast + 4)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -135,7 +135,7 @@ InsertNodUnits = function()
|
||||
local difficulty = Map.LobbyOption("difficulty")
|
||||
NodStartUnitsRight = NodStartUnitsRight[difficulty]
|
||||
NodStartUnitsLeft = NodStartUnitsLeft[difficulty]
|
||||
|
||||
|
||||
Camera.Position = UnitsRallyRight.CenterPosition
|
||||
|
||||
Media.PlaySpeechNotification(player, "Reinforce")
|
||||
@@ -183,7 +183,7 @@ WorldLoaded = function()
|
||||
OnAnyDamaged(Atk1ActorTriggerActivator, Atk1TriggerFunction)
|
||||
|
||||
OnAnyDamaged(Atk2ActorTriggerActivator, Atk2TriggerFunction)
|
||||
|
||||
|
||||
if Map.LobbyOption("difficulty") == "tough" then
|
||||
Trigger.OnDamaged(Atk3Activator, Atk3TriggerFunction)
|
||||
end
|
||||
|
||||
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
@@ -401,6 +401,20 @@ Container@LOBBY_PLAYER_BIN:
|
||||
Font: Regular
|
||||
Visible: false
|
||||
Align: Left
|
||||
LeftMargin: 24
|
||||
Children:
|
||||
Image@PROFILE:
|
||||
ImageCollection: lobby-bits
|
||||
X: 3
|
||||
Y: 3
|
||||
Visible: false
|
||||
ClientTooltipRegion@PROFILE_TOOLTIP:
|
||||
X: 3
|
||||
Y: 3
|
||||
Width: 16
|
||||
Height: 16
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
Template: ANONYMOUS_PLAYER_TOOLTIP
|
||||
Label@SPECTATOR:
|
||||
X: 190
|
||||
Width: 326
|
||||
|
||||
@@ -84,17 +84,26 @@ Container@LOBBY_SERVERS_BIN:
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X: 5
|
||||
Width: 255
|
||||
Width: 245
|
||||
Height: 25
|
||||
Image@PASSWORD_PROTECTED:
|
||||
X: 272
|
||||
Y: 6
|
||||
Width: 10
|
||||
Height: 12
|
||||
Width: 12
|
||||
Height: 13
|
||||
ImageCollection: lobby-bits
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
TooltipTemplate: SIMPLE_TOOLTIP
|
||||
TooltipText: Requires Password
|
||||
Image@REQUIRES_AUTHENTICATION:
|
||||
X: 272
|
||||
Y: 6
|
||||
Width: 12
|
||||
Height: 13
|
||||
ImageCollection: lobby-bits
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
TooltipTemplate: SIMPLE_TOOLTIP
|
||||
TooltipText: Requires OpenRA forum account
|
||||
LabelWithTooltip@PLAYERS:
|
||||
X: 290
|
||||
Width: 85
|
||||
|
||||
@@ -100,17 +100,26 @@ Background@MULTIPLAYER_PANEL:
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X: 5
|
||||
Width: 255
|
||||
Width: 245
|
||||
Height: 25
|
||||
Image@PASSWORD_PROTECTED:
|
||||
X: 272
|
||||
Y: 6
|
||||
Width: 10
|
||||
Height: 12
|
||||
Width: 12
|
||||
Height: 13
|
||||
ImageCollection: lobby-bits
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
TooltipTemplate: SIMPLE_TOOLTIP
|
||||
TooltipText: Requires Password
|
||||
Image@REQUIRES_AUTHENTICATION:
|
||||
X: 272
|
||||
Y: 6
|
||||
Width: 12
|
||||
Height: 13
|
||||
ImageCollection: lobby-bits
|
||||
TooltipContainer: TOOLTIP_CONTAINER
|
||||
TooltipTemplate: SIMPLE_TOOLTIP
|
||||
TooltipText: Requires OpenRA forum account
|
||||
LabelWithTooltip@PLAYERS:
|
||||
X: 290
|
||||
Width: 85
|
||||
|
||||
@@ -215,6 +215,8 @@ lobby-bits: buttons.png
|
||||
huepicker: 193,0,7,15
|
||||
protected: 200,0,12,13
|
||||
protected-disabled: 211,0,12,13
|
||||
authentication: 199,16,12,13
|
||||
authentication-disabled: 212,16,12,13
|
||||
admin-registered: 224,0,16,16
|
||||
admin-anonymous: 240,0,16,16
|
||||
player-registered: 224,16,16,16
|
||||
|
||||
@@ -17,7 +17,7 @@ Player:
|
||||
Silo: silo
|
||||
UnitsCommonNames:
|
||||
Mcv: mcv
|
||||
ExcludeFromSquads: harv
|
||||
ExcludeFromSquads: harvester
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 4
|
||||
@@ -140,7 +140,7 @@ Player:
|
||||
Silo: silo
|
||||
UnitsCommonNames:
|
||||
Mcv: mcv
|
||||
ExcludeFromSquads: harv
|
||||
ExcludeFromSquads: harvester
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 4
|
||||
@@ -265,7 +265,7 @@ Player:
|
||||
Silo: silo
|
||||
UnitsCommonNames:
|
||||
Mcv: mcv
|
||||
ExcludeFromSquads: harv
|
||||
ExcludeFromSquads: harvester
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 4
|
||||
|
||||
@@ -1101,18 +1101,16 @@ palace:
|
||||
Factions: corrino
|
||||
PrimaryBuilding:
|
||||
PrimaryCondition: primary
|
||||
RequiresCondition: atreides || ordos
|
||||
WithTextDecoration@primary:
|
||||
RequiresSelection: true
|
||||
Text: PRIMARY
|
||||
ReferencePoint: Top
|
||||
ZOffset: 256
|
||||
RequiresCondition: primary && (atreides || ordos)
|
||||
RequiresCondition: primary
|
||||
NukePower:
|
||||
Cursor: nuke
|
||||
Icon: deathhand
|
||||
PauseOnCondition: disabled
|
||||
RequiresCondition: harkonnen
|
||||
Prerequisites: ~techlevel.superweapons, ~palace.nuke
|
||||
ChargeInterval: 7500
|
||||
Description: Death Hand
|
||||
@@ -1129,7 +1127,7 @@ palace:
|
||||
ArrowSequence: arrow
|
||||
CircleSequence: circles
|
||||
WithNukeLaunchOverlay:
|
||||
RequiresCondition: !launchpad-damaged && harkonnen
|
||||
RequiresCondition: !launchpad-damaged
|
||||
GrantConditionOnDamageState@LAUNCHPADDAMAGED:
|
||||
Condition: launchpad-damaged
|
||||
ProduceActorPower@fremen:
|
||||
@@ -1137,10 +1135,9 @@ palace:
|
||||
LongDesc: Elite infantry unit armed with assault rifles and rockets\n Strong vs Infantry, Vehicles\n Weak vs Artillery\n Special Ability: Invisibility
|
||||
Icon: fremen
|
||||
PauseOnCondition: disabled
|
||||
RequiresCondition: atreides
|
||||
Prerequisites: ~techlevel.superweapons, ~palace.fremen
|
||||
Actors: fremen, fremen
|
||||
Type: Fremen
|
||||
Type: Palace
|
||||
ChargeInterval: 2250
|
||||
ReadyAudio: Reinforce
|
||||
BlockedAudio: NoRoom
|
||||
@@ -1150,10 +1147,9 @@ palace:
|
||||
LongDesc: Sneaky infantry, armed with explosives\n Strong vs Buildings\n Weak vs Everything\n Special Ability: destroy buildings
|
||||
Icon: saboteur
|
||||
PauseOnCondition: disabled
|
||||
RequiresCondition: ordos
|
||||
Prerequisites: ~techlevel.superweapons, ~palace.saboteur
|
||||
Actors: saboteur
|
||||
Type: Saboteur
|
||||
Type: Palace
|
||||
ChargeInterval: 2250
|
||||
ReadyAudio: Reinforce
|
||||
BlockedAudio: NoRoom
|
||||
@@ -1167,23 +1163,9 @@ palace:
|
||||
Exit@3:
|
||||
SpawnOffset: -704,768,0
|
||||
ExitCell: 0,3
|
||||
Production@Atreides:
|
||||
Produces: Fremen
|
||||
RequiresCondition: atreides
|
||||
Production@Ordos:
|
||||
Produces: Saboteur
|
||||
RequiresCondition: ordos
|
||||
GrantConditionOnFaction@Atreides:
|
||||
Condition: atreides
|
||||
Factions: atreides, fremen
|
||||
GrantConditionOnFaction@Harkonnen:
|
||||
Condition: harkonnen
|
||||
Factions: harkonnen
|
||||
GrantConditionOnFaction@Ordos:
|
||||
Condition: ordos
|
||||
Factions: ordos, mercenary, smuggler
|
||||
Production:
|
||||
Produces: Palace
|
||||
SupportPowerChargeBar:
|
||||
RequiresCondition: atreides || harkonnen || ordos
|
||||
ProvidesPrerequisite@buildingname:
|
||||
|
||||
conyard.atreides:
|
||||
@@ -1208,17 +1190,6 @@ conyard.harkonnen:
|
||||
Image: conyard.harkonnen
|
||||
-FactionImages:
|
||||
|
||||
conyard.corrino:
|
||||
Inherits: construction_yard
|
||||
Buildable:
|
||||
Queue: Building
|
||||
BuildPaletteOrder: 1000
|
||||
Prerequisites: ~disabled
|
||||
ForceFaction: corrino
|
||||
RenderSprites:
|
||||
Image: conyard.harkonnen
|
||||
-FactionImages:
|
||||
|
||||
conyard.ordos:
|
||||
Inherits: construction_yard
|
||||
Buildable:
|
||||
|
||||
@@ -310,7 +310,7 @@ fremen:
|
||||
Facings: -8
|
||||
Transpose: true
|
||||
die1: DATA.R8
|
||||
Frames: 870, 877, 884, 891, 898, 905, 912, 919, 926, 933, 940, 947
|
||||
Frames: 870, 877, 884, 891, 898, 905, 912, 919, 926, 927, 928, 929
|
||||
Length: 12
|
||||
Tick: 80
|
||||
die2: DATA.R8
|
||||
|
||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@@ -531,8 +531,10 @@ lobby-bits: buttons.png
|
||||
admin: 187,5,7,5
|
||||
colorpicker: 127,5,23,22
|
||||
huepicker: 194,0,7,15
|
||||
protected: 202,0,10,13
|
||||
protected-disabled: 213,0,10,13
|
||||
protected: 201,0,12,13
|
||||
protected-disabled: 212,0,12,13
|
||||
authentication: 199,16,12,13
|
||||
authentication-disabled: 212,16,12,13
|
||||
admin-registered: 224,0,16,16
|
||||
admin-anonymous: 240,0,16,16
|
||||
player-registered: 224,16,16,16
|
||||
|
||||
@@ -4,7 +4,6 @@ ra-origin: C&C The Ultimate Collection (Origin version, English)
|
||||
RegistryKey: EA Games\Command and Conquer Red Alert
|
||||
RegistryValue: Install Dir
|
||||
IDFiles:
|
||||
RA95Launcher.exe: 22bf7a1f9f1c2498823e3216541e6012f291c2c0
|
||||
REDALERT.MIX: 0e58f4b54f44f6cd29fecf8cf379d33cf2d4caef
|
||||
Install:
|
||||
copy: .
|
||||
@@ -463,7 +462,6 @@ cnc-origin: Command & Conquer (Origin version, English)
|
||||
RegistryKey: EA Games\CNC and The Covert Operations
|
||||
RegistryValue: Install Dir
|
||||
IDFiles:
|
||||
CNC95Launcher.exe: 1d711adf09ac08738b2599b3092a1b448169b32a
|
||||
CONQUER.MIX: 833e02a09aae694659eb312d3838367f681d1b30
|
||||
Install:
|
||||
copy: .
|
||||
|
||||
@@ -109,11 +109,11 @@ InitialAlliedReinforcements = function()
|
||||
end
|
||||
|
||||
CaptureRadarDome = function()
|
||||
Trigger.OnKilled(Radar, function()
|
||||
Trigger.OnKilled(RadarDome, function()
|
||||
player.MarkFailedObjective(CaptureRadarDomeObj)
|
||||
end)
|
||||
|
||||
Trigger.OnCapture(Radar, function()
|
||||
Trigger.OnCapture(RadarDome, function()
|
||||
player.MarkCompletedObjective(CaptureRadarDomeObj)
|
||||
Beacon.New(player, TechLab1.CenterPosition)
|
||||
Beacon.New(player, TechLab2.CenterPosition)
|
||||
|
||||
@@ -630,7 +630,7 @@ Actors:
|
||||
Refinery: proc
|
||||
Location: 81,90
|
||||
Owner: USSR
|
||||
Radar: dome
|
||||
RadarDome: dome
|
||||
Location: 20,83
|
||||
Owner: USSR
|
||||
WeaponMeetPoint: waypoint
|
||||
|
||||
@@ -120,11 +120,11 @@ InitialAlliedReinforcements = function()
|
||||
end
|
||||
|
||||
CaptureRadarDome = function()
|
||||
Trigger.OnKilled(Radar, function()
|
||||
Trigger.OnKilled(RadarDome, function()
|
||||
player.MarkFailedObjective(CaptureRadarDomeObj)
|
||||
end)
|
||||
|
||||
Trigger.OnCapture(Radar, function()
|
||||
Trigger.OnCapture(RadarDome, function()
|
||||
player.MarkCompletedObjective(CaptureRadarDomeObj)
|
||||
Beacon.New(player, TechLab1.CenterPosition)
|
||||
Beacon.New(player, TechLab2.CenterPosition)
|
||||
|
||||
@@ -618,7 +618,7 @@ Actors:
|
||||
Refinery: proc
|
||||
Location: 68,35
|
||||
Owner: USSR
|
||||
Radar: dome
|
||||
RadarDome: dome
|
||||
Location: 75,86
|
||||
Owner: USSR
|
||||
Radar2: dome
|
||||
|
||||
@@ -229,7 +229,7 @@ Actors:
|
||||
Location: 56,97
|
||||
Owner: Neutral
|
||||
Actor273: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 24,118
|
||||
Actor384: mine
|
||||
Owner: Neutral
|
||||
@@ -427,10 +427,10 @@ Actors:
|
||||
Location: 49,18
|
||||
Owner: Neutral
|
||||
Actor274: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 42,114
|
||||
Actor275: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 22,116
|
||||
Actor132: t17
|
||||
Location: 29,16
|
||||
@@ -859,28 +859,28 @@ Actors:
|
||||
Location: 121,96
|
||||
Owner: Creeps
|
||||
Actor276: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 33,121
|
||||
Actor277: tc02
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 32,117
|
||||
Actor278: t05
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 33,122
|
||||
Actor279: t05
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 21,114
|
||||
Actor280: t02
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 30,120
|
||||
Actor281: t02
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 27,113
|
||||
Actor282: t02
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 39,122
|
||||
Actor283: t02
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 31,119
|
||||
Actor284: tc01
|
||||
Owner: Neutral
|
||||
|
||||
@@ -1582,34 +1582,34 @@ Actors:
|
||||
Facing: 160
|
||||
Actor507: t11
|
||||
Location: 86,42
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor508: t03
|
||||
Location: 85,43
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor509: tc01
|
||||
Location: 84,39
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor510: t14
|
||||
Location: 79,43
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor511: tc04
|
||||
Location: 81,42
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor512: t12
|
||||
Location: 84,43
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor513: t01
|
||||
Location: 67,38
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor514: tc02
|
||||
Location: 68,40
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor515: t15
|
||||
Location: 69,36
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor516: t11
|
||||
Location: 66,39
|
||||
Owner: Soviets
|
||||
Owner: Neutral
|
||||
Actor517: tc04
|
||||
Location: 35,40
|
||||
Owner: Neutral
|
||||
|
||||
@@ -93,7 +93,7 @@ Actors:
|
||||
Owner: Neutral
|
||||
Location: 16,55
|
||||
Actor57: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 65,150
|
||||
Actor48: v19
|
||||
Owner: Neutral
|
||||
@@ -296,97 +296,97 @@ Actors:
|
||||
Owner: Neutral
|
||||
Location: 133,114
|
||||
Actor236: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 120,115
|
||||
Actor237: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 130,115
|
||||
Actor238: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 128,110
|
||||
Actor239: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 118,112
|
||||
Actor240: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 122,111
|
||||
Actor241: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 131,110
|
||||
Actor242: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 135,108
|
||||
Actor243: tc03
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 126,115
|
||||
Actor244: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 130,108
|
||||
Actor245: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 138,91
|
||||
Actor246: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 134,96
|
||||
Actor247: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 141,99
|
||||
Actor248: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 136,103
|
||||
Actor249: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 139,97
|
||||
Actor250: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 136,93
|
||||
Actor251: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 134,100
|
||||
Actor252: tc01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 139,105
|
||||
Actor253: t16
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 141,97
|
||||
Actor254: t16
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 138,95
|
||||
Actor255: t16
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 138,99
|
||||
Actor256: t16
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 133,105
|
||||
Actor257: t16
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 131,102
|
||||
Actor258: t16
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 131,97
|
||||
Actor259: t16
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 131,100
|
||||
Actor260: t16
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 133,103
|
||||
Actor261: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 131,104
|
||||
Actor263: t05
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 138,101
|
||||
Actor264: t05
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 140,103
|
||||
Actor265: t05
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 136,106
|
||||
Actor266: t05
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 133,106
|
||||
Actor268: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 130,98
|
||||
Actor610: v15
|
||||
Owner: Neutral
|
||||
@@ -935,10 +935,10 @@ Actors:
|
||||
Owner: Neutral
|
||||
Location: 223,192
|
||||
Actor634: tc04
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 194,82
|
||||
Actor567: t01
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 72,93
|
||||
Actor652: tc01
|
||||
Owner: Neutral
|
||||
@@ -1049,10 +1049,10 @@ Actors:
|
||||
Owner: Neutral
|
||||
Location: 130,148
|
||||
Actor654: t06
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 166,51
|
||||
Actor657: gmine
|
||||
Owner: Creeps
|
||||
Owner: Neutral
|
||||
Location: 37,193
|
||||
Actor658: c3
|
||||
Owner: Neutral
|
||||
|
||||
@@ -415,7 +415,7 @@ Actors:
|
||||
Actor159: mine
|
||||
Location: 77,46
|
||||
Owner: Neutral
|
||||
Radar: dome
|
||||
RadarDome: dome
|
||||
Location: 49,46
|
||||
Owner: Greece
|
||||
CYard: fact
|
||||
|
||||
@@ -39,7 +39,7 @@ AttackPaths =
|
||||
}
|
||||
|
||||
ReinfInf = function()
|
||||
if Radar.IsDead or Radar.Owner ~= Greece then
|
||||
if RadarDome.IsDead or RadarDome.Owner ~= Greece then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -49,7 +49,7 @@ ReinfInf = function()
|
||||
end
|
||||
|
||||
ReinfArmor = function()
|
||||
if not Radar.IsDead and Radar.Owner == Greece then
|
||||
if not RadarDome.IsDead and RadarDome.Owner == Greece then
|
||||
RCheck = true
|
||||
Reinforcements.Reinforce(Greece, ArmorReinfGreece, ArmorReinfPath, 0, function(soldier)
|
||||
soldier.Hunt()
|
||||
@@ -58,7 +58,7 @@ ReinfArmor = function()
|
||||
end
|
||||
|
||||
BringPatrol1 = function()
|
||||
if Radar.IsDead or Radar.Owner ~= Greece then
|
||||
if RadarDome.IsDead or RadarDome.Owner ~= Greece then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -77,7 +77,7 @@ BringPatrol1 = function()
|
||||
end
|
||||
|
||||
BringPatrol2 = function()
|
||||
if Radar.IsDead or Radar.Owner ~= Greece then
|
||||
if RadarDome.IsDead or RadarDome.Owner ~= Greece then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ WorldLoaded = function()
|
||||
Media.PlaySpeechNotification(player, "Win")
|
||||
end)
|
||||
|
||||
Trigger.OnKilled(Radar, function()
|
||||
Trigger.OnKilled(RadarDome, function()
|
||||
player.MarkCompletedObjective(KillRadar)
|
||||
Media.PlaySpeechNotification(player, "ObjectiveMet")
|
||||
end)
|
||||
|
||||
@@ -482,7 +482,7 @@ Actors:
|
||||
Actor169: mine
|
||||
Location: 91,87
|
||||
Owner: Neutral
|
||||
Radar: dome
|
||||
RadarDome: dome
|
||||
Location: 111,50
|
||||
Owner: Greece
|
||||
Pbox1: pbox
|
||||
|
||||
@@ -39,7 +39,7 @@ AttackPaths =
|
||||
}
|
||||
|
||||
ReinfInf = function()
|
||||
if Radar.IsDead or Radar.Owner ~= Greece then
|
||||
if RadarDome.IsDead or RadarDome.Owner ~= Greece then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -49,7 +49,7 @@ ReinfInf = function()
|
||||
end
|
||||
|
||||
ReinfArmor = function()
|
||||
if not Radar.IsDead and Radar.Owner == Greece then
|
||||
if not RadarDome.IsDead and RadarDome.Owner == Greece then
|
||||
RCheck = true
|
||||
Reinforcements.Reinforce(Greece, ArmorReinfGreece, InfReinfPath, 0, function(soldier)
|
||||
soldier.Hunt()
|
||||
@@ -58,7 +58,7 @@ ReinfArmor = function()
|
||||
end
|
||||
|
||||
BringPatrol1 = function()
|
||||
if Radar.IsDead or Radar.Owner ~= Greece then
|
||||
if RadarDome.IsDead or RadarDome.Owner ~= Greece then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -77,7 +77,7 @@ BringPatrol1 = function()
|
||||
end
|
||||
|
||||
BringPatrol2 = function()
|
||||
if Radar.IsDead or Radar.Owner ~= Greece then
|
||||
if RadarDome.IsDead or RadarDome.Owner ~= Greece then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ WorldLoaded = function()
|
||||
Media.PlaySpeechNotification(player, "Win")
|
||||
end)
|
||||
|
||||
Trigger.OnKilled(Radar, function()
|
||||
Trigger.OnKilled(RadarDome, function()
|
||||
player.MarkCompletedObjective(KillRadar)
|
||||
Media.PlaySpeechNotification(player, "ObjectiveMet")
|
||||
end)
|
||||
|
||||
@@ -225,7 +225,7 @@ Actors:
|
||||
Location: 69,49
|
||||
Owner: Greece
|
||||
Facing: 32
|
||||
Radar: dome
|
||||
RadarDome: dome
|
||||
Location: 70,45
|
||||
Owner: France
|
||||
Actor57: fact
|
||||
|
||||
@@ -214,7 +214,7 @@ WorldLoaded = function()
|
||||
Trigger.OnDamaged(mcvGG, Expand)
|
||||
Trigger.OnDamaged(mcvtransport, Expand)
|
||||
|
||||
Trigger.OnKilled(Radar, function()
|
||||
Trigger.OnKilled(RadarDome, function()
|
||||
if not player.IsObjectiveCompleted(CaptureObjective) then
|
||||
player.MarkFailedObjective(CaptureObjective)
|
||||
end
|
||||
@@ -224,8 +224,8 @@ WorldLoaded = function()
|
||||
end
|
||||
end)
|
||||
|
||||
Radar.GrantCondition("french")
|
||||
Trigger.OnCapture(Radar, function()
|
||||
RadarDome.GrantCondition("french")
|
||||
Trigger.OnCapture(RadarDome, function()
|
||||
HoldObjective = player.AddPrimaryObjective("Defend the Radar Dome.")
|
||||
player.MarkCompletedObjective(CaptureObjective)
|
||||
Beacon.New(player, MCVDeploy.CenterPosition)
|
||||
@@ -244,17 +244,17 @@ WorldLoaded = function()
|
||||
|
||||
Reinforcements.Reinforce(Greece, ArmorReinfGreece, AlliedCrossroadsToRadarPath , 0, IdleHunt)
|
||||
|
||||
Radar.RevokeCondition(1)
|
||||
Trigger.ClearAll(Radar)
|
||||
RadarDome.RevokeCondition(1)
|
||||
Trigger.ClearAll(RadarDome)
|
||||
Trigger.AfterDelay(0, function()
|
||||
Trigger.OnRemovedFromWorld(Radar, function()
|
||||
Trigger.OnRemovedFromWorld(RadarDome, function()
|
||||
player.MarkFailedObjective(HoldObjective)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
Trigger.OnEnteredProximityTrigger(USSRExpansionPoint.CenterPosition, WDist.New(4 * 1024), function(unit, id)
|
||||
if unit.Owner == player and Radar.Owner == player then
|
||||
if unit.Owner == player and RadarDome.Owner == player then
|
||||
Trigger.RemoveProximityTrigger(id)
|
||||
|
||||
Para2()
|
||||
|
||||
@@ -147,6 +147,7 @@ Player:
|
||||
syrd: 1
|
||||
hpad: 4
|
||||
afld: 4
|
||||
afld.ukraine: 4
|
||||
atek: 1
|
||||
stek: 1
|
||||
fix: 1
|
||||
@@ -161,6 +162,7 @@ Player:
|
||||
spen: 1%
|
||||
syrd: 1%
|
||||
afld: 4%
|
||||
afld.ukraine: 4%
|
||||
pbox: 7%
|
||||
gun: 7%
|
||||
ftur: 10%
|
||||
@@ -284,6 +286,7 @@ Player:
|
||||
syrd: 1
|
||||
hpad: 4
|
||||
afld: 4
|
||||
afld.ukraine: 4
|
||||
atek: 1
|
||||
stek: 1
|
||||
fix: 1
|
||||
@@ -294,6 +297,8 @@ Player:
|
||||
kenn: 0.5%
|
||||
weap: 3%
|
||||
hpad: 2%
|
||||
afld: 2%
|
||||
afld.ukraine: 2%
|
||||
spen: 1%
|
||||
syrd: 1%
|
||||
pbox: 10%
|
||||
@@ -418,6 +423,7 @@ Player:
|
||||
syrd: 1
|
||||
hpad: 8
|
||||
afld: 8
|
||||
afld.ukraine: 8
|
||||
weap: 1
|
||||
atek: 1
|
||||
stek: 1
|
||||
@@ -428,6 +434,7 @@ Player:
|
||||
weap: 1%
|
||||
hpad: 20%
|
||||
afld: 20%
|
||||
afld.ukraine: 20%
|
||||
atek: 1%
|
||||
stek: 1%
|
||||
spen: 1%
|
||||
|
||||
@@ -127,6 +127,7 @@ E2:
|
||||
Explodes:
|
||||
Weapon: UnitExplodeSmall
|
||||
EmptyWeapon: UnitExplodeSmall
|
||||
DamageSource: Killer
|
||||
ProducibleWithLevel:
|
||||
Prerequisites: barracks.upgraded
|
||||
|
||||
|
||||
@@ -409,8 +409,8 @@ JEEP:
|
||||
WithSpriteTurret:
|
||||
Cargo:
|
||||
Types: Infantry
|
||||
MaxWeight: 2
|
||||
PipCount: 2
|
||||
MaxWeight: 1
|
||||
PipCount: 1
|
||||
LoadingCondition: notmobile
|
||||
ProducibleWithLevel:
|
||||
Prerequisites: vehicles.upgraded
|
||||
@@ -769,7 +769,10 @@ QTNK:
|
||||
Armor:
|
||||
Type: Heavy
|
||||
Mobile:
|
||||
RequiresCondition: !deployed
|
||||
Speed: 56
|
||||
Chronoshiftable:
|
||||
RequiresCondition: !deployed
|
||||
RevealsShroud:
|
||||
Range: 6c0
|
||||
RevealGeneratedShroud: False
|
||||
@@ -777,6 +780,7 @@ QTNK:
|
||||
Range: 4c0
|
||||
SelectionDecorations:
|
||||
MadTank:
|
||||
DeployedCondition: deployed
|
||||
Targetable:
|
||||
TargetTypes: Ground, MADTank, Repair, Vehicle
|
||||
Selectable:
|
||||
|
||||
@@ -1169,19 +1169,19 @@ einstein:
|
||||
Facings: 8
|
||||
Tick: 80
|
||||
die1:
|
||||
Start: 115
|
||||
Start: 120
|
||||
Length: 8
|
||||
die2:
|
||||
Start: 123
|
||||
Start: 128
|
||||
Length: 8
|
||||
die3:
|
||||
Start: 135
|
||||
Start: 136
|
||||
Length: 12
|
||||
die4:
|
||||
Start: 135
|
||||
Start: 136
|
||||
Length: 12
|
||||
die5:
|
||||
Start: 147
|
||||
Start: 148
|
||||
Length: 17
|
||||
die6: electro
|
||||
Length: *
|
||||
@@ -1215,19 +1215,19 @@ delphi:
|
||||
Facings: 8
|
||||
Tick: 80
|
||||
die1:
|
||||
Start: 115
|
||||
Start: 329
|
||||
Length: 8
|
||||
die2:
|
||||
Start: 123
|
||||
Start: 337
|
||||
Length: 8
|
||||
die3:
|
||||
Start: 135
|
||||
Start: 345
|
||||
Length: 12
|
||||
die4:
|
||||
Start: 135
|
||||
Start: 345
|
||||
Length: 12
|
||||
die5:
|
||||
Start: 147
|
||||
Start: 357
|
||||
Length: 17
|
||||
die6: electro
|
||||
Length: *
|
||||
@@ -1261,19 +1261,19 @@ chan:
|
||||
Facings: 8
|
||||
Tick: 80
|
||||
die1:
|
||||
Start: 115
|
||||
Start: 120
|
||||
Length: 8
|
||||
die2:
|
||||
Start: 123
|
||||
Start: 128
|
||||
Length: 8
|
||||
die3:
|
||||
Start: 135
|
||||
Start: 136
|
||||
Length: 12
|
||||
die4:
|
||||
Start: 135
|
||||
Start: 136
|
||||
Length: 12
|
||||
die5:
|
||||
Start: 147
|
||||
Start: 148
|
||||
Length: 17
|
||||
die6: electro
|
||||
Length: *
|
||||
|
||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@@ -277,7 +277,7 @@ TorpTube:
|
||||
Falloff: 1000, 368, 135, 50, 18, 7, 0
|
||||
Versus:
|
||||
None: 40
|
||||
Wood: 80
|
||||
Wood: 50
|
||||
Light: 30
|
||||
Heavy: 30
|
||||
Concrete: 100
|
||||
|
||||
@@ -377,6 +377,8 @@ lobby-bits: buttons.png
|
||||
huepicker: 194,0,7,15
|
||||
protected: 202,0,10,13
|
||||
protected-disabled: 213,0,10,13
|
||||
authentication: 199,16,12,13
|
||||
authentication-disabled: 212,16,12,13
|
||||
admin-registered: 224,0,16,16
|
||||
admin-anonymous: 240,0,16,16
|
||||
player-registered: 224,16,16,16
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
@@ -15,7 +15,6 @@
|
||||
# openra_ServerName="<ServerName>" (default: "Dedicated Server")
|
||||
# openra_Mod="<Mod>" (default: ra)
|
||||
# openra_ListenPort="<number>" (default: 1234)
|
||||
# openra_ExternalPort="<number>" (default: 1234)
|
||||
# openra_AdvertiseOnline="<True|False>" (default: True)
|
||||
# openra_extraflags="<set as needed>"
|
||||
#
|
||||
@@ -43,7 +42,6 @@ status_cmd="${name}_status"
|
||||
: ${openra_ServerName="Dedicated Server"}
|
||||
: ${openra_Mod="ra"}
|
||||
: ${openra_ListenPort="1234"}
|
||||
: ${openra_ExternalPort="1234"}
|
||||
: ${openra_AdvertiseOnline="True"}
|
||||
|
||||
openra_Dedicated="True"
|
||||
@@ -54,7 +52,6 @@ openra_DedicatedLoop="True"
|
||||
Server.DedicatedLoop=${openra_DedicatedLoop} \
|
||||
Server.Name=\"${openra_ServerName}\" \
|
||||
Server.ListenPort=${openra_ListenPort} \
|
||||
Server.ExternalPort=${openra_ExternalPort} \
|
||||
Server.AdvertiseOnline=${openra_AdvertiseOnline}\
|
||||
${openra_extraflags}"}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
MINIMUM_MONO_VERSION="4.2"
|
||||
|
||||
prompt_apt_install_mono_complete() {
|
||||
command -v mono >/dev/null 2>&1 && return 1
|
||||
command -v mono >/dev/null 2>&1 && command -v cert-sync >/dev/null 2>&1 && return 1
|
||||
command -v apt-cache > /dev/null || return 1
|
||||
command -v xdg-mime > /dev/null || return 1
|
||||
command -v xdg-open > /dev/null || return 1
|
||||
@@ -19,6 +19,7 @@ make_version() {
|
||||
|
||||
mono_missing_or_old() {
|
||||
command -v mono >/dev/null 2>&1 || return 0
|
||||
command -v cert-sync >/dev/null 2>&1 || return 0
|
||||
MONO_VERSION=$(mono --version | head -n1 | cut -d' ' -f5)
|
||||
[ "$(make_version "${MONO_VERSION}")" -lt "$(make_version "${MINIMUM_MONO_VERSION}")" ] && return 0
|
||||
return 1
|
||||
@@ -43,7 +44,7 @@ if prompt_apt_install_mono_complete; then
|
||||
fi
|
||||
|
||||
if mono_missing_or_old; then
|
||||
ERROR_MESSAGE="{MODNAME} requires Mono ${MINIMUM_MONO_VERSION} or greater.\nPlease install Mono using your system package manager.\n\nSee http://wiki.openra.net/AppImages for more information."
|
||||
ERROR_MESSAGE="{MODNAME} requires Mono ${MINIMUM_MONO_VERSION} or greater and the cert-sync utility.\nPlease install Mono using your system package manager.\n\nSee http://wiki.openra.net/AppImages for more information."
|
||||
if command -v zenity > /dev/null; then
|
||||
zenity --no-wrap --error --title "{MODNAME}" --text "${ERROR_MESSAGE}" 2> /dev/null
|
||||
elif command -v kdialog > /dev/null; then
|
||||
|
||||
@@ -9,7 +9,7 @@ if [[ "$OSTYPE" != "darwin"* ]]; then
|
||||
command -v genisoimage >/dev/null 2>&1 || { echo >&2 "macOS packaging requires genisoimage."; exit 1; }
|
||||
fi
|
||||
|
||||
LAUNCHER_TAG="osx-launcher-20180723"
|
||||
LAUNCHER_TAG="osx-launcher-20171118"
|
||||
|
||||
if [ $# -ne "2" ]; then
|
||||
echo "Usage: `basename $0` tag outputdir"
|
||||
|
||||
2
thirdparty/fetch-thirdparty-deps-osx.sh
vendored
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
LAUNCHER_TAG="osx-launcher-20180723"
|
||||
LAUNCHER_TAG="osx-launcher-20171118"
|
||||
|
||||
download_dir="${0%/*}/download/osx"
|
||||
mkdir -p "$download_dir"
|
||||
|
||||