Compare commits

...

28 Commits

Author SHA1 Message Date
Paul Chote
253e02ae08 Remove dependency on VCRUNTIME140.dll.
(cherry picked from commit bb6400f6f8585523c31dfeb7ab95073263aadd3c)
2023-02-13 21:27:35 +02:00
penev92
f707b9c975 Fixed Makefile check of MacOS architecture 2023-02-05 00:19:18 +01:00
abcdefg30
8629e578e3 Throw an ArgumentException when trying to translate null keys
(cherry picked from commit e4bb13ea07)
2023-02-03 08:36:24 +02:00
abcdefg30
c65cfd3528 Fix an NRE in ConnectionLogic
(cherry picked from commit 84add8a03d)
2023-02-03 08:34:57 +02:00
Azarus
7ad6cfda40 Add an option to check if an actor can be captured via Lua 2023-01-30 13:47:02 +02:00
Dean Simmons
393fd585b1 Only return file paths when returning zip contents
(cherry picked from commit e1b78c4821)
2023-01-26 19:26:59 +02:00
penev92
ea221f9bfb Fixed RA parabomb/paradrop support power tooltips
The AFLD's AirstrikePower@parabombs' description wasn't updated to the latest balance patch (3 Badgers -> 1 Badger)
2023-01-26 09:32:54 +01:00
N.N
b4ca81d1bd Fix deviator GrantExternalCondition Warhead
Warhead now applies only to enemy and neutral units.
2023-01-18 23:43:12 +01:00
RoosterDragon
49590bb5f7 Fix Locomotor cache coherency for disabled or paused mobile actors.
The cache in Locomotor that is populated via the UpdateCellBlocking method disagreed with the non-cached logic of IsBlockedBy when dealing with Mobile actors. The cache determined an actor to be moving if it was both movable and had horizontal movement types. IsBlockedBy determined an actor to be moving if it had horizontal movement types, but did not check if it was movable. This difference in checks could allow a mobile trait that was disabled or paused and which had horizontal movement to be treated differently be the two methods. UpdateCellBlocking would consider it not moving due to the disabled/paused trait. IsBlockedBy would consider it moving as it didn't care about the disabled/paused state of the trait.

Now, we unify the two methods to consider a mobile trait that is disabled/paused as not moving. This prevents HierarchicalPathFinder from crashing on the inconsistent state, i.e. when asked to path search through a cell of a mobile unit which has disabled or paused movement, but which has horizontal movement types from prior movement.
2023-01-17 18:58:34 +01:00
David Wilson
2d059c0d95 Fix to ensure Windows uninstaller removes reg entries from the 64 bit registry 2023-01-14 13:50:04 +01:00
penev92
d5dd6a9086 Added ITilesetSpecificPaletteInfo for linting 2023-01-10 16:37:56 +00:00
Gustas
a7ca0f0699 Fixed UnhardcodeBaseBuilderBotModule update rule
Update rules should should not read `modData.DefaultRules`

(cherry picked from commit 80b92fb667)
2023-01-10 18:13:01 +02:00
Gustas
4b02d9b700 Fixed UnhardcodeSquadManager update rule
Update rules should should not read `modData.DefaultRules`

(cherry picked from commit 29d21545a6)
2023-01-10 18:12:58 +02:00
Gustas
ebf55c8d86 Exclude Plugs from TS protection types
(cherry picked from commit 326f8115a0)
2023-01-10 18:12:51 +02:00
Paul Chote
f928922f3a Add BeforeUpdate* methods for update rules.
These make it possible to write more advanced update
rules that query state across multiple actors, or
based on resolved state.

(cherry picked from commit 129db98a2f)
2023-01-10 18:05:11 +02:00
penev92
bc3743d9ff Added an update rule for adding ControlGroups 2023-01-10 00:14:45 +01:00
penev92
8aa6600655 Added an update rule for DomainIndex removal
Also for adding the new HPF-related PathFinderOverlay and HierarchicalPathFinderOverlay that were added at the same time.
2023-01-10 00:14:04 +01:00
Ivaylo Draganov
215b3d8ab3 Clarify the wording and explain the meaning of some labels in settings
(cherry picked from commit 04648a66e6)
2023-01-09 21:59:41 +02:00
Matthias Mailänder
a397670dce Fix URL button blocking the party button. 2023-01-08 23:07:44 +01:00
Matthias Mailänder
43d7f9c6df Bump DiscordRichPresence library. 2023-01-08 23:07:42 +01:00
Gustas
6904ea8c6b Fixed a spelling error in Discovery ant mission 2023-01-07 17:02:19 +01:00
Gustas
d702d58d1a Remove bogus bridge tiles from temperate tileset 2023-01-07 17:02:18 +01:00
abcdefg30
e0b0c5624f Remove custom network frame counting from ReplayConnection 2023-01-04 09:35:06 +00:00
abcdefg30
33773f895c Specify targetable offsets for the repair pad in Dune 2000 2023-01-03 13:33:20 +01:00
Matthias Mailänder
9f759f3cc2 Enforce use of 'var' instead of explicit type.
(cherry picked from commit 19ecddcd86)
2022-12-29 10:05:20 +02:00
Paul Chote
9fb4302b2f Downgrade OpenAL-soft to 1.10.1.
1.12.2 introduces noticeable behaviour changes
to source positioning and cash ticks. This also
fixes missing sound backends on Linux.
2022-12-28 00:19:39 +01:00
abcdefg30
4685c1a6b1 Change into the correct directory before trying to push
Each workflow step starts back in the default directory,
so we need to checkout the repository folder again
2022-12-24 16:04:51 +01:00
abcdefg30
70bc5b097d Let the documentation workflow fetch the required git branch 2022-12-24 16:04:45 +01:00
56 changed files with 441 additions and 110 deletions

View File

@@ -126,6 +126,9 @@ dotnet_style_predefined_type_for_locals_parameters_members = true
# Show an IDE warning when default access modifiers are explicitly specified.
dotnet_style_require_accessibility_modifiers = omit_if_default:warning
# use 'var' instead of explicit type
dotnet_diagnostic.IDE0007.severity = warning
# Don't prefer braces (for one liners).
dotnet_diagnostic.IDE0011.severity = silent

View File

@@ -79,19 +79,29 @@ jobs:
run: |
make all
- name: Clone docs.openra.net
- name: Clone docs.openra.net (Playtest)
if: startsWith(github.event.inputs.tag, 'playtest-')
uses: actions/checkout@v2
with:
repository: openra/docs
token: ${{ secrets.DOCS_TOKEN }}
path: docs
ref: playtest
- name: Clone docs.openra.net (Release)
if: startsWith(github.event.inputs.tag, 'release-')
uses: actions/checkout@v2
with:
repository: openra/docs
token: ${{ secrets.DOCS_TOKEN }}
path: docs
ref: release
- name: Update docs.openra.net (Playtest)
if: startsWith(github.event.inputs.tag, 'playtest-')
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
git checkout playtest
./utility.sh all --docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/weapons.md"
./utility.sh all --sprite-sequence-docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/sprite-sequences.md"
@@ -102,7 +112,6 @@ jobs:
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
git checkout release
./utility.sh all --docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/weapons.md"
./utility.sh all --sprite-sequence-docs "${GIT_TAG}" | python3 ./packaging/format-docs.py > "docs/api/sprite-sequences.md"
@@ -121,9 +130,11 @@ jobs:
- name: Push docs.openra.net (Release)
if: startsWith(github.event.inputs.tag, 'release-')
run: |
cd docs
git push origin release
- name: Push docs.openra.net (Playtest)
if: startsWith(github.event.inputs.tag, 'playtest-')
run: |
cd docs
git push origin playtest

View File

@@ -59,6 +59,7 @@ RM_RF = $(RM) -rf
RUNTIME ?= net6
CONFIGURATION ?= Release
DOTNET_RID = $(shell ${DOTNET} --info | grep RID: | cut -w -f3)
ARCH_X64 = $(shell echo ${DOTNET_RID} | grep x64)
# Only for use in target version:
VERSION := $(shell git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || (c=$$(git rev-parse --short HEAD 2>/dev/null) && echo git-$$c))
@@ -68,7 +69,7 @@ ifndef TARGETPLATFORM
UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m)
ifeq ($(UNAME_S),Darwin)
ifeq ($(RUNTIME)-$(DOTNET_RID),net6-osx-arm64)
ifeq ($(ARCH_X64),)
TARGETPLATFORM = osx-arm64
else
TARGETPLATFORM = osx-x64

View File

@@ -55,7 +55,8 @@ namespace OpenRA.FileSystem
get
{
foreach (ZipEntry entry in pkg)
yield return entry.Name;
if (entry.IsFile)
yield return entry.Name;
}
}

View File

@@ -108,7 +108,7 @@ namespace OpenRA.Graphics
public ImmutablePalette(IPalette p)
{
for (int i = 0; i < Palette.Size; i++)
for (var i = 0; i < Palette.Size; i++)
colors[i] = p[i];
}

View File

@@ -344,7 +344,7 @@ namespace OpenRA
if (yaml.TryGetValue("Visibility", out temp))
newData.Visibility = FieldLoader.GetValue<MapVisibility>("Visibility", temp.Value);
string requiresMod = string.Empty;
var requiresMod = string.Empty;
if (yaml.TryGetValue("RequiresMod", out temp))
requiresMod = temp.Value;

View File

@@ -27,7 +27,6 @@ namespace OpenRA.Network
readonly Queue<Chunk> chunks = new Queue<Chunk>();
readonly Queue<(int Frame, int SyncHash, ulong DefeatState)> sync = new Queue<(int, int, ulong)>();
readonly int orderLatency;
int ordersFrame;
public readonly int TickCount;
public readonly int FinalGameTick;
@@ -91,7 +90,6 @@ namespace OpenRA.Network
var gameSpeeds = Game.ModData.Manifest.Get<GameSpeeds>();
var gameSpeedName = LobbyInfo.GlobalSettings.OptionOrDefault("gamespeed", gameSpeeds.DefaultSpeed);
orderLatency = gameSpeeds.Speeds[gameSpeedName].OrderLatency;
ordersFrame = orderLatency;
}
void IConnection.StartGame() { }
@@ -103,9 +101,6 @@ namespace OpenRA.Network
void IConnection.SendSync(int frame, int syncHash, ulong defeatState)
{
sync.Enqueue((frame, syncHash, defeatState));
// Store the current frame so Receive() can return the next chunk of orders.
ordersFrame = frame + orderLatency;
}
void IConnection.Receive(OrderManager orderManager)
@@ -113,7 +108,7 @@ namespace OpenRA.Network
while (sync.Count != 0)
orderManager.ReceiveSync(sync.Dequeue());
while (chunks.Count != 0 && chunks.Peek().Frame <= ordersFrame)
while (chunks.Count != 0 && chunks.Peek().Frame <= orderManager.NetFrameNumber + orderLatency)
{
foreach (var o in chunks.Dequeue().Packets)
{

View File

@@ -122,7 +122,7 @@ namespace OpenRA.Network
Log.Write("sync", $"\t {a.ActorID} {a.Type} {a.Owner} {a.Trait} ({a.Hash})");
var nvp = a.NamesValues;
for (int i = 0; i < nvp.Names.Length; i++)
for (var i = 0; i < nvp.Names.Length; i++)
if (nvp.Values[i] != null)
Log.Write("sync", $"\t\t {nvp.Names[i]}: {nvp.Values[i]}");
}
@@ -133,7 +133,7 @@ namespace OpenRA.Network
Log.Write("sync", "\t {0} ({1})", e.Name, e.Hash);
var nvp = e.NamesValues;
for (int i = 0; i < nvp.Names.Length; i++)
for (var i = 0; i < nvp.Names.Length; i++)
if (nvp.Values[i] != null)
Log.Write("sync", $"\t\t {nvp.Names[i]}: {nvp.Values[i]}");
}

View File

@@ -8,7 +8,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Linguini.Bundle" Version="0.3.1" />
<PackageReference Include="OpenRA-Eluant" Version="1.0.19" />
<PackageReference Include="OpenRA-Eluant" Version="1.0.20" />
<PackageReference Include="Mono.NAT" Version="3.0.3" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Scripting
public static bool TryGetClrValue<T>(this LuaValue value, out T clrObject)
{
var ret = value.TryGetClrValue(typeof(T), out object temp);
var ret = value.TryGetClrValue(typeof(T), out var temp);
clrObject = ret ? (T)temp : default;
return ret;
}

View File

@@ -244,6 +244,12 @@ namespace OpenRA.Traits
IEnumerable<Rectangle> ModifyScreenBounds(Actor self, WorldRenderer wr, IEnumerable<Rectangle> r);
}
[RequireExplicitImplementation]
public interface ITilesetSpecificPaletteInfo : ITraitInfoInterface
{
string Tileset { get; }
}
[RequireExplicitImplementation]
public interface IProvidesCursorPaletteInfo : ITraitInfoInterface
{

View File

@@ -88,6 +88,9 @@ namespace OpenRA
public bool TryGetString(string key, out string value, IDictionary<string, object> arguments = null)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("A translation key must not be null or empty.", nameof(key));
if (!HasMessage(key))
{
value = null;

View File

@@ -77,12 +77,12 @@ namespace OpenRA.Mods.Cnc.FileFormats
byte* ip;
uint t;
byte* mPos;
byte* ipEnd = @in + inLen;
var ipEnd = @in + inLen;
outLen = 0;
op = @out;
ip = @in;
bool gtFirstLiteralRun = false;
bool gtMatchDone = false;
var gtFirstLiteralRun = false;
var gtMatchDone = false;
if (*ip > 17)
{
t = (uint)(*ip++ - 17);

View File

@@ -338,8 +338,8 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
var mapSection = file.GetSection("IsoMapPack5");
var data = Convert.FromBase64String(string.Concat(mapSection.Select(kvp => kvp.Value)));
int cells = (fullSize.X * 2 - 1) * fullSize.Y;
int lzoPackSize = cells * 11 + 4; // last 4 bytes contains a lzo pack header saying no more data is left
var cells = (fullSize.X * 2 - 1) * fullSize.Y;
var lzoPackSize = cells * 11 + 4; // last 4 bytes contains a lzo pack header saying no more data is left
var isoMapPack = new byte[lzoPackSize];
UnpackLZO(data, isoMapPack);
@@ -354,8 +354,8 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
var z = mf.ReadUInt8();
/*var zero2 = */mf.ReadUInt8();
int dx = rx - ry + fullSize.X - 1;
int dy = rx + ry - fullSize.X - 1;
var dx = rx - ry + fullSize.X - 1;
var dy = rx + ry - fullSize.X - 1;
var mapCell = new MPos(dx / 2, dy);
var cell = mapCell.ToCPos(map);

View File

@@ -115,6 +115,7 @@ namespace OpenRA.Mods.Common
DateTime? timestamp = null;
Party party = null;
Secrets secrets = null;
Button[] buttons = null;
switch (state)
{
@@ -161,6 +162,18 @@ namespace OpenRA.Mods.Common
throw new ArgumentOutOfRangeException(nameof(state), state, null);
}
if (party == null)
{
buttons = new[]
{
new Button
{
Label = "Visit Website",
Url = Game.ModData.Manifest.Metadata.Website
}
};
}
var richPresence = new RichPresence
{
Details = details,
@@ -173,14 +186,7 @@ namespace OpenRA.Mods.Common
Timestamps = timestamp.HasValue ? new Timestamps(timestamp.Value) : null,
Party = party,
Secrets = secrets,
Buttons = new[]
{
new Button
{
Label = "Visit Website",
Url = Game.ModData.Manifest.Metadata.Website
}
}
Buttons = buttons
};
client.SetPresence(richPresence);

View File

@@ -12,7 +12,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Server;
using OpenRA.Traits;
@@ -146,11 +145,11 @@ namespace OpenRA.Mods.Common.Lint
}
else
{
// PaletteFromFile might only be active for a single tileset
// So ignore any duplicate palette names as long as they are on different tilesets
if (traitInfo is PaletteFromFileInfo paletteFromFileInfo && paletteFromFileInfo.Tileset != null)
// Tileset-specific palettes can share a name, so check combinations.
// NOTE: This does not check PaletteFromGimpOrJascFile!
if (traitInfo is ITilesetSpecificPaletteInfo tilesetSpecificPaletteInfo && tilesetSpecificPaletteInfo.Tileset != null)
{
var tilesetPalette = (paletteFromFileInfo.Tileset, value);
var tilesetPalette = (tilesetSpecificPaletteInfo.Tileset, value);
if (tilesetPalettes.Contains(tilesetPalette))
emitError($"Duplicate palette definition for palette name {value}");
else

View File

@@ -5,7 +5,7 @@
</ProjectReference>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="OpenRA-FuzzyLogicLibrary" Version="1.0.1" />
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
<PackageReference Include="DiscordRichPresence" Version="1.1.3.18" />
<PackageReference Include="MP3Sharp" Version="1.0.5" />
<PackageReference Include="NVorbis" Version="0.10.4" />
<PackageReference Include="TagLibSharp" Version="2.2.0" />

View File

@@ -760,10 +760,10 @@ namespace OpenRA.Mods.Common.Projectiles
WVec HomingTick(World world, in WVec tarDistVec, int relTarHorDist)
{
int predClfHgt = 0;
int predClfDist = 0;
int lastHtChg = 0;
int lastHt = 0;
var predClfHgt = 0;
var predClfDist = 0;
var lastHtChg = 0;
var lastHt = 0;
if (info.TerrainHeightAware)
InclineLookahead(world, relTarHorDist, out predClfHgt, out predClfDist, out lastHtChg, out lastHt);

View File

@@ -175,8 +175,8 @@ namespace OpenRA.Mods.Common.Scripting
return false;
}
AsyncLoader l = new AsyncLoader(Media.LoadVideo);
IAsyncResult ar = l.BeginInvoke(s, null, null);
var l = new AsyncLoader(Media.LoadVideo);
var ar = l.BeginInvoke(s, null, null);
Action onLoadComplete = () =>
{
Media.StopFMVInRadar();

View File

@@ -9,7 +9,6 @@
*/
#endregion
using Eluant;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Traits;
using OpenRA.Scripting;
@@ -31,12 +30,18 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Captures the target actor.")]
public void Capture(Actor target)
{
var targetManager = target.TraitOrDefault<CaptureManager>();
if (targetManager == null || !targetManager.CanBeTargetedBy(target, Self, captureManager))
throw new LuaException($"Actor '{Self}' cannot capture actor '{target}'!");
if (!CanCapture(target))
return;
// NB: Scripted actions get no visible targetlines.
Self.QueueActivity(new CaptureActor(Self, Target.FromActor(target), null));
}
[Desc("Checks if the target actor can be catured.")]
public bool CanCapture(Actor target)
{
var targetManager = target.TraitOrDefault<CaptureManager>();
return targetManager != null && targetManager.CanBeTargetedBy(target, Self, captureManager);
}
}
}

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common
/// /// </summary>
public static Target RecalculateInvalidatingHiddenTargets(this Target t, Player viewer)
{
var updated = t.Recalculate(viewer, out bool targetIsHiddenActor);
var updated = t.Recalculate(viewer, out var targetIsHiddenActor);
return targetIsHiddenActor ? Target.Invalid : updated;
}

View File

@@ -342,7 +342,7 @@ namespace OpenRA.Mods.Common.Traits
{
var chosenTarget = Target.Invalid;
var chosenTargetPriority = int.MinValue;
int chosenTargetRange = 0;
var chosenTargetRange = 0;
var activePriorities = activeTargetPriorities.ToList();
if (activePriorities.Count == 0)

View File

@@ -136,7 +136,7 @@ namespace OpenRA.Mods.Common.Traits
var type = BuildingType.Building;
CPos? location = null;
var actorVariant = 0;
string orderString = "PlaceBuilding";
var orderString = "PlaceBuilding";
// Check if Building is a plug for other Building
var actorInfo = world.Map.Rules.Actors[currentBuilding.Item];

View File

@@ -376,7 +376,7 @@ namespace OpenRA.Mods.Common.Traits
{
var availCells = new List<CPos>();
var notStupidCells = new List<CPos>();
foreach (CVec direction in CVec.Directions)
foreach (var direction in CVec.Directions)
{
var p = ToCell + direction;
if (CanEnterCell(p) && CanStayInCell(p) && (preferToAvoid == null || !preferToAvoid(p)))

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Load VGA palette (.pal) registers.")]
class PaletteFromFileInfo : TraitInfo, IProvidesCursorPaletteInfo
class PaletteFromFileInfo : TraitInfo, ITilesetSpecificPaletteInfo, IProvidesCursorPaletteInfo
{
[PaletteDefinition]
[FieldLoader.Require]
@@ -46,6 +46,8 @@ namespace OpenRA.Mods.Common.Traits
public override object Create(ActorInitializer init) { return new PaletteFromFile(init.World, this); }
string ITilesetSpecificPaletteInfo.Tileset => Tileset;
string IProvidesCursorPaletteInfo.Palette => CursorPalette ? Name : null;
ImmutablePalette IProvidesCursorPaletteInfo.ReadPalette(IReadOnlyFileSystem fileSystem)

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Creates a greyscale palette without any base palette file.")]
class PaletteFromGrayscaleInfo : TraitInfo
class PaletteFromGrayscaleInfo : TraitInfo, ITilesetSpecificPaletteInfo
{
[PaletteDefinition]
[FieldLoader.Require]
@@ -34,6 +34,8 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Index set to be fully transparent/invisible.")]
public readonly int TransparentIndex = 0;
string ITilesetSpecificPaletteInfo.Tileset => Tileset;
public override object Create(ActorInitializer init) { return new PaletteFromGrayscale(init.World, this); }
}

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Load a PNG and use its embedded palette.")]
class PaletteFromPngInfo : TraitInfo, IProvidesCursorPaletteInfo
class PaletteFromPngInfo : TraitInfo, ITilesetSpecificPaletteInfo, IProvidesCursorPaletteInfo
{
[PaletteDefinition]
[FieldLoader.Require]
@@ -44,6 +44,8 @@ namespace OpenRA.Mods.Common.Traits
public override object Create(ActorInitializer init) { return new PaletteFromPng(init.World, this); }
string ITilesetSpecificPaletteInfo.Tileset => Tileset;
string IProvidesCursorPaletteInfo.Palette => CursorPalette ? Name : null;
ImmutablePalette IProvidesCursorPaletteInfo.ReadPalette(IReadOnlyFileSystem fileSystem)

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Creates a single color palette without any base palette file.")]
class PaletteFromRGBAInfo : TraitInfo
class PaletteFromRGBAInfo : TraitInfo, ITilesetSpecificPaletteInfo
{
[PaletteDefinition]
[FieldLoader.Require]
@@ -46,6 +46,8 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Index set to be fully transparent/invisible.")]
public readonly int TransparentIndex = 0;
string ITilesetSpecificPaletteInfo.Tileset => Tileset;
public override object Create(ActorInitializer init) { return new PaletteFromRGBA(init.World, this); }
}

View File

@@ -325,17 +325,17 @@ namespace OpenRA.Mods.Common.Traits
if (otherActor == ignoreActor)
return false;
// If the check allows: We are not blocked by units that we can force to move out of the way.
if (check <= BlockedByActor.Immovable && cellFlag.HasCellFlag(CellFlag.HasMovableActor) &&
var otherMobile = otherActor.OccupiesSpace as Mobile;
var otherIsMovable = otherMobile != null && !otherMobile.IsTraitDisabled && !otherMobile.IsTraitPaused && !otherMobile.IsImmovable;
var otherIsMoving = otherIsMovable && otherMobile.CurrentMovementTypes.HasMovementType(MovementType.Horizontal);
// If the check allows: We are not blocked by allied units that we can force to move out of the way.
if (check <= BlockedByActor.Immovable && cellFlag.HasCellFlag(CellFlag.HasMovableActor) && otherIsMovable &&
actor.Owner.RelationshipWith(otherActor.Owner) == PlayerRelationship.Ally)
{
if (otherActor.OccupiesSpace is Mobile mobile && !mobile.IsTraitDisabled && !mobile.IsTraitPaused && !mobile.IsImmovable)
return false;
}
return false;
// If the check allows: we are not blocked by moving units.
if (check <= BlockedByActor.Stationary && cellFlag.HasCellFlag(CellFlag.HasMovingActor) &&
otherActor.OccupiesSpace is Mobile otherMobile && otherMobile.CurrentMovementTypes.HasMovementType(MovementType.Horizontal))
if (check <= BlockedByActor.Stationary && cellFlag.HasCellFlag(CellFlag.HasMovingActor) && otherIsMoving)
return false;
if (cellFlag.HasCellFlag(CellFlag.HasTemporaryBlocker))

View File

@@ -0,0 +1,32 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 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 System.Collections.Generic;
using System.Linq;
namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class AddControlGroups : UpdateRule
{
public override string Name => "Add new ControlGroups trait.";
public override string Description => "A new trait ControlGroups was added, splitting logic away from Selection.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
{
if (actorNode.ChildrenMatching("Selection").Any(x => !x.IsRemoval())
&& !actorNode.ChildrenMatching("ControlGroups").Any())
actorNode.AddNode(new MiniYamlNode("ControlGroups", ""));
yield break;
}
}
}

View File

@@ -0,0 +1,33 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 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 System.Collections.Generic;
namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class RemoveDomainIndex : UpdateRule
{
public override string Name => "Remove DomainIndex from World and add path finder overlays.";
public override string Description => "The DomainIndex trait was removed from World. Two overlay traits were added at the same time.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
{
if (actorNode.RemoveNodes("DomainIndex") > 0)
{
actorNode.AddNode(new MiniYamlNode("PathFinderOverlay", ""));
actorNode.AddNode(new MiniYamlNode("HierarchicalPathFinderOverlay", ""));
}
yield break;
}
}
}

View File

@@ -11,27 +11,88 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Traits;
namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class UnhardcodeBaseBuilderBotModule : UpdateRule
{
MiniYamlNode defences;
// Excludes AttackBomber and AttackTDGunboatTurreted as actors with these AttackBase traits aren't supposed to be controlled.
readonly string[] attackBase = { "AttackLeap", "AttackPopupTurreted", "AttackAircraft", "AttackTesla", "AttackCharges", "AttackFollow", "AttackTurreted", "AttackFrontal", "AttackGarrisoned", "AttackOmni", "AttackSwallow" };
readonly string[] buildings = { "Building", "EnergyWall", "D2kBuilding" };
bool anyAdded;
public override string Name => "BaseBuilderBotModule got new fields to configure buildings that are defenses.";
public override string Description => "DefenseTypes were added.";
public override IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNode> resolvedActors)
{
var defences = new List<string>();
foreach (var actor in resolvedActors)
{
if (actor.Key.StartsWith('^'))
continue;
var isBuildable = false;
var isBuilding = false;
var canAttack = false;
foreach (var trait in actor.Value.Nodes)
{
if (trait.IsRemoval())
continue;
if (trait.KeyMatches("Buildable", includeRemovals: false))
{
isBuildable = true;
continue;
}
if (buildings.Any(v => trait.KeyMatches(v, includeRemovals: false)))
{
isBuilding = true;
continue;
}
if (attackBase.Any(ab => trait.KeyMatches(ab, includeRemovals: false)))
canAttack = true;
}
if (isBuildable && isBuilding && canAttack)
{
var name = actor.Key.ToLower();
if (!defences.Contains(name))
defences.Add(name);
}
}
this.defences = new MiniYamlNode("DefenseTypes", FieldSaver.FormatValue(defences));
yield break;
}
public override IEnumerable<string> AfterUpdate(ModData modData)
{
if (anyAdded)
yield return "`BaseBuilderBotModule` was unhardcoded and a new field added: `DefenseTypes`. Please verify the automated changes.";
anyAdded = false;
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
{
var addNodes = new List<MiniYamlNode>();
var defense = modData.DefaultRules.Actors.Values.Where(a => a.HasTraitInfo<BuildingInfo>() && a.HasTraitInfo<AttackBaseInfo>()).Select(a => a.Name);
var defensetypes = new MiniYamlNode("DefenseTypes", FieldSaver.FormatValue(defense.ToList()));
addNodes.Add(defensetypes);
foreach (var baseBuilderManager in actorNode.ChildrenMatching("BaseBuilderBotModule"))
foreach (var addNode in addNodes)
baseBuilderManager.AddNode(addNode);
foreach (var squadManager in actorNode.ChildrenMatching("BaseBuilderBotModule", includeRemovals: false))
{
if (!squadManager.ChildrenMatching(defences.Key, includeRemovals: false).Any())
{
squadManager.AddNode(defences);
anyAdded = true;
}
}
yield break;
}

View File

@@ -11,33 +11,132 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Traits;
namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class UnhardcodeSquadManager : UpdateRule
{
readonly List<MiniYamlNode> addNodes = new List<MiniYamlNode>();
// Excludes AttackBomber and AttackTDGunboatTurreted as actors with these AttackBase traits aren't supposed to be controlled.
readonly string[] attackBase = { "AttackLeap", "AttackPopupTurreted", "AttackAircraft", "AttackTesla", "AttackCharges", "AttackFollow", "AttackTurreted", "AttackFrontal", "AttackGarrisoned", "AttackOmni", "AttackSwallow" };
readonly string[] vipsNames = { "Harvester", "BaseBuilding" };
readonly string[] buildings = { "Building", "EnergyWall", "D2kBuilding" };
readonly string[] excludedBuildings = { "LineBuild", "Plug" };
public override string Name => "SquadManagerBotModule got new fields to configure ground attacks and defensive actions.";
public override string Description => "AirUnitsTypes and ProtectionTypes were added.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNode> resolvedActors)
{
var addNodes = new List<MiniYamlNode>();
var aircraft = new List<string>();
var vips = new List<string>();
var aircraft = modData.DefaultRules.Actors.Values.Where(a => a.HasTraitInfo<AircraftInfo>() && a.HasTraitInfo<AttackBaseInfo>()).Select(a => a.Name);
var airUnits = new MiniYamlNode("AirUnitsTypes", FieldSaver.FormatValue(aircraft.ToList()));
addNodes.Add(airUnits);
foreach (var actor in resolvedActors)
{
if (actor.Key.StartsWith('^'))
continue;
var vips = modData.DefaultRules.Actors.Values.Where(a => a.HasTraitInfo<HarvesterInfo>() || a.HasTraitInfo<BaseBuildingInfo>() || (a.HasTraitInfo<BuildingInfo>() && a.HasTraitInfo<BuildableInfo>() && !a.HasTraitInfo<LineBuildInfo>() && !a.HasTraitInfo<PlugInfo>())).Select(a => a.Name);
var protection = new MiniYamlNode("ProtectionTypes", FieldSaver.FormatValue(vips.ToList()));
addNodes.Add(protection);
var isVip = false;
var isBuildable = false;
var isBuilding = false;
var isAircraft = false;
var isExcluded = false;
var canAttack = false;
var isKillable = false;
foreach (var squadManager in actorNode.ChildrenMatching("SquadManagerBotModule"))
foreach (var addNode in addNodes)
squadManager.AddNode(addNode);
foreach (var trait in actor.Value.Nodes)
{
if (trait.IsRemoval())
continue;
if (trait.KeyMatches("Buildable", includeRemovals: false))
{
isBuildable = true;
continue;
}
if (trait.KeyMatches("Aircraft", includeRemovals: false))
{
isAircraft = true;
continue;
}
if (trait.KeyMatches("Health", includeRemovals: false))
{
isKillable = true;
continue;
}
if (vipsNames.Any(v => trait.KeyMatches(v, includeRemovals: false)))
{
isVip = true;
continue;
}
if (buildings.Any(b => trait.KeyMatches(b, includeRemovals: false)))
{
isBuilding = true;
continue;
}
if (excludedBuildings.Any(eb => trait.KeyMatches(eb, includeRemovals: false)))
{
isExcluded = true;
continue;
}
if (attackBase.Any(ab => trait.KeyMatches(ab, includeRemovals: false)))
canAttack = true;
}
if (isAircraft && isBuildable && canAttack && isKillable)
{
var name = actor.Key.ToLower();
if (!aircraft.Contains(name))
aircraft.Add(name);
}
if (isBuildable && isKillable && (isVip || (isBuilding && !isExcluded)))
{
var name = actor.Key.ToLower();
if (!vips.Contains(name))
vips.Add(name);
}
}
addNodes.Add(new MiniYamlNode("AirUnitsTypes", FieldSaver.FormatValue(aircraft)));
addNodes.Add(new MiniYamlNode("ProtectionTypes", FieldSaver.FormatValue(vips)));
yield break;
}
bool anyAdded = false;
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
{
foreach (var squadManager in actorNode.ChildrenMatching("SquadManagerBotModule", includeRemovals: false))
{
foreach (var addNode in addNodes)
{
if (!squadManager.ChildrenMatching(addNode.Key, includeRemovals: false).Any())
{
squadManager.AddNode(addNode);
anyAdded = true;
}
}
}
yield break;
}
public override IEnumerable<string> AfterUpdate(ModData modData)
{
if (anyAdded)
yield return "`SquadManagerBotModule` was unhardcoded and new fields added: `AirUnitsTypes` and `ProtectionTypes`. Please verify the automated changes.";
anyAdded = false;
}
}
}

View File

@@ -97,6 +97,8 @@ namespace OpenRA.Mods.Common.UpdateRules
new UnhardcodeBaseBuilderBotModule(),
new UnhardcodeVeteranProductionIconOverlay(),
new RenameContrailProperties(),
new RemoveDomainIndex(),
new AddControlGroups(),
})
};

View File

@@ -36,5 +36,9 @@ namespace OpenRA.Mods.Common.UpdateRules
public virtual IEnumerable<string> BeforeUpdate(ModData modData) { yield break; }
public virtual IEnumerable<string> AfterUpdate(ModData modData) { yield break; }
public virtual IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNode> resolvedActors) { yield break; }
public virtual IEnumerable<string> BeforeUpdateWeapons(ModData modData, List<MiniYamlNode> resolvedWeapons) { yield break; }
public virtual IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNode> resolvedImages) { yield break; }
}
}

View File

@@ -114,6 +114,9 @@ namespace OpenRA.Mods.Common.UpdateRules
var mapRulesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules");
if (mapRulesNode != null)
{
var resolvedActors = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Rules, mapRulesNode.Value);
manualSteps.AddRange(rule.BeforeUpdateActors(modData, resolvedActors));
var mapRules = LoadInternalMapYaml(modData, mapPackage, mapRulesNode.Value, externalFilenames);
manualSteps.AddRange(ApplyTopLevelTransform(modData, mapRules, rule.UpdateActorNode));
files.AddRange(mapRules);
@@ -122,6 +125,9 @@ namespace OpenRA.Mods.Common.UpdateRules
var mapWeaponsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Weapons");
if (mapWeaponsNode != null)
{
var resolvedWeapons = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Weapons, mapWeaponsNode.Value);
manualSteps.AddRange(rule.BeforeUpdateWeapons(modData, resolvedWeapons));
var mapWeapons = LoadInternalMapYaml(modData, mapPackage, mapWeaponsNode.Value, externalFilenames);
manualSteps.AddRange(ApplyTopLevelTransform(modData, mapWeapons, rule.UpdateWeaponNode));
files.AddRange(mapWeapons);
@@ -130,8 +136,11 @@ namespace OpenRA.Mods.Common.UpdateRules
var mapSequencesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Sequences");
if (mapSequencesNode != null)
{
var resolvedImages = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Sequences, mapSequencesNode.Value);
manualSteps.AddRange(rule.BeforeUpdateSequences(modData, resolvedImages));
var mapSequences = LoadInternalMapYaml(modData, mapPackage, mapSequencesNode.Value, externalFilenames);
manualSteps.AddRange(ApplyTopLevelTransform(modData, mapSequences, rule.UpdateWeaponNode));
manualSteps.AddRange(ApplyTopLevelTransform(modData, mapSequences, rule.UpdateSequenceNode));
files.AddRange(mapSequences);
}
@@ -141,6 +150,29 @@ namespace OpenRA.Mods.Common.UpdateRules
return manualSteps;
}
public static List<MiniYamlNode> LoadMapYaml(IReadOnlyFileSystem fileSystem, IReadOnlyPackage mapPackage, IEnumerable<string> files, MiniYaml mapNode)
{
var yaml = files.Select(s => MiniYaml.FromStream(fileSystem.Open(s), s)).ToList();
if (mapNode != null && mapNode.Value != null)
{
var mapFiles = FieldLoader.GetValue<string[]>("value", mapNode.Value);
yaml.AddRange(mapFiles.Select(filename =>
{
// Explicit package paths never refer to a map
if (!filename.Contains('|') && mapPackage.Contains(filename))
return MiniYaml.FromStream(mapPackage.GetStream(filename));
return MiniYaml.FromStream(fileSystem.Open(filename));
}));
}
if (mapNode != null && mapNode.Nodes.Count > 0)
yaml.Add(mapNode.Nodes);
return MiniYaml.Merge(yaml);
}
static IEnumerable<string> FilterExternalModFiles(ModData modData, IEnumerable<string> files, HashSet<string> externalFilenames)
{
foreach (var f in files)
@@ -196,9 +228,19 @@ namespace OpenRA.Mods.Common.UpdateRules
}
manualSteps.AddRange(rule.BeforeUpdate(modData));
var resolvedActors = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Rules, null);
manualSteps.AddRange(rule.BeforeUpdateActors(modData, resolvedActors));
manualSteps.AddRange(ApplyTopLevelTransform(modData, modRules, rule.UpdateActorNode));
var resolvedWeapons = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Weapons, null);
manualSteps.AddRange(rule.BeforeUpdateWeapons(modData, resolvedWeapons));
manualSteps.AddRange(ApplyTopLevelTransform(modData, modWeapons, rule.UpdateWeaponNode));
var resolvedSequences = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Sequences, null);
manualSteps.AddRange(rule.BeforeUpdateSequences(modData, resolvedSequences));
manualSteps.AddRange(ApplyTopLevelTransform(modData, modSequences, rule.UpdateSequenceNode));
manualSteps.AddRange(ApplyTopLevelTransform(modData, modTilesets, rule.UpdateTilesetNode));
manualSteps.AddRange(ApplyChromeTransform(modData, modChromeLayout, rule.UpdateChromeNode));
manualSteps.AddRange(ApplyTopLevelTransform(modData, modChromeProvider, rule.UpdateChromeProviderNode));

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var knownKeys = new HashSet<TKey>();
foreach (TSource element in source)
foreach (var element in source)
{
if (knownKeys.Add(keySelector(element)))
yield return element;

View File

@@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
return PrintUsage();
var invalid = false;
for (int i = 1; i < args.Length; i++)
for (var i = 1; i < args.Length; i++)
{
var parts = args[i].Split(Comma, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 3 && parts.Length != 4)
@@ -75,7 +75,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
[Desc("Convert r,g,b[,a] triples/quads into hex colors")]
void IUtilityCommand.Run(Utility utility, string[] args)
{
for (int i = 1; i < args.Length;)
for (var i = 1; i < args.Length;)
{
var parts = args[i].Split(Comma, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 3)
@@ -113,7 +113,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
return PrintUsage();
var invalid = false;
for (int i = 1; i < args.Length; i++)
for (var i = 1; i < args.Length; i++)
{
var parts = args[i].Split(Comma, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 3 && parts.Length != 4)
@@ -180,7 +180,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
[Desc("Convert a,r,g,b legacy colors into hex colors")]
void IUtilityCommand.Run(Utility utility, string[] args)
{
for (int i = 1; i < args.Length;)
for (var i = 1; i < args.Length;)
{
var parts = args[i].Split(Comma, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 3)

View File

@@ -124,7 +124,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
widget.Get<LabelWidget>("CONNECTING_DESC").GetText = () => connectingDescText;
var connectionError = widget.Get<LabelWidget>("CONNECTION_ERROR");
var connectionErrorText = modData.Translation.GetString(orderManager.ServerError) ?? connection.ErrorMessage ?? modData.Translation.GetString(UnknownError);
var connectionErrorText = orderManager.ServerError != null ? modData.Translation.GetString(orderManager.ServerError) : connection.ErrorMessage ?? modData.Translation.GetString(UnknownError);
connectionError.GetText = () => connectionErrorText;
var panelTitle = widget.Get<LabelWidget>("TITLE");

View File

@@ -188,7 +188,7 @@ namespace OpenRA.Mods.Common.Widgets
var animations = new ModelAnimation[] { animation };
ModelPreview preview = new ModelPreview(
var preview = new ModelPreview(
new ModelAnimation[] { animation }, WVec.Zero, 0,
cachedScale,
new WAngle(cachedLightPitch),

View File

@@ -2,7 +2,7 @@
<ItemGroup>
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj" />
<PackageReference Include="OpenRA-Freetype6" Version="1.0.9" />
<PackageReference Include="OpenRA-OpenAL-CS" Version="1.0.17" />
<PackageReference Include="OpenRA-OpenAL-CS" Version="1.0.19" />
<PackageReference Include="OpenRA-SDL2-CS" Version="1.0.36" />
</ItemGroup>
<ItemGroup>

View File

@@ -84,7 +84,9 @@ Container@AUDIO_PANEL:
Width: PARENT_RIGHT
Height: 20
Font: Regular
Text: Mute Background Music
Text: Mute Menu Music
TooltipText: Mute background music when no specific track is playing
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@MUSIC_VOLUME_CONTAINER:
X: PARENT_RIGHT / 2 + 10
Width: PARENT_RIGHT / 2 - 20

View File

@@ -159,7 +159,9 @@ Container@DISPLAY_PANEL:
Width: PARENT_RIGHT
Height: 20
Font: Regular
Text: Player Stance Colors
Text: Player Relationship Colors
TooltipText: Change minimap and health bar colors based on relationship (own, enemy, ally, neutral)
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@ROW:
Width: PARENT_RIGHT - 24
Height: 20
@@ -173,6 +175,8 @@ Container@DISPLAY_PANEL:
Height: 20
Font: Regular
Text: Show UI Feedback Notifications
TooltipText: Show transient text notifications for UI events
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@TRANSIENTS_CHECKBOX_CONTAINER:
X: PARENT_RIGHT / 2 + 10
Width: PARENT_RIGHT / 2 - 20
@@ -182,6 +186,8 @@ Container@DISPLAY_PANEL:
Height: 20
Font: Regular
Text: Show Game Event Notifications
TooltipText: Show transient text notifications for game events
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@ROW:
Width: PARENT_RIGHT - 24
Height: 20

View File

@@ -84,7 +84,9 @@ Container@AUDIO_PANEL:
Width: PARENT_RIGHT
Height: 20
Font: Regular
Text: Mute Background Music
Text: Mute Menu Music
TooltipText: Mute background music when no specific track is playing
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@MUSIC_VOLUME_CONTAINER:
X: PARENT_RIGHT / 2 + 10
Width: PARENT_RIGHT / 2 - 20

View File

@@ -159,7 +159,9 @@ Container@DISPLAY_PANEL:
Width: PARENT_RIGHT
Height: 20
Font: Regular
Text: Player Stance Colors
Text: Player Relationship Colors
TooltipText: Change minimap and health bar colors based on relationship (own, enemy, ally, neutral)
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@ROW:
Width: PARENT_RIGHT - 24
Height: 20
@@ -173,6 +175,8 @@ Container@DISPLAY_PANEL:
Height: 20
Font: Regular
Text: Show UI Feedback Notifications
TooltipText: Show transient text notifications for UI events
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@TRANSIENTS_CHECKBOX_CONTAINER:
X: PARENT_RIGHT / 2 + 10
Width: PARENT_RIGHT / 2 - 20
@@ -182,6 +186,8 @@ Container@DISPLAY_PANEL:
Height: 20
Font: Regular
Text: Show Game Event Notifications
TooltipText: Show transient text notifications for game events
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@ROW:
Width: PARENT_RIGHT - 24
Height: 20

View File

@@ -885,6 +885,7 @@ repair_pad:
Health:
HP: 30000
HitShape:
TargetableOffsets: 1024,0,0, 0,-1024,0, 0,1024,0, -1024,0,0
Type: Rectangle
TopLeft: -1536, -512
BottomRight: 1536, 512

View File

@@ -165,5 +165,6 @@ DeviatorMissile:
Range: 512
Duration: 375
InvalidTargets: Infantry, Structure
ValidRelationships: Enemy, Neutral
Warhead@4Concrete: DamagesConcrete
Damage: 1000

Binary file not shown.

View File

@@ -28,25 +28,25 @@ Players:
Name: Creeps
NonCombatant: True
Faction: england
Enemies: AntMan
Allies: Neutral
Enemies: AntMan
PlayerReference@Spain:
Name: Spain
Playable: True
AllowBots: False
Playable: True
Required: True
LockFaction: True
Faction: allies
LockColor: True
Color: F6D679
LockSpawn: True
LockTeam: True
Enemies: AntMan
Color: F6D679
PlayerReference@AntMan:
Name: AntMan
Faciton: soviet
Enemies: Spain, Creeps
Bot: campaign
Faction: soviet
Enemies: Spain, Creeps
Actors:
Actor0: brik

Binary file not shown.

View File

@@ -346,7 +346,7 @@ powerproxy.parabombs:
AirstrikePower:
Icon: parabombs
Name: Parabombs (Single Use)
Description: A Badger drops a load of parachuted bombs on your target.
Description: A Badger drops a load of parachuted bombs\nat the selected location.
OneShot: true
AllowMultiple: true
UnitType: badr.bomber

View File

@@ -1560,7 +1560,7 @@ AFLD:
Icon: paratroopers
ChargeInterval: 7500
Name: Paratroopers
Description: A Badger drops a squad of infantry\nanywhere on the map.
Description: A Badger drops a squad of infantry\nat the selected location.
DropItems: E1R1,E1R1,E1R1,E3R1,E3R1
ReinforcementsArrivedSpeechNotification: ReinforcementsArrived
SelectTargetSpeechNotification: SelectTarget
@@ -1583,7 +1583,7 @@ AFLD:
Icon: parabombs
ChargeInterval: 7500
Name: Parabombs
Description: A squad of Badgers drop parachuted\nbombs on your target.
Description: A Badger drops a load of parachuted bombs\nat the selected location.
SelectTargetSpeechNotification: SelectTarget
SelectTargetTextNotification: Select target.
CameraActor: camera

View File

@@ -2720,8 +2720,6 @@ Templates:
8: Rock
9: Rock
12: Rough
13: Clear
14: Clear
Template@382:
Id: 382
Images: bridge1x.tem

View File

@@ -74,7 +74,7 @@ Player:
ExcludeFromSquadsTypes: harv, mcv, dpod, hunter
ConstructionYardTypes: gacnst
AirUnitsTypes: orca, orcab, scrin, apache, jumpjet
ProtectionTypes: gapowr, gapowrup, gapile, gaweap, gahpad, gadept, garadr, gatech, gaplug, gagate_a, gagate_b, gactwr, gavulc, garock, gacsam, napowr, naapwr, nahand, naweap, nahpad, naradr, natech, nastlh, natmpl, namisl, nawast, nagate_a, nagate_b, nalasr, naobel, nasam, weed, gacnst, proc, gasilo, napuls, mcv, harv
ProtectionTypes: gapowr, gapile, gaweap, gahpad, gadept, garadr, gatech, gaplug, gagate_a, gagate_b, gactwr, napowr, naapwr, nahand, naweap, nahpad, naradr, natech, nastlh, natmpl, namisl, nawast, nagate_a, nagate_b, nalasr, naobel, nasam, weed, gacnst, proc, gasilo, napuls, mcv, harv
UnitBuilderBotModule@test:
RequiresCondition: enable-test-ai
UnitQueues: Vehicle, Infantry, Air

View File

@@ -226,6 +226,10 @@ Function ${UN}Clean
RMDir /r $INSTDIR\Support
!ifndef USE_PROGRAMFILES32
SetRegView 64
!endif
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenRA${SUFFIX}"
DeleteRegKey HKLM "Software\Classes\openra-ra-${TAG}"
DeleteRegKey HKLM "Software\Classes\openra-cnc-${TAG}"