Compare commits
28 Commits
playtest-2
...
devtest-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
253e02ae08 | ||
|
|
f707b9c975 | ||
|
|
8629e578e3 | ||
|
|
c65cfd3528 | ||
|
|
7ad6cfda40 | ||
|
|
393fd585b1 | ||
|
|
ea221f9bfb | ||
|
|
b4ca81d1bd | ||
|
|
49590bb5f7 | ||
|
|
2d059c0d95 | ||
|
|
d5dd6a9086 | ||
|
|
a7ca0f0699 | ||
|
|
4b02d9b700 | ||
|
|
ebf55c8d86 | ||
|
|
f928922f3a | ||
|
|
bc3743d9ff | ||
|
|
8aa6600655 | ||
|
|
215b3d8ab3 | ||
|
|
a397670dce | ||
|
|
43d7f9c6df | ||
|
|
6904ea8c6b | ||
|
|
d702d58d1a | ||
|
|
e0b0c5624f | ||
|
|
33773f895c | ||
|
|
9f759f3cc2 | ||
|
|
9fb4302b2f | ||
|
|
4685c1a6b1 | ||
|
|
70bc5b097d |
@@ -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
|
||||
|
||||
|
||||
17
.github/workflows/documentation.yml
vendored
17
.github/workflows/documentation.yml
vendored
@@ -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
|
||||
|
||||
3
Makefile
3
Makefile
@@ -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
|
||||
|
||||
@@ -55,7 +55,8 @@ namespace OpenRA.FileSystem
|
||||
get
|
||||
{
|
||||
foreach (ZipEntry entry in pkg)
|
||||
yield return entry.Name;
|
||||
if (entry.IsFile)
|
||||
yield return entry.Name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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]}");
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,8 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
new UnhardcodeBaseBuilderBotModule(),
|
||||
new UnhardcodeVeteranProductionIconOverlay(),
|
||||
new RenameContrailProperties(),
|
||||
new RemoveDomainIndex(),
|
||||
new AddControlGroups(),
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -165,5 +165,6 @@ DeviatorMissile:
|
||||
Range: 512
|
||||
Duration: 375
|
||||
InvalidTargets: Infantry, Structure
|
||||
ValidRelationships: Enemy, Neutral
|
||||
Warhead@4Concrete: DamagesConcrete
|
||||
Damage: 1000
|
||||
|
||||
Binary file not shown.
@@ -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.
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2720,8 +2720,6 @@ Templates:
|
||||
8: Rock
|
||||
9: Rock
|
||||
12: Rough
|
||||
13: Clear
|
||||
14: Clear
|
||||
Template@382:
|
||||
Id: 382
|
||||
Images: bridge1x.tem
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}"
|
||||
|
||||
Reference in New Issue
Block a user