Compare commits

...

33 Commits

Author SHA1 Message Date
Punsho
00ddf82e85 RA Balance patch 2020-03-29 21:51:52 +02:00
Paul Chote
c10ebb455b Fix actors with no footprint leaving stale data when deleted. 2020-03-29 21:08:25 +02:00
Paul Chote
d999a0534b Move selectableActor check inside InputOverridesSelection. 2020-03-29 13:26:05 +02:00
Ivaylo Draganov
02454fb764 Adjust spacing and width in editor category dropdown 2020-03-28 20:41:31 +00:00
abcdefg30
df81857abe Adjust the map visibility panel height 2020-03-28 20:41:23 +00:00
abcdefg30
ae0745b542 Start with randomized wind strength 2020-03-28 19:47:21 +01:00
Paul Chote
89b5e34320 Fix and simplify WeatherOverlay:
- Fix rendering issues
- Track particles in world pixels instead of screen pixels
- Removed un/underused fade in/out support
- Update wind once per tick instead of once per particle
- Make Particle struct readonly
2020-03-28 19:47:19 +01:00
Paul Chote
47cc6eda7e Make the right edge of the airfield transitable. 2020-03-28 19:14:43 +01:00
Paul Chote
6da23ed3d7 Fix minelayers leaking enemy mine positions through the fog. 2020-03-28 18:49:24 +01:00
Paul Chote
3ee4613a98 Fix SpriteEffect updating twice in the first tick. 2020-03-28 17:18:12 +01:00
Paul Chote
616bfbe553 Fix and simplify ScrollPanelWidget thumb rect calculation. 2020-03-26 16:53:09 +01:00
Ivaylo Draganov
ecbcc9c8bb Align lobby bits in the player tab in TD 2020-03-25 13:02:34 +01:00
Paul Chote
068ce9b215 Restore ability to configure RMB orders + RMB panning. 2020-03-25 12:37:43 +01:00
Paul Chote
170bcd500c Remove text caching from CncLoadScreen.
We have repeatedly failed at invalidating these
cached values when things change, so the small perf
win is not worth the hassle.
2020-03-25 12:21:15 +01:00
Paul Chote
6efb40c9a6 Fix detection circle line rendering. 2020-03-24 20:59:58 +01:00
Ivaylo Draganov
3c92c2d789 Adjust the stroke of the muted indicator glyph 2020-03-24 16:57:48 +01:00
Paul Chote
f823d20a86 Replace deprecated native OpenAL with OpenAL Soft on macOS. 2020-03-23 11:17:46 +01:00
Paul Chote
ca4b97cd03 Remove invalid caching from GCOT. 2020-03-23 11:17:08 +01:00
Matthias Mailänder
8b5e322891 Remove .lua scripts from the .NET solution file. 2020-03-21 21:24:03 +01:00
unknown
70e1c4bb0c Add gdi09ea 2020-03-21 21:11:14 +01:00
abcdefg30
8690ad4e19 Add support for destroying enemy carryalls 2020-03-21 11:00:39 +01:00
abcdefg30
a01233c3df Add support for an announcement function for carryall reinforcements 2020-03-21 11:00:14 +01:00
abcdefg30
d0d55b3fc1 Add Ordos06a 2020-03-21 10:59:59 +01:00
abcdefg30
2a26a07ce6 Let VS2019 remove a duplicate line from the solution 2020-03-21 10:59:45 +01:00
abcdefg30
65e088204f Fix the settings tooltip container being overwritten ingame 2020-03-20 16:06:46 +01:00
Michael Silber
77e38ceea9 Add gdi08a 2020-03-17 19:04:53 +01:00
Paul Chote
989d1475b9 Update macOS launcher to fix "View Logs" button. 2020-03-16 19:17:12 +00:00
Paul Chote
580a96cda4 Cache CandidateMovementCells within the same tick. 2020-03-12 17:07:45 +01:00
Paul Chote
5a8964aabe Fix infantry switching subcells and blocking eachother while moving. 2020-03-11 15:40:58 +01:00
Paul Chote
c9dcf305c9 Fix FreeSubCell ignoring preferred subcell requests. 2020-03-11 15:40:56 +01:00
Paul Chote
5489d6909c Fix pathing across transit-only cells. 2020-03-11 15:40:54 +01:00
Paul Chote
85412a6d98 Fix variable naming in Locomotor. 2020-03-11 15:40:53 +01:00
abcdefg30
b69806123a Fix aircraft not taking off properly 2020-03-08 17:19:56 +01:00
74 changed files with 4055 additions and 558 deletions

View File

@@ -19,6 +19,11 @@ namespace OpenRA.Graphics
[Flags]
public enum ScrollDirection { None = 0, Up = 1, Left = 2, Down = 4, Right = 8 }
public interface INotifyViewportZoomExtentsChanged
{
void ViewportZoomExtentsChanged(float minZoom, float maxZoom);
}
public static class ViewportExts
{
public static bool Includes(this ScrollDirection d, ScrollDirection s)
@@ -237,6 +242,9 @@ namespace OpenRA.Graphics
Zoom = minZoom;
else
Zoom = Zoom.Clamp(minZoom, maxZoom);
foreach (var t in worldRenderer.World.WorldActor.TraitsImplementing<INotifyViewportZoomExtentsChanged>())
t.ViewportZoomExtentsChanged(minZoom, maxZoom);
}
public CPos ViewToWorld(int2 view)

View File

@@ -96,7 +96,7 @@ namespace OpenRA.Orders
public virtual bool InputOverridesSelection(World world, int2 xy, MouseInput mi)
{
var actor = world.ScreenMap.ActorsAtMouse(xy)
.Where(a => !a.Actor.IsDead)
.Where(a => !a.Actor.IsDead && a.Actor.Info.HasTraitInfo<SelectableInfo>() && (a.Actor.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(a.Actor)))
.WithHighestSelectionPriority(xy, mi.Modifiers);
if (actor == null)

View File

@@ -228,7 +228,8 @@ namespace OpenRA
public int MouseScrollDeadzone = 8;
public bool UseClassicMouseStyle = false;
public bool ClassicMouseMiddleScroll = false;
public bool UseAlternateScrollButton = false;
public StatusBarsType StatusBars = StatusBarsType.Standard;
public TargetLinesType TargetLines = TargetLinesType.Manual;
public bool UsePlayerStanceColors = false;

View File

@@ -108,7 +108,7 @@ namespace OpenRA.Mods.Cnc.Activities
{
var positionable = (IPositionable)movement;
minefield.RemoveAll(c => self.World.ActorMap.GetActorsAt(c)
.Any(a => a.Info.Name == minelayer.Info.Mine.ToLowerInvariant()) ||
.Any(a => a.Info.Name == minelayer.Info.Mine.ToLowerInvariant() && a.CanBeViewedByPlayer(self.Owner)) ||
(!positionable.CanEnterCell(c, null, BlockedByActor.Immovable) && !self.World.FogObscures(c)));
}
}

View File

@@ -25,15 +25,11 @@ namespace OpenRA.Mods.Cnc
Sprite[] border;
float2 nodPos, gdiPos, evaPos;
Rectangle bounds;
SpriteFont loadingFont, versionFont;
string loadingText, versionText;
float2 loadingPos, versionPos;
string versionText;
Sheet lastSheet;
int lastDensity;
Size lastResolution;
IReadOnlyDictionary<string, SpriteFont> lastFonts;
public override void Init(ModData modData, Dictionary<string, string> info)
{
@@ -82,20 +78,6 @@ namespace OpenRA.Mods.Cnc
var barY = bounds.Height - 78;
// The fonts dictionary may change when switching between the mod and content installer
if (r.Fonts != lastFonts)
{
lastFonts = r.Fonts;
loadingFont = lastFonts["BigBold"];
loadingText = Info["Text"];
loadingPos = new float2((bounds.Width - loadingFont.Measure(loadingText).X) / 2, barY);
versionFont = lastFonts["Regular"];
var versionSize = versionFont.Measure(versionText);
versionPos = new float2(bounds.Width - 107 - versionSize.X / 2, 115 - versionSize.Y / 2);
}
loadTick = ++loadTick % 8;
r.RgbaSpriteRenderer.DrawSprite(gdiLogo, gdiPos);
@@ -104,11 +86,18 @@ namespace OpenRA.Mods.Cnc
WidgetUtils.DrawPanel(bounds, border);
if (loadingFont != null)
if (r.Fonts != null)
{
var loadingFont = r.Fonts["BigBold"];
var loadingText = Info["Text"];
var loadingPos = new float2((bounds.Width - loadingFont.Measure(loadingText).X) / 2, barY);
loadingFont.DrawText(loadingText, loadingPos, Color.Gray);
if (versionFont != null)
var versionFont = r.Fonts["Regular"];
var versionSize = versionFont.Measure(versionText);
var versionPos = new float2(bounds.Width - 107 - versionSize.X / 2, 115 - versionSize.Y / 2);
versionFont.DrawTextWithContrast(versionText, versionPos, Color.White, Color.Black, 2);
}
for (var i = 0; i <= 8; i++)
{

View File

@@ -305,7 +305,7 @@ namespace OpenRA.Mods.Common.Activities
var newCell = path[path.Count - 1];
path.RemoveAt(path.Count - 1);
return Pair.New(newCell, mobile.GetAvailableSubCell(nextCell, SubCell.Any, ignoreActor));
return Pair.New(newCell, mobile.GetAvailableSubCell(nextCell, mobile.FromSubCell, ignoreActor));
}
else if (mobile.IsBlocking)
{
@@ -316,7 +316,7 @@ namespace OpenRA.Mods.Common.Activities
if ((nextCell - newCell).Value.LengthSquared > 2)
path.Add(mobile.ToCell);
return Pair.New(newCell.Value, mobile.GetAvailableSubCell(newCell.Value, SubCell.Any, ignoreActor));
return Pair.New(newCell.Value, mobile.GetAvailableSubCell(newCell.Value, mobile.FromSubCell, ignoreActor));
}
}
@@ -326,7 +326,7 @@ namespace OpenRA.Mods.Common.Activities
hasWaited = false;
path.RemoveAt(path.Count - 1);
return Pair.New(nextCell, mobile.GetAvailableSubCell(nextCell, SubCell.Any, ignoreActor));
return Pair.New(nextCell, mobile.GetAvailableSubCell(nextCell, mobile.FromSubCell, ignoreActor));
}
protected override void OnLastRun(Actor self)

View File

@@ -9,6 +9,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Activities;
@@ -119,15 +120,23 @@ namespace OpenRA.Mods.Common.Activities
return TickChild(self);
}
List<CPos> searchCells = new List<CPos>();
int searchCellsTick = -1;
List<CPos> CalculatePathToTarget(Actor self, BlockedByActor check)
{
var targetCells = CandidateMovementCells(self);
var searchCells = new List<CPos>();
var loc = self.Location;
foreach (var cell in targetCells)
if (domainIndex.IsPassable(loc, cell, Mobile.Info.LocomotorInfo) && Mobile.CanEnterCell(cell))
searchCells.Add(cell);
// PERF: Assume that CandidateMovementCells doesn't change within a tick to avoid repeated queries
// when Move enumerates different BlockedByActor values
if (searchCellsTick != self.World.WorldTick)
{
searchCells.Clear();
searchCellsTick = self.World.WorldTick;
foreach (var cell in CandidateMovementCells(self))
if (domainIndex.IsPassable(loc, cell, Mobile.Info.LocomotorInfo) && Mobile.CanEnterCell(cell))
searchCells.Add(cell);
}
if (!searchCells.Any())
return NoPath;

View File

@@ -62,16 +62,18 @@ namespace OpenRA.Mods.Common.Effects
world.ScreenMap.Add(this, pos, anim.Image);
initialized = true;
}
else
{
anim.Tick();
anim.Tick();
pos = posFunc();
world.ScreenMap.Update(this, pos, anim.Image);
pos = posFunc();
world.ScreenMap.Update(this, pos, anim.Image);
}
}
public IEnumerable<IRenderable> Render(WorldRenderer wr)
{
if (!visibleThroughFog && world.FogObscures(pos))
if (!initialized || (!visibleThroughFog && world.FogObscures(pos)))
return SpriteRenderable.None;
return anim.Render(pos, wr.Palette(palette));

View File

@@ -66,18 +66,17 @@ namespace OpenRA.Mods.Common.Graphics
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
public void Render(WorldRenderer wr)
{
var wcr = Game.Renderer.WorldRgbaColorRenderer;
var center = wr.Screen3DPosition(centerPosition);
var cr = Game.Renderer.RgbaColorRenderer;
var center = wr.Viewport.WorldToViewPx(wr.Screen3DPosition(centerPosition));
for (var i = 0; i < trailCount; i++)
{
var angle = trailAngle - new WAngle(i * (trailSeparation.Angle <= 512 ? 1 : -1));
var length = radius.Length * new WVec(angle.Cos(), angle.Sin(), 0) / 1024;
var end = wr.Screen3DPosition(centerPosition + length);
var end = wr.Viewport.WorldToViewPx(wr.Screen3DPosition(centerPosition + length));
var alpha = color.A - i * color.A / trailCount;
wcr.DrawLine(center, end, 3, Color.FromArgb(alpha, contrastColor));
wcr.DrawLine(center, end, 1, Color.FromArgb(alpha, color));
cr.DrawLine(center, end, 3, Color.FromArgb(alpha, contrastColor));
cr.DrawLine(center, end, 1, Color.FromArgb(alpha, color));
}
RangeCircleAnnotationRenderable.DrawRangeCircle(wr, centerPosition, radius, 1, color, 3, contrastColor);

View File

@@ -84,7 +84,7 @@ namespace OpenRA.Mods.Common.Traits
{
if (reservedForAircraft.GetActorBelow() == self)
{
if (rallyPoint != null)
if (rallyPoint != null && rallyPoint.Path.Count > 0)
foreach (var cell in rallyPoint.Path)
reservedFor.QueueActivity(reservedForAircraft.MoveTo(cell, 1, targetLineColor: Color.Green));
else

View File

@@ -35,9 +35,7 @@ namespace OpenRA.Mods.Common.Traits
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
string cachedTerrain;
CPos cachedLocation;
public GrantConditionOnTerrain(ActorInitializer init, GrantConditionOnTerrainInfo info)
{
@@ -53,9 +51,10 @@ namespace OpenRA.Mods.Common.Traits
void ITick.Tick(Actor self)
{
var loc = self.Location;
if (conditionManager == null || loc == cachedLocation)
if (conditionManager == null)
return;
// The terrain type may change between ticks without the actor moving
var currentTerrain = loc.Layer == 0 ? self.World.Map.GetTerrainInfo(loc).Type :
tileSet[self.World.GetCustomMovementLayers()[loc.Layer].GetTerrainIndex(loc)].Type;
@@ -69,7 +68,6 @@ namespace OpenRA.Mods.Common.Traits
}
cachedTerrain = currentTerrain;
cachedLocation = loc;
}
}
}

View File

@@ -276,7 +276,7 @@ namespace OpenRA.Mods.Common.Traits
public SubCell FreeSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, bool checkTransient = true)
{
if (preferredSubCell > SubCell.Any && !AnyActorsAt(cell, preferredSubCell, checkTransient))
if (preferredSubCell != SubCell.Any && !AnyActorsAt(cell, preferredSubCell, checkTransient))
return preferredSubCell;
if (!AnyActorsAt(cell))
@@ -291,7 +291,7 @@ namespace OpenRA.Mods.Common.Traits
public SubCell FreeSubCell(CPos cell, SubCell preferredSubCell, Func<Actor, bool> checkIfBlocker)
{
if (preferredSubCell > SubCell.Any && !AnyActorsAt(cell, preferredSubCell, checkIfBlocker))
if (preferredSubCell != SubCell.Any && !AnyActorsAt(cell, preferredSubCell, checkIfBlocker))
return preferredSubCell;
if (!AnyActorsAt(cell))

View File

@@ -133,12 +133,13 @@ namespace OpenRA.Mods.Common.Traits
if (!preview.Bounds.IsEmpty)
screenMap.Add(preview, preview.Bounds);
foreach (var kv in preview.Footprint)
AddPreviewLocation(preview, kv.Key);
// Fallback to the actor's CenterPosition for the ActorMap if it has no Footprint
if (!preview.Footprint.Any())
AddPreviewLocation(preview, worldRenderer.World.Map.CellContaining(preview.CenterPosition));
var footprint = preview.Footprint.Select(kv => kv.Key).ToArray();
if (!footprint.Any())
footprint = new[] { worldRenderer.World.Map.CellContaining(preview.CenterPosition) };
foreach (var cell in footprint)
AddPreviewLocation(preview, cell);
if (!initialSetup)
{
@@ -154,16 +155,21 @@ namespace OpenRA.Mods.Common.Traits
previews.Remove(preview);
screenMap.Remove(preview);
foreach (var kv in preview.Footprint)
// Fallback to the actor's CenterPosition for the ActorMap if it has no Footprint
var footprint = preview.Footprint.Select(kv => kv.Key).ToArray();
if (!footprint.Any())
footprint = new[] { worldRenderer.World.Map.CellContaining(preview.CenterPosition) };
foreach (var cell in footprint)
{
List<EditorActorPreview> list;
if (!cellMap.TryGetValue(kv.Key, out list))
if (!cellMap.TryGetValue(cell, out list))
continue;
list.Remove(preview);
if (!list.Any())
cellMap.Remove(kv.Key);
cellMap.Remove(cell);
}
UpdateNeighbours(preview.Footprint);

View File

@@ -304,7 +304,7 @@ namespace OpenRA.Mods.Common.Traits
var otherActors = subCell == SubCell.FullCell ? world.ActorMap.GetActorsAt(cell) : world.ActorMap.GetActorsAt(cell, subCell);
foreach (var otherActor in otherActors)
if (IsBlockedBy(actor, otherActor, ignoreActor, check, cellFlag))
if (IsBlockedBy(actor, otherActor, ignoreActor, cell, check, cellFlag))
return false;
return true;
@@ -322,7 +322,7 @@ namespace OpenRA.Mods.Common.Traits
if (check > BlockedByActor.None)
{
Func<Actor, bool> checkTransient = otherActor => IsBlockedBy(self, otherActor, ignoreActor, check, GetCache(cell).CellFlag);
Func<Actor, bool> checkTransient = otherActor => IsBlockedBy(self, otherActor, ignoreActor, cell, check, GetCache(cell).CellFlag);
if (!sharesCell)
return world.ActorMap.AnyActorsAt(cell, SubCell.FullCell, checkTransient) ? SubCell.Invalid : SubCell.FullCell;
@@ -336,14 +336,14 @@ namespace OpenRA.Mods.Common.Traits
return world.ActorMap.FreeSubCell(cell, preferredSubCell);
}
bool IsBlockedBy(Actor self, Actor otherActor, Actor ignoreActor, BlockedByActor check, CellFlag cellFlag)
bool IsBlockedBy(Actor actor, Actor otherActor, Actor ignoreActor, CPos cell, BlockedByActor check, CellFlag cellFlag)
{
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) &&
self.Owner.Stances[otherActor.Owner] == Stance.Ally)
actor.Owner.Stances[otherActor.Owner] == Stance.Ally)
{
var mobile = otherActor.TraitOrDefault<Mobile>();
if (mobile != null && !mobile.IsTraitDisabled && !mobile.IsTraitPaused && !mobile.IsImmovable)
@@ -352,14 +352,22 @@ namespace OpenRA.Mods.Common.Traits
// If the check allows: we are not blocked by moving units.
if (check <= BlockedByActor.Stationary && cellFlag.HasCellFlag(CellFlag.HasMovingActor) &&
IsMoving(self, otherActor))
IsMoving(actor, otherActor))
return false;
if (cellFlag.HasCellFlag(CellFlag.HasTemporaryBlocker))
{
// If there is a temporary blocker in our path, but we can remove it, we are not blocked.
var temporaryBlocker = otherActor.TraitOrDefault<ITemporaryBlocker>();
if (temporaryBlocker != null && temporaryBlocker.CanRemoveBlockage(otherActor, self))
if (temporaryBlocker != null && temporaryBlocker.CanRemoveBlockage(otherActor, actor))
return false;
}
if (cellFlag.HasCellFlag(CellFlag.HasTransitOnlyActor))
{
// Transit only tiles should not block movement
var building = otherActor.TraitOrDefault<Building>();
if (building != null && building.TransitOnlyCells().Contains(cell))
return false;
}
@@ -371,7 +379,7 @@ namespace OpenRA.Mods.Common.Traits
// PERF: Avoid LINQ.
var crushables = otherActor.TraitsImplementing<ICrushable>();
foreach (var crushable in crushables)
if (crushable.CrushableBy(otherActor, self, Info.Crushes))
if (crushable.CrushableBy(otherActor, actor, Info.Crushes))
return false;
return true;

View File

@@ -9,9 +9,10 @@
*/
#endregion
using System.Collections.Generic;
using System;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Support;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
@@ -70,245 +71,178 @@ namespace OpenRA.Mods.Common.Traits
public object Create(ActorInitializer init) { return new WeatherOverlay(init.World, this); }
}
public class WeatherOverlay : ITick, IRenderAboveWorld
public class WeatherOverlay : ITick, IRenderAboveWorld, INotifyViewportZoomExtentsChanged
{
readonly WeatherOverlayInfo info;
readonly World world;
struct Particle
{
public float PosX;
public float PosY;
public int Size;
public float DirectionScatterX;
public float Gravity;
public float SwingOffset;
public float SwingSpeed;
public int SwingDirection;
public float SwingAmplitude;
public Color Color;
public Color TailColor;
public readonly float2 Pos;
public readonly int Size;
public readonly float DirectionScatterX;
public readonly float Gravity;
public readonly float SwingOffset;
public readonly float SwingSpeed;
public readonly int SwingDirection;
public readonly float SwingAmplitude;
public readonly Color Color;
public readonly Color TailColor;
public Particle(WeatherOverlayInfo info, MersenneTwister r, Rectangle viewport)
{
var x = r.Next(viewport.Left, viewport.Right);
var y = r.Next(viewport.Top, viewport.Bottom);
Pos = new int2(x, y);
Size = r.Next(info.ParticleSize[0], info.ParticleSize[1] + 1);
DirectionScatterX = info.ScatterDirection[0] + r.Next(info.ScatterDirection[1] - info.ScatterDirection[0]);
Gravity = float2.Lerp(info.Gravity[0], info.Gravity[1], r.NextFloat());
SwingOffset = float2.Lerp(info.SwingOffset[0], info.SwingOffset[1], r.NextFloat());
SwingSpeed = float2.Lerp(info.SwingSpeed[0], info.SwingSpeed[1], r.NextFloat());
SwingDirection = r.Next(2) == 0 ? 1 : -1;
SwingAmplitude = float2.Lerp(info.SwingAmplitude[0], info.SwingAmplitude[1], r.NextFloat());
Color = info.ParticleColors.Random(r);
TailColor = Color.FromArgb(info.LineTailAlphaValue, Color.R, Color.G, Color.B);
}
Particle(Particle source)
{
Pos = source.Pos;
Size = source.Size;
DirectionScatterX = source.DirectionScatterX;
Gravity = source.Gravity;
SwingOffset = source.SwingOffset;
SwingSpeed = source.SwingSpeed;
SwingDirection = source.SwingDirection;
SwingAmplitude = source.SwingAmplitude;
Color = source.Color;
TailColor = source.TailColor;
}
public Particle(Particle source, float2 pos)
: this(source)
{
Pos = pos;
}
public Particle(Particle source, float2 pos, int swingDirection, float swingOffset)
: this(source)
{
Pos = pos;
SwingDirection = swingDirection;
SwingOffset = swingOffset;
}
}
readonly List<Particle> particleList = new List<Particle>();
readonly int maxParticleCount;
readonly WeatherOverlayInfo info;
readonly World world;
enum ParticleCountFaderType { Hold, FadeIn, FadeOut }
ParticleCountFaderType particleCountFader = ParticleCountFaderType.FadeIn;
float targetWindXOffset = 0f;
float currentWindXOffset = 0f;
int currentWindIndex = 0;
long windTickCountdown = 1500;
float2 antiScrollPrevTopLeft;
float windStrength;
int targetWindStrengthIndex;
long windUpdateCountdown;
Particle[] particles;
Size viewportSize;
public WeatherOverlay(World world, WeatherOverlayInfo info)
{
this.info = info;
this.world = world;
currentWindIndex = info.WindLevels.Length / 2;
targetWindXOffset = info.WindLevels[0];
maxParticleCount = CalculateParticleCount(Game.Renderer.Resolution.Width, Game.Renderer.Resolution.Height);
targetWindStrengthIndex = info.ChangingWindLevel ? world.LocalRandom.Next(info.WindLevels.Length) : 0;
windUpdateCountdown = world.LocalRandom.Next(info.WindTick[0], info.WindTick[1]);
windStrength = info.WindLevels[targetWindStrengthIndex];
}
int CalculateParticleCount(int x, int y)
void INotifyViewportZoomExtentsChanged.ViewportZoomExtentsChanged(float minZoom, float maxZoom)
{
return (int)(x * y * info.ParticleDensityFactor / 10000);
}
// Track particles in a viewport fixed to the minimum zoom level
var s = (1f / minZoom * new float2(Game.Renderer.NativeResolution)).ToInt2();
viewportSize = new Size(s.X, s.Y);
void SpawnParticles(int count, int rangeY, int spawnChancePercent)
{
for (var i = 0; i < count; i++)
{
if (Game.CosmeticRandom.Next(100) < spawnChancePercent)
{
var tempColor = info.ParticleColors.Random(Game.CosmeticRandom);
var tempColorTail = Color.FromArgb(info.LineTailAlphaValue, tempColor.R, tempColor.G, tempColor.B);
var tempSwingDirection = Game.CosmeticRandom.Next(2) == 0 ? 1 : -1;
particleList.Add(
new Particle
{
PosX = Game.CosmeticRandom.Next(Game.Renderer.Resolution.Width),
PosY = Game.CosmeticRandom.Next(rangeY),
Size = Game.CosmeticRandom.Next(info.ParticleSize[0], info.ParticleSize[1] + 1),
DirectionScatterX = info.ScatterDirection[0] + Game.CosmeticRandom.Next(info.ScatterDirection[1] - info.ScatterDirection[0]),
Gravity = float2.Lerp(info.Gravity[0], info.Gravity[1], Game.CosmeticRandom.NextFloat()),
SwingOffset = float2.Lerp(info.SwingOffset[0], info.SwingOffset[1], Game.CosmeticRandom.NextFloat()),
SwingSpeed = float2.Lerp(info.SwingSpeed[0], info.SwingSpeed[1], Game.CosmeticRandom.NextFloat()),
SwingDirection = tempSwingDirection,
SwingAmplitude = float2.Lerp(info.SwingAmplitude[0], info.SwingAmplitude[1], Game.CosmeticRandom.NextFloat()),
Color = tempColor,
TailColor = tempColorTail
});
}
}
}
void ParticlesCountLogic(WorldRenderer wr)
{
// Logic to switch between the states of the particleCountFader
if (particleCountFader == ParticleCountFaderType.Hold && particleList.Count < maxParticleCount)
particleCountFader = ParticleCountFaderType.FadeIn;
else if (particleCountFader == ParticleCountFaderType.FadeIn && particleList.Count >= maxParticleCount)
particleCountFader = ParticleCountFaderType.Hold;
else if (particleCountFader == ParticleCountFaderType.FadeOut && particleList.Count == 0)
particleCountFader = ParticleCountFaderType.Hold;
// Do the fade functions
if (particleCountFader == ParticleCountFaderType.FadeIn)
FadeInParticleCount(wr);
else if (particleCountFader == ParticleCountFaderType.FadeOut)
FadeOutParticleCount(wr);
}
void FadeInParticleCount(WorldRenderer wr)
{
SpawnParticles(1, 0, 100);
// Remove Particles, which are getting replaced from the top to the bottom by the "EdgeCheckReplace",
// when scrolling down, as long as the FadeIn is not completed,
// to avoid having particles at the top and bottom, but not in the middle of the screen.
for (var i = 0; i < particleList.Count; i++)
if (particleList[i].PosY < 0)
particleList.RemoveAt(i);
// Add Particles when the weather is fading in and scrolling up, to fill areas above
if (antiScrollPrevTopLeft.Y > wr.Viewport.TopLeft.Y)
{
// Get delta Y and limit to the max value
var tempRangeY = antiScrollPrevTopLeft.Y - wr.Viewport.TopLeft.Y;
var tempParticleCount = CalculateParticleCount(Game.Renderer.Resolution.Width, (int)tempRangeY);
if (particleList.Count + tempParticleCount > maxParticleCount)
tempParticleCount = maxParticleCount - particleList.Count;
SpawnParticles(tempParticleCount, (int)tempRangeY, 50);
}
}
void FadeOutParticleCount(WorldRenderer wr)
{
for (var i = 0; i < particleList.Count; i++)
if (particleList[i].PosY > (Game.Renderer.Resolution.Height - particleList[i].Gravity))
particleList.RemoveAt(i);
}
void XAxisSwing(ref Particle tempParticle)
{
// Direction turn
if (tempParticle.SwingOffset < -tempParticle.SwingAmplitude || tempParticle.SwingOffset > tempParticle.SwingAmplitude)
tempParticle.SwingDirection *= -1;
// Perform the X-Axis-Swing
tempParticle.SwingOffset += tempParticle.SwingDirection * tempParticle.SwingSpeed;
// Randomly distribute particles within the initial viewport
var particleCount = viewportSize.Width * viewportSize.Height * info.ParticleDensityFactor / 10000;
particles = new Particle[particleCount];
var rect = new Rectangle(int2.Zero, viewportSize);
for (var i = 0; i < particles.Length; i++)
particles[i] = new Particle(info, world.LocalRandom, rect);
}
void ITick.Tick(Actor self)
{
windTickCountdown--;
}
if (!info.ChangingWindLevel || info.WindLevels.Length == 1)
return;
void WindLogic(ref Particle tempParticle)
{
if (!info.ChangingWindLevel)
targetWindXOffset = info.WindLevels[0];
else if (windTickCountdown <= 0)
if (--windUpdateCountdown <= 0)
{
windTickCountdown = Game.CosmeticRandom.Next(info.WindTick[0], info.WindTick[1]);
if (Game.CosmeticRandom.Next(2) == 1 && currentWindIndex > 0)
{
currentWindIndex--;
targetWindXOffset = info.WindLevels[currentWindIndex];
}
else if (currentWindIndex < info.WindLevels.Length - 1)
{
currentWindIndex++;
targetWindXOffset = info.WindLevels[currentWindIndex];
}
windUpdateCountdown = self.World.LocalRandom.Next(info.WindTick[0], info.WindTick[1]);
if (targetWindStrengthIndex > 0 && self.World.LocalRandom.Next(2) == 1)
targetWindStrengthIndex--;
else if (targetWindStrengthIndex < info.WindLevels.Length - 1)
targetWindStrengthIndex++;
}
// Fading the wind in little steps towards the TargetWindOffset
var targetWindLevel = info.WindLevels[targetWindStrengthIndex];
if (info.InstantWindChanges)
currentWindXOffset = targetWindXOffset;
else if (currentWindXOffset != targetWindXOffset)
windStrength = targetWindLevel;
else if (Math.Abs(windStrength - targetWindLevel) > 0.01f)
{
if (currentWindXOffset > targetWindXOffset)
currentWindXOffset -= 0.00001f;
else if (currentWindXOffset < targetWindXOffset)
currentWindXOffset += 0.00001f;
}
}
void Movement(ref Particle tempParticle)
{
tempParticle.PosX += tempParticle.DirectionScatterX + tempParticle.SwingOffset + currentWindXOffset;
tempParticle.PosY += tempParticle.Gravity;
}
// AntiScroll keeps the particles in place when scrolling the viewport
void AntiScroll(ref Particle tempParticle, WorldRenderer wr)
{
tempParticle.PosX += antiScrollPrevTopLeft.X - wr.Viewport.TopLeft.X;
tempParticle.PosY += antiScrollPrevTopLeft.Y - wr.Viewport.TopLeft.Y;
}
void EdgeCheckReplace(ref Particle tempParticle, WorldRenderer wr)
{
tempParticle.PosX %= Game.Renderer.Resolution.Width;
if (tempParticle.PosX < 0)
tempParticle.PosX += Game.Renderer.Resolution.Width;
tempParticle.PosY %= Game.Renderer.Resolution.Height;
if (tempParticle.PosY < 0 && particleCountFader != ParticleCountFaderType.FadeIn)
tempParticle.PosY += Game.Renderer.Resolution.Height;
}
void UpdateWeatherOverlay(WorldRenderer wr)
{
if (!world.Paused)
ParticlesCountLogic(wr);
for (var i = 0; i < particleList.Count; i++)
{
Particle tempParticle = particleList[i];
if (!world.Paused)
{
XAxisSwing(ref tempParticle);
WindLogic(ref tempParticle);
Movement(ref tempParticle);
}
AntiScroll(ref tempParticle, wr);
EdgeCheckReplace(ref tempParticle, wr);
particleList[i] = tempParticle;
}
antiScrollPrevTopLeft = wr.Viewport.TopLeft;
}
void DrawWeatherOverlay(WorldRenderer wr)
{
var topLeft = wr.Viewport.TopLeft;
foreach (var item in particleList)
{
var tempPos = new float2(item.PosX + topLeft.X, item.PosY + topLeft.Y);
if (info.UseSquares)
Game.Renderer.WorldRgbaColorRenderer.FillRect(tempPos, tempPos + new float2(item.Size, item.Size), item.Color);
else
{
var tempPosTail = new float2(topLeft.X + item.PosX - currentWindXOffset, item.PosY - (item.Gravity * 2 / 3) + topLeft.Y);
Game.Renderer.WorldRgbaColorRenderer.DrawLine(tempPos, tempPosTail, item.Size, item.TailColor);
}
if (windStrength > targetWindLevel)
windStrength -= 0.01f;
else if (windStrength < targetWindLevel)
windStrength += 0.01f;
}
}
void IRenderAboveWorld.RenderAboveWorld(Actor self, WorldRenderer wr)
{
UpdateWeatherOverlay(wr);
var center = wr.Viewport.CenterLocation;
var viewport = new Rectangle(center - new int2(viewportSize) / 2, viewportSize);
var wcr = Game.Renderer.WorldRgbaColorRenderer;
DrawWeatherOverlay(wr);
for (var i = 0; i < particles.Length; i++)
{
// Simulate wind and gravity effects on the particle
var p = particles[i];
if (!world.Paused)
{
var swingDirection = p.SwingDirection;
if (p.SwingOffset < -p.SwingAmplitude || p.SwingOffset > p.SwingAmplitude)
swingDirection *= -1;
var swingOffset = p.SwingOffset + p.SwingDirection * p.SwingSpeed;
var pos = p.Pos + new float2(p.DirectionScatterX + p.SwingOffset + windStrength, p.Gravity);
particles[i] = p = new Particle(p, pos, swingDirection, swingOffset);
}
// Move the particle back inside the viewport if necessary
if (!viewport.Contains(p.Pos.ToInt2()))
{
var dx = (p.Pos.X - viewport.Left) % viewport.Width;
var dy = (p.Pos.Y - viewport.Top) % viewport.Height;
if (dx < 0)
dx += viewport.Width;
if (dy < 0)
dy += viewport.Height;
particles[i] = p = new Particle(p, new float2(viewport.Left + dx, viewport.Top + dy));
}
// Render the particle
// We must provide a z coordinate to stop the GL near and far Z limits from culling the geometry
var a = new float3(p.Pos.X, p.Pos.Y, p.Pos.Y);
if (info.UseSquares)
{
var b = a + new float2(p.Size, p.Size);
wcr.FillRect(a, b, p.Color);
}
else
{
var tail = p.Pos + new float2(-windStrength, -p.Gravity * 2 / 3);
var b = new float3(tail.X, tail.Y, tail.Y);
wcr.DrawLine(a, b, p.Size, p.TailColor);
}
}
}
}
}

View File

@@ -77,12 +77,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var mouseControlDescClassic = widget.Get("MOUSE_CONTROL_DESC_CLASSIC");
mouseControlDescClassic.IsVisible = () => gs.UseClassicMouseStyle;
var classicScrollRight = mouseControlDescClassic.Get("DESC_SCROLL_RIGHT");
classicScrollRight.IsVisible = () => !gs.ClassicMouseMiddleScroll;
var classicScrollMiddle = mouseControlDescClassic.Get("DESC_SCROLL_MIDDLE");
classicScrollMiddle.IsVisible = () => gs.ClassicMouseMiddleScroll;
var mouseControlDescModern = widget.Get("MOUSE_CONTROL_DESC_MODERN");
mouseControlDescModern.IsVisible = () => !gs.UseClassicMouseStyle;
@@ -92,6 +86,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
foreach (var container in new[] { mouseControlDescClassic, mouseControlDescModern })
{
var classicScrollRight = container.Get("DESC_SCROLL_RIGHT");
classicScrollRight.IsVisible = () => gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton;
var classicScrollMiddle = container.Get("DESC_SCROLL_MIDDLE");
classicScrollMiddle.IsVisible = () => !gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton;
var zoomDesc = container.Get("DESC_ZOOM");
zoomDesc.IsVisible = () => gs.ZoomModifier == Modifiers.None;

View File

@@ -505,7 +505,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var gs = Game.Settings.Game;
BindCheckboxPref(panel, "CLASSIC_MOUSE_MIDDLE_SCROLL_CHECKBOX", gs, "ClassicMouseMiddleScroll");
BindCheckboxPref(panel, "ALTERNATE_SCROLL_CHECKBOX", gs, "UseAlternateScrollButton");
BindCheckboxPref(panel, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll");
BindCheckboxPref(panel, "LOCKMOUSE_CHECKBOX", gs, "LockMouseWindow");
BindSliderPref(panel, "ZOOMSPEED_SLIDER", gs, "ZoomSpeed");
@@ -520,23 +520,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic
mouseScrollDropdown.OnMouseDown = _ => ShowMouseScrollDropdown(mouseScrollDropdown, gs);
mouseScrollDropdown.GetText = () => gs.MouseScroll.ToString();
var classicMouseMiddleScrollCheckbox = panel.Get<CheckboxWidget>("CLASSIC_MOUSE_MIDDLE_SCROLL_CHECKBOX");
classicMouseMiddleScrollCheckbox.IsVisible = () => gs.UseClassicMouseStyle;
var mouseControlDescClassic = panel.Get("MOUSE_CONTROL_DESC_CLASSIC");
mouseControlDescClassic.IsVisible = () => gs.UseClassicMouseStyle;
var classicScrollRight = mouseControlDescClassic.Get("DESC_SCROLL_RIGHT");
classicScrollRight.IsVisible = () => !gs.ClassicMouseMiddleScroll;
var classicScrollMiddle = mouseControlDescClassic.Get("DESC_SCROLL_MIDDLE");
classicScrollMiddle.IsVisible = () => gs.ClassicMouseMiddleScroll;
var mouseControlDescModern = panel.Get("MOUSE_CONTROL_DESC_MODERN");
mouseControlDescModern.IsVisible = () => !gs.UseClassicMouseStyle;
foreach (var container in new[] { mouseControlDescClassic, mouseControlDescModern })
{
var classicScrollRight = container.Get("DESC_SCROLL_RIGHT");
classicScrollRight.IsVisible = () => gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton;
var classicScrollMiddle = container.Get("DESC_SCROLL_MIDDLE");
classicScrollMiddle.IsVisible = () => !gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton;
var zoomDesc = container.Get("DESC_ZOOM");
zoomDesc.IsVisible = () => gs.ZoomModifier == Modifiers.None;
@@ -635,7 +632,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
gs.UseClassicMouseStyle = dgs.UseClassicMouseStyle;
gs.MouseScroll = dgs.MouseScroll;
gs.ClassicMouseMiddleScroll = dgs.ClassicMouseMiddleScroll;
gs.UseAlternateScrollButton = dgs.UseAlternateScrollButton;
gs.LockMouseWindow = dgs.LockMouseWindow;
gs.ViewportEdgeScroll = dgs.ViewportEdgeScroll;
gs.ViewportEdgeScrollStep = dgs.ViewportEdgeScrollStep;

View File

@@ -146,13 +146,16 @@ namespace OpenRA.Mods.Common.Widgets
UpdateSmoothScrolling();
var rb = RenderBounds;
var scrollbarHeight = rb.Height - 2 * ScrollbarWidth;
var thumbHeight = ContentHeight == 0 ? 0 : Math.Max(MinimumThumbSize, (int)(scrollbarHeight * Math.Min(rb.Height * 1f / ContentHeight, 1f)));
var thumbOrigin = rb.Y + ScrollbarWidth + (int)((scrollbarHeight - thumbHeight) * (-1f * currentListOffset / (ContentHeight - rb.Height)));
if (thumbHeight == scrollbarHeight)
thumbHeight = 0;
// Scroll thumb is only visible if the content does not fit within the panel bounds
var thumbHeight = 0;
var thumbOrigin = rb.Y + ScrollbarWidth;
if (ContentHeight > rb.Height)
{
thumbHeight = Math.Max(MinimumThumbSize, scrollbarHeight * rb.Height / ContentHeight);
thumbOrigin += (int)((scrollbarHeight - thumbHeight) * currentListOffset / (rb.Height - ContentHeight));
}
switch (ScrollBar)
{

View File

@@ -318,7 +318,7 @@ namespace OpenRA.Mods.Common.Widgets
}
var gs = Game.Settings.Game;
var scrollButton = gs.UseClassicMouseStyle && !gs.ClassicMouseMiddleScroll ? MouseButton.Right : MouseButton.Middle;
var scrollButton = gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton ? MouseButton.Right : MouseButton.Middle;
var scrollType = mi.Button.HasFlag(scrollButton) ? gs.MouseScroll : MouseScrollType.Disabled;
if (scrollType == MouseScrollType.Disabled)

View File

@@ -124,19 +124,13 @@ namespace OpenRA.Mods.Common.Widgets
{
if (useClassicMouseStyle && HasMouseFocus)
{
if (!IsValidDragbox && World.Selection.Actors.Any() && !multiClick)
if (!IsValidDragbox && World.Selection.Actors.Any() && !multiClick && uog.InputOverridesSelection(World, mousePos, mi))
{
var selectableActor = World.ScreenMap.ActorsAtMouse(mousePos).Select(a => a.Actor).Any(x =>
x.Info.HasTraitInfo<SelectableInfo>() && (x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x)));
if (!selectableActor || uog.InputOverridesSelection(World, mousePos, mi))
{
// Order units instead of selecting
ApplyOrders(World, mi);
isDragging = false;
YieldMouseFocus(mi);
return true;
}
// Order units instead of selecting
ApplyOrders(World, mi);
isDragging = false;
YieldMouseFocus(mi);
return true;
}
}

View File

@@ -17,165 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRA.Platforms.Default",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRA.Mods.Common", "OpenRA.Mods.Common\OpenRA.Mods.Common.csproj", "{FE6C8CC0-2F07-442A-B29F-17617B3B7FC6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tiberian Dawn Lua scripts", "Tiberian Dawn Lua scripts", "{62FCD0D0-6D24-435D-9DD8-3CCADCF7ECAB}"
ProjectSection(SolutionItems) = preProject
mods\cnc\maps\cnc64gdi01\cnc64gdi01.lua = mods\cnc\maps\cnc64gdi01\cnc64gdi01.lua
mods\cnc\maps\gdi01\gdi01.lua = mods\cnc\maps\gdi01\gdi01.lua
mods\cnc\maps\gdi02\gdi02.lua = mods\cnc\maps\gdi02\gdi02.lua
mods\cnc\maps\gdi03\gdi03.lua = mods\cnc\maps\gdi03\gdi03.lua
mods\cnc\maps\gdi04a\gdi04a.lua = mods\cnc\maps\gdi04a\gdi04a.lua
mods\cnc\maps\gdi04b\gdi04b.lua = mods\cnc\maps\gdi04b\gdi04b.lua
mods\cnc\maps\gdi04c\gdi04c.lua = mods\cnc\maps\gdi04c\gdi04c.lua
mods\cnc\maps\gdi05a\gdi05a.lua = mods\cnc\maps\gdi05a\gdi05a.lua
mods\cnc\maps\gdi05b\gdi05b.lua = mods\cnc\maps\gdi05b\gdi05b.lua
mods\cnc\maps\gdi06\gdi06.lua = mods\cnc\maps\gdi06\gdi06.lua
mods\cnc\maps\gdi07\gdi07.lua = mods\cnc\maps\gdi07\gdi07.lua
mods\cnc\maps\nod01\nod01.lua = mods\cnc\maps\nod01\nod01.lua
mods\cnc\maps\nod02a\nod02a.lua = mods\cnc\maps\nod02a\nod02a.lua
mods\cnc\maps\nod02b\nod02b.lua = mods\cnc\maps\nod02b\nod02b.lua
mods\cnc\maps\nod03a\nod03a.lua = mods\cnc\maps\nod03a\nod03a.lua
mods\cnc\maps\nod03b\nod03b.lua = mods\cnc\maps\nod03b\nod03b.lua
mods\cnc\maps\nod04a\nod04a.lua = mods\cnc\maps\nod04a\nod04a.lua
mods\cnc\maps\nod04b\nod04b.lua = mods\cnc\maps\nod04b\nod04b.lua
mods\cnc\maps\nod05\nod05.lua = mods\cnc\maps\nod05\nod05.lua
mods\cnc\maps\nod06a\nod06a.lua = mods\cnc\maps\nod06a\nod06a.lua
mods\cnc\maps\nod06b\nod06b.lua = mods\cnc\maps\nod06b\nod06b.lua
mods\cnc\maps\nod06c\nod06c.lua = mods\cnc\maps\nod06c\nod06c.lua
mods\cnc\maps\nod07a\nod07a-AI.lua = mods\cnc\maps\nod07a\nod07a-AI.lua
mods\cnc\maps\nod07a\nod07a.lua = mods\cnc\maps\nod07a\nod07a.lua
mods\cnc\maps\nod07b\nod07b-AI.lua = mods\cnc\maps\nod07b\nod07b-AI.lua
mods\cnc\maps\nod07b\nod07b.lua = mods\cnc\maps\nod07b\nod07b.lua
mods\cnc\maps\nod07c\nod07c.lua = mods\cnc\maps\nod07c\nod07c.lua
mods\cnc\maps\nod08a\nod08a-AI.lua = mods\cnc\maps\nod08a\nod08a-AI.lua
mods\cnc\maps\nod08a\nod08a.lua = mods\cnc\maps\nod08a\nod08a.lua
mods\cnc\maps\nod08b\nod08b-AI.lua = mods\cnc\maps\nod08b\nod08b-AI.lua
mods\cnc\maps\nod08b\nod08b.lua = mods\cnc\maps\nod08b\nod08b.lua
mods\cnc\maps\nod09\nod09-AI.lua = mods\cnc\maps\nod09\nod09-AI.lua
mods\cnc\maps\nod09\nod09.lua = mods\cnc\maps\nod09\nod09.lua
mods\cnc\maps\funpark01\scj01ea.lua = mods\cnc\maps\funpark01\scj01ea.lua
mods\cnc\maps\shellmap\shellmap.lua = mods\cnc\maps\shellmap\shellmap.lua
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Red Alert Lua scripts", "Red Alert Lua scripts", "{B35D533F-BEB6-4674-A466-324EEFD97259}"
ProjectSection(SolutionItems) = preProject
mods\ra\maps\allies-01\allies01.lua = mods\ra\maps\allies-01\allies01.lua
mods\ra\maps\allies-02\allies02.lua = mods\ra\maps\allies-02\allies02.lua
mods\ra\maps\allies-03a\allies03a.lua = mods\ra\maps\allies-03a\allies03a.lua
mods\ra\maps\allies-03b\allies03b.lua = mods\ra\maps\allies-03b\allies03b.lua
mods\ra\maps\allies-05a\allies05a-AI.lua = mods\ra\maps\allies-05a\allies05a-AI.lua
mods\ra\maps\allies-05a\allies05a.lua = mods\ra\maps\allies-05a\allies05a.lua
mods\ra\maps\allies-06a\allies06a-AI.lua = mods\ra\maps\allies-06a\allies06a-AI.lua
mods\ra\maps\allies-06a\allies06a.lua = mods\ra\maps\allies-06a\allies06a.lua
mods\ra\maps\allies-06b\allies06b-AI.lua = mods\ra\maps\allies-06b\allies06b-AI.lua
mods\ra\maps\allies-06b\allies06b.lua = mods\ra\maps\allies-06b\allies06b.lua
mods\ra\maps\desert-shellmap\desert-shellmap.lua = mods\ra\maps\desert-shellmap\desert-shellmap.lua
mods\ra\maps\evacuation\evacuation.lua = mods\ra\maps\evacuation\evacuation.lua
mods\ra\maps\exodus\exodus.lua = mods\ra\maps\exodus\exodus.lua
mods\ra\maps\fort-lonestar\fort-lonestar-AI.lua = mods\ra\maps\fort-lonestar\fort-lonestar-AI.lua
mods\ra\maps\fort-lonestar\fort-lonestar.lua = mods\ra\maps\fort-lonestar\fort-lonestar.lua
mods\ra\maps\infiltration\infiltration.lua = mods\ra\maps\infiltration\infiltration.lua
mods\ra\maps\intervention\intervention.lua = mods\ra\maps\intervention\intervention.lua
mods\ra\maps\monster-tank-madness\monster-tank-madness.lua = mods\ra\maps\monster-tank-madness\monster-tank-madness.lua
mods\ra\maps\soviet-soldier-volkov-n-chitzkoi\scu35ea-AI.lua = mods\ra\maps\soviet-soldier-volkov-n-chitzkoi\scu35ea-AI.lua
mods\ra\maps\soviet-soldier-volkov-n-chitzkoi\scu35ea.lua = mods\ra\maps\soviet-soldier-volkov-n-chitzkoi\scu35ea.lua
mods\ra\maps\top-o-the-world\scu36ea.lua = mods\ra\maps\top-o-the-world\scu36ea.lua
mods\ra\maps\soviet-01\soviet01.lua = mods\ra\maps\soviet-01\soviet01.lua
mods\ra\maps\soviet-02a\soviet02a.lua = mods\ra\maps\soviet-02a\soviet02a.lua
mods\ra\maps\soviet-02b\soviet02b.lua = mods\ra\maps\soviet-02b\soviet02b.lua
mods\ra\maps\soviet-03\soviet03.lua = mods\ra\maps\soviet-03\soviet03.lua
mods\ra\maps\soviet-04a\soviet04a-AI.lua = mods\ra\maps\soviet-04a\soviet04a-AI.lua
mods\ra\maps\soviet-04a\soviet04a-reinforcements_teams.lua = mods\ra\maps\soviet-04a\soviet04a-reinforcements_teams.lua
mods\ra\maps\soviet-04a\soviet04a.lua = mods\ra\maps\soviet-04a\soviet04a.lua
mods\ra\maps\soviet-04b\soviet04b-AI.lua = mods\ra\maps\soviet-04b\soviet04b-AI.lua
mods\ra\maps\soviet-04b\soviet04b-reinforcements_teams.lua = mods\ra\maps\soviet-04b\soviet04b-reinforcements_teams.lua
mods\ra\maps\soviet-04b\soviet04b.lua = mods\ra\maps\soviet-04b\soviet04b.lua
mods\ra\maps\soviet-05\soviet05-AI.lua = mods\ra\maps\soviet-05\soviet05-AI.lua
mods\ra\maps\soviet-05\soviet05-reinforcements_teams.lua = mods\ra\maps\soviet-05\soviet05-reinforcements_teams.lua
mods\ra\maps\soviet-05\soviet05.lua = mods\ra\maps\soviet-05\soviet05.lua
mods\ra\maps\soviet-06a\soviet06a-AI.lua = mods\ra\maps\soviet-06a\soviet06a-AI.lua
mods\ra\maps\soviet-06a\soviet06a-reinforcements_teams.lua = mods\ra\maps\soviet-06a\soviet06a-reinforcements_teams.lua
mods\ra\maps\soviet-06a\soviet06a.lua = mods\ra\maps\soviet-06a\soviet06a.lua
mods\ra\maps\soviet-06b\soviet06b-AI.lua = mods\ra\maps\soviet-06b\soviet06b-AI.lua
mods\ra\maps\soviet-06b\soviet06b-reinforcements_teams.lua = mods\ra\maps\soviet-06b\soviet06b-reinforcements_teams.lua
mods\ra\maps\soviet-06b\soviet06b.lua = mods\ra\maps\soviet-06b\soviet06b.lua
mods\ra\maps\soviet-07\soviet07.lua = mods\ra\maps\soviet-07\soviet07.lua
mods\ra\maps\survival01\survival01.lua = mods\ra\maps\survival01\survival01.lua
mods\ra\maps\survival02\survival02.lua = mods\ra\maps\survival02\survival02.lua
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dune 2000 Lua scripts", "Dune 2000 Lua scripts", "{06B1AE07-DDB0-4287-8700-A8CD9A0E652E}"
ProjectSection(SolutionItems) = preProject
mods\d2k\maps\atreides-01a\atreides01a.lua = mods\d2k\maps\atreides-01a\atreides01a.lua
mods\d2k\maps\atreides-01b\atreides01b.lua = mods\d2k\maps\atreides-01b\atreides01b.lua
mods\d2k\maps\atreides-02a\atreides02a-AI.lua = mods\d2k\maps\atreides-02a\atreides02a-AI.lua
mods\d2k\maps\atreides-02a\atreides02a.lua = mods\d2k\maps\atreides-02a\atreides02a.lua
mods\d2k\maps\atreides-02b\atreides02b-AI.lua = mods\d2k\maps\atreides-02b\atreides02b-AI.lua
mods\d2k\maps\atreides-02b\atreides02b.lua = mods\d2k\maps\atreides-02b\atreides02b.lua
mods\d2k\maps\atreides-03a\atreides03a-AI.lua = mods\d2k\maps\atreides-03a\atreides03a-AI.lua
mods\d2k\maps\atreides-03a\atreides03a.lua = mods\d2k\maps\atreides-03a\atreides03a.lua
mods\d2k\maps\atreides-03b\atreides03b-AI.lua = mods\d2k\maps\atreides-03b\atreides03b-AI.lua
mods\d2k\maps\atreides-03b\atreides03b.lua = mods\d2k\maps\atreides-03b\atreides03b.lua
mods\d2k\maps\atreides-04\atreides04-AI.lua = mods\d2k\maps\atreides-04\atreides04-AI.lua
mods\d2k\maps\atreides-04\atreides04.lua = mods\d2k\maps\atreides-04\atreides04.lua
mods\d2k\maps\atreides-05\atreides05-AI.lua = mods\d2k\maps\atreides-05\atreides05-AI.lua
mods\d2k\maps\atreides-05\atreides05.lua = mods\d2k\maps\atreides-05\atreides05.lua
mods\d2k\bits\scripts\campaign-global.lua = mods\d2k\bits\scripts\campaign-global.lua
mods\d2k\maps\harkonnen-01a\harkonnen01a.lua = mods\d2k\maps\harkonnen-01a\harkonnen01a.lua
mods\d2k\maps\harkonnen-01b\harkonnen01b.lua = mods\d2k\maps\harkonnen-01b\harkonnen01b.lua
mods\d2k\maps\harkonnen-02a\harkonnen02a-AI.lua = mods\d2k\maps\harkonnen-02a\harkonnen02a-AI.lua
mods\d2k\maps\harkonnen-02a\harkonnen02a.lua = mods\d2k\maps\harkonnen-02a\harkonnen02a.lua
mods\d2k\maps\harkonnen-02b\harkonnen02b-AI.lua = mods\d2k\maps\harkonnen-02b\harkonnen02b-AI.lua
mods\d2k\maps\harkonnen-02b\harkonnen02b.lua = mods\d2k\maps\harkonnen-02b\harkonnen02b.lua
mods\d2k\maps\harkonnen-03a\harkonnen03a-AI.lua = mods\d2k\maps\harkonnen-03a\harkonnen03a-AI.lua
mods\d2k\maps\harkonnen-03a\harkonnen03a.lua = mods\d2k\maps\harkonnen-03a\harkonnen03a.lua
mods\d2k\maps\harkonnen-03b\harkonnen03b-AI.lua = mods\d2k\maps\harkonnen-03b\harkonnen03b-AI.lua
mods\d2k\maps\harkonnen-03b\harkonnen03b.lua = mods\d2k\maps\harkonnen-03b\harkonnen03b.lua
mods\d2k\maps\harkonnen-04\harkonnen04-AI.lua = mods\d2k\maps\harkonnen-04\harkonnen04-AI.lua
mods\d2k\maps\harkonnen-04\harkonnen04.lua = mods\d2k\maps\harkonnen-04\harkonnen04.lua
mods\d2k\maps\harkonnen-05\harkonnen05-AI.lua = mods\d2k\maps\harkonnen-05\harkonnen05-AI.lua
mods\d2k\maps\harkonnen-05\harkonnen05.lua = mods\d2k\maps\harkonnen-05\harkonnen05.lua
mods\d2k\maps\harkonnen-06a\harkonnen06a-AI.lua = mods\d2k\maps\harkonnen-06a\harkonnen06a-AI.lua
mods\d2k\maps\harkonnen-06a\harkonnen06a.lua = mods\d2k\maps\harkonnen-06a\harkonnen06a.lua
mods\d2k\maps\harkonnen-06b\harkonnen06b-AI.lua = mods\d2k\maps\harkonnen-06b\harkonnen06b-AI.lua
mods\d2k\maps\harkonnen-06b\harkonnen06b.lua = mods\d2k\maps\harkonnen-06b\harkonnen06b.lua
mods\d2k\maps\harkonnen-07\harkonnen07-AI.lua = mods\d2k\maps\harkonnen-07\harkonnen07-AI.lua
mods\d2k\maps\harkonnen-07\harkonnen07.lua = mods\d2k\maps\harkonnen-07\harkonnen07.lua
mods\d2k\maps\harkonnen-08\harkonnen08-AI.lua = mods\d2k\maps\harkonnen-08\harkonnen08-AI.lua
mods\d2k\maps\harkonnen-08\harkonnen08.lua = mods\d2k\maps\harkonnen-08\harkonnen08.lua
mods\d2k\maps\harkonnen-09a\harkonnen09a-AI.lua = mods\d2k\maps\harkonnen-09a\harkonnen09a-AI.lua
mods\d2k\maps\harkonnen-09a\harkonnen09a.lua = mods\d2k\maps\harkonnen-09a\harkonnen09a.lua
mods\d2k\maps\harkonnen-09b\harkonnen09b-AI.lua = mods\d2k\maps\harkonnen-09b\harkonnen09b-AI.lua
mods\d2k\maps\harkonnen-09b\harkonnen09b.lua = mods\d2k\maps\harkonnen-09b\harkonnen09b.lua
mods\d2k\maps\ordos-01a\ordos01a.lua = mods\d2k\maps\ordos-01a\ordos01a.lua
mods\d2k\maps\ordos-01b\ordos01b.lua = mods\d2k\maps\ordos-01b\ordos01b.lua
mods\d2k\maps\ordos-02a\ordos02a-AI.lua = mods\d2k\maps\ordos-02a\ordos02a-AI.lua
mods\d2k\maps\ordos-02a\ordos02a.lua = mods\d2k\maps\ordos-02a\ordos02a.lua
mods\d2k\maps\ordos-02b\ordos02b-AI.lua = mods\d2k\maps\ordos-02b\ordos02b-AI.lua
mods\d2k\maps\ordos-02b\ordos02b.lua = mods\d2k\maps\ordos-02b\ordos02b.lua
mods\d2k\maps\ordos-03a\ordos03a-AI.lua = mods\d2k\maps\ordos-03a\ordos03a-AI.lua
mods\d2k\maps\ordos-03a\ordos03a.lua = mods\d2k\maps\ordos-03a\ordos03a.lua
mods\d2k\maps\ordos-03b\ordos03b-AI.lua = mods\d2k\maps\ordos-03b\ordos03b-AI.lua
mods\d2k\maps\ordos-03b\ordos03b.lua = mods\d2k\maps\ordos-03b\ordos03b.lua
mods\d2k\maps\ordos-04\ordos04-AI.lua = mods\d2k\maps\ordos-04\ordos04-AI.lua
mods\d2k\maps\ordos-04\ordos04.lua = mods\d2k\maps\ordos-04\ordos04.lua
mods\d2k\maps\ordos-05\ordos05-AI.lua = mods\d2k\maps\ordos-05\ordos05-AI.lua
mods\d2k\maps\ordos-05\ordos05.lua = mods\d2k\maps\ordos-05\ordos05.lua
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System Lua scripts", "System Lua scripts", "{A4D6AEA4-8009-4256-903B-8D227E50452B}"
ProjectSection(SolutionItems) = preProject
lua\sandbox.lua = lua\sandbox.lua
lua\scriptwrapper.lua = lua\scriptwrapper.lua
lua\stacktraceplus.lua = lua\stacktraceplus.lua
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRA.Test", "OpenRA.Test\OpenRA.Test.csproj", "{6CB8E1B7-6B36-4D93-8633-7C573E194AC4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tiberian Sun Lua scripts", "Tiberian Sun Lua scripts", "{85159569-F5BD-458E-B5C0-EB16690C432B}"
ProjectSection(SolutionItems) = preProject
mods\ts\maps\fields-of-green\fields-of-green.lua = mods\ts\maps\fields-of-green\fields-of-green.lua
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRA.PostProcess", "OpenRA.PostProcess\OpenRA.PostProcess.csproj", "{EE63AF7E-92EA-48FB-81E2-53D7D92F8050}"
EndProject
Global
@@ -201,7 +44,6 @@ Global
{F33337BE-CB69-4B24-850F-07D23E408DDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F33337BE-CB69-4B24-850F-07D23E408DDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F33337BE-CB69-4B24-850F-07D23E408DDF}.Release|Any CPU.Build.0 = Release|Any CPU
{F33337BE-CB69-4B24-850F-07D23E408DDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F33337BE-CB69-4B24-850F-07D23E408DDF}.Release-x86|Any CPU.ActiveCfg = Release-x86|Any CPU
{F33337BE-CB69-4B24-850F-07D23E408DDF}.Release-x86|Any CPU.Build.0 = Release-x86|Any CPU
{76F621A1-3D8E-4A99-9F7E-B071EB657817}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

View File

@@ -388,7 +388,7 @@ sidebar-bits:
production-tooltip-time: 904, 51, 16, 16
production-tooltip-power: 870, 51, 16, 16
production-tooltip-cost: 836, 51, 16, 16
indicator-muted: 918, 221, 24, 24
indicator-muted: 918, 221, 26, 24
vertical-bars:
Inherits: ^Chrome

View File

@@ -182,8 +182,10 @@ Container@SAVE_MAP_PANEL:
Font: Bold
ScrollPanel@MAP_SAVE_VISIBILITY_PANEL:
TopBottomSpacing: 5
ItemSpacing: 5
Width: 220
Height: 64
Height: 55
Children:
Checkbox@VISIBILITY_TEMPLATE:
X: 5
@@ -642,29 +644,30 @@ Container@EDITOR_WORLD_ROOT:
Contrast: true
ScrollPanel@CATEGORY_FILTER_PANEL:
Width: 190
Width: 230
TopBottomSpacing: 5
ItemSpacing: 5
Children:
Container@SELECT_CATEGORIES_BUTTONS:
Width: PARENT_RIGHT
Height: 30
Height: 25
Children:
Button@SELECT_ALL:
X: 10
Y: 2
Width: 60
Y: 0 - 5
Width: 88
Height: 25
Text: All
Button@SELECT_NONE:
X: PARENT_RIGHT - WIDTH - 34
Y: 2
Width: 60
X: 10 + 88 + 10
Y: 0 - 5
Width: 88
Height: 25
Text: None
Checkbox@CATEGORY_TEMPLATE:
X: 5
Y: 5
Width: PARENT_RIGHT - 29
Height: 22
Height: 20
Visible: false
ScrollPanel@COPY_FILTER_PANEL:

View File

@@ -148,7 +148,7 @@ Container@LOBBY_PLAYER_BIN:
Height: 25
Font: Regular
Image@STATUS_IMAGE:
X: 521
X: 529
Y: 4
Width: 20
Height: 20
@@ -198,7 +198,6 @@ Container@LOBBY_PLAYER_BIN:
Template: ANONYMOUS_PLAYER_TOOLTIP
Label@NAME:
X: 39
Y: 0 - 1
Width: 161
Height: 25
DropDownButton@PLAYER_ACTION:
@@ -233,8 +232,8 @@ Container@LOBBY_PLAYER_BIN:
Height: 25
Children:
Image@FACTIONFLAG:
X: 5
Y: 5
X: 4
Y: 4
Width: 30
Height: 15
Label@FACTIONNAME:
@@ -265,7 +264,7 @@ Container@LOBBY_PLAYER_BIN:
Font: Regular
Visible: false
Image@STATUS_IMAGE:
X: 527
X: 529
Y: 4
Width: 20
Height: 20
@@ -287,7 +286,6 @@ Container@LOBBY_PLAYER_BIN:
Visible: false
Label@NAME:
X: 20
Y: 0 - 1
Width: 195
Height: 25
Visible: false
@@ -348,7 +346,7 @@ Container@LOBBY_PLAYER_BIN:
Align: Center
Font: Bold
Image@STATUS_IMAGE:
X: 521
X: 529
Y: 4
Width: 20
Height: 20
@@ -398,7 +396,6 @@ Container@LOBBY_PLAYER_BIN:
Template: ANONYMOUS_PLAYER_TOOLTIP
Label@NAME:
X: 39
Y: 0 - 1
Width: 161
Height: 25
DropDownButton@PLAYER_ACTION:

View File

@@ -190,7 +190,13 @@ Container@MAINMENU_INTRODUCTION_PROMPT:
Height: 16
Font: Small
Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel}
LabelWithHighlight@DESC_SCROLL:
LabelWithHighlight@DESC_SCROLL_RIGHT:
X: 265
Y: 34
Height: 16
Font: Small
Text: - Pan the battlefield using the {Right} mouse button
LabelWithHighlight@DESC_SCROLL_MIDDLE:
X: 265
Y: 34
Height: 16

View File

@@ -484,7 +484,12 @@ Container@SETTINGS_PANEL:
Height: 16
Font: Small
Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel}
LabelWithHighlight@DESC_SCROLL:
LabelWithHighlight@DESC_SCROLL_RIGHT:
Y: 85
Height: 16
Font: Small
Text: - Pan the battlefield using the {Right} mouse button
LabelWithHighlight@DESC_SCROLL_MIDDLE:
Y: 85
Height: 16
Font: Small
@@ -537,13 +542,13 @@ Container@SETTINGS_PANEL:
Height: 20
Font: Regular
Text: Screen Edge Panning
Checkbox@CLASSIC_MOUSE_MIDDLE_SCROLL_CHECKBOX:
Checkbox@ALTERNATE_SCROLL_CHECKBOX:
X: 360
Y: 133
Width: 180
Height: 20
Font: Regular
Text: Middle Mouse Panning
Text: Alternate Mouse Panning
Label@SCROLL_SPEED_LABEL:
X: 310
Y: 210
@@ -634,7 +639,7 @@ Container@SETTINGS_PANEL:
Width: 80
Height: 25
Align: Left
TooltipContainer: TOOLTIP_CONTAINER
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@THREE_COLUMN:
Width: 173
Height: 25
@@ -650,7 +655,7 @@ Container@SETTINGS_PANEL:
Width: 80
Height: 25
Align: Left
TooltipContainer: TOOLTIP_CONTAINER
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Background@HOTKEY_DIALOG_ROOT:
X: 15
Y: 230
@@ -700,7 +705,7 @@ Container@SETTINGS_PANEL:
Width: 25
Height: 25
TooltipText: Unbind the hotkey
TooltipContainer: TOOLTIP_CONTAINER
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
TooltipTemplate: SIMPLE_TOOLTIP
Children:
Image:
@@ -715,7 +720,7 @@ Container@SETTINGS_PANEL:
Width: 25
Height: 25
TooltipText: Reset to default
TooltipContainer: TOOLTIP_CONTAINER
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
TooltipTemplate: SIMPLE_TOOLTIP
Children:
Image@IMAGE_RELOAD:
@@ -860,4 +865,4 @@ Container@SETTINGS_PANEL:
Width: 140
Height: 35
Text: Reset
TooltipContainer@TOOLTIP_CONTAINER:
TooltipContainer@SETTINGS_TOOLTIP_CONTAINER:

View File

@@ -0,0 +1,194 @@
--[[
Copyright 2007-2020 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.
]]
AttackPaths = { WaypointGroup3, WaypointGroup4, WaypointGroup5 }
NodBase = { handofnod, nodairfield, nodrefinery, NodYard, nodpower1, nodpower2, nodpower3, nodpower4, gun1, gun2, nodsilo1, nodsilo2, nodsilo3, nodsilo4}
PatrolProductionQueue = { }
InfantryAttackGroup = { }
InfantryGroupSize = 5
InfantryProductionCooldown = DateTime.Minutes(3)
InfantryProductionTypes = { "e1", "e1", "e1", "e3", "e3", "e4" }
HarvesterProductionType = { "harv" }
VehicleAttackGroup = { }
VehicleGroupSize = 5
VehicleProductionCooldown = DateTime.Minutes(3)
VehicleProductionTypes = { "bggy", "bggy", "bike", "ltnk", "ltnk" }
StartingCash = 14000
BaseRefinery = { type = "proc", pos = CPos.New(24, 16), cost = 1500 }
BaseGun1 = { type = "gun", pos = CPos.New( 21, 19), cost = 600 }
BaseGun2 = { type = "gun", pos = CPos.New( 26, 21), cost = 600 }
BaseNuke1 = { type = "nuke", pos = CPos.New( 23, 14), cost = 500 }
BaseNuke2 = { type = "nuke", pos = CPos.New( 10, 9), cost = 500 }
BaseNuke3 = { type = "nuke", pos = CPos.New( 6, 8), cost = 500 }
BaseNuke4 = { type = "nuke", pos = CPos.New( 8, 8), cost = 500 }
InfantryProduction = { type = "hand", pos = CPos.New(27, 17), cost = 500 }
VehicleProduction = { type = "afld", pos = CPos.New(27, 14), cost = 2000 }
NodGuards = { Actor154, Actor155, Actor218, Actor219 }
BaseBuildings = { BaseRefinery, BaseNuke1, BaseNuke2, BaseNuke3, BaseNuke4, InfantryProduction, VehicleProduction, BaseGun1, BaseGun2 }
BuildBuilding = function(building, cyard)
if CyardIsBuilding or Nod.Cash < building.cost then
Trigger.AfterDelay(DateTime.Seconds(10), function() BuildBuilding(building, cyard) end)
return
end
CyardIsBuilding = true
Nod.Cash = Nod.Cash - building.cost
Trigger.AfterDelay(Actor.BuildTime(building.type), function()
CyardIsBuilding = false
if cyard.IsDead or cyard.Owner ~= Nod then
Nod.Cash = Nod.Cash + building.cost
return
end
local actor = Actor.Create(building.type, true, { Owner = Nod, Location = building.pos })
if actor.Type == 'hand' or actor.Type == 'pyle' then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(actor) end)
elseif actor.Type == 'afld' or actor.Type == 'weap' then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(actor) end)
end
Trigger.OnKilled(actor, function()
BuildBuilding(building, cyard)
end)
RepairBuilding(GDI, actor, 0.75)
end)
end
CheckForHarvester = function()
local harv = Nod.GetActorsByType("harv")
return #harv > 0
end
GuardBase = function()
Utils.Do(NodBase, function(building)
Trigger.OnDamaged(building, function()
Utils.Do(NodGuards, function(guard)
if not guard.IsDead and not building.IsDead then
guard.Stop()
guard.Guard(building)
end
end)
end)
end)
end
ProduceHarvester = function(building)
if not buildingHarvester then
buildingHarvester = true
building.Build(HarvesterProductionType, function()
buildingHarvester = false
end)
end
end
ProduceInfantry = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not CheckForHarvester() then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(3), DateTime.Seconds(9))
local toBuild = { Utils.Random(InfantryProductionTypes) }
local Path = Utils.Random(AttackPaths)
building.Build(toBuild, function(unit)
InfantryAttackGroup[#InfantryAttackGroup + 1] = unit[1]
if #InfantryAttackGroup >= InfantryGroupSize then
MoveAndHunt(InfantryAttackGroup, Path)
InfantryAttackGroup = { }
Trigger.AfterDelay(InfantryProductionCooldown, function() ProduceInfantry(building) end)
else
Trigger.AfterDelay(delay, function() ProduceInfantry(building) end)
end
end)
end
ProduceVehicle = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not CheckForHarvester() then
ProduceHarvester(building)
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17))
local toBuild = { Utils.Random(VehicleProductionTypes) }
local Path = Utils.Random(AttackPaths)
building.Build(toBuild, function(unit)
VehicleAttackGroup[#VehicleAttackGroup + 1] = unit[1]
if #VehicleAttackGroup >= VehicleGroupSize then
MoveAndHunt(VehicleAttackGroup, Path)
VehicleAttackGroup = { }
Trigger.AfterDelay(VehicleProductionCooldown, function() ProduceVehicle(building) end)
else
Trigger.AfterDelay(delay, function() ProduceVehicle(building) end)
end
end)
end
StartAI = function()
Nod.Cash = StartingCash
GuardBase()
end
Trigger.OnAllKilledOrCaptured(NodBase, function()
Utils.Do(Nod.GetGroundAttackers(), IdleHunt)
end)
Trigger.OnKilled(nodrefinery, function()
BuildBuilding(BaseRefinery, NodYard)
end)
Trigger.OnKilled(nodpower1, function()
BuildBuilding(BaseNuke1, NodYard)
end)
Trigger.OnKilled(nodpower2, function()
BuildBuilding(BaseNuke2, NodYard)
end)
Trigger.OnKilled(nodpower3, function()
BuildBuilding(BaseNuke3, NodYard)
end)
Trigger.OnKilled(nodpower4, function()
BuildBuilding(BaseNuke4, NodYard)
end)
Trigger.OnKilled(gun1, function()
BuildBuilding(BaseGun1, NodYard)
end)
Trigger.OnKilled(gun2, function()
BuildBuilding(BaseGun2, NodYard)
end)
Trigger.OnKilled(handofnod, function()
BuildBuilding(InfantryProduction, NodYard)
end)
Trigger.OnKilled(nodairfield, function()
BuildBuilding(VehicleProduction, NodYard)
end)

View File

@@ -0,0 +1,152 @@
--[[
Copyright 2007-2020 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.
]]
SamSites = { sam1, sam2, sam3 }
WaypointGroup1 = { waypoint4, waypoint5, waypoint6, waypoint7, waypoint10, waypoint11, waypoint12 }
WaypointGroup2 = { waypoint4, waypoint5, waypoint13, waypoint16 }
WaypointGroup3 = { waypoint4, waypoint5, waypoint6, waypoint8 }
WaypointGroup4 = { waypoint4, waypoint5, waypoint6, waypoint7, waypoint9 }
WaypointGroup5 = { waypoint4, waypoint5, waypoint6 }
WaypointGroup6 = { waypoint4, waypoint5, waypoint6, waypoint7, waypoint14, waypoint15 }
WaypointGroup7 = { waypoint4, waypoint5 }
WaypointGroupCiv = { waypoint0, waypoint1, waypoint2, waypoint3 }
Atk1 = { units = { ['ltnk'] = 1 }, waypoints = WaypointGroup1, delay = 0 }
Atk2 = { units = { ['ltnk'] = 1 }, waypoints = WaypointGroup2, delay = 0 }
Civ1 = { units = { ['c3'] = 1 }, waypoints = WaypointGroupCiv, delay = 0 }
Nod1 = { units = { ['e1'] = 2, ['e2'] = 2, ['e4'] = 2 }, waypoints = WaypointGroup3, delay = 90 }
Nod2 = { units = { ['e3'] = 2, ['e4'] = 2 }, waypoints = WaypointGroup3, delay = 130 }
Nod3 = { units = { ['e1'] = 2, ['e3'] = 3 }, waypoints = WaypointGroup3, delay = 50 }
Nod4 = { units = { ['bggy'] = 2 }, waypoints = WaypointGroup3, delay = 200 }
Nod5 = { units = { ['e4'] = 2, ['ltnk'] = 1 }, waypoints = WaypointGroup1, delay = 250 }
Nod6 = { units = { ['arty'] = 1 }, waypoints = WaypointGroup4, delay = 40 }
Nod7 = { units = { ['e3'] = 2, ['e4'] = 2 }, waypoints = WaypointGroup4, delay = 40 }
Nod8 = { units = { ['ltnk'] = 1, ['bggy'] = 1 }, waypoints = WaypointGroup3, delay = 170 }
Auto1 = { units = { ['e1'] = 2, ['e2'] = 2 }, waypoints = WaypointGroup5, delay = 50 }
Auto2 = { units = { ['e3'] = 3, ['e4'] = 2 }, waypoints = WaypointGroup3, delay = 50 }
Auto3 = { units = { ['ltnk'] = 1, ['bggy'] = 1 }, waypoints = WaypointGroup3, delay = 50 }
Auto4 = { units = { ['bggy'] = 2 }, waypoints = WaypointGroup7, delay = 50 }
Auto5 = { units = { ['ltnk'] = 1 }, waypoints = WaypointGroup6, delay = 50 }
Auto6 = { units = { ['arty'] = 1 }, waypoints = WaypointGroup4, delay = 50 }
Auto7 = { units = { ['e3'] = 3, ['e4'] = 2 }, waypoints = WaypointGroup6, delay = 50 }
AutoAttackWaves = { Atk1, Atk2, Nod1, Nod2, Nod3, Nod4, Nod5, Nod6, Nod7, Nod8, Auto1, Auto2, Auto3, Auto4, Auto5, Auto6, Auto7 }
StationaryGuardUnits = { Actor181, Actor182, Actor183, Actor184, Actor198, Actor199, Actor157, Actor175, Actor176, Actor173, Actor174, Actor158, Actor200, Actor159, Actor179, Actor180, Actor184, Actor185, Actor216, Actor217, Actor153, Actor215, Actor214, Actor213}
DamagedGDIAssets = { Actor126, Actor127, Actor128, Actor129, Actor130,Actor131, Actor132, Actor133, Actor134, Actor135, Actor136, Actor137, Actor138, Actor160, Actor161, Actor162, Actor163, Actor164, Actor165, Actor166, Actor168, Actor169, Actor170}
StartStationaryGuards = function(StationaryGuards)
Utils.Do(StationaryGuards, function(unit)
if not unit.IsDead then
unit.Patrol( { unit.Location } , true, 20)
end
end)
end
SendWaves = function(counter, Waves)
if counter <= #Waves then
local team = Waves[counter]
for type, amount in pairs(team.units) do
MoveAndHunt(Utils.Take(amount, Nod.GetActorsByType(type)), team.waypoints)
end
Trigger.AfterDelay(DateTime.Seconds(team.delay), function() SendWaves(counter + 1, Waves) end)
end
end
SendAttackWave = function(team)
for type, amount in pairs(team.units) do
count = 0
local actors = Nod.GetActorsByType(type)
Utils.Do(actors, function(actor)
if actor.IsIdle and count < amount then
SetAttackWaypoints(actor, team.waypoints)
IdleHunt(actor)
count = count + 1
end
end)
end
end
SetAttackWaypoints = function(actor, waypoints)
if not actor.IsDead then
Utils.Do(waypoints, function(waypoint)
actor.AttackMove(waypoint.Location)
end)
end
end
CeckRepairGDIAssetsObjective = function()
local failed = false
local repaired = true
Utils.Do(DamagedGDIAssets, function(actor)
if actor.IsDead then
failed = true
elseif actor.Health < actor.MaxHealth then
repaired = false
end
end)
if failed then
GDI.MarkFailedObjective(RepairAssets)
return
elseif repaired then
GDI.MarkCompletedObjective(RepairAssets)
return
end
Trigger.AfterDelay(DateTime.Seconds(3), function() CeckRepairGDIAssetsObjective() end)
end
WorldLoaded = function()
GDI = Player.GetPlayer("GDI")
Nod = Player.GetPlayer("Nod")
Camera.Position = DefaultCameraPosition.CenterPosition
StartStationaryGuards(StationaryGuardUnits)
StartAI()
InitObjectives(GDI)
SecureArea = GDI.AddObjective("Destroy the Nod strike force.")
KillGDI = Nod.AddObjective("Kill all enemies!")
RepairAssets = GDI.AddObjective("Repair GDI base and vehicles.", "Secondary", false)
Trigger.AfterDelay(DateTime.Seconds(5), function() CeckRepairGDIAssetsObjective() end)
AirSupport = GDI.AddObjective("Destroy the SAM sites to receive air support.", "Secondary", false)
Trigger.OnAllKilled(SamSites, function()
GDI.MarkCompletedObjective(AirSupport)
Actor.Create("airstrike.proxy", true, { Owner = GDI })
end)
local InitialArrivingUnits = { Actor166 }
Utils.Do(InitialArrivingUnits, function(unit)
unit.Move(unit.Location + CVec.New(1, 1), 0)
end)
Trigger.AfterDelay(DateTime.Minutes(1), function() SendWaves(1, AutoAttackWaves) end)
Trigger.AfterDelay(DateTime.Minutes(2), function() ProduceInfantry(handofnod) end)
Trigger.AfterDelay(DateTime.Minutes(2), function() ProduceVehicle(nodairfield) end)
end
Tick = function()
if DateTime.GameTime > DateTime.Seconds(5) then
if GDI.HasNoRequiredUnits() then
Nod.MarkCompletedObjective(KillGDI)
end
if Nod.HasNoRequiredUnits() then
GDI.MarkCompletedObjective(SecureArea)
end
end
end

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,886 @@
MapFormat: 11
RequiresMod: cnc
Title: 08a: Restore GDI Presence Near Salzburg
Author: Westwood Studios
Tileset: WINTER
MapSize: 64,64
Bounds: 3,7,51,50
Visibility: MissionSelector
Categories: Campaign
LockPreview: True
Players:
PlayerReference@Neutral:
Name: Neutral
OwnsWorld: True
NonCombatant: True
Faction: gdi
PlayerReference@Nod:
Name: Nod
Faction: nod
Color: FF1400
Allies: Nod
Enemies: GDI
Bot: campaign
PlayerReference@GDI:
Name: GDI
AllowBots: False
Playable: True
Required: True
LockFaction: True
Faction: gdi
LockColor: True
Color: F5D378
LockSpawn: True
LockTeam: True
Allies: GDI
Enemies: Nod
Actors:
Actor0: sbag
Location: 53,56
Owner: Neutral
Actor1: sbag
Location: 52,56
Owner: Neutral
Actor2: sbag
Location: 51,56
Owner: Neutral
Actor3: sbag
Location: 50,56
Owner: Neutral
Actor4: sbag
Location: 49,56
Owner: Neutral
Actor5: sbag
Location: 48,56
Owner: Neutral
Actor6: sbag
Location: 47,56
Owner: Neutral
Actor7: sbag
Location: 46,56
Owner: Neutral
Actor8: sbag
Location: 45,56
Owner: Neutral
Actor9: sbag
Location: 44,56
Owner: Neutral
Actor10: sbag
Location: 43,56
Owner: Neutral
Actor11: sbag
Location: 41,56
Owner: Neutral
Actor12: sbag
Location: 40,56
Owner: Neutral
Actor13: wood
Location: 5,56
Owner: Neutral
Actor14: wood
Location: 4,56
Owner: Neutral
Actor15: wood
Location: 3,56
Owner: Neutral
Actor16: sbag
Location: 53,55
Owner: Neutral
Actor17: sbag
Location: 40,55
Owner: Neutral
Actor18: v18
Location: 5,55
Owner: Neutral
Actor19: v17
Location: 4,55
Owner: Neutral
Actor20: sbag
Location: 53,54
Owner: Neutral
Actor21: sbag
Location: 40,54
Owner: Neutral
Actor22: wood
Location: 17,54
Owner: Neutral
Actor23: wood
Location: 16,54
Owner: Neutral
Actor24: wood
Location: 15,54
Owner: Neutral
Actor25: wood
Location: 14,54
Owner: Neutral
Actor26: wood
Location: 11,54
Owner: Neutral
Actor27: wood
Location: 10,54
Owner: Neutral
Actor28: v14
Location: 6,54
Owner: Neutral
Actor29: v15
Location: 5,54
Owner: Neutral
Actor30: v16
Location: 4,54
Owner: Neutral
Actor31: sbag
Location: 53,53
Owner: Neutral
Actor32: wood
Location: 6,53
Owner: Neutral
Actor33: wood
Location: 17,52
Owner: Neutral
Actor34: wood
Location: 16,52
Owner: Neutral
Actor35: wood
Location: 15,52
Owner: Neutral
Actor36: wood
Location: 14,52
Owner: Neutral
Actor37: wood
Location: 11,52
Owner: Neutral
Actor38: wood
Location: 10,52
Owner: Neutral
Actor39: sbag
Location: 53,51
Owner: Neutral
Actor40: sbag
Location: 53,50
Owner: Neutral
Actor41: sbag
Location: 40,50
Owner: Neutral
Actor42: sbag
Location: 53,49
Owner: Neutral
Actor43: sbag
Location: 40,49
Owner: Neutral
Actor44: sbag
Location: 53,48
Owner: Neutral
Actor45: sbag
Location: 53,47
Owner: Neutral
Actor46: sbag
Location: 40,47
Owner: Neutral
Actor47: sbag
Location: 53,46
Owner: Neutral
Actor48: sbag
Location: 52,46
Owner: Neutral
Actor49: sbag
Location: 51,46
Owner: Neutral
Actor50: sbag
Location: 50,46
Owner: Neutral
Actor51: sbag
Location: 49,46
Owner: Neutral
Actor52: sbag
Location: 48,46
Owner: Neutral
Actor53: sbag
Location: 42,46
Owner: Neutral
Actor54: sbag
Location: 41,46
Owner: Neutral
Actor55: sbag
Location: 40,46
Owner: Neutral
Actor56: t01
Location: 33,32
Owner: Neutral
Actor57: t01
Location: 33,34
Owner: Neutral
Actor58: tc01
Location: 47,27
Owner: Neutral
Actor59: t01
Location: 42,18
Owner: Neutral
Actor60: t01
Location: 41,16
Owner: Neutral
Actor61: t01
Location: 36,18
Owner: Neutral
Actor62: t01
Location: 15,50
Owner: Neutral
Actor63: t01
Location: 6,54
Owner: Neutral
Actor64: t01
Location: 11,48
Owner: Neutral
Actor65: tc01
Location: 14,33
Owner: Neutral
Actor66: tc04
Location: 17,35
Owner: Neutral
Actor67: tc01
Location: 9,19
Owner: Neutral
Actor68: tc04
Location: 11,20
Owner: Neutral
Actor69: t06
Location: 37,8
Owner: Neutral
Actor70: t03
Location: 33,8
Owner: Neutral
Actor71: t02
Location: 36,9
Owner: Neutral
Actor72: t01
Location: 32,7
Owner: Neutral
Actor73: tc04
Location: 50,9
Owner: Neutral
Actor74: tc01
Location: 45,7
Owner: Neutral
Actor75: tc01
Location: 38,13
Owner: Neutral
Actor76: tc02
Location: 35,22
Owner: Neutral
Actor77: tc05
Location: 32,21
Owner: Neutral
Actor78: t10
Location: 17,47
Owner: Neutral
Actor79: t13
Location: 16,50
Owner: Neutral
Actor80: tc01
Location: 15,48
Owner: Neutral
Actor81: tc02
Location: 6,51
Owner: Neutral
Actor82: tc02
Location: 3,47
Owner: Neutral
Actor83: tc04
Location: 3,51
Owner: Neutral
Actor84: tc04
Location: 5,47
Owner: Neutral
Actor85: tc04
Location: 9,54
Owner: Neutral
Actor86: tc04
Location: 3,40
Owner: Neutral
Actor87: t13
Location: 4,42
Owner: Neutral
Actor88: t11
Location: 10,12
Owner: Neutral
Actor89: t15
Location: 4,10
Owner: Neutral
Actor90: t16
Location: 3,9
Owner: Neutral
Actor91: tc02
Location: 5,12
Owner: Neutral
Actor92: tc01
Location: 4,7
Owner: Neutral
Actor93: tc04
Location: 20,11
Owner: Neutral
Actor94: tc04
Location: 19,47
Owner: Neutral
Actor95: tc05
Location: 20,49
Owner: Neutral
Actor96: tc04
Location: 40,17
Owner: Neutral
Actor97: tc01
Location: 44,36
Owner: Neutral
Actor98: tc04
Location: 39,37
Owner: Neutral
Actor99: tc02
Location: 40,30
Owner: Neutral
Actor100: tc02
Location: 30,32
Owner: Neutral
Actor101: t10
Location: 32,33
Owner: Neutral
Actor102: tc04
Location: 37,54
Owner: Neutral
Actor103: tc02
Location: 34,53
Owner: Neutral
Actor104: t01
Location: 31,53
Owner: Neutral
Actor105: t01
Location: 16,54
Owner: Neutral
Actor106: t02
Location: 18,55
Owner: Neutral
Actor107: t11
Location: 25,32
Owner: Neutral
Actor108: t11
Location: 41,44
Owner: Neutral
Actor109: tc01
Location: 51,44
Owner: Neutral
Actor110: tc04
Location: 27,40
Owner: Neutral
Actor111: tc05
Location: 30,42
Owner: Neutral
Actor112: t07
Location: 31,39
Owner: Neutral
Actor113: t06
Location: 26,42
Owner: Neutral
Actor114: t03
Location: 28,43
Owner: Neutral
sam1: sam
Location: 11,20
Owner: Nod
sam2: sam
Location: 33,18
Owner: Nod
sam3: sam
Location: 16,7
Owner: Nod
Actor118: v05
Location: 17,49
Owner: Neutral
Actor119: v07
Location: 9,49
Owner: Neutral
Actor120: v06
Location: 4,53
Owner: Neutral
Actor121: v05
Location: 6,49
Owner: Neutral
Actor122: v04
Location: 4,50
Owner: Neutral
Actor123: v03
Location: 10,50
Owner: Neutral
Actor124: v01
Location: 3,48
Owner: Neutral
Actor125: v06
Location: 20,49
Owner: Neutral
Actor126: gtwr
Location: 41,54
Owner: GDI
Health: 41
Actor127: gtwr
Location: 41,50
Owner: GDI
Health: 16
Actor128: hq
Location: 51,47
Owner: GDI
Health: 39
Actor129: proc
Location: 44,46
Owner: GDI
Health: 33
FreeActor: False
Actor130: silo
Location: 49,54
Owner: GDI
Health: 53
Actor131: silo
Location: 47,47
Owner: GDI
Health: 20
Actor132: silo
Location: 47,53
Owner: GDI
Health: 13
Actor133: silo
Location: 51,54
Owner: GDI
Health: 28
Actor134: nuke
Location: 49,51
Owner: GDI
Health: 14
Actor135: nuke
Location: 49,48
Owner: GDI
Health: 20
Actor136: nuke
Location: 51,50
Owner: GDI
Health: 35
Actor137: pyle
Location: 47,49
Owner: GDI
Health: 18
Actor138: fix
Location: 44,52
Owner: GDI
Health: 28
gun1: gun
Location: 21,19
Owner: Nod
NodYard: fact
Location: 7,11
Owner: Nod
nodrefinery: proc
Location: 24,16
Owner: Nod
FreeActor: False
nodsilo1: silo
Location: 29,17
Owner: Nod
nodsilo2: silo
Location: 9,7
Owner: Nod
nodsilo3: silo
Location: 12,9
Owner: Nod
nodsilo4: silo
Location: 11,7
Owner: Nod
nodairfield: afld
Location: 27,14
Owner: Nod
nodpower1: nuke
Location: 23,14
Owner: Nod
nodpower2: nuke
Location: 10,9
Owner: Nod
nodpower3: nuke
Location: 6,8
Owner: Nod
nodpower4: nuke
Location: 8,8
Owner: Nod
handofnod: hand
Location: 27,17
Owner: Nod
gun2: gun
Location: 26,21
Owner: Nod
Actor153: arty
Location: 4,12
Owner: Nod
Facing: 127
Actor154: bggy
Location: 20,18
Owner: Nod
Actor155: ltnk
Location: 19,18
Owner: Nod
Actor156: bggy
Location: 10,21
Owner: Nod
Facing: 95
Actor157: ltnk
Location: 40,35
Owner: Nod
Facing: 159
Actor158: ltnk
Location: 45,23
Owner: Nod
Facing: 95
Actor159: ltnk
Location: 41,14
Owner: Nod
Facing: 159
Actor160: mtnk
Location: 42,55
Owner: GDI
Health: 35
Facing: 223
Actor161: mtnk
Location: 33,52
Owner: GDI
Health: 43
Facing: 31
Actor162: apc
Location: 37,50
Owner: GDI
Health: 68
Facing: 127
Actor163: apc
Location: 39,48
Owner: GDI
Health: 45
Facing: 127
Actor164: msam
Location: 42,49
Owner: GDI
Health: 40
Facing: 95
Actor165: msam
Location: 41,51
Owner: GDI
Health: 50
Facing: 159
Actor166: msam
Location: 33,48
Owner: GDI
Health: 65
Facing: 159
Actor167: harv
Location: 23,23
Owner: Nod
Facing: 95
Actor168: harv
Location: 38,53
Owner: GDI
Health: 51
Facing: 31
Actor169: jeep
Location: 36,52
Owner: GDI
Health: 72
Facing: 95
Actor170: jeep
Location: 34,51
Owner: GDI
Health: 31
Facing: 159
Actor171: arty
Location: 19,17
Owner: Nod
Actor172: ltnk
Location: 22,11
Owner: Nod
Facing: 159
Actor173: e1
Location: 45,36
Owner: Nod
SubCell: 3
Actor174: e1
Location: 44,36
Owner: Nod
SubCell: 4
Actor175: e3
Location: 41,36
Owner: Nod
Facing: 159
SubCell: 2
Actor176: e3
Location: 41,36
Owner: Nod
Facing: 159
SubCell: 3
Actor177: e3
Location: 42,17
Owner: Nod
Facing: 159
SubCell: 0
Actor178: e3
Location: 40,17
Owner: Nod
Facing: 159
SubCell: 4
Actor179: e4
Location: 42,15
Owner: Nod
Facing: 159
SubCell: 2
Actor180: e4
Location: 42,15
Owner: Nod
Facing: 159
SubCell: 3
Actor181: e1
Location: 16,53
Owner: Nod
Facing: 191
SubCell: 3
Actor182: e1
Location: 15,53
Owner: Nod
Facing: 191
SubCell: 2
Actor183: e1
Location: 17,53
Owner: Nod
Facing: 191
SubCell: 3
Actor184: e1
Location: 16,53
Owner: Nod
Facing: 191
SubCell: 2
Actor185: c3
Location: 18,50
Owner: Neutral
Facing: 159
SubCell: 1
Actor186: e1
Location: 46,51
Owner: GDI
Facing: 159
SubCell: 1
Actor187: e1
Location: 44,52
Owner: GDI
Health: 87
Facing: 223
SubCell: 2
Actor188: e1
Location: 43,53
Owner: GDI
Health: 31
Facing: 31
SubCell: 4
Actor189: e1
Location: 42,54
Owner: GDI
Health: 75
SubCell: 2
Actor190: e1
Location: 39,52
Owner: GDI
Health: 77
Facing: 159
SubCell: 4
Actor191: e1
Location: 42,53
Owner: GDI
Health: 69
Facing: 159
SubCell: 0
Actor192: e2
Location: 40,53
Owner: GDI
Health: 75
Facing: 31
SubCell: 2
Actor193: e2
Location: 45,51
Owner: GDI
Facing: 127
SubCell: 1
Actor194: e2
Location: 38,50
Owner: GDI
Health: 27
Facing: 223
SubCell: 0
Actor195: e2
Location: 46,52
Owner: GDI
Facing: 31
SubCell: 1
Actor196: e2
Location: 36,53
Owner: GDI
Health: 57
Facing: 159
SubCell: 0
Actor197: e2
Location: 37,54
Owner: GDI
Facing: 31
SubCell: 1
Actor198: e3
Location: 27,40
Owner: Nod
SubCell: 4
Actor199: e3
Location: 29,40
Owner: Nod
SubCell: 3
Actor200: e3
Location: 48,27
Owner: Nod
SubCell: 3
Actor201: e1
Location: 27,21
Owner: Nod
SubCell: 3
Actor202: e1
Location: 27,21
Owner: Nod
SubCell: 4
Actor203: e1
Location: 27,21
Owner: Nod
SubCell: 2
Actor204: e1
Location: 27,21
Owner: Nod
SubCell: 1
Actor205: e3
Location: 28,21
Owner: Nod
SubCell: 4
Actor206: e3
Location: 28,21
Owner: Nod
SubCell: 2
Actor207: e3
Location: 29,21
Owner: Nod
SubCell: 1
Actor208: e3
Location: 29,21
Owner: Nod
SubCell: 3
Actor209: e4
Location: 30,21
Owner: Nod
SubCell: 1
Actor210: e4
Location: 30,21
Owner: Nod
SubCell: 3
Actor211: e4
Location: 30,21
Owner: Nod
SubCell: 2
Actor212: e4
Location: 30,21
Owner: Nod
SubCell: 4
Actor213: e1
Location: 13,12
Owner: Nod
SubCell: 3
Actor214: e1
Location: 14,12
Owner: Nod
SubCell: 1
Actor215: e1
Location: 15,11
Owner: Nod
SubCell: 0
Actor216: e3
Location: 5,7
Owner: Nod
SubCell: 3
Actor217: e3
Location: 7,7
Owner: Nod
SubCell: 3
Actor218: e3
Location: 19,15
Owner: Nod
SubCell: 1
Actor219: e3
Location: 20,16
Owner: Nod
SubCell: 1
DefaultChinookTarget: waypoint
Location: 41,56
Owner: Neutral
DefaultCameraPosition: waypoint
Location: 41,49
Owner: Neutral
waypoint16: waypoint
Location: 10,22
Owner: Neutral
waypoint15: waypoint
Location: 53,45
Owner: Neutral
waypoint14: waypoint
Location: 53,40
Owner: Neutral
waypoint13: waypoint
Location: 13,26
Owner: Neutral
waypoint12: waypoint
Location: 52,25
Owner: Neutral
waypoint11: waypoint
Location: 36,27
Owner: Neutral
waypoint10: waypoint
Location: 38,32
Owner: Neutral
waypoint9: waypoint
Location: 47,43
Owner: Neutral
waypoint8: waypoint
Location: 24,55
Owner: Neutral
waypoint7: waypoint
Location: 43,40
Owner: Neutral
waypoint6: waypoint
Location: 24,38
Owner: Neutral
waypoint5: waypoint
Location: 20,29
Owner: Neutral
waypoint4: waypoint
Location: 23,24
Owner: Neutral
waypoint3: waypoint
Location: 5,43
Owner: Neutral
waypoint2: waypoint
Location: 8,47
Owner: Neutral
waypoint1: waypoint
Location: 8,53
Owner: Neutral
waypoint0: waypoint
Location: 19,53
Owner: Neutral
Rules: cnc|rules/campaign-maprules.yaml, cnc|rules/campaign-tooltips.yaml, cnc|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -0,0 +1,154 @@
World:
LuaScript:
Scripts: campaign-global.lua, gdi08a.lua, gdi08a-AI.lua
MusicPlaylist:
StartingMusic: march
VictoryMusic: gdi_win1
MissionData:
Briefing: U.N. Sanction has cut funding to the Global Defense Initiative. Field Units are helpless.\n\nUse the repair facility to keep your units in the field long enough to destroy the Nod base in this region.\n\nAll Nod units and structures must be destroyed.
BriefingVideo: gdi8a.vqa
BackgroundVideo: tbrinfo1.vqa
WinVideo: paratrop.vqa
LossVideo: gameover.vqa
SmudgeLayer@SCORCH:
InitialSmudges:
42,56: sc1,0
41,52: sc6,0
38,51: sc2,0
43,50: sc3,0
40,48: sc4,0
47,46: sc5,0
ATWR:
Buildable:
Prerequisites: ~disabled
NUK2:
Buildable:
Prerequisites: ~disabled
HPAD:
Buildable:
Prerequisites: ~disabled
BRIK:
Buildable:
Prerequisites: ~disabled
EYE:
Buildable:
Prerequisites: ~disabled
OBLI:
Buildable:
Prerequisites: ~disabled
TMPL:
Buildable:
Prerequisites: ~disabled
HTNK:
Buildable:
Prerequisites: ~disabled
TRAN:
Buildable:
Prerequisites: ~disabled
ORCA:
Buildable:
Prerequisites: ~disabled
RMBO:
Buildable:
Prerequisites: ~disabled
MSAM:
Buildable:
Prerequisites: ~disabled
MCV:
Buildable:
Prerequisites: ~disabled
BOAT:
Buildable:
Prerequisites: ~disabled
FTNK:
Buildable:
Prerequisites: ~disabled
STNK:
Buildable:
Prerequisites: ~disabled
HELI:
Buildable:
Prerequisites: ~disabled
LTNK:
Buildable:
Prerequisites: ~afld
ARTY:
Buildable:
Prerequisites: ~disabled
E4:
Buildable:
Prerequisites: barracks
E5:
Buildable:
Prerequisites: ~disabled
MLRS:
Buildable:
Prerequisites: ~disabled
CYCL:
Buildable:
Prerequisites: ~disabled
GTWR:
Buildable:
Prerequisites: ~disabled
SBAG:
Buildable:
Queue: Defence.GDI, Defence.Nod
GUN:
Buildable:
Queue: Defence.GDI, Defence.Nod
C3:
Tooltip:
Name: Farmer Mike
SAM:
Buildable:
Prerequisites: ~disabled
^Bridge:
DamageMultiplier@INVULNERABLE:
Modifier: 0
BRIDGEHUT:
-Targetable:
airstrike.proxy:
AirstrikePower:
SquadSize: 2
SquadOffset: -1536, 1024, 0
HQ:
Tooltip:
-AirstrikePower:
Buildable:
Description: Provides an overview of the battlefield.\n Requires power to operate.
AFLD:
RallyPoint:
Offset: -5, 2

View File

@@ -0,0 +1,204 @@
--[[
Copyright 2007-2020 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.
]]
AttackPaths = { { waypoint7 }, { waypoint8 } }
NodBase = { handofnod, nodairfield, nodrefinery, NodCYard, nodpower1, nodpower2, nodpower3, nodpower4, nodpower5, gun5, gun6, gun7, gun8, nodsilo1, nodsilo2, nodsilo3, nodsilo4, nodobelisk }
PatrolProductionQueue = { }
InfantryAttackGroup = { }
InfantryGroupSize = 5
InfantryProductionCooldown = DateTime.Minutes(3)
InfantryProductionTypes = { "e1", "e1", "e1", "e3", "e3", "e4" }
HarvesterProductionType = { "harv" }
VehicleAttackGroup = { }
VehicleGroupSize = 5
VehicleProductionCooldown = DateTime.Minutes(3)
VehicleProductionTypes = { "bggy", "bggy", "bggy", "ltnk", "ltnk", "arty" }
StartingCash = 14000
BaseRefinery = { type = "proc", pos = CPos.New(12, 25) }
BaseNuke1 = { type = "nuke", pos = CPos.New(5, 24) }
BaseNuke2 = { type = "nuke", pos = CPos.New(3, 24) }
BaseNuke3 = { type = "nuke", pos = CPos.New(16, 30) }
BaseNuke4 = { type = "nuke", pos = CPos.New(14, 30) }
BaseNuke5 = { type = "nuke", pos = CPos.New(12, 30) }
InfantryProduction = { type = "hand", pos = CPos.New(15, 24) }
VehicleProduction = { type = "afld", pos = CPos.New(3, 27) }
NodGuards = { Actor168, Actor169, Actor170, Actor171, Actor172, Actor181, Actor177, Actor188, Actor189, Actor190 }
BaseBuildings = { BaseRefinery, BaseNuke1, BaseNuke2, BaseNuke3, BaseNuke4, InfantryProduction, VehicleProduction }
BuildBuilding = function(building, cyard)
local buildingCost = Actor.Cost(building.type)
if CyardIsBuilding or Nod.Cash < buildingCost then
Trigger.AfterDelay(DateTime.Seconds(10), function() BuildBuilding(building, cyard) end)
return
end
CyardIsBuilding = true
Nod.Cash = Nod.Cash - buildingCost
Trigger.AfterDelay(Actor.BuildTime(building.type), function()
CyardIsBuilding = false
if cyard.IsDead or cyard.Owner ~= Nod then
Nod.Cash = Nod.Cash + buildingCost
return
end
local actor = Actor.Create(building.type, true, { Owner = Nod, Location = building.pos })
if actor.Type == 'hand' or actor.Type == 'pyle' then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(actor) end)
elseif actor.Type == 'afld' or actor.Type == 'weap' then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(actor) end)
end
Trigger.OnKilled(actor, function()
BuildBuilding(building, cyard)
end)
RepairBuilding(Nod, actor, 0.75)
end)
end
HasHarvester = function()
local harv = Nod.GetActorsByType("harv")
return #harv > 0
end
GuardBase = function()
Utils.Do(NodBase, function(building)
Trigger.OnDamaged(building, function()
if not building.IsDead then
Utils.Do(NodGuards, function(guard)
if not guard.IsDead then
guard.Stop()
guard.Guard(building)
end
end)
end
end)
end)
end
ProduceHarvester = function(building)
if not buildingHarvester then
buildingHarvester = true
building.Build(HarvesterProductionType, function()
buildingHarvester = false
end)
end
end
ProduceInfantry = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not HasHarvester() then
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(building) end)
return
end
if #PatrolProductionQueue >= 1 then
local inQueue = PatrolProductionQueue[1]
local toBuild = { inQueue.unit[1] }
local patrolPath = inQueue.waypoints
building.Build(toBuild, function(unit)
ReplenishPatrolUnit(unit[1], handofnod, patrolPath, 40)
table.remove(PatrolProductionQueue, 1)
end)
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(3), DateTime.Seconds(9))
local toBuild = { Utils.Random(InfantryProductionTypes) }
local Path = Utils.Random(AttackPaths)
building.Build(toBuild, function(unit)
InfantryAttackGroup[#InfantryAttackGroup + 1] = unit[1]
if #InfantryAttackGroup >= InfantryGroupSize then
MoveAndHunt(InfantryAttackGroup, Path)
InfantryAttackGroup = { }
Trigger.AfterDelay(InfantryProductionCooldown, function() ProduceInfantry(building) end)
else
Trigger.AfterDelay(delay, function() ProduceInfantry(building) end)
end
end)
end
ProduceVehicle = function(building)
if building.IsDead or building.Owner ~= Nod then
return
elseif not HasHarvester() then
ProduceHarvester(building)
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(building) end)
return
end
local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17))
local toBuild = { Utils.Random(VehicleProductionTypes) }
local Path = Utils.Random(AttackPaths)
building.Build(toBuild, function(unit)
VehicleAttackGroup[#VehicleAttackGroup + 1] = unit[1]
if #VehicleAttackGroup >= VehicleGroupSize then
MoveAndHunt(VehicleAttackGroup, Path)
VehicleAttackGroup = { }
Trigger.AfterDelay(VehicleProductionCooldown, function() ProduceVehicle(building) end)
else
Trigger.AfterDelay(delay, function() ProduceVehicle(building) end)
end
end)
end
StartAI = function()
RepairNamedActors(Nod, 0.75)
Nod.Cash = StartingCash
GuardBase()
end
Trigger.OnAllKilledOrCaptured(NodBase, function()
Utils.Do(Nod.GetGroundAttackers(), IdleHunt)
end)
Trigger.OnKilled(nodrefinery, function(building)
BuildBuilding(BaseRefinery, NodCYard)
end)
Trigger.OnKilled(nodpower1, function(building)
BuildBuilding(BaseNuke1, NodCYard)
end)
Trigger.OnKilled(nodpower2, function(building)
BuildBuilding(BaseNuke2, NodCYard)
end)
Trigger.OnKilled(nodpower3, function(building)
BuildBuilding(BaseNuke3, NodCYard)
end)
Trigger.OnKilled(nodpower4, function(building)
BuildBuilding(BaseNuke4, NodCYard)
end)
Trigger.OnKilled(nodpower5, function(building)
BuildBuilding(BaseNuke5, NodCYard)
end)
Trigger.OnKilled(handofnod, function(building)
BuildBuilding(InfantryProduction, NodCYard)
end)
Trigger.OnKilled(nodairfield, function(building)
BuildBuilding(VehicleProduction, NodCYard)
end)

View File

@@ -0,0 +1,170 @@
--[[
Copyright 2007-2020 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.
]]
InsertionHelicopterType = "tran.insertion"
GDIHeliReinfUnits = { "e2", "e2", "e2", "e3", "e3" }
SamSites = { sam1, sam2, sam3, sam4 }
NodBunkersNorth = { gun3, gun4 }
NodBunkersSouth = { gun1, gun2 }
BoatEscapeTrigger = { CPos.New(2,37) }
WaypointGroup1 = { waypoint1, waypoint2, waypoint8 }
WaypointGroup2 = { waypoint1, waypoint2, waypoint3, waypoint9 }
WaypointGroup3 = { waypoint1, waypoint2, waypoint3, waypoint10, waypoint11, waypoint12, waypoint6, waypoint13 }
WaypointGroup4 = { waypoint1, waypoint2, waypoint3, waypoint4 }
Patrol1Waypoints = { waypoint11.Location, waypoint10.Location }
Patrol2Waypoints = { waypoint1.Location, waypoint2.Location, waypoint3.Location, waypoint4.Location, waypoint5.Location, waypoint4.Location, waypoint3.Location, waypoint2.Location, waypoint1.Location, waypoint6.Location }
Nod1 = { units = { ['e1'] = 2, ['e3'] = 2 }, waypoints = WaypointGroup1, delay = 40 }
Nod2 = { units = { ['e3'] = 2, ['e4'] = 2 }, waypoints = WaypointGroup2, delay = 50 }
Nod3 = { units = { ['e1'] = 2, ['e3'] = 3, ['e4'] = 2 }, waypoints = WaypointGroup1, delay = 50 }
Nod4 = { units = { ['bggy'] = 2 }, waypoints = WaypointGroup2, delay = 50 }
Nod5 = { units = { ['e4'] = 2, ['ltnk'] = 1 }, waypoints = WaypointGroup1, delay = 50 }
Auto1 = { units = { ['e4'] = 2, ['arty'] = 1 }, waypoints = WaypointGroup1, delay = 50 }
Auto2 = { units = { ['e1'] = 2, ['e3'] = 2 }, waypoints = WaypointGroup2, delay = 50 }
Auto3 = { units = { ['e3'] = 2, ['e4'] = 2 }, waypoints = WaypointGroup1, delay = 50 }
Auto4 = { units = { ['e1'] = 3, ['e4'] = 1 }, waypoints = WaypointGroup1, delay = 50 }
Auto5 = { units = { ['ltnk'] = 1, ['bggy'] = 1 }, waypoints = WaypointGroup1, delay = 60 }
Auto6 = { units = { ['bggy'] = 1 }, waypoints = WaypointGroup2, delay = 50 }
Auto7 = { units = { ['ltnk'] = 1 }, waypoints = WaypointGroup2, delay = 50 }
Auto8 = { units = { ['e4'] = 2, ['bggy'] = 1 }, waypoints = WaypointGroup4, delay = 0 }
Patrols = {
grd1 = { units = { ['e3'] = 3 }, waypoints = Patrol1Waypoints, wait = 40, initialWaypointPlacement = { 1 } },
grd2 = { units = { ['e1'] = 2, ['e3'] = 2, ['e4'] = 2 }, waypoints = Patrol2Waypoints, wait = 20, initialWaypointPlacement = { 4, 10, 1 } }
}
AutoAttackWaves = { Nod1, Nod2, Nod3, Nod4, Nod5, Auto1, Auto2, Auto3, Auto4, Auto5, Auto6, Auto7, Auto8 }
StationaryGuards = { Actor174, Actor173, Actor182, Actor183, Actor184, Actor185, Actor186, Actor187 , Actor199, Actor200, Actor201, Actor202, Actor203, Actor204 }
StartStationaryGuards = function()
Utils.Do(StationaryGuards, function(unit)
if not unit.IsDead then
unit.Patrol( { unit.Location } , true, 20)
end
end)
end
SendWaves = function(counter, Waves)
if counter <= #Waves then
local team = Waves[counter]
for type, amount in pairs(team.units) do
MoveAndHunt(Utils.Take(amount, Nod.GetActorsByType(type)), team.waypoints)
end
Trigger.AfterDelay(DateTime.Seconds(team.delay), function() SendWaves(counter + 1, Waves) end)
end
end
StartPatrols = function()
for k, team in pairs(Patrols) do
local group = 1
for type, amount in pairs(team.units) do
for i = 1, amount do
Reinforcements.Reinforce(Nod, { type }, { team.waypoints[team.initialWaypointPlacement[group]] }, 0, function(unit)
ReplenishPatrolUnit(unit, handofnod, team.waypoints, team.wait)
end)
end
group = group + 1
end
end
Patrols = nil
end
ReplenishPatrolUnit = function(unit, building, waypoints, waitatwaypoint)
unit.Patrol(waypoints, true, waitatwaypoint)
Trigger.OnKilled(unit, function()
local queueUnit = { unit = { unit.Type }, atbuilding = { building }, waypoints = waypoints }
PatrolProductionQueue[#PatrolProductionQueue + 1] = queueUnit
end)
end
SendGDIReinforcements = function()
Media.PlaySpeechNotification(GDI, "Reinforce")
Reinforcements.ReinforceWithTransport(GDI, InsertionHelicopterType, GDIHeliReinfUnits, { GDIHeliEntryNorth.Location, GDIHeliLZ.Location }, { GDIHeliLZ.Location + CVec.New(20, 0) })
end
SendGDIReinforcementChinook = function()
Reinforcements.ReinforceWithTransport(GDI, 'tran', nil, { GDIHeliEntryNorth.Location, GDIHeliLZ.Location })
end
SpawnGunboat = function()
Media.PlaySpeechNotification(GDI, "Reinforce")
Actor.Create("boat", true, { Owner = GDI, Facing = 0, Location = CPos.New(62,37) })
end
WorldLoaded = function()
GDI = Player.GetPlayer("GDI")
Nod = Player.GetPlayer("Nod")
Camera.Position = DefaultCameraPosition.CenterPosition
DestroyBunkers = GDI.AddObjective("Destroy the Nod bunkers to allow Carter's\nconvoy to pass through safely.")
Trigger.OnAllKilled(NodBunkersNorth, function()
GDI.MarkCompletedObjective(DestroyBunkers)
Trigger.AfterDelay(DateTime.Seconds(1), SpawnGunboat)
end)
Trigger.OnAllKilled(NodBunkersSouth, function()
GDI.MarkCompletedObjective(DestroyBunkers)
SendGDIReinforcementChinook()
Trigger.AfterDelay(DateTime.Seconds(1), SpawnGunboat)
end)
Trigger.OnEnteredFootprint(BoatEscapeTrigger, function(a, id)
if a.Type == "boat" then
a.Destroy()
Media.DisplayMessage("Part of Carter's convoy passed through!")
Media.PlaySoundNotification(GDI, "AlertBleep")
end
end)
SecureArea = GDI.AddObjective("Destroy the Nod strike force.")
KillGDI = Nod.AddObjective("Kill all enemies!")
Trigger.AfterDelay(DateTime.Seconds(5), SendGDIReinforcements)
AirSupport = GDI.AddObjective("Destroy the SAM sites to receive air support.", "Secondary", false)
Trigger.OnAllKilled(SamSites, function()
GDI.MarkCompletedObjective(AirSupport)
Actor.Create("airstrike.proxy", true, { Owner = GDI })
end)
Actor.Create("flare", true, { Owner = GDI, Location = DefaultFlareLocation.Location })
StartStationaryGuards()
StartAI()
StartPatrols()
InitObjectives(GDI)
Trigger.AfterDelay(DateTime.Minutes(1), function() SendWaves(1, AutoAttackWaves) end)
Trigger.AfterDelay(DateTime.Minutes(3), function() ProduceInfantry(handofnod) end)
Trigger.AfterDelay(DateTime.Minutes(3), function() ProduceVehicle(nodairfield) end)
local initialArrivingUnits = { Actor175, Actor191, Actor192, Actor193, Actor194, Actor195, Actor196, Actor197, Actor198 }
Utils.Do(initialArrivingUnits, function(unit)
unit.Move(unit.Location + CVec.New(0, 1), 0)
end)
end
Tick = function()
if DateTime.GameTime > DateTime.Seconds(5) then
if GDI.HasNoRequiredUnits() then
Nod.MarkCompletedObjective(KillGDI)
end
if Nod.HasNoRequiredUnits() then
GDI.MarkCompletedObjective(SecureArea)
end
end
end

BIN
mods/cnc/maps/gdi09/map.bin Normal file

Binary file not shown.

BIN
mods/cnc/maps/gdi09/map.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,782 @@
MapFormat: 11
RequiresMod: cnc
Title: 09: Secure the Danube
Author: Westwood Studios
Tileset: WINTER
MapSize: 64,64
Bounds: 2,3,60,48
Visibility: MissionSelector
Categories: Campaign
LockPreview: True
Players:
PlayerReference@Neutral:
Name: Neutral
OwnsWorld: True
NonCombatant: True
Faction: gdi
PlayerReference@Nod:
Name: Nod
Faction: nod
Color: FF1400
Allies: Nod
Enemies: GDI
Bot: campaign
PlayerReference@GDI:
Name: GDI
AllowBots: False
Playable: True
Required: True
LockFaction: True
Faction: gdi
LockColor: True
Color: F5D378
LockSpawn: True
LockTeam: True
Allies: GDI
Enemies: Nod
Actors:
Actor0: sbag
Location: 30,43
Owner: Neutral
Actor1: sbag
Location: 29,43
Owner: Neutral
Actor2: sbag
Location: 28,43
Owner: Neutral
Actor3: sbag
Location: 27,43
Owner: Neutral
Actor4: sbag
Location: 26,43
Owner: Neutral
Actor5: sbag
Location: 30,42
Owner: Neutral
Actor6: sbag
Location: 28,42
Owner: Neutral
Actor7: sbag
Location: 26,42
Owner: Neutral
Actor8: sbag
Location: 35,33
Owner: Neutral
Actor9: sbag
Location: 33,33
Owner: Neutral
Actor10: sbag
Location: 31,33
Owner: Neutral
Actor11: brik
Location: 21,33
Owner: Neutral
Actor12: brik
Location: 20,33
Owner: Neutral
Actor13: brik
Location: 19,33
Owner: Neutral
Actor14: brik
Location: 18,33
Owner: Neutral
Actor15: brik
Location: 17,33
Owner: Neutral
Actor16: brik
Location: 16,33
Owner: Neutral
Actor17: brik
Location: 15,33
Owner: Neutral
Actor18: brik
Location: 14,33
Owner: Neutral
Actor19: brik
Location: 13,33
Owner: Neutral
Actor20: brik
Location: 12,33
Owner: Neutral
Actor21: brik
Location: 11,33
Owner: Neutral
Actor22: brik
Location: 10,33
Owner: Neutral
Actor23: brik
Location: 9,33
Owner: Neutral
Actor24: brik
Location: 8,33
Owner: Neutral
Actor25: brik
Location: 7,33
Owner: Neutral
Actor26: brik
Location: 6,33
Owner: Neutral
Actor27: brik
Location: 5,33
Owner: Neutral
Actor28: brik
Location: 4,33
Owner: Neutral
Actor29: brik
Location: 3,33
Owner: Neutral
Actor30: brik
Location: 2,33
Owner: Neutral
Actor31: sbag
Location: 35,32
Owner: Neutral
Actor32: sbag
Location: 34,32
Owner: Neutral
Actor33: sbag
Location: 33,32
Owner: Neutral
Actor34: sbag
Location: 32,32
Owner: Neutral
Actor35: sbag
Location: 31,32
Owner: Neutral
Actor36: brik
Location: 21,32
Owner: Neutral
Actor37: brik
Location: 2,32
Owner: Neutral
Actor38: brik
Location: 21,31
Owner: Neutral
Actor39: brik
Location: 20,31
Owner: Neutral
Actor40: brik
Location: 2,31
Owner: Neutral
Actor41: brik
Location: 21,30
Owner: Neutral
Actor42: brik
Location: 20,30
Owner: Neutral
Actor43: brik
Location: 2,30
Owner: Neutral
Actor44: wood
Location: 31,29
Owner: Neutral
Actor45: brik
Location: 2,29
Owner: Neutral
Actor46: wood
Location: 31,28
Owner: Neutral
Actor47: brik
Location: 2,28
Owner: Neutral
Actor48: wood
Location: 42,27
Owner: Neutral
Actor49: wood
Location: 41,27
Owner: Neutral
Actor50: wood
Location: 40,27
Owner: Neutral
Actor51: wood
Location: 39,27
Owner: Neutral
Actor52: brik
Location: 2,27
Owner: Neutral
Actor53: wood
Location: 42,26
Owner: Neutral
Actor54: v16
Location: 41,26
Owner: Neutral
Actor55: v18
Location: 40,26
Owner: Neutral
Actor56: wood
Location: 39,26
Owner: Neutral
Actor57: brik
Location: 21,26
Owner: Neutral
Actor58: brik
Location: 20,26
Owner: Neutral
Actor59: brik
Location: 2,26
Owner: Neutral
Actor60: wood
Location: 42,25
Owner: Neutral
Actor61: v14
Location: 41,25
Owner: Neutral
Actor62: v15
Location: 40,25
Owner: Neutral
Actor63: wood
Location: 39,25
Owner: Neutral
Actor64: brik
Location: 21,25
Owner: Neutral
Actor65: brik
Location: 20,25
Owner: Neutral
Actor66: brik
Location: 2,25
Owner: Neutral
Actor67: wood
Location: 42,24
Owner: Neutral
Actor68: wood
Location: 39,24
Owner: Neutral
Actor69: brik
Location: 21,24
Owner: Neutral
Actor70: brik
Location: 14,24
Owner: Neutral
Actor71: brik
Location: 13,24
Owner: Neutral
Actor72: brik
Location: 8,24
Owner: Neutral
Actor73: brik
Location: 7,24
Owner: Neutral
Actor74: brik
Location: 2,24
Owner: Neutral
Actor75: brik
Location: 21,23
Owner: Neutral
Actor76: brik
Location: 20,23
Owner: Neutral
Actor77: brik
Location: 19,23
Owner: Neutral
Actor78: brik
Location: 18,23
Owner: Neutral
Actor79: brik
Location: 17,23
Owner: Neutral
Actor80: brik
Location: 16,23
Owner: Neutral
Actor81: brik
Location: 15,23
Owner: Neutral
Actor82: brik
Location: 14,23
Owner: Neutral
Actor83: brik
Location: 13,23
Owner: Neutral
Actor84: brik
Location: 8,23
Owner: Neutral
Actor85: brik
Location: 7,23
Owner: Neutral
Actor86: brik
Location: 6,23
Owner: Neutral
Actor87: brik
Location: 5,23
Owner: Neutral
Actor88: brik
Location: 4,23
Owner: Neutral
Actor89: brik
Location: 3,23
Owner: Neutral
Actor90: brik
Location: 2,23
Owner: Neutral
Actor91: t02
Location: 46,27
Owner: Neutral
Actor92: t02
Location: 14,19
Owner: Neutral
Actor93: t01
Location: 18,19
Owner: Neutral
Actor94: t14
Location: 44,27
Owner: Neutral
Actor95: tc01
Location: 43,24
Owner: Neutral
Actor96: tc02
Location: 42,27
Owner: Neutral
Actor97: tc04
Location: 45,24
Owner: Neutral
Actor98: split2
Location: 55,23
Owner: Neutral
Actor99: split2
Location: 60,28
Owner: Neutral
Actor100: tc04
Location: 34,26
Owner: Neutral
Actor101: tc02
Location: 37,25
Owner: Neutral
Actor102: t10
Location: 32,27
Owner: Neutral
Actor103: t01
Location: 34,25
Owner: Neutral
Actor104: t17
Location: 35,24
Owner: Neutral
Actor105: tc01
Location: 31,26
Owner: Neutral
Actor106: tc04
Location: 51,15
Owner: Neutral
Actor107: tc04
Location: 37,5
Owner: Neutral
Actor108: tc04
Location: 39,14
Owner: Neutral
Actor109: tc04
Location: 30,6
Owner: Neutral
Actor110: tc02
Location: 29,14
Owner: Neutral
Actor111: tc01
Location: 44,12
Owner: Neutral
Actor112: tc01
Location: 32,9
Owner: Neutral
Actor113: t03
Location: 34,17
Owner: Neutral
Actor114: t02
Location: 44,20
Owner: Neutral
Actor115: t01
Location: 42,19
Owner: Neutral
Actor116: t01
Location: 43,10
Owner: Neutral
Actor117: t01
Location: 35,15
Owner: Neutral
Actor118: t01
Location: 31,10
Owner: Neutral
Actor119: tc02
Location: 22,42
Owner: Neutral
Actor120: tc04
Location: 2,47
Owner: Neutral
Actor121: tc05
Location: 15,52
Owner: Neutral
Actor122: tc02
Location: 27,53
Owner: Neutral
Actor123: t01
Location: 30,50
Owner: Neutral
Actor124: t02
Location: 23,52
Owner: Neutral
Actor125: t03
Location: 33,45
Owner: Neutral
Actor126: tc01
Location: 22,22
Owner: Neutral
Actor127: t07
Location: 5,5
Owner: Neutral
Actor128: tc04
Location: 8,4
Owner: Neutral
Actor129: tc01
Location: 3,4
Owner: Neutral
Actor130: t07
Location: 38,23
Owner: Neutral
Actor131: t11
Location: 30,43
Owner: Neutral
Actor132: tc04
Location: 24,43
Owner: Neutral
Actor133: tc04
Location: 25,29
Owner: Neutral
Actor134: tc05
Location: 52,22
Owner: Neutral
gun1: gun
Location: 27,42
Owner: Nod
gun2: gun
Location: 29,42
Owner: Nod
gun3: gun
Location: 34,33
Owner: Nod
Facing: 159
gun4: gun
Location: 32,33
Owner: Nod
Facing: 159
Actor139: v04
Location: 45,26
Owner: Neutral
Actor140: v07
Location: 51,24
Owner: Neutral
Actor141: v06
Location: 40,24
Owner: Neutral
Actor142: v05
Location: 43,26
Owner: Neutral
Actor143: v03
Location: 35,25
Owner: Neutral
Actor144: v01
Location: 37,26
Owner: Neutral
sam1: sam
Location: 3,4
Owner: Nod
sam2: sam
Location: 19,24
Owner: Nod
sam3: sam
Location: 2,22
Owner: Nod
sam4: sam
Location: 19,32
Owner: Nod
nodpower1: nuke
Location: 5,24
Owner: Nod
nodpower2: nuke
Location: 3,24
Owner: Nod
gun5: gun
Location: 13,22
Owner: Nod
gun6: gun
Location: 8,22
Owner: Nod
NodCYard: fact
Location: 7,30
Owner: Nod
nodobelisk: obli
Location: 18,32
Owner: Nod
nodpower3: nuke
Location: 16,30
Owner: Nod
nodpower4: nuke
Location: 14,30
Owner: Nod
nodsilo1: silo
Location: 5,31
Owner: Nod
nodsilo2: silo
Location: 10,31
Owner: Nod
nodsilo3: silo
Location: 3,31
Owner: Nod
nodrefinery: proc
Location: 12,25
Owner: Nod
FreeActor: False
nodairfield: afld
Location: 3,27
Owner: Nod
handofnod: hand
Location: 15,25
Owner: Nod
nodsilo4: silo
Location: 17,24
Owner: Nod
nodpower5: nuke
Location: 12,30
Owner: Nod
gun7: gun
Location: 22,25
Owner: Nod
Facing: 191
gun8: gun
Location: 22,31
Owner: Nod
Facing: 191
Actor167: harv
Location: 20,28
Owner: Nod
Facing: 191
Actor168: ltnk
Location: 19,26
Owner: Nod
Facing: 127
Actor169: ltnk
Location: 18,26
Owner: Nod
Facing: 127
Actor170: ltnk
Location: 8,28
Owner: Nod
Facing: 127
Actor171: bggy
Location: 18,31
Owner: Nod
Actor172: bggy
Location: 19,31
Owner: Nod
Actor173: bggy
Location: 40,14
Owner: Nod
Actor174: arty
Location: 8,15
Owner: Nod
Facing: 31
Actor175: mcv
Location: 54,4
Owner: GDI
Facing: 127
Actor176: e3
Location: 19,25
Owner: Nod
SubCell: 1
Actor177: e3
Location: 17,26
Owner: Nod
SubCell: 3
Actor178: e3
Location: 8,25
Owner: Nod
SubCell: 1
Actor179: e3
Location: 10,29
Owner: Nod
SubCell: 0
Actor180: e1
Location: 5,30
Owner: Nod
SubCell: 0
Actor181: e1
Location: 8,26
Owner: Nod
SubCell: 4
Actor182: e4
Location: 7,14
Owner: Nod
Facing: 31
SubCell: 3
Actor183: e4
Location: 7,14
Owner: Nod
Facing: 31
SubCell: 2
Actor184: e4
Location: 25,6
Owner: Nod
Facing: 191
SubCell: 1
Actor185: e4
Location: 25,4
Owner: Nod
Facing: 191
SubCell: 3
Actor186: e3
Location: 33,9
Owner: Nod
SubCell: 0
Actor187: e3
Location: 31,6
Owner: Nod
SubCell: 3
Actor188: e3
Location: 17,27
Owner: Nod
SubCell: 2
Actor189: e3
Location: 17,26
Owner: Nod
SubCell: 2
Actor190: e3
Location: 17,27
Owner: Nod
SubCell: 0
Actor191: e2
Location: 53,6
Owner: GDI
Facing: 127
SubCell: 4
Actor192: e2
Location: 54,6
Owner: GDI
Facing: 127
SubCell: 3
Actor193: e2
Location: 53,7
Owner: GDI
Facing: 127
SubCell: 2
Actor194: e3
Location: 54,6
Owner: GDI
Facing: 127
SubCell: 4
Actor195: e3
Location: 55,6
Owner: GDI
Facing: 127
SubCell: 3
Actor196: e3
Location: 55,7
Owner: GDI
Facing: 127
SubCell: 1
Actor197: e3
Location: 54,7
Owner: GDI
Facing: 127
SubCell: 2
Actor198: e2
Location: 54,7
Owner: GDI
Facing: 127
SubCell: 1
Actor199: e3
Location: 25,34
Owner: Nod
Facing: 127
SubCell: 4
Actor200: e3
Location: 25,34
Owner: Nod
Facing: 127
SubCell: 3
Actor201: e3
Location: 24,34
Owner: Nod
Facing: 127
SubCell: 4
Actor202: e3
Location: 25,34
Owner: Nod
Facing: 127
SubCell: 1
Actor203: e3
Location: 24,34
Owner: Nod
Facing: 127
SubCell: 2
Actor204: e3
Location: 25,34
Owner: Nod
Facing: 127
SubCell: 2
GDIHeliEntryNorth: waypoint
Location: 57,6
Owner: Neutral
DefaultCameraPosition: waypoint
Location: 48,3
Owner: Neutral
DefaultFlareLocation: waypoint
Location: 33,31
Owner: Neutral
waypoint23: waypoint
Location: 53,37
Owner: Neutral
waypoint19: waypoint
Location: 52,42
Owner: Neutral
waypoint18: waypoint
Location: 52,19
Owner: Neutral
waypoint17: waypoint
Location: 9,30
Owner: Neutral
waypoint11: waypoint
Location: 23,24
Owner: Neutral
waypoint10: waypoint
Location: 23,32
Owner: Neutral
waypoint9: waypoint
Location: 43,5
Owner: Neutral
waypoint8: waypoint
Location: 60,18
Owner: Neutral
waypoint7: waypoint
Location: 52,6
Owner: Neutral
waypoint6: waypoint
Location: 9,16
Owner: Neutral
waypoint5: waypoint
Location: 4,10
Owner: Neutral
waypoint4: waypoint
Location: 12,5
Owner: Neutral
waypoint3: waypoint
Location: 28,5
Owner: Neutral
waypoint2: waypoint
Location: 30,20
Owner: Neutral
waypoint1: waypoint
Location: 23,28
Owner: Neutral
GDIHeliLZ: waypoint
Location: 41,44
Owner: Neutral
Rules: cnc|rules/campaign-maprules.yaml, cnc|rules/campaign-tooltips.yaml, cnc|rules/campaign-palettes.yaml, rules.yaml
Weapons: weapons.yaml

View File

@@ -0,0 +1,146 @@
World:
LuaScript:
Scripts: campaign-global.lua, gdi09.lua, gdi09-AI.lua
MusicPlaylist:
StartingMusic: march
VictoryMusic: gdi_win1
MissionData:
Briefing: Take out Nod turrets along shore so Gunboats can move in safely on the Nod base.\n\nThe Nod base must be destroyed.\n\nIf gunboats can get in, they should be able to destroy the base with no difficulty.\n\nKeep an eye out for the new weapon Nod is rumored to be working on.
BriefingVideo: gdi9.vqa
WinVideo: gunboat.vqa
LossVideo: gameover.vqa
ATWR:
Buildable:
Prerequisites: ~disabled
NUK2:
Buildable:
Prerequisites: ~disabled
HPAD:
Buildable:
Prerequisites: ~disabled
BRIK:
Buildable:
Prerequisites: ~disabled
EYE:
Buildable:
Prerequisites: ~disabled
GUN:
Buildable:
Prerequisites: ~disabled
OBLI:
Buildable:
Prerequisites: ~disabled
TMPL:
Buildable:
Prerequisites: ~disabled
HTNK:
Buildable:
Prerequisites: ~disabled
TRAN:
Buildable:
Prerequisites: ~disabled
ORCA:
Buildable:
Prerequisites: ~disabled
RMBO:
Buildable:
Prerequisites: ~disabled
MSAM:
Buildable:
Prerequisites: ~disabled
MCV:
Buildable:
Prerequisites: ~disabled
BOAT:
Buildable:
Prerequisites: ~disabled
FTNK:
Buildable:
Prerequisites: ~disabled
STNK:
Buildable:
Prerequisites: ~disabled
HELI:
Buildable:
Prerequisites: ~disabled
LTNK:
Buildable:
Prerequisites: ~afld
ARTY:
Buildable:
Prerequisites: ~afld
E4:
Buildable:
Prerequisites: barracks
E5:
Buildable:
Prerequisites: ~disabled
MLRS:
Buildable:
Prerequisites: ~disabled
SAM:
Buildable:
Prerequisites: ~disabled
^Bridge:
DamageMultiplier@INVULNERABLE:
Modifier: 0
BRIDGEHUT:
-Targetable:
TRAN.Extraction:
Inherits: TRAN
RevealsShroud:
Range: 0c0
RejectsOrders:
-Selectable:
RenderSprites:
Image: tran
Interactable:
TRAN.Insertion:
Inherits: TRAN.Extraction
Cargo:
MaxWeight: 0
HQ:
Tooltip:
-AirstrikePower:
Buildable:
Description: Provides an overview of the battlefield.\n Requires power to operate.
airstrike.proxy:
AirstrikePower:
SquadSize: 2
SquadOffset: -1536, 1024, 0
BOAT:
AutoTarget:
InitialStance: AttackAnything
RejectsOrders:
Except: Attack

View File

@@ -0,0 +1,13 @@
BoatMissile:
Warhead@Bonus: SpreadDamage
Spread: 128
Damage: 2000
Versus:
None: 50
Wood: 100
Light: 100
Heavy: 100
DamageTypes: Prone50Percent, TriggerProne, ExplosionDeath
TurretGun:
ReloadDelay: 40

View File

@@ -9,6 +9,8 @@ GDI Campaign:
gdi05b
gdi06
gdi07
gdi08a
gdi09
Nod Campaign:
nod01

View File

@@ -425,7 +425,7 @@ AFLD:
Queue: Building.Nod
Description: Provides a dropzone\nfor vehicle reinforcements
Building:
Footprint: XXXX xxxx ====
Footprint: XXX+ xxx+ ====
Dimensions: 4,3
LocalCenterOffset: 0,-512,0
Health:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 KiB

After

Width:  |  Height:  |  Size: 410 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 991 KiB

After

Width:  |  Height:  |  Size: 735 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

View File

@@ -173,8 +173,10 @@ Background@SAVE_MAP_PANEL:
Key: escape
ScrollPanel@MAP_SAVE_VISIBILITY_PANEL:
TopBottomSpacing: 5
ItemSpacing: 5
Width: 220
Height: 64
Height: 55
Children:
Checkbox@VISIBILITY_TEMPLATE:
X: 5
@@ -618,29 +620,30 @@ Container@EDITOR_WORLD_ROOT:
Contrast: true
ScrollPanel@CATEGORY_FILTER_PANEL:
Width: 170
Width: 240
TopBottomSpacing: 5
ItemSpacing: 5
Children:
Container@SELECT_CATEGORIES_BUTTONS:
Width: PARENT_RIGHT
Height: 29
Height: 25
Children:
Button@SELECT_ALL:
X: 10
Y: 2
Width: 60
Y: 0 - 5
Width: 93
Height: 25
Text: All
Font: Bold
Button@SELECT_NONE:
X: PARENT_RIGHT - WIDTH - 34
Y: 2
Width: 60
X: 10 + 93 + 10
Y: 0 - 5
Width: 93
Height: 25
Text: None
Font: Bold
Checkbox@CATEGORY_TEMPLATE:
X: 5
Y: 5
Width: PARENT_RIGHT - 29
Height: 20
Visible: false

View File

@@ -185,7 +185,13 @@ Background@MAINMENU_INTRODUCTION_PROMPT:
Height: 16
Font: Small
Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel}
LabelWithHighlight@DESC_SCROLL:
LabelWithHighlight@DESC_SCROLL_RIGHT:
X: 265
Y: 34
Height: 16
Font: Small
Text: - Pan the battlefield using the {Right} mouse button
LabelWithHighlight@DESC_SCROLL_MIDDLE:
X: 265
Y: 34
Height: 16

View File

@@ -491,7 +491,12 @@ Background@SETTINGS_PANEL:
Height: 16
Font: Small
Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel}
LabelWithHighlight@DESC_SCROLL:
LabelWithHighlight@DESC_SCROLL_RIGHT:
Y: 85
Height: 16
Font: Small
Text: - Pan the battlefield using the {Right} mouse button
LabelWithHighlight@DESC_SCROLL_MIDDLE:
Y: 85
Height: 16
Font: Small
@@ -544,13 +549,13 @@ Background@SETTINGS_PANEL:
Height: 20
Font: Regular
Text: Screen Edge Panning
Checkbox@CLASSIC_MOUSE_MIDDLE_SCROLL_CHECKBOX:
Checkbox@ALTERNATE_SCROLL_CHECKBOX:
X: 360
Y: 133
Width: 180
Height: 20
Font: Regular
Text: Middle Mouse Panning
Text: Alternate Mouse Panning
Label@SCROLL_SPEED_LABEL:
X: 305
Y: 210
@@ -648,7 +653,7 @@ Background@SETTINGS_PANEL:
Width: 80
Height: 25
Align: Left
TooltipContainer: TOOLTIP_CONTAINER
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Container@THREE_COLUMN:
Width: 173
Height: 25
@@ -664,7 +669,7 @@ Background@SETTINGS_PANEL:
Width: 80
Height: 25
Align: Left
TooltipContainer: TOOLTIP_CONTAINER
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
Background@HOTKEY_DIALOG_ROOT:
X: 15
Y: 230
@@ -716,7 +721,7 @@ Background@SETTINGS_PANEL:
Text: Clear
Font: Bold
TooltipText: Unbind the hotkey
TooltipContainer: TOOLTIP_CONTAINER
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
TooltipTemplate: SIMPLE_TOOLTIP
Button@RESET_HOTKEY_BUTTON:
X: PARENT_RIGHT - WIDTH - 20
@@ -726,7 +731,7 @@ Background@SETTINGS_PANEL:
Text: Reset
Font: Bold
TooltipText: Reset to default
TooltipContainer: TOOLTIP_CONTAINER
TooltipContainer: SETTINGS_TOOLTIP_CONTAINER
TooltipTemplate: SIMPLE_TOOLTIP
Container@ADVANCED_PANEL:
X: 5
@@ -846,4 +851,4 @@ Background@SETTINGS_PANEL:
Height: 20
Font: Regular
Text: Enable Debug Commands in Replays
TooltipContainer@TOOLTIP_CONTAINER:
TooltipContainer@SETTINGS_TOOLTIP_CONTAINER:

View File

@@ -39,7 +39,7 @@ InitObjectives = function(player)
end)
end
SendCarryallReinforcements = function(player, currentWave, totalWaves, delay, pathFunction, unitTypes, customCondition, customHuntFunction)
SendCarryallReinforcements = function(player, currentWave, totalWaves, delay, pathFunction, unitTypes, customCondition, customHuntFunction, announcementFunction)
Trigger.AfterDelay(delay, function()
if customCondition and customCondition() then
return
@@ -50,6 +50,10 @@ SendCarryallReinforcements = function(player, currentWave, totalWaves, delay, pa
return
end
if announcementFunction then
announcementFunction(currentWave)
end
local path = pathFunction()
local units = Reinforcements.ReinforceWithTransport(player, "carryall.reinforce", unitTypes[currentWave], path, { path[1] })[2]
@@ -78,6 +82,10 @@ TriggerCarryallReinforcements = function(triggeringPlayer, reinforcingPlayer, ar
end)
end
DestroyCarryalls = function(player)
Utils.Do(player.GetActorsByType("carryall"), function(actor) actor.Kill() end)
end
-- Used for the AI:
IdlingUnits = { }

View File

@@ -48,7 +48,7 @@ sidebar-bits:
production-tooltip-time: 136, 51, 16, 16
production-tooltip-power: 102, 51, 16, 16
production-tooltip-cost: 68, 51, 16, 16
indicator-muted: 0, 119, 24, 24
indicator-muted: 0, 119, 26, 24
commandbar:
Inherits: ^Chrome

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

View File

@@ -0,0 +1,578 @@
MapFormat: 11
RequiresMod: d2k
Title: Ordos 06a
Author: Westwood Studios
Tileset: ARRAKIS
MapSize: 84,84
Bounds: 2,2,80,80
Visibility: MissionSelector
Categories: Campaign
LockPreview: True
Players:
PlayerReference@Neutral:
Name: Neutral
OwnsWorld: True
NonCombatant: True
Faction: Random
PlayerReference@Creeps:
Name: Creeps
NonCombatant: True
Faction: Random
Enemies: Atreides, Ordos, Harkonnen
PlayerReference@Ordos:
Name: Ordos
Playable: True
LockFaction: True
Faction: ordos
LockColor: True
Color: B3EAA5
Enemies: Atreides, Harkonnen, Creeps
PlayerReference@Atreides:
Name: Atreides
LockFaction: True
Faction: atreides
LockColor: True
Color: 9191FF
Allies: Harkonnen
Enemies: Ordos, Creeps
PlayerReference@Harkonnen:
Name: Harkonnen
LockFaction: True
Faction: harkonnen
LockColor: True
Color: FE0000
Allies: Atreides
Enemies: Ordos, Creeps
Actors:
Actor0: wall
Location: 65,2
Owner: Ordos
AHeavyFactory: heavy_factory
Location: 3,3
Owner: Atreides
AConyard: construction_yard
Location: 8,3
Owner: Atreides
APower1: wind_trap
Location: 11,3
Owner: Atreides
APower2: wind_trap
Location: 13,3
Owner: Atreides
ALightFactory: light_factory
Location: 16,3
Owner: Atreides
Actor6: wall
Location: 65,3
Owner: Ordos
OOutpost: outpost
Location: 66,3
Owner: Ordos
OPower1: wind_trap
Location: 72,3
Owner: Ordos
OPower2: wind_trap
Location: 74,3
Owner: Ordos
OConyard: construction_yard
Location: 76,3
Owner: Ordos
OBarracks: barracks
Location: 79,3
Owner: Ordos
Actor12: wall
Location: 65,4
Owner: Ordos
ARock1: large_gun_turret
Location: 20,5
Facing: 160
Owner: Atreides
Actor14: wall
Location: 65,5
Owner: Ordos
Actor15: combat_tank_a
Location: 13,6
Owner: Atreides
Actor16: wall
Location: 65,6
Owner: Ordos
APower3: wind_trap
Location: 7,7
Owner: Atreides
APower4: wind_trap
Location: 9,7
Owner: Atreides
APower5: wind_trap
Location: 11,7
Owner: Atreides
APower6: wind_trap
Location: 13,7
Owner: Atreides
APower7: wind_trap
Location: 15,7
Owner: Atreides
Actor22: wall
Location: 65,7
Owner: Ordos
Actor23: trooper
Location: 4,8
Owner: Atreides
Actor24: wall
Location: 65,8
Owner: Ordos
Actor25: wall
Location: 66,8
Owner: Ordos
Actor26: wall
Location: 67,8
Owner: Ordos
Actor27: wall
Location: 68,8
Owner: Ordos
Actor28: wall
Location: 69,8
Owner: Ordos
Actor29: wall
Location: 70,8
Owner: Ordos
ABarracks: barracks
Location: 2,9
Owner: Atreides
Actor31: wall
Location: 70,9
Owner: Ordos
Actor32: wall
Location: 79,9
Owner: Ordos
Actor33: wall
Location: 80,9
Owner: Ordos
Actor34: wall
Location: 81,9
Owner: Ordos
APower8: wind_trap
Location: 10,10
Owner: Atreides
Actor36: wall
Location: 70,10
Owner: Ordos
Actor37: wall
Location: 79,10
Owner: Ordos
AResearch: research_centre
Location: 5,11
Owner: Atreides
Actor39: wall
Location: 70,11
Owner: Ordos
Actor40: wall
Location: 79,11
Owner: Ordos
APower9: wind_trap
Location: 2,12
Owner: Atreides
Actor42: combat_tank_a
Location: 8,12
Owner: Atreides
ARepair: repair_pad
Location: 13,12
Owner: Atreides
ARock2: large_gun_turret
Location: 16,12
Facing: 160
Owner: Atreides
Actor45: wall
Location: 70,12
Owner: Ordos
OGunt1: medium_gun_turret
Location: 71,12
Owner: Ordos
OGunt2: medium_gun_turret
Location: 78,12
Owner: Ordos
Actor48: wall
Location: 79,12
Owner: Ordos
APower10: wind_trap
Location: 2,15
Owner: Atreides
APower11: wind_trap
Location: 4,15
Owner: Atreides
APower12: wind_trap
Location: 6,15
Owner: Atreides
Actor52: combat_tank_a
Location: 11,17
Owner: Atreides
Actor53: combat_tank_a
Location: 8,18
Owner: Atreides
Actor54: wall
Location: 10,19
Owner: Atreides
Actor55: wall
Location: 11,19
Owner: Atreides
ARefinery: refinery
Location: 2,20
Owner: Atreides
Actor57: wall
Location: 10,20
Owner: Atreides
Actor58: combat_tank_a
Location: 6,21
Owner: Atreides
Actor59: wall
Location: 10,21
Owner: Atreides
Actor60: spicebloom.spawnpoint
Location: 38,21
Owner: Neutral
Actor61: wall
Location: 10,22
Owner: Atreides
Actor62: carryall
Location: 4,23
Owner: Atreides
Actor63: harvester
Location: 5,23
Owner: Atreides
ARock3: large_gun_turret
Location: 10,23
Facing: 192
Owner: Atreides
Actor65: wall
Location: 11,23
Owner: Atreides
AGunt1: medium_gun_turret
Location: 12,23
Facing: 192
Owner: Atreides
Actor67: wormspawner
Location: 26,23
Owner: Creeps
Actor68: siege_tank
Location: 5,24
Owner: Atreides
Actor69: spicebloom.spawnpoint
Location: 67,24
Owner: Neutral
Actor70: wall
Location: 2,25
Owner: Atreides
Actor71: wall
Location: 3,25
Owner: Atreides
Actor72: wall
Location: 4,25
Owner: Atreides
Actor73: wall
Location: 5,25
Owner: Atreides
Actor74: wall
Location: 6,25
Owner: Atreides
ARock4: large_gun_turret
Location: 7,25
Owner: Atreides
Actor76: wall
Location: 7,26
Owner: Atreides
AGunt2: medium_gun_turret
Location: 7,27
Owner: Atreides
Actor78: spicebloom.spawnpoint
Location: 76,30
Owner: Neutral
Actor79: spicebloom.spawnpoint
Location: 32,33
Owner: Neutral
Actor80: spicebloom.spawnpoint
Location: 56,33
Owner: Neutral
Actor81: spicebloom.spawnpoint
Location: 7,37
Owner: Neutral
Actor82: spicebloom.spawnpoint
Location: 44,48
Owner: Neutral
Actor83: spicebloom.spawnpoint
Location: 77,48
Owner: Neutral
Actor84: trooper
Location: 78,50
Owner: Ordos
Actor85: trooper
Location: 76,53
Owner: Ordos
Actor86: trooper
Location: 77,53
Owner: Ordos
OStarport: starport
Location: 79,53
Owner: Ordos
Actor88: trooper
Location: 77,55
Owner: Ordos
Actor89: raider
Location: 78,56
Owner: Ordos
HGunt1: medium_gun_turret
Location: 30,57
Facing: 0
Owner: Harkonnen
HGunt2: medium_gun_turret
Location: 34,57
Facing: 0
Owner: Harkonnen
Actor92: wall
Location: 30,58
Owner: Harkonnen
Actor93: combat_tank_h
Location: 32,58
Owner: Harkonnen
Actor94: wall
Location: 34,58
Owner: Harkonnen
Actor95: wall
Location: 30,59
Owner: Harkonnen
Actor96: trooper
Location: 33,59
Owner: Harkonnen
Actor97: wall
Location: 34,59
Owner: Harkonnen
Actor98: wall
Location: 30,60
Owner: Harkonnen
Actor99: trooper
Location: 31,60
Owner: Harkonnen
Actor100: wall
Location: 34,60
Owner: Harkonnen
Actor101: wall
Location: 29,61
Owner: Harkonnen
Actor102: wall
Location: 30,61
Owner: Harkonnen
Actor103: wall
Location: 34,61
Owner: Harkonnen
Actor104: wall
Location: 35,61
Owner: Harkonnen
Actor105: wall
Location: 29,62
Owner: Harkonnen
Actor106: wall
Location: 35,62
Owner: Harkonnen
Actor107: wall
Location: 29,63
Owner: Harkonnen
Actor108: wall
Location: 35,63
Owner: Harkonnen
Actor109: wall
Location: 36,63
Owner: Harkonnen
Actor110: wall
Location: 37,63
Owner: Harkonnen
Actor111: harvester
Location: 31,65
Owner: Harkonnen
HSilo1: silo
Location: 35,65
Owner: Harkonnen
Actor113: carryall
Location: 32,66
Owner: Harkonnen
HSilo2: silo
Location: 35,66
Owner: Harkonnen
HRefinery: refinery
Location: 30,67
Owner: Harkonnen
HSilo3: silo
Location: 35,67
Owner: Harkonnen
Actor117: spicebloom.spawnpoint
Location: 22,68
Owner: Neutral
HOutpost: outpost
Location: 35,70
Owner: Harkonnen
HPower1: wind_trap
Location: 31,71
Owner: Harkonnen
HPower2: wind_trap
Location: 34,73
Owner: Harkonnen
HPower3: wind_trap
Location: 36,73
Owner: Harkonnen
HPower4: wind_trap
Location: 38,73
Owner: Harkonnen
Actor123: wall
Location: 24,74
Owner: Harkonnen
HPower5: wind_trap
Location: 26,74
Owner: Harkonnen
HPower6: wind_trap
Location: 28,74
Owner: Harkonnen
HPower7: wind_trap
Location: 30,74
Owner: Harkonnen
Actor127: wall
Location: 24,75
Owner: Harkonnen
Actor128: spicebloom.spawnpoint
Location: 58,75
Owner: Neutral
HGunt3: medium_gun_turret
Location: 19,76
Facing: 32
Owner: Harkonnen
Actor130: wall
Location: 20,76
Owner: Harkonnen
Actor131: wall
Location: 21,76
Owner: Harkonnen
Actor132: wall
Location: 22,76
Owner: Harkonnen
Actor133: wall
Location: 23,76
Owner: Harkonnen
Actor134: wall
Location: 24,76
Owner: Harkonnen
Actor135: wall
Location: 19,77
Owner: Harkonnen
HHeavyFactory: heavy_factory
Location: 33,77
Owner: Harkonnen
HRock: large_gun_turret
Location: 38,77
Facing: 192
Owner: Harkonnen
HPower8: wind_trap
Location: 23,78
Owner: Harkonnen
HConyard: construction_yard
Location: 25,78
Owner: Harkonnen
HPower9: wind_trap
Location: 28,78
Owner: Harkonnen
HPower10: wind_trap
Location: 30,78
Owner: Harkonnen
Actor142: combat_tank_h
Location: 20,79
Owner: Harkonnen
HBarracks: barracks
Location: 36,79
Owner: Harkonnen
HGunt4: medium_gun_turret
Location: 19,80
Facing: 64
Owner: Harkonnen
Actor145: wall
Location: 39,80
Owner: Harkonnen
Actor146: wall
Location: 19,81
Owner: Harkonnen
Actor147: wall
Location: 39,81
Owner: Harkonnen
AtreidesRally1: waypoint
Owner: Neutral
Location: 8,22
AtreidesEntry1: waypoint
Owner: Neutral
Location: 2,22
HarkonnenRally1: waypoint
Owner: Neutral
Location: 32,64
HarkonnenEntry1: waypoint
Owner: Neutral
Location: 32,81
AtreidesRally2: waypoint
Owner: Neutral
Location: 77,76
AtreidesEntry2: waypoint
Owner: Neutral
Location: 77,81
AtreidesRally3: waypoint
Owner: Neutral
Location: 36,34
AtreidesEntry3: waypoint
Owner: Neutral
Location: 36,2
AtreidesRally4: waypoint
Owner: Neutral
Location: 68,41
AtreidesEntry4: waypoint
Owner: Neutral
Location: 81,41
HarkonnenRally2: waypoint
Owner: Neutral
Location: 44,59
HarkonnenEntry2: waypoint
Owner: Neutral
Location: 44,81
HarkonnenRally3: waypoint
Owner: Neutral
Location: 77,77
HarkonnenEntry3: waypoint
Owner: Neutral
Location: 81,77
HarkonnenRally4: waypoint
Owner: Neutral
Location: 56,50
HarkonnenEntry4: waypoint
Owner: Neutral
Location: 56,81
HarkonnenRally5: waypoint
Owner: Neutral
Location: 54,41
HarkonnenEntry5: waypoint
Owner: Neutral
Location: 81,41
HarkonnenRally6: waypoint
Owner: Neutral
Location: 52,33
HarkonnenEntry6: waypoint
Owner: Neutral
Location: 81,33
HarkonnenRally7: waypoint
Owner: Neutral
Location: 34,26
HarkonnenEntry7: waypoint
Owner: Neutral
Location: 34,2
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -0,0 +1,54 @@
--[[
Copyright 2007-2020 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.
]]
AttackGroupSize =
{
easy = 6,
normal = 8,
hard = 10
}
ProductionDelays =
{
easy = { DateTime.Seconds(16), DateTime.Seconds(30) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
hard = { DateTime.Seconds(1), DateTime.Seconds(3) }
}
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
EnemyVehicleTypes = { "trike", "trike", "quad" }
AtreidesTankTypes = { "combat_tank_a", "siege_tank", "missile_tank" }
HarkonnenTankTypes = { "combat_tank_h", "siege_tank" }
InitAIUnits = function(house)
LastHarvesterEaten[house] = true
IdlingUnits[house] = Reinforcements.Reinforce(house, InitialReinforcements[house.InternalName], InitialReinforcementsPaths[house.InternalName])
DefendAndRepairBase(house, Base[house.InternalName], 0.75, AttackGroupSize[Difficulty])
end
ActivateAI = function()
InitAIUnits(atreides)
InitAIUnits(harkonnen)
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuildAtreides = function() return { Utils.Random(AtreidesTankTypes) } end
local tanksToBuildHarkonnen = function() return { Utils.Random(HarkonnenTankTypes) } end
local attackTresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(atreides, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(atreides, AHeavyFactory, delay, tanksToBuildAtreides, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(harkonnen, HHeavyFactory, delay, tanksToBuildHarkonnen, AttackGroupSize[Difficulty], attackTresholdSize)
end

View File

@@ -0,0 +1,275 @@
--[[
Copyright 2007-2020 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.
]]
Base =
{
Atreides = { AConyard, APower1, APower2, APower3, APower4, APower5, APower6, APower7, APower8, APower9, APower10, APower11, APower12, ABarracks, ARefinery, ALightFactory, AHeavyFactory, ARepair, AResearch, AGunt1, AGunt2, ARock1, ARock2, ARock3, ARock4 },
Harkonnen = { HConyard, HPower1, HPower2, HPower3, HPower4, HPower5, HPower6, HPower7, HPower8, HPower9, HPower10, HBarracks, HRefinery, HOutpost, HHeavyFactory, HGunt1, HGunt2, HGunt3, HGunt4, HRock, HSilo1, HSilo2, HSilo3 }
}
AtreidesReinforcements =
{
easy =
{
{ "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "quad", "quad", "combat_tank_a" },
{ "light_inf", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad" }
},
normal =
{
{ "light_inf", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad" },
{ "quad", "quad", "combat_tank_a", "combat_tank_a" },
{ "light_inf", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad", "quad" },
{ "combat_tank_a", "combat_tank_a", "combat_tank_a" }
},
hard =
{
{ "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "quad", "quad" },
{ "quad", "quad", "quad", "combat_tank_a", "combat_tank_a" },
{ "light_inf", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad", "quad", "quad" },
{ "combat_tank_a", "combat_tank_a", "combat_tank_a", "quad" },
{ "combat_tank_a", "combat_tank_a", "missile_tank", "siege_tank" }
}
}
HarkonnenReinforcements =
{
easy =
{
{ "quad", "trike", "trike" },
{ "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "quad" },
{ "trooper", "trooper", "trooper", "trooper", "trooper" }
},
normal =
{
{ "combat_tank_h", "combat_tank_h", "trike", "trike" },
{ "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "quad", "quad" },
{ "trooper", "trooper", "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "trike", "trike", "quad", "siege_tank" }
},
hard =
{
{ "combat_tank_h", "combat_tank_h", "trike", "trike", "trike" },
{ "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "combat_tank_h", "quad", "quad" },
{ "trooper", "trooper", "trooper", "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "trike", "trike", "quad", "quad", "siege_tank" },
{ "missile_tank", "missile_tank", "missile_tank", "missile_tank" }
}
}
IxianReinforcements =
{
easy = { "deviator", "deviator", "missile_tank", "missile_tank", "missile_tank", "siege_tank", "siege_tank", "combat_tank_o", "combat_tank_o" },
normal = { "deviator", "deviator", "missile_tank", "missile_tank", "missile_tank", "siege_tank", "siege_tank", "combat_tank_o" },
hard = { "deviator", "deviator", "missile_tank", "missile_tank", "siege_tank", "siege_tank", "combat_tank_o" }
}
EnemyAttackDelay =
{
easy = DateTime.Minutes(5) + DateTime.Seconds(15),
normal = DateTime.Minutes(3) + DateTime.Seconds(15),
hard = DateTime.Minutes(1) + DateTime.Seconds(30)
}
AtreidesPaths =
{
{ AtreidesEntry2.Location, AtreidesRally2.Location },
{ AtreidesEntry3.Location, AtreidesRally3.Location },
{ AtreidesEntry4.Location, AtreidesRally4.Location }
}
HarkonnenPaths =
{
{ HarkonnenEntry2.Location, HarkonnenRally2.Location },
{ HarkonnenEntry3.Location, HarkonnenRally3.Location },
{ HarkonnenEntry4.Location, HarkonnenRally4.Location },
{ HarkonnenEntry5.Location, HarkonnenRally5.Location },
{ HarkonnenEntry6.Location, HarkonnenRally6.Location },
{ HarkonnenEntry7.Location, HarkonnenRally7.Location }
}
AtreidesAttackWaves =
{
easy = 3,
normal = 4,
hard = 5
}
HarkonnenAttackWaves =
{
easy = 4,
normal = 5,
hard = 6
}
InitialReinforcements =
{
Atreides = { "combat_tank_a", "quad", "quad", "trike", "trike" },
Harkonnen = { "trooper", "trooper", "trooper", "trooper", "trooper", "combat_tank_h" }
}
InitialReinforcementsPaths =
{
Atreides = { AtreidesEntry1.Location, AtreidesRally1.Location },
Harkonnen = { HarkonnenEntry1.Location, HarkonnenRally1.Location }
}
InitialContrabandTimes =
{
easy = DateTime.Minutes(10),
normal = DateTime.Minutes(15),
hard = DateTime.Minutes(20)
}
ContrabandTimes =
{
easy = DateTime.Minutes(4),
normal = DateTime.Minutes(6),
hard = DateTime.Minutes(7)
}
SendContraband = function()
Media.PlaySpeechNotification(player, "Reinforce")
for i = 0, 6 do
local c = player.Color
if i % 2 == 0 then
c = HSLColor.White
end
Trigger.AfterDelay(DateTime.Seconds(i), function() UserInterface.SetMissionText("Ixian reinforcements have arrived!", c) end)
end
Trigger.AfterDelay(DateTime.Seconds(6), function()
TimerTicks = ContrabandTimes[Difficulty]
end)
local entryPath = { CPos.New(82, OStarport.Location.Y + 1), OStarport.Location + CVec.New(1, 1) }
local exitPath = { CPos.New(2, OStarport.Location.Y + 1) }
Reinforcements.ReinforceWithTransport(player, "frigate", IxianReinforcements[Difficulty], entryPath, exitPath)
end
Hunt = function(house)
Trigger.OnAllKilledOrCaptured(Base[house.InternalName], function()
Utils.Do(house.GetGroundAttackers(), IdleHunt)
end)
end
CheckHarvester = function(house)
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[house] then
local units = house.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[house] = false
ProtectHarvester(units[1], house, AttackGroupSize[Difficulty])
end
end
end
Tick = function()
if not player.IsObjectiveCompleted(KillAtreides) and atreides.HasNoRequiredUnits() then
Media.DisplayMessage("The Atreides have been annihilated!", "Mentat")
player.MarkCompletedObjective(KillAtreides)
DestroyCarryalls(atreides)
if player.IsObjectiveCompleted(KillHarkonnen) then
player.MarkCompletedObjective(GuardStarport)
end
end
if not player.IsObjectiveCompleted(KillHarkonnen) and harkonnen.HasNoRequiredUnits() then
Media.DisplayMessage("The Harkonnen have been annihilated!", "Mentat")
player.MarkCompletedObjective(KillHarkonnen)
DestroyCarryalls(harkonnen)
if player.IsObjectiveCompleted(KillAtreides) then
player.MarkCompletedObjective(GuardStarport)
end
end
if TimerTicks and TimerTicks > 0 then
TimerTicks = TimerTicks - 1
if TimerTicks == 0 then
if not FirstIxiansArrived then
Media.DisplayMessage("Deliveries beginning to arrive. Massive reinforcements expected!", "Mentat")
end
FirstIxiansArrived = true
SendContraband()
else
local text = "Initial"
if FirstIxiansArrived then
text = "Additional"
end
UserInterface.SetMissionText(text .. " reinforcements will arrive in " .. Utils.FormatTime(TimerTicks), player.Color)
end
end
CheckHarvester(atreides)
CheckHarvester(harkonnen)
end
WorldLoaded = function()
atreides = Player.GetPlayer("Atreides")
harkonnen = Player.GetPlayer("Harkonnen")
player = Player.GetPlayer("Ordos")
InitObjectives(player)
GuardStarport = player.AddObjective("Defend the Starport.")
KillAtreides = player.AddObjective("Destroy the Atreides.")
KillHarkonnen = player.AddObjective("Destroy the Harkonnen.")
Camera.Position = OConyard.CenterPosition
EnemyAttackLocations = { OConyard.Location, OStarport.Location }
Trigger.OnRemovedFromWorld(OStarport, function()
player.MarkFailedObjective(GuardStarport)
end)
Trigger.AfterDelay(DateTime.Seconds(2), function()
TimerTicks = InitialContrabandTimes[Difficulty]
Media.DisplayMessage("The first batch of Ixian reinforcements will arrive in " .. Utils.FormatTime(TimerTicks) .. ".", "Mentat")
end)
Hunt(atreides)
Hunt(harkonnen)
local atreidesPath = function() return Utils.Random(AtreidesPaths) end
local harkonnenPath = function() return Utils.Random(HarkonnenPaths) end
local atreidesCondition = function() return player.IsObjectiveCompleted(KillAtreides) end
local harkonnenCondition = function() return player.IsObjectiveCompleted(KillHarkonnen) end
local huntFunction = function(unit)
unit.AttackMove(Utils.Random(EnemyAttackLocations))
IdleHunt(unit)
end
local announcementFunction = function()
Media.DisplayMessage("Enemy reinforcements have arrived.", "Mentat")
end
SendCarryallReinforcements(atreides, 0, AtreidesAttackWaves[Difficulty], EnemyAttackDelay[Difficulty], atreidesPath, AtreidesReinforcements[Difficulty], atreidesCondition, huntFunction, announcementFunction)
Trigger.AfterDelay(Utils.RandomInteger(DateTime.Seconds(45), DateTime.Minutes(1) + DateTime.Seconds(15)), function()
SendCarryallReinforcements(harkonnen, 0, HarkonnenAttackWaves[Difficulty], EnemyAttackDelay[Difficulty], harkonnenPath, HarkonnenReinforcements[Difficulty], harkonnenCondition, huntFunction, announcementFunction)
end)
Actor.Create("upgrade.barracks", true, { Owner = atreides })
Actor.Create("upgrade.light", true, { Owner = atreides })
Actor.Create("upgrade.heavy", true, { Owner = atreides })
Actor.Create("upgrade.barracks", true, { Owner = harkonnen })
Actor.Create("upgrade.heavy", true, { Owner = harkonnen })
Trigger.AfterDelay(0, ActivateAI)
end

View File

@@ -0,0 +1,60 @@
Player:
PlayerResources:
DefaultCash: 6000
World:
LuaScript:
Scripts: campaign-global.lua, ordos06a.lua, ordos06a-AI.lua
MissionData:
Briefing: The Starport must be protected. All other efforts are secondary. No House will be allowed to interfere with the arrival of our Ixian weaponry.\n\nOnce we possess these illegal technologies, we will confuse and crush our opponents. Until then, survive. This will give you a higher probability of success.
BriefingVideo: O_BR06_E.VQA
MapOptions:
TechLevel: medium
ScriptLobbyDropdown@difficulty:
ID: difficulty
Label: Difficulty
Values:
easy: Easy
normal: Normal
hard: Hard
Default: easy
carryall.reinforce:
Cargo:
MaxWeight: 10
frigate:
Aircraft:
LandableTerrainTypes: Sand, Rock, Transition, Spice, SpiceSand, Dune, Concrete
concreteb:
Buildable:
Prerequisites: ~disabled
upgrade.conyard:
Buildable:
Prerequisites: ~disabled
starport:
Buildable:
Prerequisites: heavy_factory, outpost
missile_tank:
Buildable:
Prerequisites: ~heavy.missile_tank, upgrade.heavy, research_centre
grenadier:
Buildable:
Prerequisites: ~disabled
stealth_raider:
Buildable:
Prerequisites: ~disabled
sardaukar:
Buildable:
Prerequisites: ~disabled
large_gun_turret:
Buildable:
Prerequisites: ~disabled

View File

@@ -17,6 +17,7 @@ Ordos Campaign:
ordos-03b
ordos-04
ordos-05
ordos-06a
Harkonnen Campaign:
harkonnen-01a

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -135,7 +135,7 @@ sidebar-bits:
production-tooltip-time: 136, 51, 16, 16
production-tooltip-power: 102, 51, 16, 16
production-tooltip-cost: 68, 51, 16, 16
indicator-muted: 68, 145, 24, 24
indicator-muted: 68, 145, 26, 24
commandbar:
Inherits: ^Sidebar

View File

@@ -95,7 +95,7 @@ MIG:
UpdatesPlayerStatistics:
AddToArmyValue: true
Health:
HP: 7500
HP: 10000
RevealsShroud:
MinRange: 11c0
Range: 13c0
@@ -112,6 +112,7 @@ MIG:
AttackAircraft:
FacingTolerance: 20
PersistentTargeting: false
OpportunityFire: False
Aircraft:
CruiseAltitude: 2560
InitialFacing: 192
@@ -120,7 +121,6 @@ MIG:
RepulsionSpeed: 40
MaximumPitch: 56
AutoTarget:
ScanOnIdle: false
InitialStance: HoldFire
InitialStanceAI: HoldFire
AmmoPool:
@@ -183,6 +183,7 @@ YAK:
AttackAircraft:
FacingTolerance: 20
PersistentTargeting: false
OpportunityFire: False
Aircraft:
CruiseAltitude: 2560
InitialFacing: 192
@@ -191,7 +192,6 @@ YAK:
RepulsionSpeed: 40
MaximumPitch: 56
AutoTarget:
ScanOnIdle: false
InitialStance: HoldFire
InitialStanceAI: HoldFire
AmmoPool:
@@ -230,7 +230,7 @@ TRAN:
UpdatesPlayerStatistics:
AddToArmyValue: true
Health:
HP: 14000
HP: 20000
RevealsShroud:
MinRange: 6c0
Range: 8c0
@@ -307,6 +307,7 @@ HELI:
FacingTolerance: 20
PersistentTargeting: false
AttackType: Hover
OpportunityFire: False
Aircraft:
TurnSpeed: 4
Speed: 149
@@ -376,6 +377,7 @@ HIND:
FacingTolerance: 20
PersistentTargeting: false
AttackType: Hover
OpportunityFire: False
Aircraft:
TurnSpeed: 4
Speed: 112

View File

@@ -514,6 +514,8 @@ MNLY:
Image: MNLY
Rearmable:
RearmActors: fix
Targetable:
TargetTypes: Ground, Vehicle, Mine
TRUK:
Inherits: ^Vehicle
@@ -760,11 +762,11 @@ CTNK:
AddToArmyValue: true
SelectionDecorations:
Health:
HP: 45000
HP: 40000
Armor:
Type: Light
Mobile:
Speed: 113
Speed: 96
Locomotor: heavywheeled
RevealsShroud:
MinRange: 4c0
@@ -862,7 +864,7 @@ STNK:
InitialStance: HoldFire
InitialStanceAI: ReturnFire
Armament:
Weapon: APTusk
Weapon: APTusk.stnk
LocalOffset: 192,0,176
Turreted:
TurnSpeed: 5
@@ -870,7 +872,7 @@ STNK:
WithSpriteTurret:
Cargo:
Types: Infantry
MaxWeight: 4
MaxWeight: 5
PipCount: 4
LoadingCondition: notmobile
Cloak:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -72,10 +72,10 @@ Dragon:
HellfireAG:
Inherits: ^AntiGroundMissile
ReloadDelay: 60
ReloadDelay: 30
MinRange: 1c256
Burst: 4
BurstDelays: 14
Burst: 2
BurstDelays: 7
Projectile: Missile
Speed: 256
HorizontalRateOfTurn: 10
@@ -90,15 +90,17 @@ HellfireAG:
HellfireAA:
Inherits: ^AntiAirMissile
ReloadDelay: 60
ReloadDelay: 30
MinRange: 1c256
Range: 4c0
Burst: 2
BurstDelays: 10
Projectile: Missile
Speed: 384
Speed: 492
Inaccuracy: 128
HorizontalRateOfTurn: 10
HorizontalRateOfTurn: 25
RangeLimit: 7c0
CloseEnough: 0c600
Warhead@1Dam: SpreadDamage
Damage: 4000
ValidTargets: Air
@@ -211,14 +213,10 @@ APTusk:
TrailImage: smokey
HorizontalRateOfTurn: 10
RangeLimit: 7c204
Warhead@1Dam: SpreadDamage
Damage: 2500
Versus:
None: 28
Wood: 88
Light: 88
Heavy: 120
Concrete: 60
APTusk.stnk:
Inherits: APTusk
ReloadDelay: 100
TorpTube:
ReloadDelay: 100

View File

@@ -3,9 +3,7 @@
Range: 8c0
Report: aacanon3.aud
ValidTargets: Air
Projectile: Bullet
Speed: 1c682
Blockable: false
Projectile: InstantHit
Warhead@1Dam: SpreadDamage
Spread: 213
Damage: 2000
@@ -27,8 +25,6 @@ ZSU-23:
BurstDelays: 0
ReloadDelay: 6
Range: 10c0
Projectile: Bullet
Speed: 3c340
Warhead@1Dam: SpreadDamage
Damage: 1200
Versus:
@@ -47,8 +43,8 @@ FLAK-23-AG:
Inherits: ^AACannon
Range: 6c0
ValidTargets: Ground, Water
Projectile: Bullet
Blockable: True
Projectile: InstantHit
Blockable: true
Warhead@1Dam: SpreadDamage
ValidTargets: Air, Ground, Water
Warhead@2Eff: CreateEffect
@@ -63,8 +59,8 @@ FLAK-23-AG:
ReloadDelay: 30
Range: 6c0
Report: gun13.aud
Projectile: Bullet
Speed: 1c682
Projectile: InstantHit
Blockable: true
Warhead@1Dam: SpreadDamage
Spread: 128
Damage: 2500
@@ -211,7 +207,7 @@ ChainGun:
ReloadDelay: 10
Range: 5c0
MinRange: 0c768
Projectile: Bullet
Projectile: InstantHit
Blockable: false
Warhead@1Dam: SpreadDamage
Versus:
@@ -222,7 +218,7 @@ ChainGun.Yak:
ReloadDelay: 3
Range: 5c0
MinRange: 3c0
Projectile: Bullet
Projectile: InstantHit
Blockable: false
Warhead@1Dam: SpreadDamage
Damage: 4000
@@ -272,8 +268,8 @@ M60mg:
Report: gun5.aud
ValidTargets: Ground, Infantry
InvalidTargets: Vehicle, Water, Structure, Wall, Husk, Mine
Projectile: Bullet
Speed: 1c682
Projectile: InstantHit
Blockable: true
Warhead@1Dam: SpreadDamage
Spread: 42
Damage: 15000

View File

@@ -445,7 +445,7 @@ sidebar-bits:
production-tooltip-time: 136, 51, 16, 16
production-tooltip-power: 102, 51, 16, 16
production-tooltip-cost: 68, 51, 16, 16
indicator-muted: 0, 119, 24, 24
indicator-muted: 0, 119, 26, 24
flags:
Inherits: ^Glyphs

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -13,7 +13,7 @@
# MACOS_DEVELOPER_PASSWORD: App-specific password for the developer account
#
LAUNCHER_TAG="osx-launcher-20200209"
LAUNCHER_TAG="osx-launcher-20200316"
if [ $# -ne "2" ]; then
echo "Usage: $(basename "$0") tag outputdir"

View File

@@ -1,6 +1,6 @@
#!/bin/bash
LAUNCHER_TAG="osx-launcher-20200209"
LAUNCHER_TAG="osx-launcher-20200316"
download_dir="${0%/*}/download/osx"
mkdir -p "$download_dir"
@@ -25,3 +25,8 @@ if [ ! -f libfreetype.6.dylib ]; then
echo "Fetching OS X FreeType library from GitHub."
curl -LOs https://github.com/OpenRA/OpenRALauncherOSX/releases/download/${LAUNCHER_TAG}/libfreetype.6.dylib
fi
if [ ! -f libopenal.1.dylib ]; then
echo "Fetching OS X OpenAL Soft library from GitHub."
curl -LOs https://github.com/OpenRA/OpenRALauncherOSX/releases/download/${LAUNCHER_TAG}/libopenal.1.dylib
fi

View File

@@ -71,11 +71,11 @@ fi
if [ ! -f OpenAL-CS.dll ] || [ ! -f OpenAL-CS.dll.config ]; then
echo "Fetching OpenAL-CS from GitHub."
if command -v curl >/dev/null 2>&1; then
curl -s -L -O https://github.com/OpenRA/OpenAL-CS/releases/download/20190907/OpenAL-CS.dll
curl -s -L -O https://github.com/OpenRA/OpenAL-CS/releases/download/20190907/OpenAL-CS.dll.config
curl -s -L -O https://github.com/OpenRA/OpenAL-CS/releases/download/20200316/OpenAL-CS.dll
curl -s -L -O https://github.com/OpenRA/OpenAL-CS/releases/download/20200316/OpenAL-CS.dll.config
else
wget -cq https://github.com/OpenRA/OpenAL-CS/releases/download/20190907/OpenAL-CS.dll
wget -cq https://github.com/OpenRA/OpenAL-CS/releases/download/20190907/OpenAL-CS.dll.config
wget -cq https://github.com/OpenRA/OpenAL-CS/releases/download/20200316/OpenAL-CS.dll
wget -cq https://github.com/OpenRA/OpenAL-CS/releases/download/20200316/OpenAL-CS.dll.config
fi
fi