Compare commits

...

64 Commits

Author SHA1 Message Date
Oliver Brakmann
029be6120f Fix a spurious NRE in GlobalChat 2016-05-08 14:05:21 +02:00
Paul Chote
1f9fd2cb3f Include version/mod/modversion in the game list query. 2016-05-08 13:15:04 +02:00
Paul Chote
7bfb0feed7 Add an opt-out prompt for system information collection. 2016-05-08 13:14:48 +02:00
abcdefg30
61aa1bb366 Add TheRaffy to AUTHORS 2016-05-08 00:46:49 +02:00
Oliver Brakmann
5c9445a115 Fix trait lookup of destroyed actor in SpawnActorOnDeath
The sequence of events leading to that crash looks like this:

1. Truk enters a building.

2. `Enter.FindAndTransitionToNextState()` is running, and since `DonateSupplies` uses `EnterBehaviour.Dispose`, `Actor.Dispose()` runs for the actor, queueing a FrameEndTask.

3. Truk is then killed:

 * `Health.InflictDamage()` first calls `SpawnActorOnDeath.Killed()`, which queues a FrameEndTask during which some trait lookups happen.

 * `Health.InflightDamage()` then calls `Actor.Dispose()` as well, queueing another FrameEndTask (which will never run, the game crashes before).

4. After the tick, the first FrameEndTask disposes of the actor. The second FrameEndTask would spawn the crate from the truk, but the trait lookups then fail and throw an exception.
2016-05-07 15:59:19 +01:00
Paul Chote
9b5c71a033 Update appdata description using text from the website About page. 2016-05-07 13:53:18 +02:00
Oliver Brakmann
006aecfde9 Re-instate owner row for oil pumps and tech buildings in TD 2016-05-07 10:42:51 +01:00
abcdefg30
56da6282eb Fix possible instant repairs by spamming Repair activities
Noticeable when spam-clicking on a naval yard/sub pen.
2016-05-07 10:33:01 +01:00
abcdefg30
f47d19fa4f Fix the supply truck in allies03b not being targetable by tanya 2016-05-07 11:05:25 +02:00
HenrytheSlav
9b224da1bc Fixes Utility import facings mirror-flip 2016-05-06 23:44:02 +02:00
Matthias Mailänder
30803f704e Check for invalid targets to avoid crashing. 2016-05-05 14:01:22 +02:00
Paul Chote
9c120ff9c3 Fix a crash when multi-turreted units leave a transport. 2016-05-05 13:59:58 +02:00
Oliver Brakmann
581e302e7d Fix self-healing percentage in yaml rules for all mods 2016-05-05 12:51:30 +02:00
HenrytheSlav
747bc1d24d Allow Chinook to land/deploy on gems 2016-05-05 12:21:57 +02:00
reaperrr
4aaded0ca3 Fix potential NRE in Parachutable 2016-04-30 13:56:39 +02:00
Zimmermann Gyula
4c3014e7a4 Increase Stinger RangeLimit from 50 to 65.
With the 170 Speed, the Stinger can pass a maximum of 50*170 = 8500 (8c308) world units, while having a range of 9c0, which mean it runs out of fuel before it reaches it's effective maximum range. To prevent this, RangeLimit has been increased to 65 (9c0*1.25/170 is 67.8, rounded downwards).
2016-04-28 14:18:47 +02:00
Zimmermann Gyula
487c4e83cf Halven CloseEnough on Stinger.
With 170 Speed, 298 CloseEnough, and 128 Spread, it will always act as a proximity weapon against the targets. Other missiles aren't affected because all the other missiles have a fair margin to satisfy the optimal Speed+Spread > CloseEnough condition.
2016-04-28 14:18:31 +02:00
Paul Chote
8039ed7310 Fix GPS satellite palette. 2016-04-24 13:17:50 +02:00
reaperrr
854cbe7ca9 Disable OwnerRow on RA trees, rocks, bridges and crates 2016-04-24 13:00:04 +02:00
reaperrr
86373246c9 Disable OwnerRow on TD bridges, destroyed fields and crates 2016-04-24 13:00:04 +02:00
reaperrr
4d5a6faaa7 Disabled OwnerRow on TD trees, tib trees and rocks 2016-04-24 13:00:04 +02:00
reaperrr
39fdf86130 Fixed owner of some trees on Lessons from Kosovo and Treasure Island
They're owned by Neutral instead of Creeps now.
2016-04-24 13:00:04 +02:00
reaperrr
20831d332c Fix Creeps enemy config on RA conquest maps 2016-04-24 11:52:18 +01:00
reaperrr
5aab8d5485 Fixed Creeps on non-Conquest RA maps 2016-04-24 11:52:18 +01:00
reaperrr
fd59408928 Fix Creeps on Llamas 2 not seeing Multi4 and Multi5 as enemies 2016-04-24 11:52:18 +01:00
Paul Chote
1f1300639d Simplify and fix missile turnaround facing check. 2016-04-23 23:03:31 +02:00
Paul Chote
ee5d6d8c65 Fix initial render state for walls. 2016-04-23 16:27:17 +02:00
Paul Chote
00d6b5764c Generate initial frozen renderables for all map-placed actors. 2016-04-23 16:27:10 +02:00
Paul Chote
d177b68067 Only refresh tooltip/health status of revealed frozen actors. 2016-04-23 16:13:47 +02:00
Paul Chote
a23fae327b Fix missile facing check. 2016-04-23 15:47:59 +02:00
reaperrr
35b08bc6b7 Give RA MiG missiles a higher CruiseAltitude 2016-04-23 15:05:42 +02:00
reaperrr
ad997263a5 Fix missiles not moving to CruiseAltitude if launched above it 2016-04-23 15:05:42 +02:00
Oliver Brakmann
4196543678 Fix PixelDoubling not working properly after zooming with mousewheel
I decided to write it this way (instead of setting `Game.Settings.Graphics.PixelDouble` in `Viewport.Zoom` appropriately) because I see the double pixel setting as the user's preference that the game uses at the start of a match and which should not be changed only because the user decided to zoom in a bit.
2016-04-23 11:57:32 +02:00
reaperrr
78613eab38 Enable Targetable to handle multiple Cloak traits 2016-04-22 22:15:48 +02:00
Paul Chote
ccf369c9c1 Fix game timer when adjusting replay speed. 2016-04-21 21:18:04 +02:00
abcdefg30
76a44f6463 Fix the debris spawned when walls are destroyed in d2k 2016-04-21 21:04:43 +02:00
Oliver Brakmann
25e27e7f1e Fix looking up un-required trait in Targetable ctor 2016-04-21 13:07:26 +02:00
abcdefg30
d6b3d2cc2d Fix the length of the idle2 sequence of tanya 2016-04-20 20:44:47 +02:00
Paul Chote
40f2dc9140 Preserve editor actor order. 2016-04-18 20:10:28 +02:00
Paul Chote
f7c9e5ecaa Increase ambient light level in gdi06. 2016-04-18 15:33:10 +02:00
Paul Chote
2b3c9421ff Increase ambient light level in fort lonestar. 2016-04-18 15:33:02 +02:00
reaperrr
2ff6e937c9 Removed custom selection priority from D2k engineer 2016-04-18 15:29:28 +02:00
reaperrr
4c7eae56ff Remove custom TD engineer selection priority 2016-04-18 15:29:20 +02:00
Curtis Shmyr
d39dd9980d Move Spectators and Team chat labels before nicknames 2016-04-18 15:25:09 +02:00
Oliver Brakmann
29a826172d Add a bunch of new maps to RA 2016-04-17 11:12:36 +02:00
Oliver Brakmann
e2a60b1f46 Re-add map Caffeinated to RA 2016-04-17 11:12:24 +02:00
Oliver Brakmann
192bab75ff Re-balance a couple of RA maps 2016-04-17 11:12:07 +02:00
Oliver Brakmann
3f39a056c6 Remove some skirmish maps from RA 2016-04-17 11:11:53 +02:00
Paul Chote
bac5e80eac Change InputOverridesSelection return values to match name. 2016-04-16 20:26:08 +02:00
Oliver Brakmann
57db412ad9 Add upgrade rule for moving InsufficientFundsWarning logic to PlayerResources 2016-04-16 14:07:50 -04:00
Oliver Brakmann
012a71a7a2 Re-implement the insufficient funds warning in a simpler manner 2016-04-16 14:07:50 -04:00
Oliver Brakmann
3773b1e893 Enable the insufficient funds warning in ra, d2k and ts 2016-04-16 14:07:50 -04:00
Oliver Brakmann
fd26f08a1b Revert the previous InsufficientFundsWarning implementation 2016-04-16 14:07:50 -04:00
abcdefg30
f6edbb7cfe Drop "U2" out of the spy planes tooltip 2016-04-16 19:49:34 +02:00
abcdefg30
e3f667be4b Fix the spyplane not having a tooltip ingame 2016-04-16 19:49:34 +02:00
Oliver Brakmann
0dcf0bab32 Fix ready checkbox in the lobby being unusable after installing a map 2016-04-16 12:42:32 -04:00
Oliver Brakmann
34ef718543 Fix submarines not being attackable when surfaced
This will also fix the issue of all pre-placed subs playing the submerging sound during the start of a map.
2016-04-14 20:12:22 +02:00
Paul Chote
2b778e2226 Fix custom order generators for left-click targeting. 2016-04-10 17:34:59 +02:00
Paul Chote
20e977e4c2 Whitelist lighting and weather traits. 2016-04-10 14:53:21 +02:00
Paul Chote
53a88c6870 Fix and improve custom rule detection. 2016-04-10 14:53:21 +02:00
Oliver Brakmann
bbf95f1f13 Fix several NREs during setup of client tooltips in GameInfoStatsLogic 2016-04-10 12:02:42 +02:00
jaZzKCS
d2a494b7bb Update ai.yaml
Enabling AI to build Repair Pad, which is now needed to build the MCV, hence needed for the AI to be able to replace the ConYard when it's gone.
2016-04-06 19:46:05 +02:00
reaperrr
89630cf91e Fix value of infantry emitted on sell 2016-04-05 22:31:38 +02:00
Oliver Brakmann
c271ce4e1d Fix opening the ScriptWrappers.lua file as read-write 2016-04-03 19:29:28 +02:00
128 changed files with 683 additions and 536 deletions

View File

@@ -108,6 +108,7 @@ Also thanks to:
* Pizzaoverhead
* Piët Delport (pjdelport)
* Psydev
* Raphael Vogt (TheRaffy, Yellow)
* Raymond Bedrossian (Squiggles211)
* Raymond Martineau (mart0258)
* Riderr3

View File

@@ -200,5 +200,55 @@ namespace OpenRA
return ruleset;
}
static bool AnyCustomYaml(MiniYaml yaml)
{
return yaml != null && (yaml.Value != null || yaml.Nodes.Any());
}
static bool AnyFlaggedTraits(ModData modData, List<MiniYamlNode> actors)
{
foreach (var actorNode in actors)
{
foreach (var traitNode in actorNode.Value.Nodes)
{
try
{
var traitName = traitNode.Key.Split('@')[0];
var traitType = modData.ObjectCreator.FindType(traitName + "Info");
if (traitType.GetInterface("ILobbyCustomRulesIgnore") == null)
return true;
}
catch { }
}
}
return false;
}
public static bool DefinesUnsafeCustomRules(ModData modData, IReadOnlyFileSystem fileSystem,
MiniYaml mapRules, MiniYaml mapWeapons, MiniYaml mapVoices, MiniYaml mapNotifications, MiniYaml mapSequences)
{
// Maps that define any weapon, voice, notification, or sequence overrides are always flagged
if (AnyCustomYaml(mapWeapons) || AnyCustomYaml(mapVoices) || AnyCustomYaml(mapNotifications) || AnyCustomYaml(mapSequences))
return true;
// Any trait overrides that aren't explicitly whitelisted are flagged
if (mapRules != null)
{
if (AnyFlaggedTraits(modData, mapRules.Nodes))
return true;
if (mapRules.Value != null)
{
var mapFiles = FieldLoader.GetValue<string[]>("value", mapRules.Value);
foreach (var f in mapFiles)
if (AnyFlaggedTraits(modData, MiniYaml.FromStream(fileSystem.Open(f))))
return true;
}
}
return false;
}
}
}

View File

@@ -241,7 +241,7 @@ namespace OpenRA.Chat
void OnJoin(object sender, JoinEventArgs e)
{
if (e.Who == client.Nickname || e.Channel != channel.Name)
if (e.Who == client.Nickname || channel == null || e.Channel != channel.Name)
return;
AddNotification("{0} joined the chat.".F(e.Who));
@@ -284,7 +284,7 @@ namespace OpenRA.Chat
void OnPart(object sender, PartEventArgs e)
{
if (e.Data.Channel != channel.Name)
if (channel == null || e.Data.Channel != channel.Name)
return;
AddNotification("{0} left the chat.".F(e.Who));

View File

@@ -21,6 +21,7 @@ using System.Text;
using System.Threading;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Primitives;
namespace OpenRA
{
@@ -80,12 +81,14 @@ namespace OpenRA
Lazy<Ruleset> rules;
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
public bool InvalidCustomRules { get; private set; }
public bool DefinesUnsafeCustomRules { get; private set; }
public bool RulesLoaded { get; private set; }
public void SetRulesetGenerator(ModData modData, Func<Ruleset> generator)
public void SetRulesetGenerator(ModData modData, Func<Pair<Ruleset, bool>> generator)
{
InvalidCustomRules = false;
RulesLoaded = false;
DefinesUnsafeCustomRules = false;
// Note: multiple threads may try to access the value at the same time
// We rely on the thread-safety guarantees given by Lazy<T> to prevent race conitions.
@@ -97,7 +100,9 @@ namespace OpenRA
try
{
return generator();
var ret = generator();
DefinesUnsafeCustomRules = ret.Second;
return ret.First;
}
catch (Exception e)
{
@@ -146,6 +151,15 @@ namespace OpenRA
public Ruleset Rules { get { return innerData.Rules; } }
public bool InvalidCustomRules { get { return innerData.InvalidCustomRules; } }
public bool RulesLoaded { get { return innerData.RulesLoaded; } }
public bool DefinesUnsafeCustomRules
{
get
{
// Force lazy rules to be evaluated
var force = innerData.Rules;
return innerData.DefinesUnsafeCustomRules;
}
}
Download download;
public long DownloadBytes { get; private set; }
@@ -297,8 +311,11 @@ namespace OpenRA
var musicDefinitions = LoadRuleSection(yaml, "Music");
var notificationDefinitions = LoadRuleSection(yaml, "Notifications");
var sequenceDefinitions = LoadRuleSection(yaml, "Sequences");
return Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions);
var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
return Pair.New(rules, flagged);
});
if (p.Contains("map.png"))
@@ -338,6 +355,11 @@ namespace OpenRA
return true;
}
public void PreloadRules()
{
var unused = Rules;
}
public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml, Action<MapPreview> parseMetadata = null)
{
var newData = innerData.Clone();
@@ -384,8 +406,11 @@ namespace OpenRA
var musicDefinitions = LoadRuleSection(rulesYaml, "Music");
var notificationDefinitions = LoadRuleSection(rulesYaml, "Notifications");
var sequenceDefinitions = LoadRuleSection(rulesYaml, "Sequences");
return Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions);
var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
return Pair.New(rules, flagged);
});
}
catch (Exception) { }

View File

@@ -77,18 +77,17 @@ namespace OpenRA.Network
if (world == null)
{
if (orderManager.LocalClient != null && client.Team == orderManager.LocalClient.Team)
Game.AddChatLine(client.Color.RGB, client.Name + " (Team)", order.TargetString);
Game.AddChatLine(client.Color.RGB, "[Team] " + client.Name, order.TargetString);
}
else
{
var player = world.FindPlayerByClient(client);
if (player != null && ((world.LocalPlayer != null && player.Stances[world.LocalPlayer] == Stance.Ally) || player.WinState == WinState.Lost))
{
var suffix = player.WinState == WinState.Lost ? " (Dead)" : " (Team)";
Game.AddChatLine(client.Color.RGB, client.Name + suffix, order.TargetString);
}
if (player != null && player.WinState == WinState.Lost)
Game.AddChatLine(client.Color.RGB, client.Name + " (Dead)", order.TargetString);
else if (player != null && world.LocalPlayer != null && player.Stances[world.LocalPlayer] == Stance.Ally)
Game.AddChatLine(client.Color.RGB, "[Team] " + client.Name, order.TargetString);
else if (orderManager.LocalClient != null && orderManager.LocalClient.IsObserver && client.IsObserver)
Game.AddChatLine(client.Color.RGB, client.Name + " (Spectators)", order.TargetString);
Game.AddChatLine(client.Color.RGB, "[Spectators] " + client.Name, order.TargetString);
}
}

View File

@@ -58,5 +58,11 @@ namespace OpenRA.Orders
{
return world.Map.Contains(cell) ? Cursor : "generic-blocked";
}
public override bool InputOverridesSelection(World world, int2 xy, MouseInput mi)
{
// Custom order generators always override selection
return true;
}
}
}

View File

@@ -83,7 +83,7 @@ namespace OpenRA.Orders
}
// Used for classic mouse orders, determines whether or not action at xy is move or select
public static bool InputOverridesSelection(World world, int2 xy, MouseInput mi)
public virtual bool InputOverridesSelection(World world, int2 xy, MouseInput mi)
{
var actor = world.ScreenMap.ActorsAt(xy).WithHighestSelectionPriority(xy);
if (actor == null)
@@ -95,10 +95,21 @@ namespace OpenRA.Orders
var underCursor = world.Selection.Actors.WithHighestSelectionPriority(xy);
var o = OrderForUnit(underCursor, target, actorsAt, cell, mi);
if (o != null && o.Order.OverrideSelection)
return false;
if (o != null)
{
var modifiers = TargetModifiers.None;
if (mi.Modifiers.HasModifier(Modifiers.Ctrl))
modifiers |= TargetModifiers.ForceAttack;
if (mi.Modifiers.HasModifier(Modifiers.Shift))
modifiers |= TargetModifiers.ForceQueue;
if (mi.Modifiers.HasModifier(Modifiers.Alt))
modifiers |= TargetModifiers.ForceMove;
return true;
if (o.Order.TargetOverridesSelection(modifiers))
return true;
}
return false;
}
/// <summary>

View File

@@ -160,7 +160,7 @@ namespace OpenRA.Scripting
.ToArray();
runtime.Globals["GameDir"] = Platform.GameDir;
runtime.DoBuffer(File.Open(Platform.ResolvePath(".", "lua", "scriptwrapper.lua"), FileMode.Open).ReadAllText(), "scriptwrapper.lua").Dispose();
runtime.DoBuffer(File.Open(Platform.ResolvePath(".", "lua", "scriptwrapper.lua"), FileMode.Open, FileAccess.Read).ReadAllText(), "scriptwrapper.lua").Dispose();
tick = (LuaFunction)runtime.Globals["Tick"];
// Register globals

View File

@@ -392,7 +392,7 @@ namespace OpenRA.Server
SendOrderTo(newConn, "Message", motd);
}
if (Map.Rules != ModData.DefaultRules && !LobbyInfo.IsSinglePlayer)
if (!LobbyInfo.IsSinglePlayer && Map.DefinesUnsafeCustomRules)
SendOrderTo(newConn, "Message", "This map contains custom rules. Game experience may change.");
if (Settings.DisableSinglePlayer)

View File

@@ -101,6 +101,7 @@ namespace OpenRA
public int Samples = 25;
public bool IgnoreVersionMismatch = false;
public bool SendSystemInformation = true;
public int SystemInformationVersionPrompt = 0;
public string UUID = System.Guid.NewGuid().ToString();
}

View File

@@ -25,6 +25,12 @@ namespace OpenRA.Traits
[Desc("Force the DefaultCash option by disabling changes in the lobby.")]
public readonly bool DefaultCashLocked = false;
[Desc("Speech notification to play when the player does not have any funds.")]
public readonly string InsufficientFundsNotification = null;
[Desc("Delay (in ticks) during which warnings will be muted.")]
public readonly int InsufficientFundsNotificationDelay = 750;
public object Create(ActorInitializer init) { return new PlayerResources(init.Self, this); }
}
@@ -32,10 +38,12 @@ namespace OpenRA.Traits
{
const float DisplayCashFracPerFrame = .07f;
const int DisplayCashDeltaPerFrame = 37;
readonly PlayerResourcesInfo info;
readonly Player owner;
public PlayerResources(Actor self, PlayerResourcesInfo info)
{
this.info = info;
owner = self.Owner;
Cash = self.World.LobbyInfo.GlobalSettings.StartingCash;
@@ -52,6 +60,8 @@ namespace OpenRA.Traits
public int Earned;
public int Spent;
int lastNotificationTick;
public bool CanGiveResources(int amount)
{
return Resources + amount <= ResourceCapacity;
@@ -111,9 +121,19 @@ namespace OpenRA.Traits
}
}
public bool TakeCash(int num)
public bool TakeCash(int num, bool notifyLowFunds = false)
{
if (Cash + Resources < num) return false;
if (Cash + Resources < num)
{
if (notifyLowFunds && !string.IsNullOrEmpty(info.InsufficientFundsNotification) &&
owner.World.WorldTick - lastNotificationTick >= info.InsufficientFundsNotificationDelay)
{
lastNotificationTick = owner.World.WorldTick;
Game.Sound.PlayNotification(owner.World.Map.Rules, owner, "Speech", info.InsufficientFundsNotification, owner.Faction.InternalName);
}
return false;
}
// Spend ore before cash
Resources -= num;

View File

@@ -108,7 +108,7 @@ namespace OpenRA.Traits
int OrderPriority { get; }
bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor);
bool IsQueued { get; }
bool OverrideSelection { get; }
bool TargetOverridesSelection(TargetModifiers modifiers);
}
public interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
@@ -319,6 +319,7 @@ namespace OpenRA.Traits
public interface ITraitInfo : ITraitInfoInterface { object Create(ActorInitializer init); }
public class TraitInfo<T> : ITraitInfo where T : new() { public virtual object Create(ActorInitializer init) { return new T(); } }
public interface ILobbyCustomRulesIgnore { }
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1302:InterfaceNamesMustBeginWithI", Justification = "Not a real interface, but more like a tag.")]
public interface Requires<T> where T : class, ITraitInfoInterface { }

View File

@@ -103,10 +103,8 @@ namespace OpenRA.Widgets
var selectableActor = World.ScreenMap.ActorsAt(mousePos).Any(x =>
x.Info.HasTraitInfo<SelectableInfo>() && (x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x)));
var ignoreSelection = mi.Modifiers.HasModifier(Modifiers.Ctrl) || mi.Modifiers.HasModifier(Modifiers.Alt) ||
UnitOrderGenerator.InputOverridesSelection(World, mousePos, mi);
if (ignoreSelection || !selectableActor)
var uog = (UnitOrderGenerator)World.OrderGenerator;
if (!selectableActor || uog.InputOverridesSelection(World, mousePos, mi))
{
// Order units instead of selecting
ApplyOrders(World, mi);
@@ -347,8 +345,16 @@ namespace OpenRA.Widgets
bool TogglePixelDouble()
{
Game.Settings.Graphics.PixelDouble ^= true;
worldRenderer.Viewport.Zoom = Game.Settings.Graphics.PixelDouble ? 2 : 1;
if (worldRenderer.Viewport.Zoom == 1f)
worldRenderer.Viewport.Zoom = 2f;
else
{
// Reset zoom to regular view if it was anything else before
// (like a zoom level only reachable by using the scroll wheel).
worldRenderer.Viewport.Zoom = 1f;
}
Game.Settings.Graphics.PixelDouble = worldRenderer.Viewport.Zoom == 2f;
return true;
}

View File

@@ -32,11 +32,20 @@ namespace OpenRA.Mods.Common.Activities
public override Activity Tick(Actor self)
{
if (IsCanceled) return NextActivity;
if (host == null || !host.IsInWorld) return NextActivity;
if (IsCanceled)
{
if (remainingTicks-- == 0)
return NextActivity;
return this;
}
if (host == null || !host.IsInWorld)
return NextActivity;
health = self.TraitOrDefault<Health>();
if (health == null) return NextActivity;
if (health == null)
return NextActivity;
if (health.DamageState == DamageState.Undamaged)
{
@@ -56,7 +65,7 @@ namespace OpenRA.Mods.Common.Activities
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", repairsUnits.StartRepairingNotification, self.Owner.Faction.InternalName);
}
if (!self.Owner.PlayerActor.Trait<PlayerResources>().TakeCash(cost))
if (!self.Owner.PlayerActor.Trait<PlayerResources>().TakeCash(cost, true))
{
remainingTicks = 1;
return this;

View File

@@ -9,6 +9,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
@@ -664,6 +665,11 @@ namespace OpenRA.Mods.Common.Effects
// of vertical facing bound by the maximum vertical rate of turn
var vDist = new WVec(-diffClfMslHgt - info.CruiseAltitude.Length, -speed, 0);
desiredVFacing = (sbyte)vDist.HorizontalLengthSquared != 0 ? vDist.Yaw.Facing : vFacing;
// If the missile is launched above CruiseAltitude, it has to descend instead of climbing
if (-diffClfMslHgt > info.CruiseAltitude.Length)
desiredVFacing = -desiredVFacing;
desiredVFacing = desiredVFacing.Clamp(-info.VerticalRateOfTurn, info.VerticalRateOfTurn);
ChangeSpeed();
@@ -675,6 +681,11 @@ namespace OpenRA.Mods.Common.Effects
// of vertical facing bound by the maximum vertical rate of turn
var vDist = new WVec(-diffClfMslHgt - info.CruiseAltitude.Length, -speed, 0);
desiredVFacing = (sbyte)vDist.HorizontalLengthSquared != 0 ? vDist.Yaw.Facing : vFacing;
// If the missile is launched above CruiseAltitude, it has to descend instead of climbing
if (-diffClfMslHgt > info.CruiseAltitude.Length)
desiredVFacing = -desiredVFacing;
desiredVFacing = desiredVFacing.Clamp(-info.VerticalRateOfTurn, info.VerticalRateOfTurn);
ChangeSpeed();
@@ -701,9 +712,10 @@ namespace OpenRA.Mods.Common.Effects
var velVec = tarDistVec + predVel;
var desiredHFacing = velVec.HorizontalLengthSquared != 0 ? velVec.Yaw.Facing : hFacing;
if (allowPassBy && System.Math.Abs(desiredHFacing - hFacing) >= System.Math.Abs(desiredHFacing + 128 - hFacing))
var delta = Util.NormalizeFacing(hFacing - desiredHFacing);
if (allowPassBy && delta > 64 && delta < 192)
{
desiredHFacing += 128;
desiredHFacing = (desiredHFacing + 128) & 0xFF;
targetPassedBy = true;
}
else

View File

@@ -299,7 +299,6 @@
<Compile Include="Traits\Burns.cs" />
<Compile Include="Traits\C4Demolition.cs" />
<Compile Include="Traits\Health.cs" />
<Compile Include="Traits\Player\InsufficientFundsWarning.cs" />
<Compile Include="Traits\PowerTooltip.cs" />
<Compile Include="Traits\VeteranProductionIconOverlay.cs" />
<Compile Include="Traits\Capturable.cs" />

View File

@@ -19,7 +19,10 @@ namespace OpenRA.Mods.Common.Orders
{
public string OrderID { get { return "Move"; } }
public int OrderPriority { get { return 4; } }
public bool OverrideSelection { get { return false; } }
public bool TargetOverridesSelection(TargetModifiers modifiers)
{
return modifiers.HasModifier(TargetModifiers.ForceMove);
}
readonly AircraftInfo info;

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Orders
public string OrderID { get; private set; }
public int OrderPriority { get; private set; }
public bool OverrideSelection { get { return true; } }
public bool TargetOverridesSelection(TargetModifiers modifiers) { return true; }
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
{

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Orders
public string OrderID { get; private set; }
public int OrderPriority { get; private set; }
public bool? ForceAttack = null;
public bool OverrideSelection { get { return true; } }
public bool TargetOverridesSelection(TargetModifiers modifiers) { return true; }
public abstract bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor);
public abstract bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor);

View File

@@ -398,7 +398,7 @@ namespace OpenRA.Mods.Common.Server
server.SendMessage("{0} changed the map to {1}.".F(client.Name, server.Map.Title));
if (server.Map.Rules.Actors != server.ModData.DefaultRules.Actors)
if (server.Map.DefinesUnsafeCustomRules)
server.SendMessage("This map contains custom rules. Game experience may change.");
if (server.Settings.DisableSinglePlayer)

View File

@@ -309,7 +309,7 @@ namespace OpenRA.Mods.Common.Traits
public string OrderID { get; private set; }
public int OrderPriority { get; private set; }
public bool OverrideSelection { get { return true; } }
public bool TargetOverridesSelection(TargetModifiers modifiers) { return true; }
bool CanTargetActor(Actor self, Target target, ref TargetModifiers modifiers, ref string cursor)
{

View File

@@ -88,7 +88,7 @@ namespace OpenRA.Mods.Common.Traits
{
public string OrderID { get { return "SetRallyPoint"; } }
public int OrderPriority { get { return 0; } }
public bool OverrideSelection { get { return true; } }
public bool TargetOverridesSelection(TargetModifiers modifiers) { return true; }
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
{

View File

@@ -115,7 +115,7 @@ namespace OpenRA.Mods.Common.Traits
var cost = Math.Max(1, (hpToRepair * Info.RepairPercent * buildingValue) / (health.MaxHP * 100));
// TakeCash will return false if the player can't pay, and will stop him from contributing this Tick
var activePlayers = Repairers.Count(player => player.PlayerActor.Trait<PlayerResources>().TakeCash(cost));
var activePlayers = Repairers.Count(player => player.PlayerActor.Trait<PlayerResources>().TakeCash(cost, true));
RepairActive = activePlayers > 0;

View File

@@ -266,9 +266,8 @@ namespace OpenRA.Mods.Common.Traits
if (passengerFacing != null)
passengerFacing.Facing = facing.Value.Facing + Info.PassengerFacing;
var passengerTurreted = passenger.TraitOrDefault<Turreted>();
if (passengerTurreted != null)
passengerTurreted.TurretFacing = facing.Value.Facing + Info.PassengerFacing;
foreach (var t in passenger.TraitsImplementing<Turreted>())
t.TurretFacing = facing.Value.Facing + Info.PassengerFacing;
}
public IEnumerable<PipType> GetPips(Actor self)

View File

@@ -84,7 +84,10 @@ namespace OpenRA.Mods.Common.Traits
// The upgrade manager exists, but may not have finished being created yet.
// We'll defer the upgrades until the end of the tick, at which point it will be ready.
if (Cloaked)
{
wasCloaked = true;
self.World.AddFrameEndTask(_ => GrantUpgrades(self));
}
}
public bool Cloaked { get { return !IsTraitDisabled && remainingTime <= 0; } }

View File

@@ -57,7 +57,7 @@ namespace OpenRA.Mods.Common.Traits
var cost = csv != null ? csv.Value : (valued != null ? valued.Cost : 0);
var health = self.TraitOrDefault<Health>();
var dudesValue = info.ValuePercent * cost;
var dudesValue = info.ValuePercent * cost / 100;
if (health != null)
{
if (100 * health.HP >= info.MinHpPercent * health.MaxHP)

View File

@@ -452,7 +452,7 @@ namespace OpenRA.Mods.Common.Traits
public string OrderID { get { return "Harvest"; } }
public int OrderPriority { get { return 10; } }
public bool IsQueued { get; protected set; }
public bool OverrideSelection { get { return true; } }
public bool TargetOverridesSelection(TargetModifiers modifiers) { return true; }
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
{

View File

@@ -720,7 +720,10 @@ namespace OpenRA.Mods.Common.Traits
{
readonly Mobile mobile;
readonly bool rejectMove;
public bool OverrideSelection { get { return false; } }
public bool TargetOverridesSelection(TargetModifiers modifiers)
{
return modifiers.HasModifier(TargetModifiers.ForceMove);
}
public MoveOrderTargeter(Actor self, Mobile unit)
{

View File

@@ -20,8 +20,6 @@ namespace OpenRA.Mods.Common.Traits
[Desc("This actor will remain visible (but not updated visually) under fog, once discovered.")]
public class FrozenUnderFogInfo : ITraitInfo, Requires<BuildingInfo>, IDefaultVisibilityInfo
{
public readonly bool StartsRevealed = false;
[Desc("Players with these stances can always see the actor.")]
public readonly Stance AlwaysVisibleStances = Stance.Ally;
@@ -55,8 +53,9 @@ namespace OpenRA.Mods.Common.Traits
var map = init.World.Map;
// Spawned actors (e.g. building husks) shouldn't be revealed
startsRevealed = info.StartsRevealed && !init.Contains<ParentActorInit>();
// Explore map-placed actors if the "Explore Map" option is enabled
var exploredMap = !init.World.LobbyInfo.GlobalSettings.Shroud;
startsRevealed = exploredMap && init.Contains<SpawnedByMapInit>() && !init.Contains<HiddenUnderFogInit>();
var footprintCells = FootprintUtils.Tiles(init.Self).ToList();
footprint = footprintCells.SelectMany(c => map.ProjectedCellsCovering(c.ToMPos(map))).ToArray();
}
@@ -142,4 +141,6 @@ namespace OpenRA.Mods.Common.Traits
return IsVisible(self, self.World.RenderPlayer) || isRendering ? r : SpriteRenderable.None;
}
}
public class HiddenUnderFogInit : IActorInit { }
}

View File

@@ -17,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Used for day/night effects.")]
class GlobalLightingPaletteEffectInfo : ITraitInfo
class GlobalLightingPaletteEffectInfo : ITraitInfo, ILobbyCustomRulesIgnore
{
[Desc("Do not modify graphics that use any palette in this list.")]
public readonly HashSet<string> ExcludePalettes = new HashSet<string> { "cursor", "chrome", "colorpicker", "fog", "shroud", "alpha" };

View File

@@ -16,7 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Can be paradropped by a ParaDrop actor.")]
class ParachutableInfo : ITraitInfo
class ParachutableInfo : ITraitInfo, Requires<IPositionableInfo>
{
[Desc("If we land on invalid terrain for my actor type should we be killed?")]
public readonly bool KilledOnImpassableTerrain = true;
@@ -51,8 +51,7 @@ namespace OpenRA.Mods.Common.Traits
{
self = init.Self;
this.info = info;
positionable = self.TraitOrDefault<IPositionable>();
positionable = self.Trait<IPositionable>();
}
void INotifyParachuteLanded.OnLanded(Actor ignore)

View File

@@ -1,54 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2016 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Provides the player with an audible warning when they run out of money while producing.")]
public class InsufficientFundsWarningInfo : ITraitInfo, Requires<PlayerResourcesInfo>
{
[Desc("The speech to play for the warning.")]
public readonly string Notification = "InsufficientFunds";
public object Create(ActorInitializer init) { return new InsufficientFundsWarning(this); }
}
public class InsufficientFundsWarning : INotifyInsufficientFunds
{
readonly InsufficientFundsWarningInfo info;
bool played;
public InsufficientFundsWarning(InsufficientFundsWarningInfo info)
{
this.info = info;
}
void INotifyInsufficientFunds.InsufficientFunds(Actor self)
{
Game.RunAfterTick(() =>
{
if (played)
return;
played = true;
var owner = self.Owner;
Game.Sound.PlayNotification(self.World.Map.Rules, owner, "Speech", info.Notification, owner.Faction.InternalName);
});
}
void INotifyInsufficientFunds.SufficientFunds(Actor self)
{
played = false;
}
}
}

View File

@@ -415,12 +415,8 @@ namespace OpenRA.Mods.Common.Traits
public bool Started { get; private set; }
public int Slowdown { get; private set; }
readonly INotifyInsufficientFunds[] insufficientFunds;
readonly Player owner;
readonly PowerManager pm;
bool insufficientFundsPlayed;
public ProductionItem(ProductionQueue queue, string item, int cost, PowerManager pm, Action onComplete)
{
Item = item;
@@ -429,8 +425,6 @@ namespace OpenRA.Mods.Common.Traits
OnComplete = onComplete;
Queue = queue;
this.pm = pm;
owner = queue.Actor.Owner;
insufficientFunds = owner.PlayerActor.TraitsImplementing<INotifyInsufficientFunds>().ToArray();
}
public void Tick(PlayerResources pr)
@@ -441,13 +435,6 @@ namespace OpenRA.Mods.Common.Traits
if (time > 0)
RemainingTime = TotalTime = time;
// Don't play a QueuedAudio notification when we can't start building (because we don't have the money to)
// Also don't play it when the time to build is actually 0 (i.e. normally dev cheats)
// to prevent overlapping with the ReadyAudio notification
var initialCost = RemainingCost / RemainingTime;
if (time != 0 && initialCost != 0 && pr.Cash + pr.Resources > initialCost)
Game.Sound.PlayNotification(owner.World.Map.Rules, owner, "Speech", Queue.Info.QueuedAudio, owner.Faction.InternalName);
Started = true;
}
@@ -471,23 +458,8 @@ namespace OpenRA.Mods.Common.Traits
}
var costThisFrame = RemainingCost / RemainingTime;
if (costThisFrame != 0 && !pr.TakeCash(costThisFrame))
{
if (!insufficientFundsPlayed)
{
insufficientFundsPlayed = true;
foreach (var funds in insufficientFunds)
funds.InsufficientFunds(owner.PlayerActor);
}
if (costThisFrame != 0 && !pr.TakeCash(costThisFrame, true))
return;
}
if (insufficientFundsPlayed)
insufficientFundsPlayed = false;
foreach (var funds in insufficientFunds)
funds.SufficientFunds(owner.PlayerActor);
RemainingCost -= costThisFrame;
RemainingTime -= 1;

View File

@@ -140,6 +140,9 @@ namespace OpenRA.Mods.Common.Traits
{
DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), () => adjacent);
UpdateNeighbours(self);
// Set the initial animation frame before the render tick (for frozen actor previews)
self.World.AddFrameEndTask(_ => DefaultAnimation.Tick());
}
static void UpdateNeighbours(Actor self)

View File

@@ -77,6 +77,10 @@ namespace OpenRA.Mods.Common.Traits
self.World.AddFrameEndTask(w =>
{
// Actor has been disposed by something else before its death (for example `Enter`).
if (self.Disposed)
return;
var td = new TypeDictionary
{
new ParentActorInit(self),

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
@@ -26,25 +27,28 @@ namespace OpenRA.Mods.Common.Traits
public override object Create(ActorInitializer init) { return new Targetable(init.Self, this); }
}
public class Targetable : UpgradableTrait<TargetableInfo>, ITargetable
public class Targetable : UpgradableTrait<TargetableInfo>, ITargetable, INotifyCreated
{
protected static readonly string[] None = new string[] { };
protected Cloak cloak;
protected Cloak[] cloaks;
public Targetable(Actor self, TargetableInfo info)
: base(info)
: base(info) { }
void INotifyCreated.Created(Actor self)
{
cloak = self.TraitOrDefault<Cloak>();
cloaks = self.TraitsImplementing<Cloak>().ToArray();
}
public virtual bool TargetableBy(Actor self, Actor viewer)
{
if (IsTraitDisabled)
return false;
if (cloak == null || (!viewer.IsDead && viewer.Info.HasTraitInfo<IgnoresCloakInfo>()))
if (!cloaks.Any() || (!viewer.IsDead && viewer.Info.HasTraitInfo<IgnoresCloakInfo>()))
return true;
return cloak.IsVisible(self, viewer.Owner);
return cloaks.All(c => c.IsTraitDisabled || c.IsVisible(self, viewer.Owner));
}
public virtual HashSet<string> TargetTypes { get { return Info.TargetTypes; } }

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits
public class EditorActorLayer : IWorldLoaded, ITickRender, IRender, IRadarSignature, ICreatePlayers
{
readonly EditorActorLayerInfo info;
readonly Dictionary<string, EditorActorPreview> previews = new Dictionary<string, EditorActorPreview>();
readonly List<EditorActorPreview> previews = new List<EditorActorPreview>();
readonly Dictionary<CPos, List<EditorActorPreview>> cellMap = new Dictionary<CPos, List<EditorActorPreview>>();
SpatiallyPartitioned<EditorActorPreview> screenMap;
@@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.Traits
Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary()), true);
// Update neighbours in one pass
foreach (var p in previews.Values)
foreach (var p in previews)
UpdateNeighbours(p.Footprint);
}
@@ -83,8 +83,8 @@ namespace OpenRA.Mods.Common.Traits
if (wr.World.Type != WorldType.Editor)
return;
foreach (var kv in previews.Values)
kv.Tick();
foreach (var p in previews)
p.Tick();
}
static readonly IEnumerable<IRenderable> NoRenderables = Enumerable.Empty<IRenderable>();
@@ -104,7 +104,7 @@ namespace OpenRA.Mods.Common.Traits
var owner = Players.Players[reference.InitDict.Get<OwnerInit>().PlayerName];
var preview = new EditorActorPreview(worldRenderer, id, reference, owner);
previews.Add(id, preview);
previews.Add(preview);
screenMap.Add(preview, preview.Bounds);
foreach (var kv in preview.Footprint)
@@ -132,7 +132,7 @@ namespace OpenRA.Mods.Common.Traits
public void Remove(EditorActorPreview preview)
{
previews.Remove(preview.ID);
previews.Remove(preview);
screenMap.Remove(preview);
foreach (var kv in preview.Footprint)
@@ -155,7 +155,7 @@ namespace OpenRA.Mods.Common.Traits
void SyncMultiplayerCount()
{
var newCount = previews.Count(p => p.Value.Info.Name == "mpspawn");
var newCount = previews.Count(p => p.Info.Name == "mpspawn");
var mp = Players.Players.Where(p => p.Key.StartsWith("Multi")).ToList();
foreach (var kv in mp)
{
@@ -245,7 +245,7 @@ namespace OpenRA.Mods.Common.Traits
var id = previews.Count();
var possibleName = "Actor" + id.ToString();
while (previews.ContainsKey(possibleName))
while (previews.Any(p => p.ID == possibleName))
{
id++;
possibleName = "Actor" + id.ToString();
@@ -258,7 +258,7 @@ namespace OpenRA.Mods.Common.Traits
{
var nodes = new List<MiniYamlNode>();
foreach (var a in previews)
nodes.Add(new MiniYamlNode(a.Key, a.Value.Save()));
nodes.Add(new MiniYamlNode(a.ID, a.Save()));
return nodes;
}

View File

@@ -37,6 +37,7 @@ namespace OpenRA.Mods.Common.Traits
var initDict = actorReference.InitDict;
initDict.Add(new SkipMakeAnimsInit());
initDict.Add(new SpawnedByMapInit(kv.Key));
var actor = world.CreateActor(actorReference.Type, initDict);
Actors[kv.Key] = actor;
LastMapActorID = actor.ActorID;
@@ -45,4 +46,14 @@ namespace OpenRA.Mods.Common.Traits
}
public class SkipMakeAnimsInit : IActorInit, ISuppressInitExport { }
public class SpawnedByMapInit : IActorInit<string>, ISuppressInitExport
{
public readonly string Name;
public SpawnedByMapInit(string name) { Name = name; }
public string Value(World world)
{
return Name;
}
}
}

View File

@@ -17,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Adds a particle-based overlay.")]
public class WeatherOverlayInfo : ITraitInfo
public class WeatherOverlayInfo : ITraitInfo, ILobbyCustomRulesIgnore
{
[Desc("Factor for particle density. As higher as more particles will get spawned.")]
public readonly float ParticleDensityFactor = 0.0007625f;

View File

@@ -124,11 +124,4 @@ namespace OpenRA.Mods.Common.Traits
bool AdjacentWallCanConnect(Actor self, CPos wallLocation, string wallType, out CVec facing);
void SetDirty();
}
[RequireExplicitImplementation]
interface INotifyInsufficientFunds
{
void InsufficientFunds(Actor self);
void SufficientFunds(Actor self);
}
}

View File

@@ -73,6 +73,14 @@ namespace OpenRA.Mods.Common
}
}
public static int NormalizeFacing(int f)
{
if (f >= 0)
return f & 0xFF;
return 0xFF - (-f & 0xFF);
}
public static WPos BetweenCells(World w, CPos from, CPos to)
{
return WPos.Lerp(w.Map.CenterOfCell(from), w.Map.CenterOfCell(to), 1, 2);

View File

@@ -390,7 +390,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
if (health != 100)
initDict.Add(new HealthInit(health));
if (facing != 0)
initDict.Add(new FacingInit(facing));
initDict.Add(new FacingInit(255 - facing));
if (section == "INFANTRY")
actor.Add(new SubCellInit(Exts.ParseIntegerInvariant(parts[4])));

View File

@@ -757,6 +757,26 @@ namespace OpenRA.Mods.Common.UtilityCommands
node.Key = "EffectImage";
}
if (engineVersion < 20160408)
{
var traitNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "InsufficientFundsWarning");
if (traitNode != null)
{
var prNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "PlayerResources");
if (prNode != null)
prNode.Value.Nodes.Add(new MiniYamlNode("InsufficientFundsNotification", new MiniYaml("InsufficientFunds")));
node.Value.Nodes.Remove(traitNode);
}
}
if (engineVersion < 20160418)
{
// Removed FrozenUnderFog.StartsRevealed
if (node.Key == "FrozenUnderFog")
node.Value.Nodes.RemoveAll(x => x.Key == "StartsRevealed");
}
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
}
}

View File

@@ -91,6 +91,9 @@ namespace OpenRA.Mods.Common.Warheads
public override void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers)
{
if (!target.IsValidFor(firedBy))
return;
var pos = target.CenterPosition;
var world = firedBy.World;
var targetTile = world.Map.CellContaining(pos);

View File

@@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var pp = p;
var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex);
var item = playerTemplate.Clone();
LobbyUtils.SetupClientWidget(item, client, orderManager, client.Bot == null);
LobbyUtils.SetupClientWidget(item, client, orderManager, client != null && client.Bot == null);
var nameLabel = item.Get<LabelWidget>("NAME");
var nameFont = Game.Renderer.Fonts[nameLabel.Font];

View File

@@ -40,12 +40,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (timer != null)
{
// Timers in replays should be synced to the effective game time, not the playback time.
var timestep = world.Timestep;
if (world.IsReplay)
{
GameSpeed speed;
var gameSpeeds = Game.ModData.Manifest.Get<GameSpeeds>();
if (gameSpeeds.Speeds.TryGetValue(world.LobbyInfo.GlobalSettings.GameSpeedType, out speed))
timestep = speed.Timestep;
}
timer.GetText = () =>
{
if (status == null && shouldShowStatus())
return statusText();
return WidgetUtils.FormatTime(world.WorldTick, world.Timestep);
return WidgetUtils.FormatTime(world.WorldTick, timestep);
};
}

View File

@@ -781,7 +781,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
new Task(() =>
{
// Force map rules to be loaded on this background thread
var unused = map.Rules;
map.PreloadRules();
}).Start();
}
@@ -799,7 +799,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
new Task(() =>
{
// Force map rules to be loaded on this background thread
var unused = currentMap.Rules;
currentMap.PreloadRules();
Game.RunAfterTick(() =>
{
// Map may have changed in the meantime

View File

@@ -109,8 +109,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var install = download.GetOrNull<ButtonWidget>("MAP_INSTALL");
if (install != null)
{
install.OnClick = () => lobby.Map.Install(
() => orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady))));
install.OnClick = () => lobby.Map.Install(() =>
{
lobby.Map.PreloadRules();
Game.RunAfterTick(() => orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady))));
});
install.IsHighlighted = () => installHighlighted;
}
}

View File

@@ -240,7 +240,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var adminIndicator = parent.GetOrNull("ADMIN_INDICATOR");
if (adminIndicator != null)
adminIndicator.IsVisible = () => c.IsAdmin;
adminIndicator.IsVisible = () => c != null && c.IsAdmin;
var block = parent.GetOrNull("LATENCY");
if (block != null)
@@ -253,8 +253,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
}
var tooltip = parent.Get<ClientTooltipRegionWidget>("CLIENT_REGION");
tooltip.IsVisible = () => visible;
tooltip.Bind(orderManager, c.Index);
tooltip.IsVisible = () => c != null && visible;
if (c != null)
tooltip.Bind(orderManager, c.Index);
}
public static void SetupEditableNameWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager)

View File

@@ -12,16 +12,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net;
using OpenRA.Primitives;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
{
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1203:ConstantsMustAppearBeforeFields",
Justification = "SystemInformation version should be defined next to the dictionary it refers to.")]
public class MainMenuLogic : ChromeLogic
{
protected enum MenuType { Main, Singleplayer, Extras, MapEditor, None }
protected enum MenuType { Main, Singleplayer, Extras, MapEditor, SystemInfoPrompt, None }
protected MenuType menuType = MenuType.Main;
readonly Widget rootMenu;
@@ -32,6 +36,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Update news once per game launch
static bool fetchedNews;
// Increment the version number when adding new stats
const int SystemInformationVersion = 1;
Dictionary<string, Pair<string, string>> GetSystemInformation()
{
var lang = System.Globalization.CultureInfo.InstalledUICulture.TwoLetterISOLanguageName;
return new Dictionary<string, Pair<string, string>>()
{
{ "id", Pair.New("Anonymous ID", Game.Settings.Debug.UUID) },
{ "platform", Pair.New("OS Type", Platform.CurrentPlatform.ToString()) },
{ "os", Pair.New("OS Version", Environment.OSVersion.ToString()) },
{ "runtime", Pair.New(".NET Runtime", Platform.RuntimeVersion) },
{ "gl", Pair.New("OpenGL Version", Game.Renderer.GLVersion) },
{ "lang", Pair.New("System Language", lang) }
};
}
void SwitchMenu(MenuType type)
{
menuType = type;
@@ -201,7 +221,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var newsBG = widget.GetOrNull("NEWS_BG");
if (newsBG != null)
{
newsBG.IsVisible = () => Game.Settings.Game.FetchNews && menuType != MenuType.None;
newsBG.IsVisible = () => Game.Settings.Game.FetchNews && menuType != MenuType.None && menuType != MenuType.SystemInfoPrompt;
newsPanel = Ui.LoadWidget<ScrollPanelWidget>("NEWS_PANEL", null, new WidgetArgs());
newsTemplate = newsPanel.Get("NEWS_ITEM_TEMPLATE");
@@ -209,26 +229,79 @@ namespace OpenRA.Mods.Common.Widgets.Logic
newsStatus = newsPanel.Get<LabelWidget>("NEWS_STATUS");
SetNewsStatus("Loading news");
}
Game.OnRemoteDirectConnect += OnRemoteDirectConnect;
// System information opt-out prompt
var sysInfoPrompt = widget.Get("SYSTEM_INFO_PROMPT");
sysInfoPrompt.IsVisible = () => menuType == MenuType.SystemInfoPrompt;
if (Game.Settings.Debug.SystemInformationVersionPrompt < SystemInformationVersion)
{
menuType = MenuType.SystemInfoPrompt;
var sysInfoCheckbox = sysInfoPrompt.Get<CheckboxWidget>("SYSINFO_CHECKBOX");
sysInfoCheckbox.IsChecked = () => Game.Settings.Debug.SendSystemInformation;
sysInfoCheckbox.OnClick = () => Game.Settings.Debug.SendSystemInformation ^= true;
var sysInfoData = sysInfoPrompt.Get<ScrollPanelWidget>("SYSINFO_DATA");
var template = sysInfoData.Get<LabelWidget>("DATA_TEMPLATE");
sysInfoData.RemoveChildren();
foreach (var info in GetSystemInformation().Values)
{
var label = template.Clone() as LabelWidget;
var text = info.First + ": " + info.Second;
label.GetText = () => text;
sysInfoData.AddChild(label);
}
sysInfoPrompt.Get<ButtonWidget>("BACK_BUTTON").OnClick = () =>
{
Game.Settings.Debug.SystemInformationVersionPrompt = SystemInformationVersion;
Game.Settings.Save();
SwitchMenu(MenuType.Main);
LoadAndDisplayNews(newsBG);
};
}
else
LoadAndDisplayNews(newsBG);
}
void LoadAndDisplayNews(Widget newsBG)
{
if (newsBG != null)
{
var cacheFile = Platform.ResolvePath("^", "news.yaml");
var currentNews = ParseNews(cacheFile);
if (currentNews != null)
DisplayNews(currentNews);
var newsButton = newsBG.GetOrNull<DropDownButtonWidget>("NEWS_BUTTON");
if (newsButton != null)
{
if (!fetchedNews)
new Download(Game.Settings.Game.NewsUrl + SysInfoQuery(), cacheFile, e => { },
{
// Send the mod and engine version to support version-filtered news (update prompts)
var newsURL = Game.Settings.Game.NewsUrl + "?version={0}&mod={1}&modversion={2}".F(
Uri.EscapeUriString(ModMetadata.AllMods["modchooser"].Version),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Id),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Version));
// Append system profile data if the player has opted in
if (Game.Settings.Debug.SendSystemInformation)
newsURL += "&" + GetSystemInformation()
.Select(kv => kv.Key + "=" + Uri.EscapeUriString(kv.Value.Second))
.JoinWith("&");
new Download(newsURL, cacheFile, e => { },
(e, c) => NewsDownloadComplete(e, cacheFile, currentNews,
() => newsButton.AttachPanel(newsPanel)));
}
newsButton.OnClick = () => newsButton.AttachPanel(newsPanel);
}
}
Game.OnRemoteDirectConnect += OnRemoteDirectConnect;
}
void OnRemoteDirectConnect(string host, int port)
@@ -252,23 +325,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
() => { Game.CloseServer(); SwitchMenu(MenuType.MapEditor); });
}
string SysInfoQuery()
{
if (!Game.Settings.Debug.SendSystemInformation)
return null;
return "?id={0}&platform={1}&os={2}&runtime={3}&gl={4}&lang={5}&version={6}&mod={7}&modversion={8}".F(
Uri.EscapeUriString(Game.Settings.Debug.UUID),
Uri.EscapeUriString(Platform.CurrentPlatform.ToString()),
Uri.EscapeUriString(Environment.OSVersion.ToString()),
Uri.EscapeUriString(Platform.RuntimeVersion),
Uri.EscapeUriString(Game.Renderer.GLVersion),
Uri.EscapeUriString(System.Globalization.CultureInfo.InstalledUICulture.TwoLetterISOLanguageName),
Uri.EscapeUriString(ModMetadata.AllMods["modchooser"].Version),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Id),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Version));
}
void SetNewsStatus(string message)
{
message = WidgetUtils.WrapText(message, newsStatus.Bounds.Width, Game.Renderer.Fonts[newsStatus.Font]);

View File

@@ -134,7 +134,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
foreach (var p in allPreviews)
{
p.GetMinimap();
var unused = p.Rules;
p.PreloadRules();
}
}).Start();

View File

@@ -315,7 +315,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
Game.RunAfterTick(() => RefreshServerListInner(games));
};
currentQuery = new Download(Game.Settings.Server.MasterServer + "games", _ => { }, onComplete);
var queryURL = Game.Settings.Server.MasterServer + "games?version={0}&mod={1}&modversion={2}".F(
Uri.EscapeUriString(ModMetadata.AllMods["modchooser"].Version),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Id),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Version));
currentQuery = new Download(queryURL, _ => { }, onComplete);
}
int GroupSortOrder(GameServer testEntry)

View File

@@ -233,6 +233,7 @@ namespace OpenRA.Mods.Common.Widgets
{
// Queue a new item
Game.Sound.Play(TabClick);
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Faction.InternalName);
World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, handleCount));
return true;
}

View File

@@ -18,17 +18,17 @@ namespace OpenRA.Mods.RA.Effects
{
class GpsSatellite : IEffect
{
readonly GpsPowerInfo info;
readonly Animation anim;
readonly string palette;
WPos pos;
public GpsSatellite(World world, WPos pos, GpsPowerInfo info)
public GpsSatellite(World world, WPos pos, string image, string sequence, string palette)
{
this.info = info;
this.palette = palette;
this.pos = pos;
anim = new Animation(world, info.SatelliteImage);
anim.PlayRepeating(info.SatelliteSequence);
anim = new Animation(world, image);
anim.PlayRepeating(sequence);
}
public void Tick(World world)
@@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA.Effects
public IEnumerable<IRenderable> Render(WorldRenderer wr)
{
return anim.Render(pos, wr.Palette(info.SatellitePalette));
return anim.Render(pos, wr.Palette(palette));
}
}
}

View File

@@ -19,19 +19,21 @@ namespace OpenRA.Mods.RA.Effects
class SatelliteLaunch : IEffect
{
readonly GpsPowerInfo info;
readonly Actor launcher;
readonly Animation doors;
readonly WPos pos;
int frame = 0;
public SatelliteLaunch(Actor a, GpsPowerInfo info)
public SatelliteLaunch(Actor launcher, GpsPowerInfo info)
{
this.info = info;
this.launcher = launcher;
doors = new Animation(a.World, info.DoorImage);
doors = new Animation(launcher.World, info.DoorImage);
doors.PlayThen(info.DoorSequence,
() => a.World.AddFrameEndTask(w => w.Remove(this)));
() => launcher.World.AddFrameEndTask(w => w.Remove(this)));
pos = a.CenterPosition;
pos = launcher.CenterPosition;
}
public void Tick(World world)
@@ -39,12 +41,16 @@ namespace OpenRA.Mods.RA.Effects
doors.Tick();
if (++frame == 19)
world.AddFrameEndTask(w => w.Add(new GpsSatellite(world, pos, info)));
{
var palette = info.SatellitePaletteIsPlayerPalette ? info.SatellitePalette + launcher.Owner.InternalName : info.SatellitePalette;
world.AddFrameEndTask(w => w.Add(new GpsSatellite(world, pos, info.SatelliteImage, info.SatelliteSequence, palette)));
}
}
public IEnumerable<IRenderable> Render(WorldRenderer wr)
{
return doors.Render(pos, wr.Palette(info.DoorPalette));
var palette = info.DoorPaletteIsPlayerPalette ? info.DoorPalette + launcher.Owner.InternalName : info.DoorPalette;
return doors.Render(pos, wr.Palette(palette));
}
}
}

View File

@@ -29,9 +29,12 @@ namespace OpenRA.Mods.RA.Traits
static readonly FrozenActorAction Refresh = (fufubg, fal, gps, fa) =>
{
// Refreshes the visual state of the frozen actor, so ownership changes can be seen.
fa.RefreshState();
// This only makes sense if the frozen actor has already been revealed (i.e. has renderables)
if (fa.HasRenderables)
{
fa.RefreshState();
fa.NeedRenderables = true;
}
};
static readonly FrozenActorAction Remove = (fufubg, fal, gps, fa) =>
{

View File

@@ -201,7 +201,7 @@ namespace OpenRA.Mods.RA.Traits
{
public string OrderID { get { return "BeginMinefield"; } }
public int OrderPriority { get { return 5; } }
public bool OverrideSelection { get { return true; } }
public bool TargetOverridesSelection(TargetModifiers modifiers) { return true; }
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
{

View File

@@ -119,7 +119,7 @@ namespace OpenRA.Mods.RA.Traits
public string OrderID { get { return "PortableChronoTeleport"; } }
public int OrderPriority { get { return 5; } }
public bool IsQueued { get; protected set; }
public bool OverrideSelection { get { return true; } }
public bool TargetOverridesSelection(TargetModifiers modifiers) { return true; }
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
{

View File

@@ -25,11 +25,21 @@ namespace OpenRA.Mods.RA.Traits
public readonly string DoorImage = "atek";
[SequenceReference("DoorImage")] public readonly string DoorSequence = "active";
[PaletteReference] public readonly string DoorPalette = "effect";
[Desc("Palette to use for rendering the launch animation")]
[PaletteReference("DoorPaletteIsPlayerPalette")] public readonly string DoorPalette = "player";
[Desc("Custom palette is a player palette BaseName")]
public readonly bool DoorPaletteIsPlayerPalette = true;
public readonly string SatelliteImage = "sputnik";
[SequenceReference("SatelliteImage")] public readonly string SatelliteSequence = "idle";
[PaletteReference] public readonly string SatellitePalette = "effect";
[Desc("Palette to use for rendering the satellite projectile")]
[PaletteReference("SatellitePaletteIsPlayerPalette")] public readonly string SatellitePalette = "player";
[Desc("Custom palette is a player palette BaseName")]
public readonly bool SatellitePaletteIsPlayerPalette = true;
public override object Create(ActorInitializer init) { return new GpsPower(init.Self, this); }
}

View File

@@ -226,6 +226,66 @@ Container@MENU_BACKGROUND:
Text: Back
Font: Bold
Key: escape
Container@SYSTEM_INFO_PROMPT:
X: (WINDOW_RIGHT - WIDTH)/2
Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 490
Height: 222
Children:
Label@TITLE:
Width: PARENT_RIGHT
Y: 0-25
Font: BigBold
Contrast: true
Align: Center
Text: System Information
Background@bg:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Background: panel-black
Children:
Label@PROMPT_TEXT_A:
X: 15
Y: 15
Width: PARENT_RIGHT - 30
Height: 16
Align: Center
Text: We would like to collect some details that will help us optimize OpenRA.
Label@PROMPT_TEXT_B:
X: 15
Y: 33
Width: PARENT_RIGHT - 30
Height: 16
Align: Center
Text: With your permission, the following anonymous system data will be sent:
ScrollPanel@SYSINFO_DATA:
X: 15
Y: 63
Width: PARENT_RIGHT - 30
TopBottomSpacing: 4
ItemSpacing: 4
Height: 110
Children:
Label@DATA_TEMPLATE:
X: 8
Height: 13
VAlign: Top
Font: Small
Checkbox@SYSINFO_CHECKBOX:
X: PARENT_RIGHT - 15 - WIDTH
Y: PARENT_BOTTOM - 35
Width: 190
Height: 20
Font: Regular
Text: Send System Information
Button@BACK_BUTTON:
X: PARENT_RIGHT - WIDTH
Y: PARENT_BOTTOM - 1
Width: 140
Height: 35
Text: Continue
Font: Bold
Key: return
Container@NEWS_BG:
Children:
DropDownButton@NEWS_BUTTON:

View File

@@ -23,7 +23,7 @@ World:
Red: 0.75
Green: 0.85
Blue: 1.5
Ambient: 0.35
Ambient: 0.45
MissionData:
Briefing: Use a GDI Commando to infiltrate the Nod base. **** ** destroy the ******** so that the base is incapacitated. Get in, hit it, and get the **** out.
BriefingVideo: gdi6.vqa

Binary file not shown.

View File

@@ -25,7 +25,7 @@ Player:
hpad: 0
eye: 1
tmpl: 1
fix: 0
fix: 1
silo: 1
BuildingFractions:
proc: 20%
@@ -146,7 +146,7 @@ Player:
hpad: 2
eye: 1
tmpl: 1
fix: 0
fix: 1
silo: 1
BuildingFractions:
proc: 17%
@@ -267,7 +267,7 @@ Player:
hpad: 2
eye: 1
tmpl: 1
fix: 0
fix: 1
silo: 1
BuildingFractions:
proc: 17%

View File

@@ -48,6 +48,11 @@
GenericVisibility: Enemy, Neutral
ShowOwnerRow: false
^TechBuilding:
Tooltip:
GenericVisibility: None
ShowOwnerRow: false
^CommonHuskDefaults:
Tooltip:
GenericVisibility: Enemy, Ally, Neutral
@@ -57,3 +62,29 @@
^DINO:
Tooltip:
ShowOwnerRow: false
MISS:
Tooltip:
GenericVisibility: None
ShowOwnerRow: False
ARCO:
Tooltip:
GenericVisibility: None
ShowOwnerRow: False
ARCO.Husk:
Tooltip:
GenericVisibility: None
V19.Husk:
Tooltip:
GenericVisibility: None
HOSP.Husk:
Tooltip:
GenericVisibility: None
BIO.Husk:
Tooltip:
GenericVisibility: None

View File

@@ -337,6 +337,7 @@ ARCO:
Actor: ARCO.Husk
Tooltip:
Name: Oil Pump
ShowOwnerRow: True
ARCO.Husk:
Inherits: ^CivBuildingHusk

View File

@@ -39,7 +39,7 @@
SelfHealing@ELITE:
Step: 2
Delay: 100
HealIfBelow: 1
HealIfBelow: 100
DamageCooldown: 125
UpgradeTypes: selfheal
UpgradeMinEnabledLevel: 1
@@ -234,7 +234,7 @@
SelfHealing@HOSPITAL:
Step: 5
Delay: 100
HealIfBelow: 1
HealIfBelow: 100
DamageCooldown: 125
UpgradeTypes: hospitalheal
UpgradeMinEnabledLevel: 1
@@ -518,7 +518,6 @@
GenericStancePrefix: false
ShowOwnerRow: false
FrozenUnderFog:
StartsRevealed: true
^CivBuildingHusk:
Inherits@1: ^SpriteActor
@@ -532,7 +531,6 @@
GenericStancePrefix: false
ShowOwnerRow: false
FrozenUnderFog:
StartsRevealed: true
ScriptTriggers:
^TechBuilding:
@@ -546,6 +544,8 @@
EngineerRepairable:
RevealsShroud:
Range: 3c0
Tooltip:
ShowOwnerRow: True
^CivField:
Inherits: ^CivBuilding
@@ -567,11 +567,11 @@
Tooltip:
Name: Field (Destroyed)
GenericVisibility: None
ShowOwnerRow: false
RenderSprites:
Palette: terrain
WithSpriteBody:
FrozenUnderFog:
StartsRevealed: true
ScriptTriggers:
^Wall:
@@ -614,6 +614,7 @@
Inherits@1: ^SpriteActor
Tooltip:
Name: Tree
ShowOwnerRow: false
RenderSprites:
Palette: staticterrain
WithSpriteBody:
@@ -635,6 +636,7 @@
Inherits@1: ^SpriteActor
Tooltip:
Name: Blossom Tree
ShowOwnerRow: false
RenderSprites:
Palette: staticterrain
WithSpriteBody:
@@ -651,6 +653,7 @@
Inherits@1: ^SpriteActor
Tooltip:
Name: Rock
ShowOwnerRow: false
RenderSprites:
Palette: staticterrain
WithSpriteBody:
@@ -720,6 +723,7 @@
AlwaysVisible:
Tooltip:
Name: Bridge
ShowOwnerRow: false
Targetable:
RequiresForceFire: yes
TargetTypes: Ground, Water
@@ -736,6 +740,7 @@
Tooltip:
Name: Crate
GenericName: Crate
ShowOwnerRow: false
Crate:
TerrainTypes: Clear, Rough, Road, Tiberium, BlueTiberium, Beach
RenderSprites:

View File

@@ -148,8 +148,6 @@ E6:
CaptureTypes: building, husk
-AutoTarget:
-GainsExperience:
Selectable:
Priority: 5
RMBO:
Inherits: ^Soldier

View File

@@ -190,6 +190,61 @@ Container@MAINMENU:
Height: 30
Text: Back
Font: Bold
Background@SYSTEM_INFO_PROMPT:
X: (WINDOW_RIGHT - WIDTH)/2
Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 520
Height: 260
Children:
Label@PROMPT_TITLE:
Width: PARENT_RIGHT
Y: 20
Height: 25
Font: Bold
Align: Center
Text: System Information
Label@PROMPT_TEXT_A:
X: 15
Y: 50
Width: PARENT_RIGHT - 30
Height: 16
Align: Center
Text: We would like to collect some details that will help us optimize OpenRA.
Label@PROMPT_TEXT_B:
X: 15
Y: 68
Width: PARENT_RIGHT - 30
Height: 16
Align: Center
Text: With your permission, the following anonymous system data will be sent:
ScrollPanel@SYSINFO_DATA:
X: 20
Y: 98
Width: PARENT_RIGHT - 40
TopBottomSpacing: 4
ItemSpacing: 4
Height: 110
Children:
Label@DATA_TEMPLATE:
X: 8
Height: 13
VAlign: Top
Font: Small
Checkbox@SYSINFO_CHECKBOX:
X: 40
Y: PARENT_BOTTOM - 42
Width: 200
Height: 20
Font: Regular
Text: Send System Information
Button@BACK_BUTTON:
X: PARENT_RIGHT - WIDTH - 20
Y: PARENT_BOTTOM - 45
Width: 120
Height: 25
Text: Continue
Font: Bold
Key: return
Background@NEWS_BG:
X: (WINDOW_RIGHT - WIDTH)/2
Y: 35

View File

@@ -39,7 +39,7 @@
SelfHealing@ELITE:
Step: 2
Delay: 125
HealIfBelow: 1
HealIfBelow: 100
DamageCooldown: 125
UpgradeTypes: selfheal
UpgradeMinEnabledLevel: 1

View File

@@ -47,8 +47,6 @@ engineer:
-AutoTarget:
Voiced:
VoiceSet: EngineerVoice
Selectable:
Priority: 5
trooper:
Inherits: ^Infantry

View File

@@ -61,6 +61,7 @@ Player:
AllyRepair:
PlayerResources:
SelectableCash: 2500, 5000, 7000, 10000, 20000
InsufficientFundsNotification: InsufficientFunds
ActorGroupProxy:
DeveloperMode:
BaseAttackNotifier:
@@ -86,4 +87,3 @@ Player:
GlobalUpgradeManager:
ResourceStorageWarning:
AdviceInterval: 26
InsufficientFundsWarning:

View File

@@ -652,9 +652,9 @@ wall:
SellSounds: CHUNG.WAV
Guardable:
ThrowsShrapnel:
Weapons: Debris, Debris2, Debris3, Debris4
Pieces: 3, 7
Range: 2c0, 5c0
Weapons: Debris, Debris3
Pieces: 2, 2
Range: 2c0, 4c0
medium_gun_turret:
Inherits: ^Defense

View File

@@ -203,6 +203,61 @@ Container@MAINMENU:
Height: 30
Text: Back
Font: Bold
Background@SYSTEM_INFO_PROMPT:
X: (WINDOW_RIGHT - WIDTH)/2
Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 520
Height: 260
Children:
Label@PROMPT_TITLE:
Width: PARENT_RIGHT
Y: 20
Height: 25
Font: Bold
Align: Center
Text: System Information
Label@PROMPT_TEXT_A:
X: 15
Y: 50
Width: PARENT_RIGHT - 30
Height: 16
Align: Center
Text: We would like to collect some details that will help us optimize OpenRA.
Label@PROMPT_TEXT_B:
X: 15
Y: 68
Width: PARENT_RIGHT - 30
Height: 16
Align: Center
Text: With your permission, the following anonymous system data will be sent:
ScrollPanel@SYSINFO_DATA:
X: 20
Y: 98
Width: PARENT_RIGHT - 40
TopBottomSpacing: 4
ItemSpacing: 4
Height: 110
Children:
Label@DATA_TEMPLATE:
X: 8
Height: 13
VAlign: Top
Font: Small
Checkbox@SYSINFO_CHECKBOX:
X: 40
Y: PARENT_BOTTOM - 42
Width: 200
Height: 20
Font: Regular
Text: Send System Information
Button@BACK_BUTTON:
X: PARENT_RIGHT - WIDTH - 20
Y: PARENT_BOTTOM - 45
Width: 120
Height: 25
Text: Continue
Font: Bold
Key: return
Container@PERFORMANCE_INFO:
Logic: PerfDebugLogic
Children:

View File

@@ -190,6 +190,8 @@ DOG:
TRUK:
-Demolishable:
Targetable:
TargetTypes: Ground, Truk
Armor:
Type: Truk

View File

@@ -1,5 +1,7 @@
Colt45:
ValidTargets: Ground, Infantry, Truk
Warhead@1Dam: SpreadDamage
ValidTargets: Barrel, Infantry, Truk
Versus:
Truk: 50

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -26,7 +26,7 @@ Players:
Name: Creeps
NonCombatant: True
Faction: allies
Enemies: Creeps
Enemies: Multi0, Multi1, Multi2, Multi3, Multi4, Multi5, Multi6, Multi7
PlayerReference@Multi0:
Name: Multi0
Playable: True

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 921 B

View File

@@ -1,211 +0,0 @@
MapFormat: 11
RequiresMod: ra
Title: Burlesca
Author: s1w
Tileset: TEMPERAT
MapSize: 64,64
Bounds: 4,4,56,56
Visibility: Lobby
Categories: Conquest
Players:
PlayerReference@Neutral:
Name: Neutral
OwnsWorld: True
NonCombatant: True
Faction: allies
PlayerReference@Multi0:
Name: Multi0
Playable: True
AllowBots: False
Faction: Random
Enemies: Creeps
PlayerReference@Multi1:
Name: Multi1
Playable: True
AllowBots: False
Faction: Random
Enemies: Creeps
PlayerReference@Creeps:
Name: Creeps
NonCombatant: True
Faction: allies
Enemies: Multi0, Multi1
Actors:
Actor2: mpspawn
Location: 13,25
Owner: Neutral
Actor17: tc05
Location: 32,52
Owner: Neutral
Actor23: tc03
Location: 33,51
Owner: Neutral
Actor24: t08
Location: 32,55
Owner: Neutral
Actor3: brl3
Location: 28,33
Owner: Neutral
Actor4: brl3
Location: 23,39
Owner: Neutral
Actor6: brl3
Location: 38,27
Owner: Neutral
Actor0: brl3
Location: 33,33
Owner: Neutral
Actor5: mpspawn
Location: 50,38
Owner: Neutral
Actor1: t02
Location: 23,41
Owner: Neutral
Actor7: v15
Location: 6,30
Owner: Neutral
Actor8: v16
Location: 6,31
Owner: Neutral
Actor14: tc04
Location: 30,8
Owner: Neutral
Actor13: t12
Location: 33,7
Owner: Neutral
Actor12: tc03
Location: 44,4
Owner: Neutral
Actor11: tc02
Location: 40,4
Owner: Neutral
Actor9: v16
Location: 57,38
Owner: Neutral
Actor10: rice
Location: 58,38
Owner: Neutral
Actor15: tc05
Location: 57,4
Owner: Neutral
Actor16: t01
Location: 59,7
Owner: Neutral
Actor18: t16
Location: 55,3
Owner: Neutral
Actor19: t03
Location: 56,20
Owner: Neutral
Actor20: tc04
Location: 46,25
Owner: Neutral
Actor21: t07
Location: 52,24
Owner: Neutral
Actor22: tc04
Location: 9,38
Owner: Neutral
Actor25: tc01
Location: 13,37
Owner: Neutral
Actor26: tc03
Location: 16,15
Owner: Neutral
Actor27: tc03
Location: 58,39
Owner: Neutral
Actor28: t06
Location: 4,22
Owner: Neutral
Actor29: t10
Location: 39,15
Owner: Neutral
Actor30: t15
Location: 15,48
Owner: Neutral
Actor31: tc04
Location: 4,57
Owner: Neutral
Actor32: t01
Location: 7,58
Owner: Neutral
Actor33: t06
Location: 4,55
Owner: Neutral
Actor34: t08
Location: 7,53
Owner: Neutral
Actor35: t08
Location: 19,41
Owner: Neutral
Actor36: t08
Location: 56,4
Owner: Neutral
Actor37: t08
Location: 59,51
Owner: Neutral
Actor39: tc01
Location: 21,58
Owner: Neutral
Actor50: mine
Location: 30,53
Owner: Neutral
Actor40: t12
Location: 46,49
Owner: Neutral
Actor41: t17
Location: 4,12
Owner: Neutral
Actor42: t12
Location: 19,10
Owner: Neutral
Actor43: t08
Location: 57,35
Owner: Neutral
Actor44: tc01
Location: 56,28
Owner: Neutral
Actor45: t08
Location: 51,8
Owner: Neutral
Actor46: tc04
Location: 4,26
Owner: Neutral
Actor47: tc01
Location: 42,43
Owner: Neutral
Actor48: t08
Location: 27,44
Owner: Neutral
Actor49: tc03
Location: 43,42
Owner: Neutral
Actor38: mine
Location: 28,57
Owner: Neutral
Actor51: mine
Location: 37,6
Owner: Neutral
Actor52: mine
Location: 34,10
Owner: Neutral
Actor53: t07
Location: 25,57
Owner: Neutral
Actor55: mine
Location: 57,43
Owner: Neutral
Actor54: mine
Location: 6,19
Owner: Neutral

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -22,66 +22,54 @@ Players:
OwnsWorld: True
NonCombatant: True
Faction: allies
PlayerReference@Creeps:
Name: Creeps
NonCombatant: True
Faction: allies
PlayerReference@Multi0:
Name: Multi0
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi1:
Name: Multi1
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi2:
Name: Multi2
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi3:
Name: Multi3
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi4:
Name: Multi4
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi5:
Name: Multi5
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi6:
Name: Multi6
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi7:
Name: Multi7
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
Actors:
Actor0: apc

View File

@@ -22,66 +22,54 @@ Players:
OwnsWorld: True
NonCombatant: True
Faction: allies
PlayerReference@Creeps:
Name: Creeps
NonCombatant: True
Faction: allies
PlayerReference@Multi0:
Name: Multi0
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi1:
Name: Multi1
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi2:
Name: Multi2
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi3:
Name: Multi3
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi4:
Name: Multi4
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi5:
Name: Multi5
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi6:
Name: Multi6
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
PlayerReference@Multi7:
Name: Multi7
Playable: True
AllowBots: False
LockFaction: True
Faction: soviet
Enemies: Creeps
Actors:
Actor0: apc

Binary file not shown.

View File

@@ -21,7 +21,7 @@ World:
Red: 0.75
Green: 0.85
Blue: 1.5
Ambient: 0.35
Ambient: 0.45
MusicPlaylist:
BackgroundMusic: rain
FlashPaletteEffect@LIGHTNINGSTRIKE:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More