Merge remote-tracking branch 'scott/allies'
This commit is contained in:
@@ -23,8 +23,10 @@ namespace OpenRA.Widgets
|
||||
public int VisualHeight = ChromeMetrics.Get<int>("ButtonDepth");
|
||||
public string Font = ChromeMetrics.Get<string>("ButtonFont");
|
||||
public bool Disabled = false;
|
||||
public bool Highlighted = false;
|
||||
public Func<string> GetText;
|
||||
public Func<bool> IsDisabled;
|
||||
public Func<bool> IsHighlighted;
|
||||
public Action<MouseInput> OnMouseDown = _ => {};
|
||||
public Action<MouseInput> OnMouseUp = _ => {};
|
||||
|
||||
@@ -39,6 +41,7 @@ namespace OpenRA.Widgets
|
||||
OnMouseUp = _ => OnClick();
|
||||
OnKeyPress = _ => OnClick();
|
||||
IsDisabled = () => Disabled;
|
||||
IsHighlighted = () => Highlighted;
|
||||
}
|
||||
|
||||
protected ButtonWidget(ButtonWidget widget)
|
||||
@@ -52,6 +55,8 @@ namespace OpenRA.Widgets
|
||||
OnMouseDown = widget.OnMouseDown;
|
||||
Disabled = widget.Disabled;
|
||||
IsDisabled = widget.IsDisabled;
|
||||
Highlighted = widget.Highlighted;
|
||||
IsHighlighted = widget.IsHighlighted;
|
||||
|
||||
OnMouseUp = mi => OnClick();
|
||||
OnKeyPress = _ => OnClick();
|
||||
@@ -124,13 +129,14 @@ namespace OpenRA.Widgets
|
||||
{
|
||||
var rb = RenderBounds;
|
||||
var disabled = IsDisabled();
|
||||
var highlighted = IsHighlighted();
|
||||
|
||||
var font = Game.Renderer.Fonts[Font];
|
||||
var text = GetText();
|
||||
var s = font.Measure(text);
|
||||
var stateOffset = (Depressed) ? new int2(VisualHeight, VisualHeight) : new int2(0, 0);
|
||||
|
||||
DrawBackground(rb, disabled, Depressed, Ui.MouseOverWidget == this);
|
||||
DrawBackground(rb, disabled, Depressed, Ui.MouseOverWidget == this, highlighted);
|
||||
font.DrawText(text, new int2(rb.X + (UsableWidth - s.X)/ 2, rb.Y + (Bounds.Height - s.Y) / 2) + stateOffset,
|
||||
disabled ? Color.Gray : Color.White);
|
||||
}
|
||||
@@ -138,17 +144,19 @@ namespace OpenRA.Widgets
|
||||
public override Widget Clone() { return new ButtonWidget(this); }
|
||||
public virtual int UsableWidth { get { return Bounds.Width; } }
|
||||
|
||||
public virtual void DrawBackground(Rectangle rect, bool disabled, bool pressed, bool hover)
|
||||
public virtual void DrawBackground(Rectangle rect, bool disabled, bool pressed, bool hover, bool highlighted)
|
||||
{
|
||||
ButtonWidget.DrawBackground("button", rect, disabled, pressed, hover);
|
||||
ButtonWidget.DrawBackground("button", rect, disabled, pressed, hover, highlighted);
|
||||
}
|
||||
|
||||
public static void DrawBackground(string baseName, Rectangle rect, bool disabled, bool pressed, bool hover)
|
||||
public static void DrawBackground(string baseName, Rectangle rect, bool disabled, bool pressed, bool hover, bool highlighted)
|
||||
{
|
||||
var state = disabled ? "-disabled" :
|
||||
pressed ? "-pressed" :
|
||||
hover ? "-hover" :
|
||||
"";
|
||||
if (highlighted)
|
||||
state += "-highlighted";
|
||||
|
||||
WidgetUtils.DrawPanel(baseName + state, rect);
|
||||
}
|
||||
|
||||
@@ -79,11 +79,11 @@ namespace OpenRA.Widgets
|
||||
var thumbHover = Ui.MouseOverWidget == this && thumbRect.Contains(Viewport.LastMousePos);
|
||||
WidgetUtils.DrawPanel(Background, backgroundRect);
|
||||
WidgetUtils.DrawPanel("scrollpanel-bg", scrollbarRect);
|
||||
ButtonWidget.DrawBackground("button", upButtonRect, upDisabled, UpPressed, upHover);
|
||||
ButtonWidget.DrawBackground("button", downButtonRect, downDisabled, DownPressed, downHover);
|
||||
ButtonWidget.DrawBackground("button", upButtonRect, upDisabled, UpPressed, upHover, false);
|
||||
ButtonWidget.DrawBackground("button", downButtonRect, downDisabled, DownPressed, downHover, false);
|
||||
|
||||
if (thumbHeight > 0)
|
||||
ButtonWidget.DrawBackground("scrollthumb", thumbRect, false, Focused && thumbHover, thumbHover);
|
||||
ButtonWidget.DrawBackground("scrollthumb", thumbRect, false, Focused && thumbHover, thumbHover, false);
|
||||
|
||||
var upOffset = !UpPressed || upDisabled ? 4 : 4 + ButtonDepth;
|
||||
var downOffset = !DownPressed || downDisabled ? 4 : 4 + ButtonDepth;
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace OpenRA.Widgets
|
||||
|
||||
// Thumb
|
||||
var thumbHover = Ui.MouseOverWidget == this && tr.Contains(Viewport.LastMousePos);
|
||||
ButtonWidget.DrawBackground("scrollthumb", tr, IsDisabled(), isMoving, thumbHover);
|
||||
ButtonWidget.DrawBackground("scrollthumb", tr, IsDisabled(), isMoving, thumbHover, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ namespace OpenRA.Mods.Cnc.Widgets
|
||||
var rightHover = Ui.MouseOverWidget == this && rightButtonRect.Contains(Viewport.LastMousePos);
|
||||
|
||||
WidgetUtils.DrawPanel("panel-black", rb);
|
||||
ButtonWidget.DrawBackground("button", leftButtonRect, leftDisabled, leftPressed, leftHover);
|
||||
ButtonWidget.DrawBackground("button", rightButtonRect, rightDisabled, rightPressed, rightHover);
|
||||
ButtonWidget.DrawBackground("button", leftButtonRect, leftDisabled, leftPressed, leftHover, false);
|
||||
ButtonWidget.DrawBackground("button", rightButtonRect, rightDisabled, rightPressed, rightHover, false);
|
||||
|
||||
WidgetUtils.DrawRGBA(ChromeProvider.GetImage("scrollbar", leftPressed || leftDisabled ? "left_pressed" : "left_arrow"),
|
||||
new float2(leftButtonRect.Left + 2, leftButtonRect.Top + 2));
|
||||
@@ -157,7 +157,7 @@ namespace OpenRA.Mods.Cnc.Widgets
|
||||
var rect = new Rectangle(origin.X + ContentWidth, origin.Y, TabWidth, rb.Height);
|
||||
var hover = !leftHover && !rightHover && Ui.MouseOverWidget == this && rect.Contains(Viewport.LastMousePos);
|
||||
var baseName = tab.Queue == CurrentQueue ? "button-toggled" : "button";
|
||||
ButtonWidget.DrawBackground(baseName, rect, false, false, hover);
|
||||
ButtonWidget.DrawBackground(baseName, rect, false, false, hover, false);
|
||||
ContentWidth += TabWidth - 1;
|
||||
|
||||
int2 textSize = font.Measure(tab.Name);
|
||||
|
||||
@@ -53,10 +53,10 @@ namespace OpenRA.Mods.Cnc.Widgets
|
||||
tooltipContainer.Value.RemoveTooltip();
|
||||
}
|
||||
|
||||
public override void DrawBackground(Rectangle rect, bool disabled, bool pressed, bool hover)
|
||||
public override void DrawBackground(Rectangle rect, bool disabled, bool pressed, bool hover, bool highlighted)
|
||||
{
|
||||
var baseName = IsToggled() ? "button-toggled" : "button";
|
||||
ButtonWidget.DrawBackground(baseName, rect, disabled, pressed, hover);
|
||||
ButtonWidget.DrawBackground(baseName, rect, disabled, pressed, hover, highlighted);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
OpenRA.Mods.RA/ContainsCrate.cs
Normal file
29
OpenRA.Mods.RA/ContainsCrate.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
public class ContainsCrateInfo : TraitInfo<ContainsCrate> { }
|
||||
|
||||
public class ContainsCrate : INotifyKilled
|
||||
{
|
||||
public void Killed(Actor self, AttackInfo e)
|
||||
{
|
||||
self.World.AddFrameEndTask(w => w.CreateActor("crate", new TypeDictionary
|
||||
{
|
||||
new LocationInit(self.Location),
|
||||
new OwnerInit(self.World.WorldActor.Owner),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
39
OpenRA.Mods.RA/Crates/HealUnitsCrateAction.cs
Normal file
39
OpenRA.Mods.RA/Crates/HealUnitsCrateAction.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Crates
|
||||
{
|
||||
class HealUnitsCrateActionInfo : CrateActionInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new HealUnitsCrateAction(init.self, this); }
|
||||
}
|
||||
|
||||
class HealUnitsCrateAction : CrateAction
|
||||
{
|
||||
public HealUnitsCrateAction(Actor self, HealUnitsCrateActionInfo info)
|
||||
: base(self, info) { }
|
||||
|
||||
public override void Activate(Actor collector)
|
||||
{
|
||||
base.Activate(collector);
|
||||
foreach (var unit in collector.World.Actors.Where(a => a.Owner == collector.Owner))
|
||||
{
|
||||
var health = unit.TraitOrDefault<Health>();
|
||||
if (health != null && !health.IsDead)
|
||||
{
|
||||
health.InflictDamage(unit, unit, -(health.MaxHP - health.HP), null, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,14 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Scripting;
|
||||
using OpenRA.Traits;
|
||||
@@ -22,15 +24,23 @@ namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Allies01ScriptInfo : TraitInfo<Allies01Script>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Allies01Script : IWorldLoaded, ITick
|
||||
class Allies01Script : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
static readonly string[] Objectives =
|
||||
public event ObjectivesUpdatedEventHandler OnObjectivesUpdated;
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return objectives.Values; } }
|
||||
|
||||
Dictionary<int, Objective> objectives = new Dictionary<int, Objective>
|
||||
{
|
||||
"Find Einstein. Tanya and Einstein must survive.",
|
||||
"Wait for the helicopter and extract Einstein. Tanya and Einstein must survive."
|
||||
{ FindEinsteinID, new Objective(ObjectiveType.Primary, FindEinstein, ObjectiveStatus.InProgress) },
|
||||
{ ExtractEinsteinID, new Objective(ObjectiveType.Primary, ExtractEinstein, ObjectiveStatus.Inactive) }
|
||||
};
|
||||
|
||||
int currentObjective;
|
||||
const int FindEinsteinID = 0;
|
||||
const int ExtractEinsteinID = 1;
|
||||
|
||||
const string FindEinstein = "Find Einstein. Tanya and Einstein must survive.";
|
||||
const string ExtractEinstein = "Wait for the helicopter and extract Einstein. Tanya and Einstein must survive.";
|
||||
|
||||
Player allies;
|
||||
Player soviets;
|
||||
@@ -65,15 +75,8 @@ namespace OpenRA.Mods.RA.Missions
|
||||
const int LabClearRange = 5;
|
||||
const string EinsteinName = "einstein";
|
||||
const string TanyaName = "e7";
|
||||
const string ChinookName = "tran";
|
||||
const string SignalFlareName = "flare";
|
||||
|
||||
void DisplayObjective()
|
||||
{
|
||||
Game.AddChatLine(Color.LimeGreen, "Objective", Objectives[currentObjective]);
|
||||
Sound.Play("bleep6.aud");
|
||||
}
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
if (allies.WinState != WinState.Undefined)
|
||||
@@ -106,18 +109,11 @@ namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
return;
|
||||
}
|
||||
// display current objective every so often
|
||||
if (world.FrameNumber % 1500 == 1)
|
||||
{
|
||||
DisplayObjective();
|
||||
}
|
||||
// taunt every so often
|
||||
if (world.FrameNumber % 1000 == 0)
|
||||
{
|
||||
Sound.Play(Taunts[world.SharedRandom.Next(Taunts.Length)]);
|
||||
}
|
||||
// objectives
|
||||
if (currentObjective == 0)
|
||||
if (objectives[FindEinsteinID].Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
if (AlliesControlLab())
|
||||
{
|
||||
@@ -125,40 +121,48 @@ namespace OpenRA.Mods.RA.Missions
|
||||
Sound.Play("flaren1.aud");
|
||||
SpawnEinsteinAtLab();
|
||||
SendShips();
|
||||
currentObjective++;
|
||||
DisplayObjective();
|
||||
objectives[FindEinsteinID].Status = ObjectiveStatus.Completed;
|
||||
objectives[ExtractEinsteinID].Status = ObjectiveStatus.InProgress;
|
||||
OnObjectivesUpdated(true);
|
||||
currentAttackWaveFrameNumber = world.FrameNumber;
|
||||
}
|
||||
if (lab.Destroyed)
|
||||
{
|
||||
objectives[FindEinsteinID].Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("Einstein was killed.");
|
||||
}
|
||||
}
|
||||
else if (currentObjective == 1)
|
||||
if (objectives[ExtractEinsteinID].Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
SendAttackWave();
|
||||
if (world.FrameNumber >= currentAttackWaveFrameNumber + 600)
|
||||
{
|
||||
Sound.Play("enmyapp1.aud");
|
||||
SendAttackWave(AttackWave);
|
||||
SpawnAttackWave(AttackWave);
|
||||
currentAttackWave++;
|
||||
currentAttackWaveFrameNumber = world.FrameNumber;
|
||||
if (currentAttackWave >= EinsteinChinookAttackWave)
|
||||
{
|
||||
SendAttackWave(LastAttackWaveAddition);
|
||||
SpawnAttackWave(LastAttackWaveAddition);
|
||||
}
|
||||
if (currentAttackWave == EinsteinChinookAttackWave)
|
||||
{
|
||||
FlyEinsteinFromExtractionLZ();
|
||||
ExtractEinsteinAtLZ();
|
||||
}
|
||||
}
|
||||
if (einsteinChinook != null)
|
||||
{
|
||||
if (einsteinChinook.Destroyed)
|
||||
{
|
||||
objectives[ExtractEinsteinID].Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The extraction helicopter was destroyed.");
|
||||
}
|
||||
else if (!world.Map.IsInMap(einsteinChinook.Location) && einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein))
|
||||
{
|
||||
objectives[ExtractEinsteinID].Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionAccomplished("Einstein was rescued.");
|
||||
}
|
||||
}
|
||||
@@ -186,22 +190,47 @@ namespace OpenRA.Mods.RA.Missions
|
||||
world.CreateActor(SignalFlareName, new TypeDictionary { new OwnerInit(allies), new LocationInit(extractionLZ.Location) });
|
||||
}
|
||||
|
||||
void SendAttackWave(IEnumerable<string> wave)
|
||||
void SpawnAttackWave(IEnumerable<string> wave)
|
||||
{
|
||||
foreach (var unit in wave)
|
||||
{
|
||||
var spawnActor = world.SharedRandom.Next(2) == 0 ? attackEntryPoint1 : attackEntryPoint2;
|
||||
var actor = world.CreateActor(unit, new TypeDictionary { new OwnerInit(soviets), new LocationInit(spawnActor.Location) });
|
||||
}
|
||||
}
|
||||
|
||||
void SendAttackWave()
|
||||
{
|
||||
foreach (var unit in world.Actors.Where(
|
||||
a => a != world.WorldActor
|
||||
&& a.IsInWorld
|
||||
&& a.Owner == soviets
|
||||
&& !a.IsDead()
|
||||
&& a.IsIdle
|
||||
&& a.HasTrait<Mobile>()
|
||||
&& a.HasTrait<AttackBase>()))
|
||||
{
|
||||
Activity innerActivity;
|
||||
if (einstein != null && einstein.IsInWorld)
|
||||
if (einstein != null)
|
||||
{
|
||||
if (einstein.IsInWorld)
|
||||
{
|
||||
innerActivity = new Attack(Target.FromActor(einstein), 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
var container = world.UnitContaining(einstein);
|
||||
if (container != null && !container.HasTrait<Aircraft>() && container.HasTrait<Mobile>())
|
||||
{
|
||||
innerActivity = new Attack(Target.FromActor(container), 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
innerActivity = new Move.Move(extractionLZ.Location, 3);
|
||||
}
|
||||
actor.QueueActivity(new AttackMove.AttackMoveActivity(actor, innerActivity));
|
||||
}
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, innerActivity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,16 +243,9 @@ namespace OpenRA.Mods.RA.Missions
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<Actor> UnitsNearActor(Actor actor, int range)
|
||||
{
|
||||
return world.FindUnitsInCircle(actor.CenterLocation, Game.CellSize * range)
|
||||
.Where(a => a.IsInWorld && a != world.WorldActor && !a.Destroyed && a.HasTrait<IMove>() && !a.Owner.NonCombatant);
|
||||
}
|
||||
|
||||
bool AlliesControlLab()
|
||||
{
|
||||
var units = UnitsNearActor(lab, LabClearRange);
|
||||
return units.Any() && units.All(a => a.Owner == allies);
|
||||
return MissionUtils.AreaSecuredWithUnits(world, allies, lab.CenterLocation, LabClearRange);
|
||||
}
|
||||
|
||||
void SpawnEinsteinAtLab()
|
||||
@@ -242,32 +264,31 @@ namespace OpenRA.Mods.RA.Missions
|
||||
}
|
||||
}
|
||||
|
||||
void FlyEinsteinFromExtractionLZ()
|
||||
void ExtractEinsteinAtLZ()
|
||||
{
|
||||
einsteinChinook = world.CreateActor(ChinookName, new TypeDictionary { new OwnerInit(allies), new LocationInit(extractionLZEntryPoint.Location) });
|
||||
einsteinChinook.QueueActivity(new HeliFly(extractionLZ.CenterLocation));
|
||||
einsteinChinook.QueueActivity(new Turn(0));
|
||||
einsteinChinook.QueueActivity(new HeliLand(true, 0));
|
||||
einsteinChinook.QueueActivity(new WaitFor(() => einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein)));
|
||||
einsteinChinook.QueueActivity(new Wait(150));
|
||||
einsteinChinook.QueueActivity(new HeliFly(chinookExitPoint.CenterLocation));
|
||||
einsteinChinook.QueueActivity(new RemoveSelf());
|
||||
einsteinChinook = MissionUtils.ExtractUnitWithChinook(
|
||||
world,
|
||||
allies,
|
||||
einstein,
|
||||
extractionLZEntryPoint.Location,
|
||||
extractionLZ.Location,
|
||||
chinookExitPoint.Location);
|
||||
}
|
||||
|
||||
void FlyTanyaToInsertionLZ()
|
||||
void InsertTanyaAtLZ()
|
||||
{
|
||||
tanya = world.CreateActor(false, TanyaName, new TypeDictionary { new OwnerInit(allies) });
|
||||
var chinook = world.CreateActor(ChinookName, new TypeDictionary { new OwnerInit(allies), new LocationInit(insertionLZEntryPoint.Location) });
|
||||
chinook.Trait<Cargo>().Load(chinook, tanya);
|
||||
chinook.QueueActivity(new HeliFly(insertionLZ.CenterLocation));
|
||||
chinook.QueueActivity(new Turn(0));
|
||||
chinook.QueueActivity(new HeliLand(true, 0));
|
||||
chinook.QueueActivity(new UnloadCargo(true));
|
||||
chinook.QueueActivity(new CallFunc(() => Sound.Play("laugh1.aud")));
|
||||
chinook.QueueActivity(new CallFunc(() => tanya.QueueActivity(new Move.Move(insertionLZ.Location - new CVec(1, 0)))));
|
||||
chinook.QueueActivity(new Wait(150));
|
||||
chinook.QueueActivity(new HeliFly(chinookExitPoint.CenterLocation));
|
||||
chinook.QueueActivity(new RemoveSelf());
|
||||
tanya = MissionUtils.InsertUnitWithChinook(
|
||||
world,
|
||||
allies,
|
||||
TanyaName,
|
||||
insertionLZEntryPoint.Location,
|
||||
insertionLZ.Location,
|
||||
chinookExitPoint.Location,
|
||||
unit =>
|
||||
{
|
||||
Sound.Play("laugh1.aud");
|
||||
unit.QueueActivity(new Move.Move(insertionLZ.Location - new CVec(1, 0)));
|
||||
}).Second;
|
||||
}
|
||||
|
||||
void SetAlliedUnitsToDefensiveStance()
|
||||
@@ -310,7 +331,7 @@ namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
Media.PlayFMVFullscreen(w, "landing.vqa", () =>
|
||||
{
|
||||
FlyTanyaToInsertionLZ();
|
||||
InsertTanyaAtLZ();
|
||||
SendPatrol();
|
||||
PlayMusic();
|
||||
});
|
||||
|
||||
@@ -16,6 +16,8 @@ using OpenRA.FileFormats;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Mods.RA.Effects;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
@@ -24,15 +26,34 @@ namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Allies02ScriptInfo : TraitInfo<Allies02Script>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Allies02Script : IWorldLoaded, ITick
|
||||
class Allies02Script : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
static readonly string[] Objectives =
|
||||
public event ObjectivesUpdatedEventHandler OnObjectivesUpdated;
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return objectives.Values; } }
|
||||
|
||||
Dictionary<int, Objective> objectives = new Dictionary<int, Objective>()
|
||||
{
|
||||
"Hold off the Soviet forces and destroy the SAM sites. Tanya and Einstein must survive.",
|
||||
"Wait for the helicopter and extract Einstein. Tanya and Einstein must survive."
|
||||
{ FindEinsteinID, new Objective(ObjectiveType.Primary, FindEinstein, ObjectiveStatus.InProgress) },
|
||||
{ DestroySamSitesID, new Objective(ObjectiveType.Primary, DestroySamSites, ObjectiveStatus.InProgress) },
|
||||
{ ExtractEinsteinID, new Objective(ObjectiveType.Primary, ExtractEinstein, ObjectiveStatus.Inactive) },
|
||||
{ MaintainPresenceID, new Objective(ObjectiveType.Primary, MaintainPresence, ObjectiveStatus.InProgress) },
|
||||
{ FewDeathsID, new Objective(ObjectiveType.Secondary, "", ObjectiveStatus.InProgress) }
|
||||
};
|
||||
|
||||
int currentObjective;
|
||||
const int FindEinsteinID = 0;
|
||||
const int DestroySamSitesID = 1;
|
||||
const int ExtractEinsteinID = 2;
|
||||
const int MaintainPresenceID = 3;
|
||||
const int FewDeathsID = 4;
|
||||
|
||||
const string FindEinstein = "Find Einstein's crashed helicopter. Tanya must survive.";
|
||||
const string DestroySamSites = "Destroy the SAM sites. Tanya must survive.";
|
||||
const string ExtractEinstein = "Wait for the helicopter and extract Einstein. Tanya and Einstein must survive.";
|
||||
const string MaintainPresence = "Maintain an Allied presence in the area. Reinforcements will arrive soon.";
|
||||
const string FewDeathsTemplate = "Lose fewer than {0}/{1} units.";
|
||||
|
||||
const int DeathsThreshold = 100;
|
||||
|
||||
Actor sam1;
|
||||
Actor sam2;
|
||||
@@ -42,17 +63,29 @@ namespace OpenRA.Mods.RA.Missions
|
||||
Actor einstein;
|
||||
Actor engineer;
|
||||
|
||||
Actor engineerMiss;
|
||||
|
||||
Actor chinookHusk;
|
||||
Actor allies2BasePoint;
|
||||
Actor reinforcementsEntryPoint;
|
||||
Actor extractionLZEntryPoint;
|
||||
Actor extractionLZ;
|
||||
Actor badgerEntryPoint;
|
||||
Actor badgerDropPoint;
|
||||
Actor badgerEntryPoint1;
|
||||
Actor badgerEntryPoint2;
|
||||
Actor badgerDropPoint1;
|
||||
Actor badgerDropPoint2;
|
||||
Actor badgerDropPoint3;
|
||||
Actor parabombPoint1;
|
||||
Actor parabombPoint2;
|
||||
Actor sovietRallyPoint;
|
||||
Actor flamersEntryPoint;
|
||||
Actor tanksEntryPoint;
|
||||
Actor townPoint;
|
||||
Actor sovietTownAttackPoint1;
|
||||
Actor sovietTownAttackPoint2;
|
||||
Actor yakEntryPoint;
|
||||
Actor yakAttackPoint;
|
||||
Actor yak;
|
||||
Actor sovietReinforcementsEntryPoint1;
|
||||
Actor sovietReinforcementsEntryPoint2;
|
||||
|
||||
Actor einsteinChinook;
|
||||
|
||||
@@ -67,36 +100,56 @@ namespace OpenRA.Mods.RA.Missions
|
||||
CountdownTimer reinforcementsTimer;
|
||||
CountdownTimerWidget reinforcementsTimerWidget;
|
||||
|
||||
List<Actor> sovietReinforcementsUnits = new List<Actor>();
|
||||
|
||||
const string InfantryQueueName = "Infantry";
|
||||
const string VehicleQueueName = "Vehicle";
|
||||
readonly List<string> sovietInfantry = new List<string> { "e1", "e2", "e3" };
|
||||
readonly List<string> sovietVehicles = new List<string> { "3tnk" };
|
||||
static readonly string[] SovietVehicleAdditions = { "v2rl" };
|
||||
const int SovietGroupSize = 5;
|
||||
const int SovietVehicleAdditionsTicks = 1500 * 4;
|
||||
static readonly string[] SovietInfantry = { "e1", "e2", "e3" };
|
||||
static readonly string[] SovietVehicles1 = { "3tnk" };
|
||||
static readonly string[] SovietVehicles2 = { "3tnk", "v2rl" };
|
||||
const int SovietVehiclesUpgradeTicks = 1500 * 4;
|
||||
const int SovietGroupSize = 8;
|
||||
const int SovietHelperCash = 2000;
|
||||
|
||||
const int ReinforcementsTicks = 1500 * 12;
|
||||
static readonly string[] Reinforcements = { "2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "1tnk", "1tnk", "jeep", "e1", "e1", "e1", "e1", "e3", "e3", "mcv" };
|
||||
const int ReinforcementsCash = 2000;
|
||||
static readonly string[] Reinforcements =
|
||||
{
|
||||
"2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "2tnk",
|
||||
"1tnk", "1tnk",
|
||||
"jeep",
|
||||
"e1", "e1", "e1", "e1",
|
||||
"e3", "e3",
|
||||
"mcv",
|
||||
"truk", "truk", "truk", "truk", "truk", "truk"
|
||||
};
|
||||
const int SovietReinforcementsTicks = 1500 * 16;
|
||||
static readonly string[] SovietReinforcements =
|
||||
{
|
||||
"3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk",
|
||||
"v2rl", "v2rl", "v2rl", "v2rl",
|
||||
"ftrk", "ftrk"
|
||||
};
|
||||
|
||||
const int ParatroopersTicks = 1500 * 10;
|
||||
static readonly string[] Paratroopers = { "e1", "e1", "e1", "e2", "3tnk" };
|
||||
const string BadgerName = "badr";
|
||||
const int ParabombTicks = 750;
|
||||
|
||||
const int FlamersTicks = 1500 * 7;
|
||||
const int FlamersTicks = 1500 * 2;
|
||||
static readonly string[] Flamers = { "e4", "e4", "e4", "e4", "e4" };
|
||||
const string ApcName = "apc";
|
||||
|
||||
const string ChinookName = "tran";
|
||||
const string SignalFlareName = "flare";
|
||||
const string EngineerName = "e6";
|
||||
const int EngineerMissClearRange = 5;
|
||||
const int ParatroopersTicks = 1500 * 5;
|
||||
static readonly string[] Badger1Passengers = { "e1", "e1", "e1", "e2", "3tnk" };
|
||||
static readonly string[] Badger2Passengers = { "e1", "e1", "e1", "e2", "e2" };
|
||||
static readonly string[] Badger3Passengers = { "e1", "e1", "e1", "e2", "e2" };
|
||||
|
||||
void DisplayObjective()
|
||||
{
|
||||
Game.AddChatLine(Color.LimeGreen, "Objective", Objectives[currentObjective]);
|
||||
Sound.Play("bleep6.aud");
|
||||
}
|
||||
const int TanksTicks = 1500 * 11;
|
||||
static readonly string[] Tanks = { "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk" };
|
||||
|
||||
const string SignalFlareName = "flare";
|
||||
const string YakName = "yak";
|
||||
|
||||
const int AlliedTownTransferRange = 15;
|
||||
const int SovietTownAttackGroupRange = 5;
|
||||
const int SovietTownMoveNearEnough = 3;
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
@@ -138,9 +191,9 @@ namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (world.FrameNumber % 3500 == 1)
|
||||
if (world.FrameNumber % 50 == 1 && chinookHusk.IsInWorld)
|
||||
{
|
||||
DisplayObjective();
|
||||
world.Add(new Smoke(world, chinookHusk.CenterLocation, "smoke_m"));
|
||||
}
|
||||
if (world.FrameNumber == 1)
|
||||
{
|
||||
@@ -150,15 +203,35 @@ namespace OpenRA.Mods.RA.Missions
|
||||
reinforcementsTimer.Tick();
|
||||
if (world.FrameNumber == ParatroopersTicks)
|
||||
{
|
||||
ParadropSovietUnits();
|
||||
MissionUtils.Paradrop(world, soviets, Badger1Passengers, badgerEntryPoint1.Location, badgerDropPoint1.Location);
|
||||
MissionUtils.Paradrop(world, soviets, Badger2Passengers, badgerEntryPoint1.Location + new CVec(3, 0), badgerDropPoint2.Location);
|
||||
MissionUtils.Paradrop(world, soviets, Badger3Passengers, badgerEntryPoint1.Location + new CVec(6, 0), badgerDropPoint3.Location);
|
||||
}
|
||||
if (world.FrameNumber == FlamersTicks)
|
||||
{
|
||||
RushSovietFlamers();
|
||||
}
|
||||
if (world.FrameNumber == SovietVehicleAdditionsTicks)
|
||||
if (world.FrameNumber == TanksTicks)
|
||||
{
|
||||
sovietVehicles.AddRange(SovietVehicleAdditions);
|
||||
RushSovietUnits();
|
||||
}
|
||||
if (world.FrameNumber == ParabombTicks)
|
||||
{
|
||||
MissionUtils.Parabomb(world, soviets, badgerEntryPoint2.Location, parabombPoint1.Location);
|
||||
MissionUtils.Parabomb(world, soviets, badgerEntryPoint2.Location + new CVec(0, 3), parabombPoint2.Location);
|
||||
}
|
||||
if (world.FrameNumber == SovietReinforcementsTicks)
|
||||
{
|
||||
SendSovietReinforcements();
|
||||
}
|
||||
if (yak == null || (yak != null && !yak.IsDead() && (yak.GetCurrentActivity() is FlyCircle || yak.IsIdle)))
|
||||
{
|
||||
var alliedUnitsNearYakPoint = world.FindAliveCombatantActorsInCircle(yakAttackPoint.CenterLocation, 10)
|
||||
.Where(a => a.Owner != soviets && a.HasTrait<IMove>() && a != tanya && a != einstein && a != engineer);
|
||||
if (alliedUnitsNearYakPoint.Any())
|
||||
{
|
||||
YakStrafe(alliedUnitsNearYakPoint);
|
||||
}
|
||||
}
|
||||
if (world.FrameNumber % 25 == 0)
|
||||
{
|
||||
@@ -166,30 +239,47 @@ namespace OpenRA.Mods.RA.Missions
|
||||
BuildSovietUnits();
|
||||
ManageSovietUnits();
|
||||
}
|
||||
if (!engineerMiss.Destroyed && engineer == null && AlliesControlMiss())
|
||||
UpdateDeaths();
|
||||
if (objectives[FindEinsteinID].Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
SpawnEngineerAtMiss();
|
||||
engineerMiss.QueueActivity(new Demolish(engineerMiss, 0));
|
||||
if (AlliesNearTown())
|
||||
{
|
||||
objectives[FindEinsteinID].Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
TransferTownUnitsToAllies();
|
||||
SovietsAttackTown();
|
||||
}
|
||||
if (currentObjective == 0)
|
||||
}
|
||||
if (objectives[DestroySamSitesID].Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
if (sam1.Destroyed && sam2.Destroyed && sam3.Destroyed && sam4.Destroyed)
|
||||
{
|
||||
currentObjective++;
|
||||
DisplayObjective();
|
||||
objectives[DestroySamSitesID].Status = ObjectiveStatus.Completed;
|
||||
objectives[ExtractEinsteinID].Status = ObjectiveStatus.InProgress;
|
||||
OnObjectivesUpdated(true);
|
||||
SpawnSignalFlare();
|
||||
Sound.Play("flaren1.aud");
|
||||
SendChinook();
|
||||
ExtractEinsteinAtLZ();
|
||||
}
|
||||
}
|
||||
else if (currentObjective == 1 && einsteinChinook != null)
|
||||
if (objectives[ExtractEinsteinID].Status == ObjectiveStatus.InProgress && einsteinChinook != null)
|
||||
{
|
||||
if (einsteinChinook.Destroyed)
|
||||
{
|
||||
objectives[ExtractEinsteinID].Status = ObjectiveStatus.Failed;
|
||||
objectives[MaintainPresenceID].Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The extraction helicopter was destroyed.");
|
||||
}
|
||||
else if (!world.Map.IsInMap(einsteinChinook.Location) && einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein))
|
||||
{
|
||||
objectives[ExtractEinsteinID].Status = ObjectiveStatus.Completed;
|
||||
objectives[MaintainPresenceID].Status = ObjectiveStatus.Completed;
|
||||
if (objectives[FewDeathsID].Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
objectives[FewDeathsID].Status = ObjectiveStatus.Completed;
|
||||
}
|
||||
OnObjectivesUpdated(true);
|
||||
MissionAccomplished("Einstein was rescued.");
|
||||
}
|
||||
}
|
||||
@@ -201,18 +291,58 @@ namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
MissionFailed("Einstein was killed.");
|
||||
}
|
||||
else if (!world.Actors.Any(a => a.IsInWorld && a.HasTrait<Building>() && !a.HasTrait<Wall>() && a.Owner == allies2))
|
||||
world.AddFrameEndTask(w =>
|
||||
{
|
||||
if (!world.FindAliveCombatantActorsInCircle(allies2BasePoint.CenterLocation, 20).Any(a => a.HasTrait<Building>() && !a.HasTrait<Wall>() && a.Owner == allies2))
|
||||
{
|
||||
objectives[MaintainPresenceID].Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The Allied reinforcements have been defeated.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateDeaths()
|
||||
{
|
||||
var unitDeaths = allies1.Deaths + allies2.Deaths;
|
||||
objectives[FewDeathsID].Text = FewDeathsTemplate.F(unitDeaths, DeathsThreshold);
|
||||
OnObjectivesUpdated(false);
|
||||
if (unitDeaths >= DeathsThreshold && objectives[FewDeathsID].Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
objectives[FewDeathsID].Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
}
|
||||
|
||||
void YakStrafe(IEnumerable<Actor> candidates)
|
||||
{
|
||||
if (yak == null)
|
||||
{
|
||||
yak = world.CreateActor(YakName, new TypeDictionary
|
||||
{
|
||||
new LocationInit(yakEntryPoint.Location),
|
||||
new OwnerInit(soviets),
|
||||
new FacingInit(Util.GetFacing(yakAttackPoint.Location - yakEntryPoint.Location, 0)),
|
||||
new AltitudeInit(Rules.Info[YakName].Traits.Get<PlaneInfo>().CruiseAltitude),
|
||||
});
|
||||
}
|
||||
if (yak.Trait<LimitedAmmo>().HasAmmo())
|
||||
{
|
||||
yak.QueueActivity(new FlyAttack(Target.FromActor(candidates.Random(world.SharedRandom))));
|
||||
}
|
||||
else
|
||||
{
|
||||
yak.QueueActivity(new FlyOffMap());
|
||||
yak.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
}
|
||||
|
||||
void AddSovietCashIfRequired()
|
||||
{
|
||||
var resources = soviets.PlayerActor.Trait<PlayerResources>();
|
||||
if (resources.Cash < ReinforcementsCash)
|
||||
if (resources.Cash < SovietHelperCash)
|
||||
{
|
||||
resources.GiveCash(ReinforcementsCash);
|
||||
resources.GiveCash(SovietHelperCash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,66 +355,75 @@ namespace OpenRA.Mods.RA.Missions
|
||||
}
|
||||
if (!sovietBarracks.Destroyed)
|
||||
{
|
||||
BuildSovietUnit(InfantryQueueName, sovietInfantry.Random(world.SharedRandom));
|
||||
BuildSovietUnit(InfantryQueueName, SovietInfantry.Random(world.SharedRandom));
|
||||
}
|
||||
if (!sovietWarFactory.Destroyed)
|
||||
{
|
||||
BuildSovietUnit(VehicleQueueName, sovietVehicles.Random(world.SharedRandom));
|
||||
var vehicles = world.FrameNumber >= SovietVehiclesUpgradeTicks ? SovietVehicles2 : SovietVehicles1;
|
||||
BuildSovietUnit(VehicleQueueName, vehicles.Random(world.SharedRandom));
|
||||
}
|
||||
}
|
||||
|
||||
void ManageSovietUnits()
|
||||
{
|
||||
var idleSovietUnits = ForcesNearActor(allies2BasePoint, 10).Where(a => a.Owner == soviets && a.IsIdle);
|
||||
var idleSovietUnitsAtRP = ForcesNearActor(sovietRallyPoint, 5).Where(a => a.Owner == soviets && a.IsIdle);
|
||||
var idleSovietUnitsAtRP = world.FindAliveCombatantActorsInCircle(sovietRallyPoint.CenterLocation, 3).Where(a => a.Owner == soviets && a.IsIdle && a.HasTrait<IMove>());
|
||||
if (idleSovietUnitsAtRP.Count() >= SovietGroupSize)
|
||||
{
|
||||
idleSovietUnits = idleSovietUnits.Union(idleSovietUnitsAtRP);
|
||||
}
|
||||
foreach (var unit in idleSovietUnits)
|
||||
var firstUnit = idleSovietUnitsAtRP.FirstOrDefault();
|
||||
if (firstUnit != null)
|
||||
{
|
||||
var closestAlliedBuilding = ClosestAlliedBuilding(unit, 20);
|
||||
var closestAlliedBuilding = ClosestAlliedBuilding(firstUnit, 40);
|
||||
if (closestAlliedBuilding != null)
|
||||
{
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(closestAlliedBuilding.Location, 3)));
|
||||
foreach (var unit in idleSovietUnitsAtRP)
|
||||
{
|
||||
unit.Trait<Mobile>().Nudge(unit, unit, true);
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Attack(Target.FromActor(closestAlliedBuilding), 3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var idleSovietUnits = world.FindAliveCombatantActorsInCircle(allies2BasePoint.CenterLocation, 20).Where(a => a.Owner == soviets && a.IsIdle && a.HasTrait<IMove>());
|
||||
foreach (var unit in idleSovietUnits)
|
||||
{
|
||||
var closestAlliedBuilding = ClosestAlliedBuilding(unit, 40);
|
||||
if (closestAlliedBuilding != null)
|
||||
{
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Attack(Target.FromActor(closestAlliedBuilding), 3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Actor ClosestAlliedBuilding(Actor actor, int range)
|
||||
{
|
||||
return BuildingsNearActor(actor, range)
|
||||
.Where(a => a.Owner == allies2)
|
||||
.OrderBy(a => (actor.Location - a.Location).LengthSquared)
|
||||
.FirstOrDefault();
|
||||
return MissionUtils.ClosestPlayerBuilding(world, allies2, actor.CenterLocation, range);
|
||||
}
|
||||
|
||||
IEnumerable<Actor> ClosestAlliedBuildings(Actor actor, int range)
|
||||
{
|
||||
return MissionUtils.ClosestPlayerBuildings(world, allies2, actor.CenterLocation, range);
|
||||
}
|
||||
|
||||
void InitializeSovietFactories()
|
||||
{
|
||||
sovietBarracks.Trait<RallyPoint>().rallyPoint = sovietRallyPoint.Location;
|
||||
sovietWarFactory.Trait<RallyPoint>().rallyPoint = sovietRallyPoint.Location;
|
||||
var sbrp = sovietBarracks.Trait<RallyPoint>();
|
||||
var swrp = sovietWarFactory.Trait<RallyPoint>();
|
||||
sbrp.rallyPoint = swrp.rallyPoint = sovietRallyPoint.Location;
|
||||
sbrp.nearEnough = swrp.nearEnough = 3;
|
||||
sovietBarracks.Trait<PrimaryBuilding>().SetPrimaryProducer(sovietBarracks, true);
|
||||
sovietWarFactory.Trait<PrimaryBuilding>().SetPrimaryProducer(sovietWarFactory, true);
|
||||
}
|
||||
|
||||
IEnumerable<ProductionQueue> FindQueues(Player player, string category)
|
||||
{
|
||||
return world.ActorsWithTrait<ProductionQueue>()
|
||||
.Where(a => a.Actor.Owner == player && a.Trait.Info.Type == category)
|
||||
.Select(a => a.Trait);
|
||||
}
|
||||
|
||||
void BuildSovietUnit(string category, string unit)
|
||||
{
|
||||
var queue = FindQueues(soviets, category).FirstOrDefault(q => q.CurrentItem() == null);
|
||||
var queue = MissionUtils.FindQueues(world, soviets, category).FirstOrDefault(q => q.CurrentItem() == null);
|
||||
if (queue == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var order = Order.StartProduction(queue.self, unit, 1);
|
||||
if (Game.IsHost)
|
||||
{
|
||||
world.IssueOrder(order);
|
||||
world.IssueOrder(Order.StartProduction(queue.self, unit, 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,32 +435,76 @@ namespace OpenRA.Mods.RA.Missions
|
||||
void StartReinforcementsTimer()
|
||||
{
|
||||
Sound.Play("timergo1.aud");
|
||||
reinforcementsTimer = new CountdownTimer(ReinforcementsTicks, ReinforcementsTimerExpired);
|
||||
reinforcementsTimerWidget = new CountdownTimerWidget(reinforcementsTimer, "Reinforcements arrive in", new float2(128, 96));
|
||||
reinforcementsTimer = new CountdownTimer(ReinforcementsTicks, ReinforcementsTimerExpired, true);
|
||||
reinforcementsTimerWidget = new CountdownTimerWidget(
|
||||
reinforcementsTimer,
|
||||
"Allied reinforcements arrive in: {0}",
|
||||
new float2(Game.viewport.Width * 0.35f, Game.viewport.Height * 0.9f));
|
||||
Ui.Root.AddChild(reinforcementsTimerWidget);
|
||||
}
|
||||
|
||||
void ParadropSovietUnits()
|
||||
void SendSovietReinforcements()
|
||||
{
|
||||
var badger = world.CreateActor(BadgerName, new TypeDictionary
|
||||
foreach (var entryPoint in new[] { sovietReinforcementsEntryPoint1, sovietReinforcementsEntryPoint2 })
|
||||
{
|
||||
new LocationInit(badgerEntryPoint.Location),
|
||||
new OwnerInit(soviets),
|
||||
new FacingInit(Util.GetFacing(badgerDropPoint.Location - badgerEntryPoint.Location, 0)),
|
||||
new AltitudeInit(Rules.Info[BadgerName].Traits.Get<PlaneInfo>().CruiseAltitude),
|
||||
foreach (var unit in SovietReinforcements)
|
||||
{
|
||||
var u = world.CreateActor(unit, new TypeDictionary
|
||||
{
|
||||
new LocationInit(entryPoint.Location),
|
||||
new FacingInit(Util.GetFacing(allies2BasePoint.Location - entryPoint.Location, 0)),
|
||||
new OwnerInit(soviets)
|
||||
});
|
||||
badger.QueueActivity(new FlyAttack(Target.FromCell(badgerDropPoint.Location)));
|
||||
badger.Trait<ParaDrop>().SetLZ(badgerDropPoint.Location);
|
||||
var cargo = badger.Trait<Cargo>();
|
||||
foreach (var unit in Paratroopers)
|
||||
u.QueueActivity(new Move.Move(sovietRallyPoint.Location, 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReinforcementsTimerExpired(CountdownTimer countdownTimer)
|
||||
{
|
||||
cargo.Load(badger, world.CreateActor(false, unit, new TypeDictionary { new OwnerInit(soviets) }));
|
||||
reinforcementsTimerWidget.Visible = false;
|
||||
SendReinforcements();
|
||||
Sound.Play("aarrivs1.aud");
|
||||
}
|
||||
|
||||
void SendReinforcements()
|
||||
{
|
||||
foreach (var unit in Reinforcements)
|
||||
{
|
||||
var u = world.CreateActor(unit, new TypeDictionary
|
||||
{
|
||||
new LocationInit(reinforcementsEntryPoint.Location),
|
||||
new FacingInit(0),
|
||||
new OwnerInit(allies2)
|
||||
});
|
||||
u.QueueActivity(new Move.Move(allies2BasePoint.Location));
|
||||
}
|
||||
}
|
||||
|
||||
void RushSovietUnits()
|
||||
{
|
||||
var closestAlliedBuildings = ClosestAlliedBuildings(badgerDropPoint1, 40);
|
||||
if (!closestAlliedBuildings.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var tank in Tanks)
|
||||
{
|
||||
var unit = world.CreateActor(tank, new TypeDictionary
|
||||
{
|
||||
new OwnerInit(soviets),
|
||||
new LocationInit(tanksEntryPoint.Location)
|
||||
});
|
||||
foreach (var building in closestAlliedBuildings)
|
||||
{
|
||||
unit.QueueActivity(new Attack(Target.FromActor(building), 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RushSovietFlamers()
|
||||
{
|
||||
var closestAlliedBuilding = ClosestAlliedBuilding(badgerDropPoint, 10);
|
||||
var closestAlliedBuilding = ClosestAlliedBuilding(badgerDropPoint1, 40);
|
||||
if (closestAlliedBuilding == null)
|
||||
{
|
||||
return;
|
||||
@@ -336,67 +519,41 @@ namespace OpenRA.Mods.RA.Missions
|
||||
apc.QueueActivity(new UnloadCargo(true));
|
||||
}
|
||||
|
||||
void ReinforcementsTimerExpired(CountdownTimer countdownTimer)
|
||||
void ExtractEinsteinAtLZ()
|
||||
{
|
||||
reinforcementsTimerWidget.Visible = false;
|
||||
SendReinforcements();
|
||||
einsteinChinook = MissionUtils.ExtractUnitWithChinook(
|
||||
world,
|
||||
allies1,
|
||||
einstein,
|
||||
extractionLZEntryPoint.Location,
|
||||
extractionLZ.Location,
|
||||
extractionLZEntryPoint.Location);
|
||||
}
|
||||
|
||||
void SendReinforcements()
|
||||
bool AlliesNearTown()
|
||||
{
|
||||
Sound.Play("reinfor1.aud");
|
||||
var resources = allies2.PlayerActor.Trait<PlayerResources>();
|
||||
resources.GiveCash(2000);
|
||||
foreach (var unit in Reinforcements)
|
||||
return world.FindAliveCombatantActorsInCircle(townPoint.CenterLocation, AlliedTownTransferRange)
|
||||
.Any(a => a.Owner == allies1 && a.HasTrait<IMove>());
|
||||
}
|
||||
|
||||
void TransferTownUnitsToAllies()
|
||||
{
|
||||
var actor = world.CreateActor(unit, new TypeDictionary
|
||||
foreach (var unit in world.FindAliveNonCombatantActorsInCircle(townPoint.CenterLocation, AlliedTownTransferRange).Where(a => a.HasTrait<IMove>()))
|
||||
{
|
||||
new LocationInit(reinforcementsEntryPoint.Location),
|
||||
new FacingInit(0),
|
||||
new OwnerInit(allies2)
|
||||
});
|
||||
actor.QueueActivity(new Move.Move(allies2BasePoint.Location));
|
||||
unit.ChangeOwner(allies1);
|
||||
}
|
||||
}
|
||||
|
||||
void SendChinook()
|
||||
void SovietsAttackTown()
|
||||
{
|
||||
einsteinChinook = world.CreateActor(ChinookName, new TypeDictionary { new OwnerInit(allies1), new LocationInit(extractionLZEntryPoint.Location) });
|
||||
einsteinChinook.QueueActivity(new HeliFly(extractionLZ.CenterLocation));
|
||||
einsteinChinook.QueueActivity(new Turn(0));
|
||||
einsteinChinook.QueueActivity(new HeliLand(true, 0));
|
||||
einsteinChinook.QueueActivity(new WaitFor(() => einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein)));
|
||||
einsteinChinook.QueueActivity(new Wait(150));
|
||||
einsteinChinook.QueueActivity(new HeliFly(extractionLZEntryPoint.CenterLocation));
|
||||
einsteinChinook.QueueActivity(new RemoveSelf());
|
||||
var sovietAttackUnits = world.FindAliveCombatantActorsInCircle(sovietTownAttackPoint1.CenterLocation, SovietTownAttackGroupRange)
|
||||
.Union(world.FindAliveCombatantActorsInCircle(sovietTownAttackPoint2.CenterLocation, SovietTownAttackGroupRange))
|
||||
.Union(world.FindAliveCombatantActorsInCircle(townPoint.CenterLocation, AlliedTownTransferRange))
|
||||
.Where(a => a.HasTrait<IMove>() && a.Owner == soviets);
|
||||
foreach (var unit in sovietAttackUnits)
|
||||
{
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(townPoint.Location, SovietTownMoveNearEnough)));
|
||||
}
|
||||
|
||||
IEnumerable<Actor> UnitsNearActor(Actor actor, int range)
|
||||
{
|
||||
return world.FindUnitsInCircle(actor.CenterLocation, Game.CellSize * range)
|
||||
.Where(a => a.IsInWorld && a != world.WorldActor && !a.Destroyed && !a.Owner.NonCombatant);
|
||||
}
|
||||
|
||||
IEnumerable<Actor> BuildingsNearActor(Actor actor, int range)
|
||||
{
|
||||
return UnitsNearActor(actor, range).Where(a => a.HasTrait<Building>() && !a.HasTrait<Wall>());
|
||||
}
|
||||
|
||||
IEnumerable<Actor> ForcesNearActor(Actor actor, int range)
|
||||
{
|
||||
return UnitsNearActor(actor, range).Where(a => a.HasTrait<IMove>());
|
||||
}
|
||||
|
||||
bool AlliesControlMiss()
|
||||
{
|
||||
var units = ForcesNearActor(engineerMiss, EngineerMissClearRange);
|
||||
return units.Any() && units.All(a => a.Owner == allies1);
|
||||
}
|
||||
|
||||
void SpawnEngineerAtMiss()
|
||||
{
|
||||
engineer = world.CreateActor(EngineerName, new TypeDictionary { new OwnerInit(allies1), new LocationInit(engineerMiss.Location) });
|
||||
engineer.QueueActivity(new Move.Move(engineerMiss.Location + new CVec(5, 0)));
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w)
|
||||
@@ -412,18 +569,31 @@ namespace OpenRA.Mods.RA.Missions
|
||||
sam4 = actors["SAM4"];
|
||||
tanya = actors["Tanya"];
|
||||
einstein = actors["Einstein"];
|
||||
engineer = actors["Engineer"];
|
||||
chinookHusk = actors["ChinookHusk"];
|
||||
allies2BasePoint = actors["Allies2BasePoint"];
|
||||
reinforcementsEntryPoint = actors["ReinforcementsEntryPoint"];
|
||||
extractionLZ = actors["ExtractionLZ"];
|
||||
extractionLZEntryPoint = actors["ExtractionLZEntryPoint"];
|
||||
badgerEntryPoint = actors["BadgerEntryPoint"];
|
||||
badgerDropPoint = actors["BadgerDropPoint"];
|
||||
engineerMiss = actors["EngineerMiss"];
|
||||
badgerEntryPoint1 = actors["BadgerEntryPoint1"];
|
||||
badgerEntryPoint2 = actors["BadgerEntryPoint2"];
|
||||
badgerDropPoint1 = actors["BadgerDropPoint1"];
|
||||
badgerDropPoint2 = actors["BadgerDropPoint2"];
|
||||
badgerDropPoint3 = actors["BadgerDropPoint3"];
|
||||
parabombPoint1 = actors["ParabombPoint1"];
|
||||
parabombPoint2 = actors["ParabombPoint2"];
|
||||
sovietBarracks = actors["SovietBarracks"];
|
||||
sovietWarFactory = actors["SovietWarFactory"];
|
||||
sovietRallyPoint = actors["SovietRallyPoint"];
|
||||
flamersEntryPoint = actors["FlamersEntryPoint"];
|
||||
tanksEntryPoint = actors["TanksEntryPoint"];
|
||||
townPoint = actors["TownPoint"];
|
||||
sovietTownAttackPoint1 = actors["SovietTownAttackPoint1"];
|
||||
sovietTownAttackPoint2 = actors["SovietTownAttackPoint2"];
|
||||
yakEntryPoint = actors["YakEntryPoint"];
|
||||
yakAttackPoint = actors["YakAttackPoint"];
|
||||
sovietReinforcementsEntryPoint1 = actors["SovietReinforcementsEntryPoint1"];
|
||||
sovietReinforcementsEntryPoint2 = actors["SovietReinforcementsEntryPoint2"];
|
||||
var shroud = w.WorldActor.Trait<Shroud>();
|
||||
shroud.Explore(w, sam1.Location, 2);
|
||||
shroud.Explore(w, sam2.Location, 2);
|
||||
@@ -460,81 +630,4 @@ namespace OpenRA.Mods.RA.Missions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CountdownTimer
|
||||
{
|
||||
public int TicksLeft { get; set; }
|
||||
|
||||
public Action<CountdownTimer> OnExpired { get; set; }
|
||||
public Action<CountdownTimer> OnOneMinuteRemaining { get; set; }
|
||||
public Action<CountdownTimer> OnTwoMinutesRemaining { get; set; }
|
||||
public Action<CountdownTimer> OnThreeMinutesRemaining { get; set; }
|
||||
public Action<CountdownTimer> OnFourMinutesRemaining { get; set; }
|
||||
public Action<CountdownTimer> OnFiveMinutesRemaining { get; set; }
|
||||
public Action<CountdownTimer> OnTenMinutesRemaining { get; set; }
|
||||
public Action<CountdownTimer> OnTwentyMinutesRemaining { get; set; }
|
||||
public Action<CountdownTimer> OnThirtyMinutesRemaining { get; set; }
|
||||
public Action<CountdownTimer> OnFortyMinutesRemaining { get; set; }
|
||||
|
||||
public CountdownTimer(int ticksLeft, Action<CountdownTimer> onExpired)
|
||||
{
|
||||
TicksLeft = ticksLeft;
|
||||
OnExpired = onExpired;
|
||||
OnOneMinuteRemaining = t => Sound.Play("1minr.aud");
|
||||
OnTwoMinutesRemaining = t => Sound.Play("2minr.aud");
|
||||
OnThreeMinutesRemaining = t => Sound.Play("3minr.aud");
|
||||
OnFourMinutesRemaining = t => Sound.Play("4minr.aud");
|
||||
OnFiveMinutesRemaining = t => Sound.Play("5minr.aud");
|
||||
OnTenMinutesRemaining = t => Sound.Play("10minr.aud");
|
||||
OnTwentyMinutesRemaining = t => Sound.Play("20minr.aud");
|
||||
OnThirtyMinutesRemaining = t => Sound.Play("30minr.aud");
|
||||
OnFortyMinutesRemaining = t => Sound.Play("40minr.aud");
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
if (TicksLeft > 0)
|
||||
{
|
||||
TicksLeft--;
|
||||
switch (TicksLeft)
|
||||
{
|
||||
case 1500 * 00: OnExpired(this); break;
|
||||
case 1500 * 01: OnOneMinuteRemaining(this); break;
|
||||
case 1500 * 02: OnTwoMinutesRemaining(this); break;
|
||||
case 1500 * 03: OnThreeMinutesRemaining(this); break;
|
||||
case 1500 * 04: OnFourMinutesRemaining(this); break;
|
||||
case 1500 * 05: OnFiveMinutesRemaining(this); break;
|
||||
case 1500 * 10: OnTenMinutesRemaining(this); break;
|
||||
case 1500 * 20: OnTwentyMinutesRemaining(this); break;
|
||||
case 1500 * 30: OnThirtyMinutesRemaining(this); break;
|
||||
case 1500 * 40: OnFortyMinutesRemaining(this); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CountdownTimerWidget : Widget
|
||||
{
|
||||
public CountdownTimer CountdownTimer { get; set; }
|
||||
public string Header { get; set; }
|
||||
public float2 Position { get; set; }
|
||||
|
||||
public CountdownTimerWidget(CountdownTimer countdownTimer, string header, float2 position)
|
||||
{
|
||||
CountdownTimer = countdownTimer;
|
||||
Header = header;
|
||||
Position = position;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
if (!IsVisible())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var font = Game.Renderer.Fonts["Bold"];
|
||||
var text = "{0}: {1}".F(Header, WidgetUtils.FormatTime(CountdownTimer.TicksLeft));
|
||||
font.DrawTextWithContrast(text, Position, CountdownTimer.TicksLeft == 0 && Game.LocalTick % 60 >= 30 ? Color.Red : Color.White, Color.Black, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
OpenRA.Mods.RA/Missions/CountdownTimer.cs
Normal file
96
OpenRA.Mods.RA/Missions/CountdownTimer.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
public class CountdownTimer
|
||||
{
|
||||
public int TicksLeft { get; set; }
|
||||
|
||||
public event Action<CountdownTimer> OnExpired = t => { };
|
||||
public event Action<CountdownTimer> OnOneMinuteRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnTwoMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnThreeMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnFourMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnFiveMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnTenMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnTwentyMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnThirtyMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnFortyMinutesRemaining = t => { };
|
||||
|
||||
public CountdownTimer(int ticksLeft, Action<CountdownTimer> onExpired, bool withNotifications)
|
||||
{
|
||||
TicksLeft = ticksLeft;
|
||||
OnExpired += onExpired;
|
||||
if (withNotifications)
|
||||
{
|
||||
OnOneMinuteRemaining += t => Sound.Play("1minr.aud");
|
||||
OnTwoMinutesRemaining += t => Sound.Play("2minr.aud");
|
||||
OnThreeMinutesRemaining += t => Sound.Play("3minr.aud");
|
||||
OnFourMinutesRemaining += t => Sound.Play("4minr.aud");
|
||||
OnFiveMinutesRemaining += t => Sound.Play("5minr.aud");
|
||||
OnTenMinutesRemaining += t => Sound.Play("10minr.aud");
|
||||
OnTwentyMinutesRemaining += t => Sound.Play("20minr.aud");
|
||||
OnThirtyMinutesRemaining += t => Sound.Play("30minr.aud");
|
||||
OnFortyMinutesRemaining += t => Sound.Play("40minr.aud");
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
if (TicksLeft > 0)
|
||||
{
|
||||
TicksLeft--;
|
||||
switch (TicksLeft)
|
||||
{
|
||||
case 1500 * 00: OnExpired(this); break;
|
||||
case 1500 * 01: OnOneMinuteRemaining(this); break;
|
||||
case 1500 * 02: OnTwoMinutesRemaining(this); break;
|
||||
case 1500 * 03: OnThreeMinutesRemaining(this); break;
|
||||
case 1500 * 04: OnFourMinutesRemaining(this); break;
|
||||
case 1500 * 05: OnFiveMinutesRemaining(this); break;
|
||||
case 1500 * 10: OnTenMinutesRemaining(this); break;
|
||||
case 1500 * 20: OnTwentyMinutesRemaining(this); break;
|
||||
case 1500 * 30: OnThirtyMinutesRemaining(this); break;
|
||||
case 1500 * 40: OnFortyMinutesRemaining(this); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CountdownTimerWidget : Widget
|
||||
{
|
||||
public CountdownTimer Timer { get; set; }
|
||||
public string Format { get; set; }
|
||||
public float2 Position { get; set; }
|
||||
|
||||
public CountdownTimerWidget(CountdownTimer timer, string format, float2 position)
|
||||
{
|
||||
Timer = timer;
|
||||
Format = format;
|
||||
Position = position;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
if (!IsVisible())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var font = Game.Renderer.Fonts["Bold"];
|
||||
var text = Format.F(WidgetUtils.FormatTime(Timer.TicksLeft));
|
||||
font.DrawTextWithContrast(text, Position, Timer.TicksLeft <= 25 * 10 && Game.LocalTick % 50 < 25 ? Color.Red : Color.White, Color.Black, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
140
OpenRA.Mods.RA/Missions/MissionUtils.cs
Normal file
140
OpenRA.Mods.RA/Missions/MissionUtils.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
public static class MissionUtils
|
||||
{
|
||||
public static IEnumerable<Actor> FindAliveCombatantActorsInCircle(this World world, PPos location, int range)
|
||||
{
|
||||
return world.FindUnitsInCircle(location, Game.CellSize * range)
|
||||
.Where(a => a.IsInWorld && a != world.WorldActor && !a.IsDead() && !a.Owner.NonCombatant);
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindAliveNonCombatantActorsInCircle(this World world, PPos location, int range)
|
||||
{
|
||||
return world.FindUnitsInCircle(location, Game.CellSize * range)
|
||||
.Where(a => a.IsInWorld && a != world.WorldActor && !a.IsDead() && a.Owner.NonCombatant);
|
||||
}
|
||||
|
||||
public static Actor ExtractUnitWithChinook(World world, Player owner, Actor unit, CPos entry, CPos lz, CPos exit)
|
||||
{
|
||||
var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) });
|
||||
chinook.QueueActivity(new HeliFly(Util.CenterOfCell(lz)));
|
||||
chinook.QueueActivity(new Turn(0));
|
||||
chinook.QueueActivity(new HeliLand(true, 0));
|
||||
chinook.QueueActivity(new WaitFor(() => chinook.Trait<Cargo>().Passengers.Contains(unit)));
|
||||
chinook.QueueActivity(new Wait(150));
|
||||
chinook.QueueActivity(new HeliFly(Util.CenterOfCell(exit)));
|
||||
chinook.QueueActivity(new RemoveSelf());
|
||||
return chinook;
|
||||
}
|
||||
|
||||
public static Pair<Actor, Actor> InsertUnitWithChinook(World world, Player owner, string unitName, CPos entry, CPos lz, CPos exit, Action<Actor> afterUnload)
|
||||
{
|
||||
var unit = world.CreateActor(false, unitName, new TypeDictionary { new OwnerInit(owner) });
|
||||
var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) });
|
||||
chinook.Trait<Cargo>().Load(chinook, unit);
|
||||
chinook.QueueActivity(new HeliFly(Util.CenterOfCell(lz)));
|
||||
chinook.QueueActivity(new Turn(0));
|
||||
chinook.QueueActivity(new HeliLand(true, 0));
|
||||
chinook.QueueActivity(new UnloadCargo(true));
|
||||
chinook.QueueActivity(new CallFunc(() => afterUnload(unit)));
|
||||
chinook.QueueActivity(new Wait(150));
|
||||
chinook.QueueActivity(new HeliFly(Util.CenterOfCell(exit)));
|
||||
chinook.QueueActivity(new RemoveSelf());
|
||||
return Pair.New(chinook, unit);
|
||||
}
|
||||
|
||||
public static void Paradrop(World world, Player owner, IEnumerable<string> units, CPos entry, CPos location)
|
||||
{
|
||||
var badger = world.CreateActor("badr", new TypeDictionary
|
||||
{
|
||||
new LocationInit(entry),
|
||||
new OwnerInit(owner),
|
||||
new FacingInit(Util.GetFacing(location - entry, 0)),
|
||||
new AltitudeInit(Rules.Info["badr"].Traits.Get<PlaneInfo>().CruiseAltitude),
|
||||
});
|
||||
badger.QueueActivity(new FlyAttack(Target.FromCell(location)));
|
||||
badger.Trait<ParaDrop>().SetLZ(location);
|
||||
var cargo = badger.Trait<Cargo>();
|
||||
foreach (var unit in units)
|
||||
{
|
||||
cargo.Load(badger, world.CreateActor(false, unit, new TypeDictionary { new OwnerInit(owner) }));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Parabomb(World world, Player owner, CPos entry, CPos location)
|
||||
{
|
||||
var badger = world.CreateActor("badr.bomber", new TypeDictionary
|
||||
{
|
||||
new LocationInit(entry),
|
||||
new OwnerInit(owner),
|
||||
new FacingInit(Util.GetFacing(location - entry, 0)),
|
||||
new AltitudeInit(Rules.Info["badr.bomber"].Traits.Get<PlaneInfo>().CruiseAltitude),
|
||||
});
|
||||
badger.Trait<CarpetBomb>().SetTarget(location);
|
||||
badger.QueueActivity(Fly.ToCell(location));
|
||||
badger.QueueActivity(new FlyOffMap());
|
||||
badger.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
|
||||
public static bool AreaSecuredWithUnits(World world, Player player, PPos location, int range)
|
||||
{
|
||||
var units = world.FindAliveCombatantActorsInCircle(location, range).Where(a => a.HasTrait<IMove>());
|
||||
return units.Any() && units.All(a => a.Owner == player);
|
||||
}
|
||||
|
||||
public static Actor ClosestPlayerUnit(World world, Player player, PPos location, int range)
|
||||
{
|
||||
return ClosestPlayerUnits(world, player, location, range).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> ClosestPlayerUnits(World world, Player player, PPos location, int range)
|
||||
{
|
||||
return world.FindAliveCombatantActorsInCircle(location, range)
|
||||
.Where(a => a.Owner == player && a.HasTrait<IMove>())
|
||||
.OrderBy(a => (location - a.CenterLocation).LengthSquared);
|
||||
}
|
||||
|
||||
public static Actor ClosestPlayerBuilding(World world, Player player, PPos location, int range)
|
||||
{
|
||||
return ClosestPlayerBuildings(world, player, location, range).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> ClosestPlayerBuildings(World world, Player player, PPos location, int range)
|
||||
{
|
||||
return world.FindAliveCombatantActorsInCircle(location, range)
|
||||
.Where(a => a.Owner == player && a.HasTrait<Building>() && !a.HasTrait<Wall>())
|
||||
.OrderBy(a => (location - a.CenterLocation).LengthSquared);
|
||||
}
|
||||
|
||||
public static IEnumerable<ProductionQueue> FindQueues(World world, Player player, string category)
|
||||
{
|
||||
return world.ActorsWithTrait<ProductionQueue>()
|
||||
.Where(a => a.Actor.Owner == player && a.Trait.Info.Type == category)
|
||||
.Select(a => a.Trait);
|
||||
}
|
||||
|
||||
public static Actor UnitContaining(this World world, Actor actor)
|
||||
{
|
||||
return world.Actors.FirstOrDefault(a => a.HasTrait<Cargo>() && a.Trait<Cargo>().Passengers.Contains(actor));
|
||||
}
|
||||
}
|
||||
}
|
||||
54
OpenRA.Mods.RA/Missions/Objective.cs
Normal file
54
OpenRA.Mods.RA/Missions/Objective.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
public class Objective
|
||||
{
|
||||
public ObjectiveType Type { get; set; }
|
||||
public string Text { get; set; }
|
||||
public ObjectiveStatus Status { get; set; }
|
||||
|
||||
public Objective(ObjectiveType type, string text, ObjectiveStatus status)
|
||||
{
|
||||
Type = type;
|
||||
Text = text;
|
||||
Status = status;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ObjectiveType { Primary, Secondary }
|
||||
public enum ObjectiveStatus { Inactive, InProgress, Completed, Failed }
|
||||
|
||||
public delegate void ObjectivesUpdatedEventHandler(bool notify);
|
||||
|
||||
public interface IHasObjectives
|
||||
{
|
||||
event ObjectivesUpdatedEventHandler OnObjectivesUpdated;
|
||||
IEnumerable<Objective> Objectives { get; }
|
||||
}
|
||||
|
||||
public class MissionObjectivesPanelInfo : ITraitInfo
|
||||
{
|
||||
public string ObjectivesPanel = null;
|
||||
public object Create(ActorInitializer init) { return new MissionObjectivesPanel(this); }
|
||||
}
|
||||
|
||||
public class MissionObjectivesPanel : IObjectivesPanel
|
||||
{
|
||||
MissionObjectivesPanelInfo info;
|
||||
public MissionObjectivesPanel(MissionObjectivesPanelInfo info) { this.info = info; }
|
||||
public string ObjectivesPanel { get { return info.ObjectivesPanel; } }
|
||||
}
|
||||
}
|
||||
@@ -172,6 +172,7 @@
|
||||
<Compile Include="ColorPickerPaletteModifier.cs" />
|
||||
<Compile Include="Combat.cs" />
|
||||
<Compile Include="ConquestVictoryConditions.cs" />
|
||||
<Compile Include="ContainsCrate.cs" />
|
||||
<Compile Include="Crate.cs" />
|
||||
<Compile Include="CrateAction.cs" />
|
||||
<Compile Include="CrateDrop.cs" />
|
||||
@@ -181,6 +182,7 @@
|
||||
<Compile Include="Crates\GiveCashCrateAction.cs" />
|
||||
<Compile Include="Crates\GiveMcvCrateAction.cs" />
|
||||
<Compile Include="Crates\GiveUnitCrateAction.cs" />
|
||||
<Compile Include="Crates\HealUnitsCrateAction.cs" />
|
||||
<Compile Include="Crates\HideMapCrateAction.cs" />
|
||||
<Compile Include="Crates\LevelUpCrateAction.cs" />
|
||||
<Compile Include="Crates\RevealMapCrateAction.cs" />
|
||||
@@ -238,7 +240,10 @@
|
||||
<Compile Include="Minelayer.cs" />
|
||||
<Compile Include="Missions\Allies01Script.cs" />
|
||||
<Compile Include="Missions\Allies02Script.cs" />
|
||||
<Compile Include="Missions\CountdownTimer.cs" />
|
||||
<Compile Include="Missions\DefaultShellmapScript.cs" />
|
||||
<Compile Include="Missions\MissionUtils.cs" />
|
||||
<Compile Include="Missions\Objective.cs" />
|
||||
<Compile Include="Modifiers\FrozenUnderFog.cs" />
|
||||
<Compile Include="Modifiers\HiddenUnderFog.cs" />
|
||||
<Compile Include="Move\Drag.cs" />
|
||||
@@ -361,6 +366,7 @@
|
||||
<Compile Include="Widgets\Logic\LobbyUtils.cs" />
|
||||
<Compile Include="Widgets\Logic\MainMenuButtonsLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\MapChooserLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\MissionObjectivesLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\MusicPlayerLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\OrderButtonsChromeLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\PerfDebugLogic.cs" />
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace OpenRA.Mods.RA
|
||||
if (mobile != null)
|
||||
{
|
||||
newUnit.QueueActivity(new AttackMove.AttackMoveActivity(
|
||||
newUnit, mobile.MoveTo(rp.rallyPoint, 1)));
|
||||
newUnit, mobile.MoveTo(rp.rallyPoint, rp.nearEnough)));
|
||||
return rp.rallyPoint;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#region Copyright & License Information
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
@@ -24,6 +24,7 @@ namespace OpenRA.Mods.RA
|
||||
public class RallyPoint : IIssueOrder, IResolveOrder, ISync
|
||||
{
|
||||
[Sync] public CPos rallyPoint;
|
||||
public int nearEnough = 1;
|
||||
|
||||
public RallyPoint(Actor self)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
using System.Linq;
|
||||
using OpenRA.Widgets;
|
||||
using System.Drawing;
|
||||
|
||||
@@ -38,6 +39,16 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
};
|
||||
cheatsButton.IsVisible = () => world.LocalPlayer != null && world.LobbyInfo.GlobalSettings.AllowCheats;
|
||||
|
||||
var iop = world.WorldActor.TraitsImplementing<IObjectivesPanel>().FirstOrDefault();
|
||||
if (iop != null && iop.ObjectivesPanel != null)
|
||||
{
|
||||
var objectivesButton = gameRoot.Get<ButtonWidget>("OBJECTIVES_BUTTON");
|
||||
var objectivesWidget = Game.LoadWidget(world, iop.ObjectivesPanel, Ui.Root, new WidgetArgs());
|
||||
objectivesWidget.Visible = false;
|
||||
objectivesButton.OnClick += () => objectivesWidget.Visible = !objectivesWidget.Visible;
|
||||
objectivesButton.IsVisible = () => world.LocalPlayer != null;
|
||||
}
|
||||
|
||||
optionsBG.Get<ButtonWidget>("DISCONNECT").OnClick = () => LeaveGame(optionsBG, world);
|
||||
|
||||
optionsBG.Get<ButtonWidget>("SETTINGS").OnClick = () => Ui.OpenWindow("SETTINGS_MENU");
|
||||
|
||||
95
OpenRA.Mods.RA/Widgets/Logic/MissionObjectivesLogic.cs
Normal file
95
OpenRA.Mods.RA/Widgets/Logic/MissionObjectivesLogic.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.RA.Missions;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
public class MissionObjectivesLogic
|
||||
{
|
||||
IHasObjectives objectives;
|
||||
Widget primaryPanel;
|
||||
Widget secondaryPanel;
|
||||
Widget primaryTemplate;
|
||||
Widget secondaryTemplate;
|
||||
ButtonWidget objectivesButton;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public MissionObjectivesLogic(World world, Widget widget)
|
||||
{
|
||||
var gameRoot = Ui.Root.Get("INGAME_ROOT");
|
||||
primaryPanel = widget.Get("PRIMARY_OBJECTIVES");
|
||||
secondaryPanel = widget.Get("SECONDARY_OBJECTIVES");
|
||||
primaryTemplate = primaryPanel.Get("PRIMARY_OBJECTIVE_TEMPLATE");
|
||||
secondaryTemplate = secondaryPanel.Get("SECONDARY_OBJECTIVE_TEMPLATE");
|
||||
|
||||
objectives = world.WorldActor.TraitsImplementing<IHasObjectives>().First();
|
||||
|
||||
objectivesButton = gameRoot.Get<ButtonWidget>("OBJECTIVES_BUTTON");
|
||||
objectivesButton.IsHighlighted = () => Game.LocalTick % 50 < 25 && objectivesButton.Highlighted;
|
||||
objectivesButton.OnClick += () => objectivesButton.Highlighted = false;
|
||||
|
||||
objectives.OnObjectivesUpdated += UpdateObjectives;
|
||||
UpdateObjectives(true);
|
||||
Game.ConnectionStateChanged += RemoveHandlers;
|
||||
}
|
||||
|
||||
public void RemoveHandlers(OrderManager orderManager)
|
||||
{
|
||||
if (!orderManager.GameStarted)
|
||||
{
|
||||
Game.ConnectionStateChanged -= RemoveHandlers;
|
||||
objectives.OnObjectivesUpdated -= UpdateObjectives;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateObjectives(bool notify)
|
||||
{
|
||||
if (notify)
|
||||
{
|
||||
objectivesButton.Highlighted = true;
|
||||
}
|
||||
primaryPanel.RemoveChildren();
|
||||
secondaryPanel.RemoveChildren();
|
||||
foreach (var o in objectives.Objectives.Where(o => o.Status != ObjectiveStatus.Inactive))
|
||||
{
|
||||
var objective = o;
|
||||
if (objective.Type == ObjectiveType.Secondary)
|
||||
{
|
||||
var template = secondaryTemplate.Clone();
|
||||
template.Get<LabelWidget>("SECONDARY_OBJECTIVE").GetText = () => objective.Text;
|
||||
template.Get<LabelWidget>("SECONDARY_STATUS").GetText = () => GetObjectiveStatusText(objective.Status);
|
||||
secondaryPanel.AddChild(template);
|
||||
}
|
||||
else
|
||||
{
|
||||
var template = primaryTemplate.Clone();
|
||||
template.Get<LabelWidget>("PRIMARY_OBJECTIVE").GetText = () => objective.Text;
|
||||
template.Get<LabelWidget>("PRIMARY_STATUS").GetText = () => GetObjectiveStatusText(objective.Status);
|
||||
primaryPanel.AddChild(template);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static string GetObjectiveStatusText(ObjectiveStatus status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case ObjectiveStatus.InProgress: return "In Progress";
|
||||
case ObjectiveStatus.Completed: return "Completed";
|
||||
case ObjectiveStatus.Failed: return "Failed";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
mods/ra/bits/invun.shp
Normal file
BIN
mods/ra/bits/invun.shp
Normal file
Binary file not shown.
@@ -249,6 +249,17 @@ button: dialog.png
|
||||
corner-bl: 512,82,1,1
|
||||
corner-br: 594,82,1,1
|
||||
|
||||
button-highlighted: dialog.png
|
||||
background: 513,145,126,126
|
||||
border-r: 639,145,1,126
|
||||
border-l: 512,145,1,126
|
||||
border-b: 513,271,126,1
|
||||
border-t: 513,144,126,1
|
||||
corner-tl: 512,144,1,1
|
||||
corner-tr: 594,144,1,1
|
||||
corner-bl: 512,271,1,1
|
||||
corner-br: 594,271,1,1
|
||||
|
||||
# A copy of dialog2
|
||||
button-hover: dialog.png
|
||||
background: 513,1,126,126
|
||||
@@ -261,6 +272,17 @@ button-hover: dialog.png
|
||||
corner-bl: 512,82,1,1
|
||||
corner-br: 594,82,1,1
|
||||
|
||||
button-hover-highlighted: dialog.png
|
||||
background: 513,145,126,126
|
||||
border-r: 639,145,1,126
|
||||
border-l: 512,145,1,126
|
||||
border-b: 513,271,126,1
|
||||
border-t: 513,144,126,1
|
||||
corner-tl: 512,144,1,1
|
||||
corner-tr: 594,144,1,1
|
||||
corner-bl: 512,271,1,1
|
||||
corner-br: 594,271,1,1
|
||||
|
||||
# A copy of dialog2
|
||||
button-disabled: dialog.png
|
||||
background: 513,1,126,126
|
||||
@@ -273,6 +295,17 @@ button-disabled: dialog.png
|
||||
corner-bl: 512,82,1,1
|
||||
corner-br: 594,82,1,1
|
||||
|
||||
button-disabled-highlighted: dialog.png
|
||||
background: 513,145,126,126
|
||||
border-r: 639,145,1,126
|
||||
border-l: 512,145,1,126
|
||||
border-b: 513,271,126,1
|
||||
border-t: 513,144,126,1
|
||||
corner-tl: 512,144,1,1
|
||||
corner-tr: 594,144,1,1
|
||||
corner-bl: 512,271,1,1
|
||||
corner-br: 594,271,1,1
|
||||
|
||||
# A copy of dialog3
|
||||
button-pressed: dialog.png
|
||||
background: 641,1,126,126
|
||||
@@ -285,6 +318,17 @@ button-pressed: dialog.png
|
||||
corner-bl: 640,82,1,1
|
||||
corner-br: 722,82,1,1
|
||||
|
||||
button-pressed-highlighted: dialog.png
|
||||
background: 641,145,126,126
|
||||
border-r: 767,145,1,126
|
||||
border-l: 640,145,1,126
|
||||
border-b: 641,271,126,1
|
||||
border-t: 641,144,126,1
|
||||
corner-tl: 640,144,1,1
|
||||
corner-tr: 722,144,1,1
|
||||
corner-bl: 640,271,1,1
|
||||
corner-br: 722,271,1,1
|
||||
|
||||
scrollthumb: dialog.png
|
||||
background: 513,1,126,126
|
||||
border-r: 639,1,1,126
|
||||
|
||||
@@ -81,6 +81,14 @@ Container@INGAME_ROOT:
|
||||
Text:Cheats
|
||||
Visible:false
|
||||
Font:Bold
|
||||
Button@OBJECTIVES_BUTTON:
|
||||
X:486
|
||||
Y:0
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Objectives
|
||||
Visible:false
|
||||
Font:Bold
|
||||
RadarBin@INGAME_RADAR_BIN:
|
||||
WorldInteractionController:INTERACTION_CONTROLLER
|
||||
PowerBin@INGAME_POWER_BIN:
|
||||
|
||||
102
mods/ra/chrome/objectives.yaml
Normal file
102
mods/ra/chrome/objectives.yaml
Normal file
@@ -0,0 +1,102 @@
|
||||
Container@MISSION_OBJECTIVES:
|
||||
Logic:MissionObjectivesLogic
|
||||
X:25
|
||||
Y:50
|
||||
Width:512
|
||||
Height:530
|
||||
Children:
|
||||
Background@BACKGROUND:
|
||||
Width:512
|
||||
Height:530
|
||||
Background:dialog
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:0
|
||||
Y:15
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Font:Bold
|
||||
Align:Center
|
||||
Text:Objectives
|
||||
Label@PRIMARY_OBJECTIVE_HEADER:
|
||||
X:40
|
||||
Y:40
|
||||
Width:300
|
||||
Height:25
|
||||
Font:Bold
|
||||
Text:Primary Objectives
|
||||
Label@PRIMARY_STATUS_HEADER:
|
||||
X:350
|
||||
Y:40
|
||||
Width:122
|
||||
Height:25
|
||||
Font:Bold
|
||||
Text:Status
|
||||
ScrollPanel@PRIMARY_OBJECTIVES:
|
||||
X:25
|
||||
Y:70
|
||||
Width:PARENT_RIGHT-50
|
||||
Height:200
|
||||
ItemSpacing:5
|
||||
Children:
|
||||
Container@PRIMARY_OBJECTIVE_TEMPLATE:
|
||||
X:15
|
||||
Y:0-15
|
||||
Width:PARENT_RIGHT
|
||||
Height:60
|
||||
Children:
|
||||
Label@PRIMARY_OBJECTIVE:
|
||||
X:0
|
||||
Y:0
|
||||
Width:300
|
||||
Height:PARENT_BOTTOM
|
||||
Font:Regular
|
||||
WordWrap:True
|
||||
Label@PRIMARY_STATUS:
|
||||
X:310
|
||||
Y:0
|
||||
Width:122
|
||||
Height:PARENT_BOTTOM
|
||||
Font:Bold
|
||||
WordWrap:True
|
||||
Label@SECONDARY_OBJECTIVE_HEADER:
|
||||
X:40
|
||||
Y:275
|
||||
Width:300
|
||||
Height:25
|
||||
Font:Bold
|
||||
Text:Secondary Objectives
|
||||
Label@SECONDARY_STATUS_HEADER:
|
||||
X:350
|
||||
Y:275
|
||||
Width:122
|
||||
Height:25
|
||||
Font:Bold
|
||||
Text:Status
|
||||
ScrollPanel@SECONDARY_OBJECTIVES:
|
||||
X:25
|
||||
Y:305
|
||||
Width:PARENT_RIGHT-50
|
||||
Height:200
|
||||
ItemSpacing:5
|
||||
Children:
|
||||
Container@SECONDARY_OBJECTIVE_TEMPLATE:
|
||||
X:15
|
||||
Y:0-15
|
||||
Width:PARENT_RIGHT
|
||||
Height:60
|
||||
Children:
|
||||
Label@SECONDARY_OBJECTIVE:
|
||||
X:0
|
||||
Y:0
|
||||
Width:300
|
||||
Height:PARENT_BOTTOM
|
||||
Font:Regular
|
||||
WordWrap:True
|
||||
Label@SECONDARY_STATUS:
|
||||
X:310
|
||||
Y:0
|
||||
Width:122
|
||||
Height:PARENT_BOTTOM
|
||||
Font:Bold
|
||||
WordWrap:True
|
||||
Binary file not shown.
BIN
mods/ra/maps/allies-01/map.bin
Normal file
BIN
mods/ra/maps/allies-01/map.bin
Normal file
Binary file not shown.
403
mods/ra/maps/allies-01/map.yaml
Normal file
403
mods/ra/maps/allies-01/map.yaml
Normal file
@@ -0,0 +1,403 @@
|
||||
Selectable: True
|
||||
|
||||
MapFormat: 5
|
||||
|
||||
RequiresMod: ra
|
||||
|
||||
Title: Allies 01
|
||||
|
||||
Description: Allies' first mission
|
||||
|
||||
Author: Scott_NZ
|
||||
|
||||
Tileset: SNOW
|
||||
|
||||
MapSize: 48,64
|
||||
|
||||
Bounds: 8,8,32,38
|
||||
|
||||
UseAsShellmap: False
|
||||
|
||||
Type: Mission
|
||||
|
||||
Players:
|
||||
PlayerReference@Neutral:
|
||||
Name: Neutral
|
||||
OwnsWorld: True
|
||||
NonCombatant: True
|
||||
Race: allies
|
||||
PlayerReference@Creeps:
|
||||
Name: Creeps
|
||||
NonCombatant: True
|
||||
Race: allies
|
||||
PlayerReference@Allies:
|
||||
Name: Allies
|
||||
Playable: True
|
||||
AllowBots: False
|
||||
LockRace: True
|
||||
Race: allies
|
||||
LockColor: True
|
||||
ColorRamp: 153,240,130,10
|
||||
LockSpawn: True
|
||||
LockTeam: True
|
||||
Allies: Creeps
|
||||
Enemies: Soviets
|
||||
PlayerReference@Soviets:
|
||||
Name: Soviets
|
||||
Race: soviet
|
||||
ColorRamp: 0,255,128,10
|
||||
Enemies: Allies,Creeps
|
||||
|
||||
Actors:
|
||||
Actor1: tc01
|
||||
Location: 13,9
|
||||
Owner: Neutral
|
||||
Actor10: oilb
|
||||
Location: 17,19
|
||||
Owner: Soviets
|
||||
Actor3: t13
|
||||
Location: 17,13
|
||||
Owner: Neutral
|
||||
Actor5: t16
|
||||
Location: 25,9
|
||||
Owner: Neutral
|
||||
Actor4: t17
|
||||
Location: 17,10
|
||||
Owner: Neutral
|
||||
Actor8: brl3
|
||||
Location: 19,21
|
||||
Owner: Soviets
|
||||
Actor7: barl
|
||||
Location: 19,20
|
||||
Owner: Soviets
|
||||
Actor2: brl3
|
||||
Location: 19,19
|
||||
Owner: Soviets
|
||||
Actor6: brl3
|
||||
Location: 20,19
|
||||
Owner: Soviets
|
||||
Actor71: t01
|
||||
Location: 33,31
|
||||
Owner: Neutral
|
||||
Actor11: powr
|
||||
Location: 20,20
|
||||
Owner: Soviets
|
||||
Actor12: powr
|
||||
Location: 24,20
|
||||
Owner: Soviets
|
||||
Actor13: powr
|
||||
Location: 26,20
|
||||
Owner: Soviets
|
||||
Actor14: t08
|
||||
Location: 25,13
|
||||
Owner: Neutral
|
||||
Actor15: fenc
|
||||
Location: 27,18
|
||||
Owner: Soviets
|
||||
Actor16: fenc
|
||||
Location: 28,18
|
||||
Owner: Soviets
|
||||
Actor17: fenc
|
||||
Location: 27,17
|
||||
Owner: Soviets
|
||||
Actor18: jeep
|
||||
Location: 21,13
|
||||
Owner: Allies
|
||||
Actor19: jeep
|
||||
Location: 22,13
|
||||
Owner: Allies
|
||||
Actor20: jeep
|
||||
Location: 23,13
|
||||
Owner: Allies
|
||||
Actor22: e2
|
||||
Location: 21,19
|
||||
Owner: Soviets
|
||||
Actor23: e1
|
||||
Location: 17,23
|
||||
Owner: Soviets
|
||||
Actor28: e1
|
||||
Location: 23,12
|
||||
Owner: Allies
|
||||
Actor26: e1
|
||||
Location: 22,12
|
||||
Owner: Allies
|
||||
Actor25: e1
|
||||
Location: 21,12
|
||||
Owner: Allies
|
||||
Actor65: fenc
|
||||
Location: 33,33
|
||||
Owner: Soviets
|
||||
Actor31: mine
|
||||
Location: 33,14
|
||||
Owner: Neutral
|
||||
Actor32: tc03
|
||||
Location: 28,13
|
||||
Owner: Neutral
|
||||
Actor33: v04
|
||||
Location: 35,8
|
||||
Owner: Neutral
|
||||
Actor34: tsla
|
||||
Location: 30,22
|
||||
Owner: Soviets
|
||||
Actor35: proc
|
||||
Location: 32,21
|
||||
Owner: Soviets
|
||||
Actor37: e1
|
||||
Location: 23,24
|
||||
Owner: Soviets
|
||||
Actor0: e2
|
||||
Location: 22,27
|
||||
Owner: Soviets
|
||||
Actor21: e2
|
||||
Location: 20,27
|
||||
Owner: Soviets
|
||||
Actor40: weap
|
||||
Location: 24,25
|
||||
Owner: Soviets
|
||||
Actor41: fact
|
||||
Location: 28,25
|
||||
Owner: Soviets
|
||||
Actor42: barr
|
||||
Location: 20,28
|
||||
Owner: Soviets
|
||||
Actor43: silo
|
||||
Location: 18,28
|
||||
Owner: Soviets
|
||||
Actor44: dome
|
||||
Location: 26,28
|
||||
Owner: Soviets
|
||||
Actor45: t12
|
||||
Location: 15,19
|
||||
Owner: Neutral
|
||||
Actor46: t12
|
||||
Location: 15,25
|
||||
Owner: Neutral
|
||||
Actor47: fenc
|
||||
Location: 14,27
|
||||
Owner: Soviets
|
||||
Actor48: fenc
|
||||
Location: 14,28
|
||||
Owner: Soviets
|
||||
Actor49: fenc
|
||||
Location: 14,29
|
||||
Owner: Soviets
|
||||
Actor50: fenc
|
||||
Location: 14,30
|
||||
Owner: Soviets
|
||||
Actor51: tsla
|
||||
Location: 19,30
|
||||
Owner: Soviets
|
||||
Actor52: tsla
|
||||
Location: 26,30
|
||||
Owner: Soviets
|
||||
Actor53: fenc
|
||||
Location: 14,31
|
||||
Owner: Soviets
|
||||
Actor54: fenc
|
||||
Location: 15,31
|
||||
Owner: Soviets
|
||||
Actor55: fenc
|
||||
Location: 16,31
|
||||
Owner: Soviets
|
||||
Actor56: fenc
|
||||
Location: 17,31
|
||||
Owner: Soviets
|
||||
Actor57: fenc
|
||||
Location: 17,32
|
||||
Owner: Soviets
|
||||
Actor70: fenc
|
||||
Location: 35,33
|
||||
Owner: Soviets
|
||||
Actor59: e1
|
||||
Location: 23,31
|
||||
Owner: Soviets
|
||||
Actor60: e1
|
||||
Location: 21,31
|
||||
Owner: Soviets
|
||||
Actor61: powr
|
||||
Location: 34,30
|
||||
Owner: Soviets
|
||||
Actor58: powr
|
||||
Location: 36,27
|
||||
Owner: Soviets
|
||||
Actor64: t05
|
||||
Location: 32,27
|
||||
Owner: Neutral
|
||||
Actor62: powr
|
||||
Location: 36,30
|
||||
Owner: Soviets
|
||||
Actor63: fenc
|
||||
Location: 32,33
|
||||
Owner: Soviets
|
||||
Actor30: powr
|
||||
Location: 34,27
|
||||
Owner: Soviets
|
||||
Actor67: fenc
|
||||
Location: 34,33
|
||||
Owner: Soviets
|
||||
Actor68: c1
|
||||
Location: 28,16
|
||||
Owner: Creeps
|
||||
Actor69: c2
|
||||
Location: 30,17
|
||||
Owner: Creeps
|
||||
Actor72: e1
|
||||
Location: 35,29
|
||||
Owner: Soviets
|
||||
Actor66: e1
|
||||
Location: 31,29
|
||||
Owner: Soviets
|
||||
Actor9: barl
|
||||
Location: 18,21
|
||||
Owner: Soviets
|
||||
Actor74: tc02
|
||||
Location: 11,23
|
||||
Owner: Neutral
|
||||
Actor73: tc03
|
||||
Location: 37,22
|
||||
Owner: Neutral
|
||||
Actor75: t02
|
||||
Location: 29,31
|
||||
Owner: Neutral
|
||||
Actor76: t02
|
||||
Location: 12,34
|
||||
Owner: Neutral
|
||||
Actor79: fenc
|
||||
Location: 14,21
|
||||
Owner: Soviets
|
||||
Actor78: fenc
|
||||
Location: 14,22
|
||||
Owner: Soviets
|
||||
Actor77: fenc
|
||||
Location: 14,23
|
||||
Owner: Soviets
|
||||
Actor85: 3tnk
|
||||
Location: 17,25
|
||||
Owner: Soviets
|
||||
Facing: 0
|
||||
Actor92: wood
|
||||
Location: 34,9
|
||||
Owner: Neutral
|
||||
Actor94: c1
|
||||
Location: 19,24
|
||||
Owner: Soviets
|
||||
Actor95: c2
|
||||
Location: 31,23
|
||||
Owner: Soviets
|
||||
InsertionLZ: waypoint
|
||||
Location: 22,10
|
||||
Owner: Neutral
|
||||
Lab: stek
|
||||
Location: 20,24
|
||||
Owner: Soviets
|
||||
Actor24: e2
|
||||
Location: 27,24
|
||||
Owner: Soviets
|
||||
ShipSpawnPoint: waypoint
|
||||
Location: 23,45
|
||||
Owner: Neutral
|
||||
ShipMovePoint: waypoint
|
||||
Location: 23,40
|
||||
Owner: Neutral
|
||||
InsertionLZEntryPoint: waypoint
|
||||
Location: 22,4
|
||||
Owner: Neutral
|
||||
Actor27: e2
|
||||
Location: 27,27
|
||||
Owner: Soviets
|
||||
ChinookExitPoint: waypoint
|
||||
Location: 55,11
|
||||
Owner: Neutral
|
||||
ExtractionLZEntryPoint: waypoint
|
||||
Location: 31,48
|
||||
Owner: Neutral
|
||||
SovietAttackEntryPoint2: waypoint
|
||||
Location: 39,11
|
||||
Owner: Neutral
|
||||
ExtractionLZ: waypoint
|
||||
Location: 13,12
|
||||
Owner: Neutral
|
||||
Actor36: e1
|
||||
Location: 20,12
|
||||
Owner: Allies
|
||||
Actor38: e1
|
||||
Location: 24,12
|
||||
Owner: Allies
|
||||
Actor39: e3
|
||||
Location: 21,11
|
||||
Owner: Allies
|
||||
Actor80: e3
|
||||
Location: 22,11
|
||||
Owner: Allies
|
||||
Actor81: e3
|
||||
Location: 23,11
|
||||
Owner: Allies
|
||||
SovietAttackEntryPoint1: waypoint
|
||||
Location: 8,30
|
||||
Owner: Neutral
|
||||
Actor29: kenn
|
||||
Location: 23,28
|
||||
Owner: Soviets
|
||||
|
||||
Smudges:
|
||||
|
||||
Rules:
|
||||
Player:
|
||||
-ConquestVictoryConditions:
|
||||
World:
|
||||
-CrateDrop:
|
||||
-SpawnMPUnits:
|
||||
-MPStartLocations:
|
||||
Allies01Script:
|
||||
MissionObjectivesPanel:
|
||||
ObjectivesPanel: MISSION_OBJECTIVES
|
||||
TRAN:
|
||||
-Selectable:
|
||||
RevealsShroud:
|
||||
Range: 0
|
||||
E7:
|
||||
AutoTarget:
|
||||
InitialStance: ReturnFire
|
||||
Passenger:
|
||||
Weight: 0
|
||||
EINSTEIN:
|
||||
Passenger:
|
||||
Weight: 0
|
||||
JEEP:
|
||||
Cargo:
|
||||
MaxWeight: 0
|
||||
PipCount: 0
|
||||
|
||||
Sequences:
|
||||
|
||||
Weapons:
|
||||
8Inch:
|
||||
ROF: 200
|
||||
Range: 25
|
||||
Burst: 2
|
||||
Report: TURRET1
|
||||
Projectile: Bullet
|
||||
Speed: 30
|
||||
High: true
|
||||
Angle: .1
|
||||
Inaccuracy: 100
|
||||
Image: 120MM
|
||||
ContrailLength: 10
|
||||
Warhead:
|
||||
Spread: 5
|
||||
Versus:
|
||||
None: 60%
|
||||
Wood: 75%
|
||||
Light: 60%
|
||||
Heavy: 25%
|
||||
Explosion: large_explosion
|
||||
WaterExplosion: large_splash
|
||||
InfDeath: 2
|
||||
SmudgeType: Crater
|
||||
Damage: 500
|
||||
ImpactSound: kaboom12
|
||||
WaterImpactSound: splash9
|
||||
|
||||
Voices:
|
||||
|
||||
Notifications:
|
||||
Binary file not shown.
BIN
mods/ra/maps/allies-02/map.bin
Normal file
BIN
mods/ra/maps/allies-02/map.bin
Normal file
Binary file not shown.
3050
mods/ra/maps/allies-02/map.yaml
Normal file
3050
mods/ra/maps/allies-02/map.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -64,6 +64,7 @@ ChromeLayout:
|
||||
mods/ra/chrome/dropdowns.yaml
|
||||
mods/ra/chrome/modchooser.yaml
|
||||
mods/ra/chrome/cheats.yaml
|
||||
mods/ra/chrome/objectives.yaml
|
||||
|
||||
Weapons:
|
||||
mods/ra/weapons.yaml
|
||||
|
||||
@@ -8,6 +8,8 @@ FCOM:
|
||||
HP: 400
|
||||
Armor:
|
||||
Type: Wood
|
||||
Tooltip:
|
||||
Name: Forward Command
|
||||
RevealsShroud:
|
||||
Range: 10
|
||||
Bib:
|
||||
@@ -136,6 +138,7 @@ BARL:
|
||||
Health:
|
||||
HP: 10
|
||||
Explodes:
|
||||
Weapon: BarrelExplode
|
||||
Tooltip:
|
||||
Name: Explosive Barrel
|
||||
|
||||
@@ -146,6 +149,7 @@ BRL3:
|
||||
Health:
|
||||
HP: 10
|
||||
Explodes:
|
||||
Weapon: BarrelExplode
|
||||
Tooltip:
|
||||
Name: Explosive Barrel
|
||||
|
||||
|
||||
@@ -1214,6 +1214,7 @@ KENN:
|
||||
Range: 4
|
||||
IronCurtainable:
|
||||
-EmitInfantryOnSell:
|
||||
-AcceptsSupplies:
|
||||
|
||||
FIX:
|
||||
Inherits: ^Building
|
||||
|
||||
@@ -355,6 +355,10 @@ CRATE:
|
||||
HideMapCrateAction:
|
||||
SelectionShares: 5
|
||||
Effect: hide-map
|
||||
HealUnitsCrateAction:
|
||||
Notification: heal2.aud
|
||||
SelectionShares: 2
|
||||
Effect: heal
|
||||
RevealMapCrateAction:
|
||||
SelectionShares: 1
|
||||
Effect: reveal-map
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@@ -1108,6 +1108,23 @@ UnitExplodeSmall:
|
||||
InfDeath: 4
|
||||
ImpactSound: kaboom15
|
||||
|
||||
BarrelExplode:
|
||||
Warhead:
|
||||
Damage: 500
|
||||
Spread: 10
|
||||
Versus:
|
||||
None: 120%
|
||||
Wood: 200%
|
||||
Light: 50%
|
||||
Heavy: 25%
|
||||
Concrete: 10%
|
||||
Explosion: napalm
|
||||
InfDeath: 4
|
||||
ImpactSound: firebl3
|
||||
SmudgeType: Scorch
|
||||
Delay: 5
|
||||
Size: 2,2
|
||||
|
||||
Crush:
|
||||
Warhead:
|
||||
ImpactSound: squishy2
|
||||
|
||||
Reference in New Issue
Block a user