Compare commits
18 Commits
log_chat_s
...
809cb16075
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
809cb16075 | ||
|
|
f4c186b7a6 | ||
|
|
c3cf94b67a | ||
|
|
8b3e7bec2a | ||
|
|
64ec6eef0a | ||
|
|
4dec1fe430 | ||
|
|
db3145ed5e | ||
|
|
e49135bb09 | ||
|
|
9d79e52989 | ||
|
|
0ac9d96ab8 | ||
|
|
5ce559c853 | ||
|
|
a4821b51a2 | ||
|
|
cfc026a1ac | ||
|
|
58ab3eb153 | ||
|
|
47b6542b1d | ||
|
|
3c7addcb80 | ||
|
|
37f1b9efbf | ||
|
|
82acdbc32a |
@@ -41,7 +41,11 @@ namespace OpenRA.FileSystem
|
||||
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
try { return File.OpenRead(Path.Combine(Name, filename)); }
|
||||
var combined = Path.Combine(Name, filename);
|
||||
if (!File.Exists(combined))
|
||||
return null;
|
||||
|
||||
try { return File.OpenRead(combined); }
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
|
||||
@@ -549,7 +549,7 @@ namespace OpenRA.Traits
|
||||
{
|
||||
Id = id;
|
||||
Name = map.GetLocalisedString(name);
|
||||
Description = map.GetLocalisedString(description);
|
||||
Description = description != null ? map.GetLocalisedString(description) : null;
|
||||
IsVisible = visible;
|
||||
DisplayOrder = displayorder;
|
||||
Values = values.ToDictionary(v => v.Key, v => map.GetLocalisedString(v.Value));
|
||||
|
||||
@@ -103,6 +103,8 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
if (Map.Rules.TerrainInfo is ITerrainInfoNotifyMapCreated notifyMapCreated)
|
||||
notifyMapCreated.MapCreated(Map);
|
||||
|
||||
ReplaceInvalidTerrainTiles(Map);
|
||||
|
||||
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";
|
||||
|
||||
Map.Save(ZipFileLoader.Create(dest));
|
||||
@@ -159,6 +161,19 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
missionData.Value.Nodes.Add(new MiniYamlNode("Briefing", briefing.Replace("\n", " ").ToString()));
|
||||
}
|
||||
|
||||
static void ReplaceInvalidTerrainTiles(Map map)
|
||||
{
|
||||
var terrainInfo = map.Rules.TerrainInfo;
|
||||
foreach (var uv in map.AllCells.MapCoords)
|
||||
{
|
||||
if (!terrainInfo.TryGetTerrainInfo(map.Tiles[uv], out _))
|
||||
{
|
||||
map.Tiles[uv] = terrainInfo.DefaultTerrainTile;
|
||||
Console.WriteLine($"Replaced invalid terrain tile at {uv}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SetBounds(Map map, IniSection mapSection)
|
||||
{
|
||||
var offsetX = Exts.ParseIntegerInvariant(mapSection.GetValue("X", "0"));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Activities;
|
||||
@@ -185,7 +186,19 @@ namespace OpenRA.Mods.Common.Activities
|
||||
return true;
|
||||
|
||||
var isSlider = aircraft.Info.CanSlide;
|
||||
var desiredFacing = delta.HorizontalLengthSquared != 0 ? delta.Yaw : aircraft.Facing;
|
||||
|
||||
var desiredFacing = aircraft.Facing;
|
||||
if (delta.HorizontalLengthSquared != 0)
|
||||
{
|
||||
var facing = delta.Yaw;
|
||||
|
||||
// Prevent jittering.
|
||||
var diff = Math.Abs(facing.Angle - desiredFacing.Angle);
|
||||
var deadzone = aircraft.Info.TurnDeadzone.Angle;
|
||||
if (diff > deadzone && diff < 1024 - deadzone)
|
||||
desiredFacing = facing;
|
||||
}
|
||||
|
||||
var move = isSlider ? aircraft.FlyStep(desiredFacing) : aircraft.FlyStep(aircraft.Facing);
|
||||
|
||||
// Inside the minimum range, so reverse if we CanSlide, otherwise face away from the target.
|
||||
@@ -194,9 +207,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
if (isSlider)
|
||||
FlyTick(self, aircraft, desiredFacing, aircraft.Info.CruiseAltitude, -move);
|
||||
else
|
||||
{
|
||||
FlyTick(self, aircraft, desiredFacing + new WAngle(512), aircraft.Info.CruiseAltitude, move);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -10,32 +10,21 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Mods.Common.Scripting;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public class CheckLuaScript : ILintMapPass, ILintServerMapPass
|
||||
public class CheckLuaScript : ILintMapPass
|
||||
{
|
||||
void ILintMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
|
||||
{
|
||||
CheckLuaScriptFileExistance(emitError, map.Package, modData.DefaultFileSystem, map.Rules);
|
||||
}
|
||||
|
||||
void ILintServerMapPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, MapPreview map, Ruleset mapRules)
|
||||
{
|
||||
CheckLuaScriptFileExistance(emitError, map.Package, modData.DefaultFileSystem, mapRules);
|
||||
}
|
||||
|
||||
static void CheckLuaScriptFileExistance(Action<string> emitError, IReadOnlyPackage package, IReadOnlyFileSystem fileSystem, Ruleset mapRules)
|
||||
{
|
||||
var luaScriptInfo = mapRules.Actors[SystemActors.World].TraitInfoOrDefault<LuaScriptInfo>();
|
||||
var luaScriptInfo = map.Rules.Actors[SystemActors.World].TraitInfoOrDefault<LuaScriptInfo>();
|
||||
if (luaScriptInfo == null)
|
||||
return;
|
||||
|
||||
// We aren't running this lint on servers as they don't create map packages.
|
||||
foreach (var script in luaScriptInfo.Scripts)
|
||||
if (!package.Contains(script) && !fileSystem.Exists(script))
|
||||
if (!map.Package.Contains(script) && !modData.DefaultFileSystem.Exists(script))
|
||||
emitError($"Lua script `{script}` does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,18 +170,15 @@ namespace OpenRA.Mods.Common.Terrain
|
||||
|
||||
void ITerrainInfoNotifyMapCreated.MapCreated(Map map)
|
||||
{
|
||||
// Randomize PickAny tile variants
|
||||
// Randomize PickAny tile variants.
|
||||
var r = new MersenneTwister();
|
||||
for (var j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
|
||||
foreach (var uv in map.AllCells.MapCoords)
|
||||
{
|
||||
for (var i = map.Bounds.Left; i < map.Bounds.Right; i++)
|
||||
{
|
||||
var type = map.Tiles[new MPos(i, j)].Type;
|
||||
if (!Templates.TryGetValue(type, out var template) || !template.PickAny)
|
||||
continue;
|
||||
var type = map.Tiles[uv].Type;
|
||||
if (!Templates.TryGetValue(type, out var template) || !template.PickAny)
|
||||
continue;
|
||||
|
||||
map.Tiles[new MPos(i, j)] = new TerrainTile(type, (byte)r.Next(0, template.TilesCount));
|
||||
}
|
||||
map.Tiles[uv] = new TerrainTile(type, (byte)r.Next(0, template.TilesCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Turn speed to apply when aircraft flies in circles while idle. Defaults to TurnSpeed if undefined.")]
|
||||
public readonly WAngle? IdleTurnSpeed = null;
|
||||
|
||||
[Desc("When flying if the difference between current facing and desired facing is less than this value, don't turn. This prevents visual jitter.")]
|
||||
public readonly WAngle TurnDeadzone = new(2);
|
||||
|
||||
[Desc("Maximum flight speed when cruising.")]
|
||||
public readonly int Speed = 1;
|
||||
|
||||
|
||||
@@ -128,10 +128,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return true;
|
||||
|
||||
var dropRange = carryall.Info.DropRange;
|
||||
var destination = carryable.Destination;
|
||||
if (destination != null)
|
||||
self.QueueActivity(true, new DeliverUnit(self, Target.FromCell(self.World, destination.Value), dropRange, carryall.Info.TargetLineColor));
|
||||
|
||||
self.QueueActivity(true, new DeliverUnit(self, Target.FromCell(self.World, carryable.Destination ?? self.Location), dropRange, carryall.Info.TargetLineColor));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
var autoTarget = ScanForTarget(self, AllowMove, true);
|
||||
|
||||
if (autoTarget != Target.Invalid)
|
||||
if (autoTarget.Type != TargetType.Invalid)
|
||||
attacker = autoTarget.Actor;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Grants a condition on the collector.")]
|
||||
[Desc("Grants a condition to the collector and nearby units.")]
|
||||
public class GrantExternalConditionCrateActionInfo : CrateActionInfo
|
||||
{
|
||||
[FieldLoader.Require]
|
||||
@@ -60,38 +60,36 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public override void Activate(Actor collector)
|
||||
{
|
||||
if (collector.IsInWorld && !collector.IsDead)
|
||||
GrantCondition(collector);
|
||||
|
||||
var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, info.Range)
|
||||
.Where(a => a != self && a != collector && a.Owner == collector.Owner && AcceptsCondition(a));
|
||||
.Where(a => a != self && a != collector && a.IsInWorld && !a.IsDead && a.Owner == collector.Owner && AcceptsCondition(a))
|
||||
.OrderBy(a => (a.CenterPosition - self.CenterPosition).LengthSquared);
|
||||
|
||||
if (info.MaxExtraCollectors > -1)
|
||||
actorsInRange = actorsInRange.Take(info.MaxExtraCollectors);
|
||||
|
||||
collector.World.AddFrameEndTask(w =>
|
||||
{
|
||||
foreach (var a in actorsInRange.Append(collector))
|
||||
{
|
||||
if (!a.IsInWorld || a.IsDead)
|
||||
continue;
|
||||
|
||||
var externals = a.TraitsImplementing<ExternalCondition>()
|
||||
.Where(t => t.Info.Condition == info.Condition);
|
||||
|
||||
ExternalCondition external = null;
|
||||
for (var n = 0; n < info.Levels; n++)
|
||||
{
|
||||
if (external == null || !external.CanGrantCondition(self))
|
||||
{
|
||||
external = externals.FirstOrDefault(t => t.CanGrantCondition(self));
|
||||
if (external == null)
|
||||
break;
|
||||
}
|
||||
|
||||
external.GrantCondition(a, self, info.Duration);
|
||||
}
|
||||
}
|
||||
});
|
||||
foreach (var a in info.MaxExtraCollectors > -1 ? actorsInRange.Take(info.MaxExtraCollectors) : actorsInRange)
|
||||
GrantCondition(a);
|
||||
|
||||
base.Activate(collector);
|
||||
}
|
||||
|
||||
void GrantCondition(Actor actor)
|
||||
{
|
||||
var externals = actor.TraitsImplementing<ExternalCondition>()
|
||||
.Where(t => t.Info.Condition == info.Condition);
|
||||
|
||||
ExternalCondition external = null;
|
||||
for (var n = 0; n < info.Levels; n++)
|
||||
{
|
||||
if (external == null || !external.CanGrantCondition(self))
|
||||
{
|
||||
external = externals.FirstOrDefault(t => t.CanGrantCondition(self));
|
||||
if (external == null)
|
||||
break;
|
||||
}
|
||||
|
||||
external.GrantCondition(actor, self, info.Duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
devMode = self.Trait<DeveloperMode>();
|
||||
wasHackEnabled = devMode.UnlimitedPower;
|
||||
PlayLowPowerNotification = info.AdviceInterval > 0;
|
||||
}
|
||||
|
||||
void INotifyCreated.Created(Actor self)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
[FieldLoader.Require]
|
||||
[TranslationReference(dictionaryReference: LintDictionaryReference.Values)]
|
||||
[Desc("Difficulty levels supported by the map.")]
|
||||
[Desc("Options to choose from.")]
|
||||
public readonly Dictionary<string, string> Values = null;
|
||||
|
||||
[Desc("Prevent the option from being changed from its default value.")]
|
||||
|
||||
@@ -83,7 +83,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
this.isSavePanel = isSavePanel;
|
||||
Game.BeforeGameStart += OnGameStart;
|
||||
|
||||
panel.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () =>
|
||||
var cancelButton = panel.Get<ButtonWidget>("CANCEL_BUTTON");
|
||||
cancelButton.OnClick = () =>
|
||||
{
|
||||
Ui.CloseWindow();
|
||||
onExit();
|
||||
@@ -117,17 +118,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
saveButton.IsVisible = () => true;
|
||||
|
||||
var saveWidgets = panel.Get("SAVE_WIDGETS");
|
||||
saveTextField = saveWidgets.Get<TextFieldWidget>("SAVE_TEXTFIELD");
|
||||
gameList.Bounds.Height -= saveWidgets.Bounds.Height;
|
||||
saveWidgets.IsVisible = () => true;
|
||||
|
||||
saveTextField.OnEnterKey = _ =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(saveTextField.Text))
|
||||
Save(world);
|
||||
|
||||
return true;
|
||||
};
|
||||
saveTextField = saveWidgets.Get<TextFieldWidget>("SAVE_TEXTFIELD");
|
||||
saveTextField.OnEnterKey = input => saveButton.HandleKeyPress(input);
|
||||
saveTextField.OnEscKey = input => cancelButton.HandleKeyPress(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
@@ -510,8 +511,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{ "PARENT_BOTTOM", parentBounds.Height }
|
||||
};
|
||||
|
||||
var width = w.Width.Evaluate(substitutions);
|
||||
var height = w.Height.Evaluate(substitutions);
|
||||
var readOnlySubstitutions = new ReadOnlyDictionary<string, int>(substitutions);
|
||||
var width = w.Width != null ? w.Width.Evaluate(readOnlySubstitutions) : 0;
|
||||
var height = w.Height != null ? w.Height.Evaluate(readOnlySubstitutions) : 0;
|
||||
|
||||
substitutions.Add("WIDTH", width);
|
||||
substitutions.Add("HEIGHT", height);
|
||||
@@ -520,8 +522,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
w.Bounds = new Rectangle(w.Bounds.X, w.Bounds.Y, width, w.Bounds.Height);
|
||||
else
|
||||
w.Bounds = new Rectangle(
|
||||
w.X.Evaluate(substitutions),
|
||||
w.Y.Evaluate(substitutions),
|
||||
w.X != null ? w.X.Evaluate(readOnlySubstitutions) : 0,
|
||||
w.Y != null ? w.Y.Evaluate(readOnlySubstitutions) : 0,
|
||||
width,
|
||||
height);
|
||||
|
||||
|
||||
@@ -1093,14 +1093,14 @@ Container@OBSERVER_WIDGETS:
|
||||
Align: Right
|
||||
Shadow: True
|
||||
Label@ARMY_VALUE:
|
||||
X: 605
|
||||
X: 610
|
||||
Y: 0
|
||||
Width: 85
|
||||
Width: 90
|
||||
Height: PARENT_BOTTOM
|
||||
Align: Right
|
||||
Shadow: True
|
||||
Label@VISION:
|
||||
X: 690
|
||||
X: 700
|
||||
Y: 0
|
||||
Width: 60
|
||||
Height: PARENT_BOTTOM
|
||||
|
||||
@@ -234,7 +234,6 @@ cncr-origin: C&C Remastered Collection (Origin version, English)
|
||||
RegistryValue: Install Dir
|
||||
IDFiles:
|
||||
Data/CNCDATA/RED_ALERT/CD1/REDALERT.MIX: 0e58f4b54f44f6cd29fecf8cf379d33cf2d4caef
|
||||
Length: 4096
|
||||
# The Remastered Collection doesn't include the RA Soviet CD unfortunately, so we can't install Soviet campaign briefings.
|
||||
Install:
|
||||
# Base game files:
|
||||
|
||||
@@ -3,7 +3,6 @@ cncr-steam: C&C Remastered Collection (Steam version, English)
|
||||
AppId: 1213210
|
||||
IDFiles:
|
||||
Data/CNCDATA/RED_ALERT/CD1/REDALERT.MIX: 0e58f4b54f44f6cd29fecf8cf379d33cf2d4caef
|
||||
Length: 4096
|
||||
# The Remastered Collection doesn't include the RA Soviet CD unfortunately, so we can't install Soviet campaign briefings.
|
||||
Install:
|
||||
# Base game files:
|
||||
|
||||
@@ -100,6 +100,7 @@ GroundWavesDelays =
|
||||
normal = 3,
|
||||
hard = 2
|
||||
}
|
||||
GroundWavesDelay = GroundWavesDelays[Difficulty]
|
||||
|
||||
GroundWaves = function()
|
||||
if not ForwardCommand.IsDead then
|
||||
@@ -107,7 +108,7 @@ GroundWaves = function()
|
||||
local units = Reinforcements.Reinforce(BadGuy, Utils.Random(GroundAttackUnits), path)
|
||||
Utils.Do(units, IdleHunt)
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(GroundWavesDelays), GroundWaves)
|
||||
Trigger.AfterDelay(DateTime.Minutes(GroundWavesDelay), GroundWaves)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -132,8 +133,6 @@ ProduceAircraft = function()
|
||||
end
|
||||
|
||||
ActivateAI = function()
|
||||
GroundWavesDelays = GroundWavesDelays[Difficulty]
|
||||
|
||||
local buildings = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == USSR and self.HasProperty("StartBuildingRepairs") end)
|
||||
Utils.Do(buildings, function(actor)
|
||||
Trigger.OnDamaged(actor, function(building)
|
||||
@@ -146,6 +145,6 @@ ActivateAI = function()
|
||||
ProduceBadGuyInfantry()
|
||||
ProduceUSSRInfantry()
|
||||
ProduceVehicles()
|
||||
Trigger.AfterDelay(DateTime.Minutes(GroundWavesDelays), GroundWaves)
|
||||
Trigger.AfterDelay(DateTime.Minutes(GroundWavesDelay), GroundWaves)
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), ProduceAircraft)
|
||||
end
|
||||
|
||||
@@ -66,14 +66,21 @@ SetupTriggers = function()
|
||||
Trigger.OnAllKilledOrCaptured(SarinPlants, function()
|
||||
Greece.MarkCompletedObjective(CaptureSarin)
|
||||
end)
|
||||
|
||||
Trigger.OnEnteredProximityTrigger(AlliesMove.CenterPosition, WDist.FromCells(3), function(actor, id)
|
||||
if actor.Owner == Greece then
|
||||
Trigger.RemoveProximityTrigger(id)
|
||||
Media.PlaySpeechNotification(Greece, "SignalFlareSouth")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
MCVArrived = false
|
||||
MCVArrivedTick = false
|
||||
PowerDownTeslas = function()
|
||||
if not MCVArrived then
|
||||
CaptureSarin = Greece.AddObjective("capture-sarin-plants-intact")
|
||||
KillBase = Greece.AddObjective("destroy-enemy-compound")
|
||||
CaptureSarin = AddPrimaryObjective(Greece, "capture-sarin-plants-intact")
|
||||
KillBase = AddPrimaryObjective(Greece, "destroy-enemy-compound")
|
||||
Greece.MarkCompletedObjective(TakeOutPower)
|
||||
Media.PlaySpeechNotification(Greece, "ReinforcementsArrived")
|
||||
Reinforcements.Reinforce(Greece, MCVReinforcements[Difficulty], { AlliesSpawn.Location, AlliesMove.Location })
|
||||
@@ -85,6 +92,7 @@ PowerDownTeslas = function()
|
||||
|
||||
Trigger.AfterDelay(DateTime.Seconds(1), function()
|
||||
MCVArrivedTick = true
|
||||
PrepareFinishingHunt(USSR)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(DateTime.Seconds(60), function()
|
||||
@@ -99,6 +107,25 @@ PowerDownTeslas = function()
|
||||
end
|
||||
end
|
||||
|
||||
PrepareFinishingHunt = function(player)
|
||||
local buildings = GetBaseBuildings(player)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(buildings, function()
|
||||
Utils.Do(player.GetGroundAttackers(), function(actor)
|
||||
actor.Stop()
|
||||
IdleHunt(actor)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
GetBaseBuildings = function(player)
|
||||
-- Excludes the unrepairable sarin plants, which is desired anyway.
|
||||
local buildings = Utils.Where(player.GetActors(), function(actor)
|
||||
return actor.HasProperty("StartBuildingRepairs")
|
||||
end)
|
||||
return buildings
|
||||
end
|
||||
|
||||
Tick = function()
|
||||
USSR.Cash = 10000
|
||||
BadGuy.Cash = 10000
|
||||
|
||||
@@ -19,6 +19,9 @@ Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 7500
|
||||
|
||||
HARV:
|
||||
-MustBeDestroyed:
|
||||
|
||||
APC:
|
||||
Buildable:
|
||||
Prerequisites: ~vehicles.allies
|
||||
|
||||
BIN
mods/ra/maps/soviet-13b/map.bin
Normal file
BIN
mods/ra/maps/soviet-13b/map.bin
Normal file
Binary file not shown.
BIN
mods/ra/maps/soviet-13b/map.png
Normal file
BIN
mods/ra/maps/soviet-13b/map.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
957
mods/ra/maps/soviet-13b/map.yaml
Normal file
957
mods/ra/maps/soviet-13b/map.yaml
Normal file
@@ -0,0 +1,957 @@
|
||||
MapFormat: 12
|
||||
|
||||
RequiresMod: ra
|
||||
|
||||
Title: 13b: Capture the Chronosphere
|
||||
|
||||
Author: Westwood Studios
|
||||
|
||||
Tileset: SNOW
|
||||
|
||||
MapSize: 128,128
|
||||
|
||||
Bounds: 18,14,92,93
|
||||
|
||||
Visibility: MissionSelector
|
||||
|
||||
Categories: Campaign
|
||||
|
||||
LockPreview: True
|
||||
|
||||
Players:
|
||||
PlayerReference@Neutral:
|
||||
Name: Neutral
|
||||
OwnsWorld: True
|
||||
NonCombatant: True
|
||||
Faction: england
|
||||
PlayerReference@Greece:
|
||||
Name: Greece
|
||||
Bot: campaign
|
||||
Faction: allies
|
||||
Color: E2E6F6
|
||||
Allies: GoodGuy
|
||||
Enemies: USSR
|
||||
PlayerReference@GoodGuy:
|
||||
Name: GoodGuy
|
||||
Faction: allies
|
||||
Color: E2E6F6
|
||||
Allies: Greece
|
||||
Enemies: USSR
|
||||
PlayerReference@USSR:
|
||||
Name: USSR
|
||||
AllowBots: False
|
||||
Playable: True
|
||||
Required: True
|
||||
LockFaction: True
|
||||
Faction: soviet
|
||||
LockColor: True
|
||||
Color: FE1100
|
||||
LockSpawn: True
|
||||
LockTeam: True
|
||||
Enemies: GoodGuy, Greece
|
||||
|
||||
Actors:
|
||||
Actor0: cycl
|
||||
Location: 42,73
|
||||
Owner: Greece
|
||||
Actor1: cycl
|
||||
Location: 43,73
|
||||
Owner: Greece
|
||||
Actor2: cycl
|
||||
Location: 44,73
|
||||
Owner: Greece
|
||||
Actor3: cycl
|
||||
Location: 45,73
|
||||
Owner: Greece
|
||||
Actor4: cycl
|
||||
Location: 46,73
|
||||
Owner: Greece
|
||||
Actor5: cycl
|
||||
Location: 50,73
|
||||
Owner: Greece
|
||||
Actor6: cycl
|
||||
Location: 51,73
|
||||
Owner: Greece
|
||||
Actor7: cycl
|
||||
Location: 52,73
|
||||
Owner: Greece
|
||||
Actor8: cycl
|
||||
Location: 53,73
|
||||
Owner: Greece
|
||||
Actor9: cycl
|
||||
Location: 54,73
|
||||
Owner: Greece
|
||||
Actor10: cycl
|
||||
Location: 55,73
|
||||
Owner: Greece
|
||||
Actor11: cycl
|
||||
Location: 26,74
|
||||
Owner: Greece
|
||||
Actor12: cycl
|
||||
Location: 27,74
|
||||
Owner: Greece
|
||||
Actor13: cycl
|
||||
Location: 28,74
|
||||
Owner: Greece
|
||||
Actor14: cycl
|
||||
Location: 29,74
|
||||
Owner: Greece
|
||||
Actor15: cycl
|
||||
Location: 30,74
|
||||
Owner: Greece
|
||||
Actor16: cycl
|
||||
Location: 35,74
|
||||
Owner: Greece
|
||||
Actor17: cycl
|
||||
Location: 36,74
|
||||
Owner: Greece
|
||||
Actor18: cycl
|
||||
Location: 41,74
|
||||
Owner: Greece
|
||||
Actor19: cycl
|
||||
Location: 42,74
|
||||
Owner: Greece
|
||||
Actor20: cycl
|
||||
Location: 55,74
|
||||
Owner: Greece
|
||||
Actor21: cycl
|
||||
Location: 56,74
|
||||
Owner: Greece
|
||||
Actor22: cycl
|
||||
Location: 25,75
|
||||
Owner: Greece
|
||||
Actor23: cycl
|
||||
Location: 26,75
|
||||
Owner: Greece
|
||||
Actor24: cycl
|
||||
Location: 36,75
|
||||
Owner: Greece
|
||||
Actor25: cycl
|
||||
Location: 37,75
|
||||
Owner: Greece
|
||||
Actor26: cycl
|
||||
Location: 38,75
|
||||
Owner: Greece
|
||||
Actor27: cycl
|
||||
Location: 39,75
|
||||
Owner: Greece
|
||||
Actor28: cycl
|
||||
Location: 40,75
|
||||
Owner: Greece
|
||||
Actor29: cycl
|
||||
Location: 41,75
|
||||
Owner: Greece
|
||||
Actor30: cycl
|
||||
Location: 56,75
|
||||
Owner: Greece
|
||||
Actor31: cycl
|
||||
Location: 57,75
|
||||
Owner: Greece
|
||||
Actor32: cycl
|
||||
Location: 58,75
|
||||
Owner: Greece
|
||||
Actor33: cycl
|
||||
Location: 59,75
|
||||
Owner: Greece
|
||||
Actor34: cycl
|
||||
Location: 25,76
|
||||
Owner: Greece
|
||||
Actor35: cycl
|
||||
Location: 59,76
|
||||
Owner: Greece
|
||||
Actor36: cycl
|
||||
Location: 62,79
|
||||
Owner: Greece
|
||||
Actor37: cycl
|
||||
Location: 63,79
|
||||
Owner: Greece
|
||||
Actor38: cycl
|
||||
Location: 64,79
|
||||
Owner: Greece
|
||||
Actor39: cycl
|
||||
Location: 64,80
|
||||
Owner: Greece
|
||||
Actor40: cycl
|
||||
Location: 65,80
|
||||
Owner: Greece
|
||||
Actor41: cycl
|
||||
Location: 66,80
|
||||
Owner: Greece
|
||||
Actor42: cycl
|
||||
Location: 66,81
|
||||
Owner: Greece
|
||||
Actor43: cycl
|
||||
Location: 67,81
|
||||
Owner: Greece
|
||||
Actor44: cycl
|
||||
Location: 68,81
|
||||
Owner: Greece
|
||||
Actor45: cycl
|
||||
Location: 69,81
|
||||
Owner: Greece
|
||||
Actor46: cycl
|
||||
Location: 66,88
|
||||
Owner: Greece
|
||||
Actor47: cycl
|
||||
Location: 67,88
|
||||
Owner: Greece
|
||||
Actor48: cycl
|
||||
Location: 68,88
|
||||
Owner: Greece
|
||||
Actor49: cycl
|
||||
Location: 69,88
|
||||
Owner: Greece
|
||||
Actor50: cycl
|
||||
Location: 70,88
|
||||
Owner: Greece
|
||||
Actor51: cycl
|
||||
Location: 71,88
|
||||
Owner: Greece
|
||||
Actor52: cycl
|
||||
Location: 71,89
|
||||
Owner: Greece
|
||||
Actor53: cycl
|
||||
Location: 71,90
|
||||
Owner: Greece
|
||||
Actor54: cycl
|
||||
Location: 57,93
|
||||
Owner: Greece
|
||||
Actor55: cycl
|
||||
Location: 60,93
|
||||
Owner: Greece
|
||||
Actor56: cycl
|
||||
Location: 57,94
|
||||
Owner: Greece
|
||||
Actor57: cycl
|
||||
Location: 58,94
|
||||
Owner: Greece
|
||||
Actor58: cycl
|
||||
Location: 59,94
|
||||
Owner: Greece
|
||||
Actor59: cycl
|
||||
Location: 60,94
|
||||
Owner: Greece
|
||||
Actor60: brik
|
||||
Location: 70,94
|
||||
Owner: Greece
|
||||
Actor61: brik
|
||||
Location: 71,94
|
||||
Owner: Greece
|
||||
Actor62: brik
|
||||
Location: 70,95
|
||||
Owner: Greece
|
||||
Actor63: brik
|
||||
Location: 71,95
|
||||
Owner: Greece
|
||||
Actor64: cycl
|
||||
Location: 47,96
|
||||
Owner: Greece
|
||||
Actor65: cycl
|
||||
Location: 48,96
|
||||
Owner: Greece
|
||||
Actor66: cycl
|
||||
Location: 49,96
|
||||
Owner: Greece
|
||||
Actor67: cycl
|
||||
Location: 50,96
|
||||
Owner: Greece
|
||||
Actor68: cycl
|
||||
Location: 47,97
|
||||
Owner: Greece
|
||||
Actor69: brik
|
||||
Location: 26,100
|
||||
Owner: Greece
|
||||
Actor70: brik
|
||||
Location: 27,100
|
||||
Owner: Greece
|
||||
Actor71: brik
|
||||
Location: 28,100
|
||||
Owner: Greece
|
||||
Actor72: brik
|
||||
Location: 29,100
|
||||
Owner: Greece
|
||||
Actor73: brik
|
||||
Location: 70,100
|
||||
Owner: Greece
|
||||
Actor74: brik
|
||||
Location: 71,100
|
||||
Owner: Greece
|
||||
Actor75: brik
|
||||
Location: 26,101
|
||||
Owner: Greece
|
||||
Actor76: brik
|
||||
Location: 29,101
|
||||
Owner: Greece
|
||||
Actor77: brik
|
||||
Location: 70,101
|
||||
Owner: Greece
|
||||
Actor78: brik
|
||||
Location: 71,101
|
||||
Owner: Greece
|
||||
Actor79: brik
|
||||
Location: 26,102
|
||||
Owner: Greece
|
||||
Actor80: brik
|
||||
Location: 29,102
|
||||
Owner: Greece
|
||||
Actor81: brik
|
||||
Location: 26,103
|
||||
Owner: Greece
|
||||
Actor82: brik
|
||||
Location: 27,103
|
||||
Owner: Greece
|
||||
Actor83: brik
|
||||
Location: 28,103
|
||||
Owner: Greece
|
||||
Actor84: brik
|
||||
Location: 29,103
|
||||
Owner: Greece
|
||||
Actor85: tc05
|
||||
Location: 52,104
|
||||
Owner: Neutral
|
||||
Actor86: tc02
|
||||
Location: 46,99
|
||||
Owner: Neutral
|
||||
Actor87: t01
|
||||
Location: 92,88
|
||||
Owner: Neutral
|
||||
Actor88: tc04
|
||||
Location: 76,95
|
||||
Owner: Neutral
|
||||
Actor89: tc01
|
||||
Location: 76,91
|
||||
Owner: Neutral
|
||||
Actor90: tc04
|
||||
Location: 60,65
|
||||
Owner: Neutral
|
||||
Actor91: t12
|
||||
Location: 64,65
|
||||
Owner: Neutral
|
||||
Actor92: tc01
|
||||
Location: 46,56
|
||||
Owner: Neutral
|
||||
Actor93: tc05
|
||||
Location: 53,63
|
||||
Owner: Neutral
|
||||
Actor94: tc03
|
||||
Location: 37,67
|
||||
Owner: Neutral
|
||||
Actor95: tc03
|
||||
Location: 70,59
|
||||
Owner: Neutral
|
||||
Actor96: tc02
|
||||
Location: 87,65
|
||||
Owner: Neutral
|
||||
Actor97: t16
|
||||
Location: 42,48
|
||||
Owner: Neutral
|
||||
Actor98: t15
|
||||
Location: 27,68
|
||||
Owner: Neutral
|
||||
Actor99: t14
|
||||
Location: 56,68
|
||||
Owner: Neutral
|
||||
Actor100: t13
|
||||
Location: 59,50
|
||||
Owner: Neutral
|
||||
Actor101: t12
|
||||
Location: 92,54
|
||||
Owner: Neutral
|
||||
Actor102: tc04
|
||||
Location: 23,63
|
||||
Owner: Neutral
|
||||
Actor103: tc02
|
||||
Location: 18,52
|
||||
Owner: Neutral
|
||||
Actor104: tc01
|
||||
Location: 29,53
|
||||
Owner: Neutral
|
||||
Actor105: t15
|
||||
Location: 27,59
|
||||
Owner: Neutral
|
||||
Actor106: tc01
|
||||
Location: 20,57
|
||||
Owner: Neutral
|
||||
Actor107: t16
|
||||
Location: 19,58
|
||||
Owner: Neutral
|
||||
Actor108: t13
|
||||
Location: 18,57
|
||||
Owner: Neutral
|
||||
Actor111: tc04
|
||||
Location: 56,102
|
||||
Owner: Neutral
|
||||
Actor112: tc02
|
||||
Location: 58,100
|
||||
Owner: Neutral
|
||||
Actor114: tc05
|
||||
Location: 84,33
|
||||
Owner: Neutral
|
||||
Actor116: atek
|
||||
Location: 26,96
|
||||
Owner: Greece
|
||||
Chronosphere: pdox
|
||||
Location: 27,101
|
||||
Owner: Greece
|
||||
Actor118: pbox
|
||||
Location: 48,75
|
||||
Owner: Greece
|
||||
Actor119: pbox
|
||||
Location: 58,80
|
||||
Owner: Greece
|
||||
Actor120: pbox
|
||||
Location: 34,74
|
||||
Owner: Greece
|
||||
Actor121: pbox
|
||||
Location: 31,74
|
||||
Owner: Greece
|
||||
Actor122: hbox
|
||||
Location: 46,99
|
||||
Owner: Greece
|
||||
Actor123: hbox
|
||||
Location: 26,81
|
||||
Owner: Greece
|
||||
Actor124: hbox
|
||||
Location: 26,93
|
||||
Owner: Greece
|
||||
Actor125: hbox
|
||||
Location: 68,89
|
||||
Owner: Greece
|
||||
Radar4: dome
|
||||
Location: 49,104
|
||||
Owner: Greece
|
||||
Actor127: gap
|
||||
Location: 47,105
|
||||
Owner: Greece
|
||||
Actor128: gap
|
||||
Location: 68,91
|
||||
Owner: Greece
|
||||
Actor129: gun
|
||||
Location: 58,78
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor130: gun
|
||||
Location: 60,80
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor131: gun
|
||||
Location: 50,72
|
||||
Owner: Greece
|
||||
Actor132: gun
|
||||
Location: 46,72
|
||||
Owner: Greece
|
||||
Actor133: gun
|
||||
Location: 72,96
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor134: gun
|
||||
Location: 72,99
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor135: fact
|
||||
Location: 47,84
|
||||
Owner: Greece
|
||||
Actor136: proc
|
||||
Location: 52,90
|
||||
Owner: Greece
|
||||
Actor137: proc
|
||||
Location: 50,96
|
||||
Owner: Greece
|
||||
Actor138: silo
|
||||
Location: 59,93
|
||||
Owner: Greece
|
||||
Actor139: silo
|
||||
Location: 49,97
|
||||
Owner: Greece
|
||||
Actor140: silo
|
||||
Location: 48,97
|
||||
Owner: Greece
|
||||
Actor141: silo
|
||||
Location: 58,93
|
||||
Owner: Greece
|
||||
HPad1: hpad
|
||||
Location: 32,73
|
||||
Owner: Greece
|
||||
HPad4: hpad
|
||||
Location: 55,96
|
||||
Owner: Greece
|
||||
Actor144: apwr
|
||||
Location: 44,86
|
||||
Owner: Greece
|
||||
Actor145: apwr
|
||||
Location: 42,104
|
||||
Owner: Greece
|
||||
Actor146: apwr
|
||||
Location: 43,98
|
||||
Owner: Greece
|
||||
Actor147: apwr
|
||||
Location: 44,92
|
||||
Owner: Greece
|
||||
Actor148: apwr
|
||||
Location: 27,83
|
||||
Owner: Greece
|
||||
Actor149: apwr
|
||||
Location: 50,86
|
||||
Owner: Greece
|
||||
Actor150: apwr
|
||||
Location: 37,104
|
||||
Owner: Greece
|
||||
Actor151: apwr
|
||||
Location: 31,92
|
||||
Owner: Greece
|
||||
GreeceTent2: tent
|
||||
Location: 19,98
|
||||
Owner: Greece
|
||||
GreeceTent1: tent
|
||||
Location: 46,80
|
||||
Owner: Greece
|
||||
Radar1: dome
|
||||
Location: 29,90
|
||||
Owner: Greece
|
||||
Radar2: dome
|
||||
Location: 48,88
|
||||
Owner: Greece
|
||||
Radar3: dome
|
||||
Location: 69,89
|
||||
Owner: Greece
|
||||
HPad2: hpad
|
||||
Location: 56,76
|
||||
Owner: Greece
|
||||
GreeceShipyard: syrd
|
||||
Location: 73,84
|
||||
Owner: Greece
|
||||
GoodGuyShipyard: syrd
|
||||
Location: 32,43
|
||||
Owner: GoodGuy
|
||||
Actor160: brl3
|
||||
Location: 71,87
|
||||
Owner: Greece
|
||||
Actor161: barl
|
||||
Location: 71,86
|
||||
Owner: Greece
|
||||
Actor162: barl
|
||||
Location: 70,87
|
||||
Owner: Greece
|
||||
Actor163: hbox
|
||||
Location: 26,89
|
||||
Owner: Greece
|
||||
HPad3: hpad
|
||||
Location: 61,80
|
||||
Owner: Greece
|
||||
Actor165: gap
|
||||
Location: 24,46
|
||||
Owner: GoodGuy
|
||||
Actor166: gun
|
||||
Location: 27,42
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor167: gun
|
||||
Location: 25,41
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor168: agun
|
||||
Location: 28,45
|
||||
Owner: GoodGuy
|
||||
Actor169: agun
|
||||
Location: 23,42
|
||||
Owner: GoodGuy
|
||||
Actor170: fact
|
||||
Location: 20,42
|
||||
Owner: GoodGuy
|
||||
GoodGuyWarFactory: weap
|
||||
Location: 25,50
|
||||
Owner: GoodGuy
|
||||
Actor172: apwr
|
||||
Location: 25,47
|
||||
Owner: GoodGuy
|
||||
Actor173: apwr
|
||||
Location: 18,46
|
||||
Owner: GoodGuy
|
||||
Actor174: agun
|
||||
Location: 24,50
|
||||
Owner: GoodGuy
|
||||
Actor175: apwr
|
||||
Location: 27,79
|
||||
Owner: Greece
|
||||
GreeceWarFactory: weap
|
||||
Location: 59,85
|
||||
Owner: Greece
|
||||
Actor177: agun
|
||||
Location: 47,101
|
||||
Owner: Greece
|
||||
Actor178: v19
|
||||
Location: 26,78
|
||||
Owner: Greece
|
||||
Actor179: brl3
|
||||
Location: 26,77
|
||||
Owner: Greece
|
||||
Actor180: brl3
|
||||
Location: 54,97
|
||||
Owner: Greece
|
||||
Actor181: barl
|
||||
Location: 53,97
|
||||
Owner: Greece
|
||||
Actor182: v19
|
||||
Location: 54,96
|
||||
Owner: Greece
|
||||
Actor183: brl3
|
||||
Location: 53,96
|
||||
Owner: Greece
|
||||
Actor184: gun
|
||||
Location: 63,78
|
||||
Owner: Greece
|
||||
Actor190: gap
|
||||
Location: 30,88
|
||||
Owner: Greece
|
||||
StartAttack3: 2tnk
|
||||
Location: 75,60
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
StartAttack4: 2tnk
|
||||
Location: 76,62
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
StartAttack5: 2tnk
|
||||
Location: 78,62
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
StartAttack2: arty
|
||||
Location: 80,59
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
StartAttack1: arty
|
||||
Location: 79,58
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
V2A: v2rl
|
||||
Location: 84,20
|
||||
Owner: USSR
|
||||
Facing: 508
|
||||
V2B: v2rl
|
||||
Location: 82,20
|
||||
Owner: USSR
|
||||
Facing: 508
|
||||
Actor199: 4tnk
|
||||
Location: 80,20
|
||||
Owner: USSR
|
||||
Facing: 508
|
||||
Actor200: 4tnk
|
||||
Location: 86,20
|
||||
Owner: USSR
|
||||
Facing: 508
|
||||
Actor201: 3tnk
|
||||
Location: 81,21
|
||||
Owner: USSR
|
||||
Facing: 508
|
||||
Actor202: 3tnk
|
||||
Location: 85,21
|
||||
Owner: USSR
|
||||
Facing: 508
|
||||
Actor203: 2tnk
|
||||
Location: 28,41
|
||||
Owner: Greece
|
||||
Actor204: 2tnk
|
||||
Location: 30,41
|
||||
Owner: Greece
|
||||
Actor205: 2tnk
|
||||
Location: 24,40
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor206: 2tnk
|
||||
Location: 26,40
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor207: arty
|
||||
Location: 29,42
|
||||
Owner: Greece
|
||||
Actor208: arty
|
||||
Location: 24,41
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
OreAttack3: 2tnk
|
||||
Location: 39,16
|
||||
Owner: GoodGuy
|
||||
Facing: 764
|
||||
OreAttack5: 2tnk
|
||||
Location: 40,17
|
||||
Owner: GoodGuy
|
||||
Facing: 764
|
||||
OreAttack4: 2tnk
|
||||
Location: 41,16
|
||||
Owner: GoodGuy
|
||||
Facing: 764
|
||||
OreAttack2: 2tnk
|
||||
Location: 40,15
|
||||
Owner: GoodGuy
|
||||
Facing: 764
|
||||
OreAttack6: arty
|
||||
Location: 40,18
|
||||
Owner: GoodGuy
|
||||
Facing: 764
|
||||
OreAttack1: arty
|
||||
Location: 40,14
|
||||
Owner: GoodGuy
|
||||
Facing: 764
|
||||
Actor215: 2tnk
|
||||
Location: 68,97
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor216: 2tnk
|
||||
Location: 68,98
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor217: 2tnk
|
||||
Location: 67,96
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor218: 2tnk
|
||||
Location: 67,99
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor221: e3
|
||||
Location: 67,91
|
||||
Owner: Greece
|
||||
SubCell: 1
|
||||
Actor222: e3
|
||||
Location: 67,89
|
||||
Owner: Greece
|
||||
SubCell: 0
|
||||
Actor223: e3
|
||||
Location: 71,89
|
||||
Owner: Greece
|
||||
SubCell: 1
|
||||
Actor224: e3
|
||||
Location: 56,93
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor225: e3
|
||||
Location: 51,106
|
||||
Owner: Greece
|
||||
SubCell: 1
|
||||
Actor226: e3
|
||||
Location: 48,106
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor227: e3
|
||||
Location: 55,75
|
||||
Owner: Greece
|
||||
SubCell: 0
|
||||
Actor228: e3
|
||||
Location: 55,76
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor229: e3
|
||||
Location: 63,80
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor230: e3
|
||||
Location: 63,81
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor231: e3
|
||||
Location: 30,75
|
||||
Owner: Greece
|
||||
SubCell: 4
|
||||
Actor232: e3
|
||||
Location: 31,76
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor233: e3
|
||||
Location: 35,75
|
||||
Owner: Greece
|
||||
SubCell: 3
|
||||
Actor234: e3
|
||||
Location: 35,76
|
||||
Owner: Greece
|
||||
SubCell: 1
|
||||
Actor235: e3
|
||||
Location: 46,79
|
||||
Owner: Greece
|
||||
SubCell: 3
|
||||
Actor236: e3
|
||||
Location: 47,79
|
||||
Owner: Greece
|
||||
SubCell: 3
|
||||
Actor237: e3
|
||||
Location: 45,85
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor238: e3
|
||||
Location: 45,85
|
||||
Owner: Greece
|
||||
SubCell: 1
|
||||
Actor239: e3
|
||||
Location: 50,85
|
||||
Owner: Greece
|
||||
SubCell: 1
|
||||
Actor240: e3
|
||||
Location: 51,85
|
||||
Owner: Greece
|
||||
SubCell: 1
|
||||
Actor241: e3
|
||||
Location: 47,88
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor242: e3
|
||||
Location: 50,89
|
||||
Owner: Greece
|
||||
SubCell: 2
|
||||
Actor243: e3
|
||||
Location: 28,90
|
||||
Owner: Greece
|
||||
SubCell: 3
|
||||
Actor244: e3
|
||||
Location: 28,92
|
||||
Owner: Greece
|
||||
SubCell: 1
|
||||
Actor245: e3
|
||||
Location: 32,91
|
||||
Owner: Greece
|
||||
SubCell: 0
|
||||
Actor246: dd
|
||||
Location: 92,101
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor247: dd
|
||||
Location: 38,24
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor248: pt
|
||||
Location: 92,97
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor249: pt
|
||||
Location: 97,101
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor250: pt
|
||||
Location: 40,27
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor251: pt
|
||||
Location: 41,21
|
||||
Owner: Greece
|
||||
Facing: 764
|
||||
Actor252: pt
|
||||
Location: 82,82
|
||||
Owner: Greece
|
||||
Facing: 508
|
||||
Actor253: pt
|
||||
Location: 82,87
|
||||
Owner: Greece
|
||||
Actor254: dd
|
||||
Location: 80,81
|
||||
Owner: Greece
|
||||
Facing: 636
|
||||
Actor255: dd
|
||||
Location: 80,87
|
||||
Owner: Greece
|
||||
Facing: 892
|
||||
Actor256: dd
|
||||
Location: 35,41
|
||||
Owner: GoodGuy
|
||||
Actor257: dd
|
||||
Location: 38,46
|
||||
Owner: GoodGuy
|
||||
Facing: 892
|
||||
Actor258: pt
|
||||
Location: 36,40
|
||||
Owner: GoodGuy
|
||||
Actor259: pt
|
||||
Location: 39,44
|
||||
Owner: GoodGuy
|
||||
Facing: 892
|
||||
Actor260: pt
|
||||
Location: 35,39
|
||||
Owner: GoodGuy
|
||||
Actor273: fix
|
||||
Owner: Greece
|
||||
Location: 38,79
|
||||
Jeep2: jeep
|
||||
Owner: Greece
|
||||
Location: 25,91
|
||||
Facing: 384
|
||||
Jeep1: jeep
|
||||
Owner: Greece
|
||||
Location: 24,91
|
||||
Facing: 384
|
||||
Actor277: arty
|
||||
Owner: Greece
|
||||
Location: 31,88
|
||||
Facing: 951
|
||||
Actor278: arty
|
||||
Owner: Greece
|
||||
Location: 34,94
|
||||
Facing: 919
|
||||
Actor279: arty
|
||||
Owner: Greece
|
||||
Location: 45,101
|
||||
Facing: 1023
|
||||
Actor280: arty
|
||||
Owner: Greece
|
||||
Location: 50,102
|
||||
Facing: 991
|
||||
Actor272: mine
|
||||
Owner: Neutral
|
||||
Location: 99,23
|
||||
Actor274: mine
|
||||
Owner: Neutral
|
||||
Location: 64,21
|
||||
Actor275: mine
|
||||
Owner: Neutral
|
||||
Location: 84,74
|
||||
Actor276: mine
|
||||
Owner: Neutral
|
||||
Location: 84,92
|
||||
DefaultCameraPosition: waypoint
|
||||
Location: 83,20
|
||||
Owner: Neutral
|
||||
MCVEntry: waypoint
|
||||
Location: 83,14
|
||||
Owner: Neutral
|
||||
EastWaterEntry: waypoint
|
||||
Location: 91,106
|
||||
Owner: Neutral
|
||||
EastBeach1: waypoint
|
||||
Location: 102,51
|
||||
Owner: Neutral
|
||||
EastBeach2: waypoint
|
||||
Location: 103,19
|
||||
Owner: Neutral
|
||||
EastBeach3: waypoint
|
||||
Location: 90,73
|
||||
Owner: Neutral
|
||||
WestWaterEntry: waypoint
|
||||
Location: 18,22
|
||||
Owner: Neutral
|
||||
WestBeach1: waypoint
|
||||
Location: 30,29
|
||||
Owner: Neutral
|
||||
WestBeach2: waypoint
|
||||
Location: 36,17
|
||||
Owner: Neutral
|
||||
JeepWaypoint1: waypoint
|
||||
Location: 23,47
|
||||
Owner: Neutral
|
||||
JeepWaypoint2: waypoint
|
||||
Location: 25,91
|
||||
Owner: Neutral
|
||||
ChinookLZ: waypoint
|
||||
Location: 51,16
|
||||
Owner: Neutral
|
||||
BridgeAttackProxy: waypoint
|
||||
Location: 78,60
|
||||
Owner: Neutral
|
||||
ChronoshiftPoint: waypoint
|
||||
Location: 32,101
|
||||
Owner: Neutral
|
||||
WarFactoryRally: waypoint
|
||||
Location: 56,82
|
||||
Owner: Neutral
|
||||
CruiserStop: waypoint
|
||||
Location: 52,25
|
||||
Owner: Neutral
|
||||
|
||||
Rules: ra|rules/campaign-rules.yaml, ra|rules/campaign-tooltips.yaml, ra|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
Translations: ra|languages/lua/en.ftl, ra|languages/difficulties/en.ftl
|
||||
79
mods/ra/maps/soviet-13b/rules.yaml
Normal file
79
mods/ra/maps/soviet-13b/rules.yaml
Normal file
@@ -0,0 +1,79 @@
|
||||
World:
|
||||
LuaScript:
|
||||
Scripts: campaign.lua, soviet13b.lua, soviet13b-AI.lua, utils.lua
|
||||
MissionData:
|
||||
BriefingVideo: soviet13.vqa
|
||||
WinVideo: sovtstar.vqa
|
||||
LossVideo: allymorf.vqa
|
||||
StartVideo: mtnkfact.vqa
|
||||
Briefing: We have another chance to capture the Chronosphere. Take out the Radar Domes to cut the link between them and the Chronosphere. Then capture it!
|
||||
ScriptLobbyDropdown@difficulty:
|
||||
ID: difficulty
|
||||
Label: dropdown-difficulty.label
|
||||
Description: dropdown-difficulty.description
|
||||
Values:
|
||||
easy: options-difficulty.easy
|
||||
normal: options-difficulty.normal
|
||||
hard: options-difficulty.hard
|
||||
Default: normal
|
||||
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 10000
|
||||
|
||||
AFLD:
|
||||
AirstrikePower@parabombs:
|
||||
Prerequisites: aircraft.soviet
|
||||
ParatroopersPower@paratroopers:
|
||||
DropItems: E1,E1,E1,E2,E2
|
||||
|
||||
PDOX:
|
||||
Power:
|
||||
Amount: 0
|
||||
-WithColoredOverlay@IDISABLE:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
ATEK:
|
||||
GpsPower:
|
||||
DisplayTimerRelationships: Ally
|
||||
|
||||
MSLO:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
MCV:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
MECH:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
IRON:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
QTNK:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
E7:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
E7.noautotarget:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
E3:
|
||||
Buildable:
|
||||
Prerequisites: ~tent
|
||||
|
||||
MSUB:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
THF:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
170
mods/ra/maps/soviet-13b/soviet13b-AI.lua
Normal file
170
mods/ra/maps/soviet-13b/soviet13b-AI.lua
Normal file
@@ -0,0 +1,170 @@
|
||||
--[[
|
||||
Copyright (c) The OpenRA Developers and Contributors
|
||||
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.
|
||||
]]
|
||||
WTransWays =
|
||||
{
|
||||
{ EastWaterEntry.Location, EastBeach1.Location },
|
||||
{ EastWaterEntry.Location, EastBeach2.Location },
|
||||
{ EastWaterEntry.Location, EastBeach3.Location },
|
||||
{ WestWaterEntry.Location, WestBeach1.Location },
|
||||
{ WestWaterEntry.Location, WestBeach2.Location }
|
||||
}
|
||||
|
||||
WTransUnits =
|
||||
{
|
||||
hard = { { "2tnk", "2tnk", "e3", "e3", "e3" }, { "2tnk", "2tnk", "2tnk", "2tnk" } },
|
||||
normal = { { "2tnk", "1tnk", "e3", "e3", "jeep" }, { "2tnk", "2tnk", "1tnk", "jeep" } },
|
||||
easy = { { "2tnk", "e1", "e1", "e3", "e3" }, { "1tnk", "1tnk", "jeep", "jeep" } }
|
||||
}
|
||||
|
||||
WTransDelays =
|
||||
{
|
||||
easy = DateTime.Minutes(5),
|
||||
normal = DateTime.Minutes(4),
|
||||
hard = DateTime.Minutes(3)
|
||||
}
|
||||
|
||||
AttackGroup = { }
|
||||
AttackGroupSize = 8
|
||||
|
||||
ProductionInterval =
|
||||
{
|
||||
easy = DateTime.Seconds(20),
|
||||
normal = DateTime.Seconds(14),
|
||||
hard = DateTime.Seconds(8)
|
||||
}
|
||||
|
||||
AlliedInfantry = { "e1", "e3" }
|
||||
AlliedVehiclesUpgradeDelay = DateTime.Minutes(8)
|
||||
AlliedVehicleType = "Normal"
|
||||
AlliedVehicles =
|
||||
{
|
||||
Normal = { "1tnk", "2tnk", "2tnk" },
|
||||
Upgraded = { "2tnk", "2tnk", "arty" }
|
||||
}
|
||||
|
||||
WTransWaves = function()
|
||||
local way = Utils.Random(WTransWays)
|
||||
local units = Utils.Random(WTransUnits)
|
||||
local attackUnits = Reinforcements.ReinforceWithTransport(Greece, "lst", units , way, { way[2], way[1] })[2]
|
||||
Utils.Do(attackUnits, function(a)
|
||||
Trigger.OnAddedToWorld(a, function()
|
||||
IdleHunt(a)
|
||||
end)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(WTransDelay, WTransWaves)
|
||||
end
|
||||
|
||||
SendAttackGroup = function()
|
||||
if #AttackGroup < AttackGroupSize then
|
||||
return
|
||||
end
|
||||
|
||||
Utils.Do(AttackGroup, IdleHunt)
|
||||
|
||||
AttackGroup = { }
|
||||
end
|
||||
|
||||
ProduceInfantry = function()
|
||||
if (GreeceTent1.IsDead or GreeceTent1.Owner ~= Greece) and (GreeceTent2.IsDead or GreeceTent2.Owner ~= Greece) then
|
||||
return
|
||||
end
|
||||
|
||||
Greece.Build({ Utils.Random(AlliedInfantry) }, function(units)
|
||||
table.insert(AttackGroup, units[1])
|
||||
SendAttackGroup()
|
||||
Trigger.AfterDelay(ProductionInterval[Difficulty], ProduceInfantry)
|
||||
end)
|
||||
end
|
||||
|
||||
ProduceVehicles = function()
|
||||
if GreeceWarFactory.IsDead or GreeceWarFactory.Owner ~= Greece then
|
||||
return
|
||||
end
|
||||
|
||||
Greece.Build({ Utils.Random(AlliedVehicles[AlliedVehicleType]) }, function(units)
|
||||
table.insert(AttackGroup, units[1])
|
||||
SendAttackGroup()
|
||||
Trigger.AfterDelay(ProductionInterval[Difficulty], ProduceVehicles)
|
||||
end)
|
||||
end
|
||||
|
||||
AlliedAircraftType = { "heli" }
|
||||
Longbows = { }
|
||||
|
||||
AlliedAircraft = function()
|
||||
if (HPad1.IsDead or HPad1.Owner ~= Greece) and (HPad2.IsDead or HPad2.Owner ~= Greece) and (HPad3.IsDead or HPad3.Owner ~= Greece) and (HPad4.IsDead or HPad4.Owner ~= Greece) then
|
||||
return
|
||||
end
|
||||
|
||||
Greece.Build(AlliedAircraftType, function(units)
|
||||
local longbow = units[1]
|
||||
Longbows[#Longbows + 1] = longbow
|
||||
|
||||
Trigger.OnKilled(longbow, AlliedAircraft)
|
||||
|
||||
local alive = Utils.Where(Longbows, function(y) return not y.IsDead end)
|
||||
if #alive < 2 then
|
||||
Trigger.AfterDelay(DateTime.Seconds(75), AlliedAircraft)
|
||||
end
|
||||
|
||||
InitializeAttackAircraft(longbow, USSR)
|
||||
end)
|
||||
end
|
||||
|
||||
SendCruiser = function()
|
||||
if GoodGuyShipyard.IsDead or GoodGuyShipyard.Owner ~= GoodGuy then
|
||||
return
|
||||
end
|
||||
|
||||
local boat = Reinforcements.Reinforce(Greece, { "ca" }, { WestWaterEntry.Location })
|
||||
Utils.Do(boat, function(ca)
|
||||
ca.Move(CruiserStop.Location)
|
||||
Trigger.OnKilled(ca, function()
|
||||
Trigger.AfterDelay(DateTime.Minutes(6), SendCruiser)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
ChinookChalk = { "e1", "e1", "e1", "e3", "e3", "e3", "e3", "e3" }
|
||||
ChinookPath = { WestWaterEntry.Location, ChinookLZ.Location }
|
||||
|
||||
SendChinook = function()
|
||||
if (HPad1.IsDead or HPad1.Owner ~= Greece) and (HPad2.IsDead or HPad2.Owner ~= Greece) and (HPad3.IsDead or HPad3.Owner ~= Greece) and (HPad4.IsDead or HPad4.Owner ~= Greece) then
|
||||
return
|
||||
end
|
||||
|
||||
local chalk = Reinforcements.ReinforceWithTransport(Greece, "tran", ChinookChalk , ChinookPath, { ChinookPath[1] })[2]
|
||||
Utils.Do(chalk, function(unit)
|
||||
Trigger.OnAddedToWorld(unit, IdleHunt)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendChinook)
|
||||
end
|
||||
|
||||
ActivateAI = function()
|
||||
WTransUnits = WTransUnits[Difficulty]
|
||||
WTransDelay = WTransDelays[Difficulty]
|
||||
|
||||
local buildings = Utils.Where(Map.ActorsInWorld, function(self) return self.Owner == Greece and self.HasProperty("StartBuildingRepairs") end)
|
||||
Utils.Do(buildings, function(actor)
|
||||
Trigger.OnDamaged(actor, function(building)
|
||||
if building.Owner == Greece and building.Health < building.MaxHealth * 3/4 then
|
||||
building.StartBuildingRepairs()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(AlliedVehiclesUpgradeDelay, function() AlliedVehicleType = "Upgraded" end)
|
||||
ProduceInfantry()
|
||||
Trigger.AfterDelay(DateTime.Minutes(3), ProduceVehicles)
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), AlliedAircraft)
|
||||
Trigger.AfterDelay(DateTime.Minutes(6), WTransWaves)
|
||||
Trigger.AfterDelay(DateTime.Minutes(10), SendCruiser)
|
||||
end
|
||||
125
mods/ra/maps/soviet-13b/soviet13b.lua
Normal file
125
mods/ra/maps/soviet-13b/soviet13b.lua
Normal file
@@ -0,0 +1,125 @@
|
||||
--[[
|
||||
Copyright (c) The OpenRA Developers and Contributors
|
||||
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.
|
||||
]]
|
||||
Jeeps = { Jeep1, Jeep2 }
|
||||
JeepWaypoints = { JeepWaypoint1.Location, JeepWaypoint2.Location }
|
||||
OreAttackers = { OreAttack1, OreAttack2, OreAttack3, OreAttack4, OreAttack5, OreAttack6 }
|
||||
RadarSites = { Radar1, Radar2, Radar3, Radar4 }
|
||||
StartAttack = { StartAttack1, StartAttack2, StartAttack3, StartAttack4, StartAttack5 }
|
||||
ChronoDemolitionTrigger = { CPos.New(36,96), CPos.New(37,96), CPos.New(37,97), CPos.New(38,97), CPos.New(38,98), CPos.New(39,98) }
|
||||
OreAttackFootprintTrigger = { CPos.New(57,20), CPos.New(57,19), CPos.New(57,18), CPos.New(57,17), CPos.New(57,16), CPos.New(57,15), CPos.New(57,14) }
|
||||
|
||||
Start = function()
|
||||
Reinforcements.Reinforce(USSR, { "mcv" }, { MCVEntry.Location, DefaultCameraPosition.Location }, 5)
|
||||
|
||||
Utils.Do(Jeeps, function(jeep)
|
||||
jeep.Patrol(JeepWaypoints, true, 125)
|
||||
end)
|
||||
|
||||
Utils.Do(StartAttack, function(a)
|
||||
IdleHunt(a)
|
||||
end)
|
||||
|
||||
ChronoCam = Actor.Create("camera", true, { Owner = USSR, Location = Chronosphere.Location})
|
||||
end
|
||||
|
||||
MissionTriggers = function()
|
||||
Trigger.OnAllKilled(RadarSites, function()
|
||||
USSR.MarkCompletedObjective(TakeDownRadar)
|
||||
ChronoshiftAlliedUnits()
|
||||
end)
|
||||
|
||||
Trigger.OnCapture(Chronosphere, function()
|
||||
if not USSR.IsObjectiveCompleted(TakeDownRadar) then
|
||||
Media.DisplayMessage(UserInterface.Translate("chrono-trap-triggered"), UserInterface.Translate("headquarters"))
|
||||
Chronosphere.Kill()
|
||||
else
|
||||
USSR.MarkCompletedObjective(CaptureChronosphere)
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnKilled(Chronosphere, function()
|
||||
USSR.MarkFailedObjective(CaptureChronosphere)
|
||||
end)
|
||||
|
||||
local chronoTriggered
|
||||
Trigger.OnEnteredFootprint(ChronoDemolitionTrigger, function(actor, id)
|
||||
if actor.Owner == USSR and not chronoTriggered and not USSR.IsObjectiveCompleted(TakeDownRadar) then
|
||||
Trigger.RemoveFootprintTrigger(id)
|
||||
Media.DisplayMessage(UserInterface.Translate("chrono-trap-triggered"), UserInterface.Translate("headquarters"))
|
||||
chronoTriggered = true
|
||||
Chronosphere.Kill()
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnEnteredProximityTrigger(ChinookLZ.CenterPosition, WDist.FromCells(5), function(actor, id)
|
||||
if actor.Owner == USSR and actor.Type == "harv" then
|
||||
Trigger.RemoveProximityTrigger(id)
|
||||
SendChinook()
|
||||
end
|
||||
end)
|
||||
|
||||
local oreAttackTriggered
|
||||
Trigger.OnEnteredFootprint(OreAttackFootprintTrigger, function(actor, id)
|
||||
if actor.Owner == USSR and not oreAttackTriggered then
|
||||
Trigger.RemoveProximityTrigger(id)
|
||||
oreAttackTrigger = true
|
||||
|
||||
Utils.Do(OreAttackers, function(a)
|
||||
if not a.IsDead then
|
||||
IdleHunt(a)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
ChronoshiftAlliedUnits = function()
|
||||
if Chronosphere.IsDead then
|
||||
return
|
||||
end
|
||||
|
||||
local cells = Utils.ExpandFootprint({ ChronoshiftPoint.Location }, false)
|
||||
local units = { }
|
||||
for i = 1, #cells do
|
||||
local unit = Actor.Create("2tnk", true, { Owner = Greece, Facing = Angle.North })
|
||||
units[unit] = cells[i]
|
||||
IdleHunt(unit)
|
||||
end
|
||||
Chronosphere.Chronoshift(units)
|
||||
end
|
||||
|
||||
Tick = function()
|
||||
Greece.Cash = 20000
|
||||
|
||||
if USSR.HasNoRequiredUnits() then
|
||||
Greece.MarkCompletedObjective(AlliesObjective)
|
||||
end
|
||||
end
|
||||
|
||||
WorldLoaded = function()
|
||||
USSR = Player.GetPlayer("USSR")
|
||||
Greece = Player.GetPlayer("Greece")
|
||||
GoodGuy = Player.GetPlayer("GoodGuy")
|
||||
|
||||
InitObjectives(USSR)
|
||||
|
||||
AlliesObjective = AddPrimaryObjective(Greece, "")
|
||||
TakeDownRadar = AddPrimaryObjective(USSR, "destroy-allied-radar-sites")
|
||||
CaptureChronosphere = AddPrimaryObjective(USSR, "capture-the-chronosphere")
|
||||
|
||||
Camera.Position = DefaultCameraPosition.CenterPosition
|
||||
Start()
|
||||
MissionTriggers()
|
||||
ActivateAI()
|
||||
GreeceWarFactory.RallyPoint = WarFactoryRally.Location
|
||||
if Difficulty == "hard" then
|
||||
V2A.Destroy()
|
||||
V2B.Destroy()
|
||||
end
|
||||
end
|
||||
@@ -33,6 +33,7 @@ Soviet Campaign:
|
||||
soviet-11a
|
||||
soviet-11b
|
||||
soviet-13a
|
||||
soviet-13b
|
||||
Counterstrike Allied Missions:
|
||||
sarin-gas-1-crackdown
|
||||
sarin-gas-2-down-under
|
||||
|
||||
Reference in New Issue
Block a user