Merge pull request #6934 from abcdefg30/survival01

Ported Survival01 to Lua
This commit is contained in:
Matthias Mailänder
2014-11-23 15:17:42 +01:00
17 changed files with 2060 additions and 12 deletions

View File

@@ -137,11 +137,13 @@ namespace OpenRA.Traits
var entered = currentActors.Except(oldActors);
var exited = oldActors.Except(currentActors);
foreach (var a in entered)
onActorEntered(a);
if (onActorEntered != null)
foreach (var a in entered)
onActorEntered(a);
foreach (var a in exited)
onActorExited(a);
if (onActorExited != null)
foreach (var a in exited)
onActorExited(a);
Dirty = false;
}

View File

@@ -408,6 +408,7 @@
<Compile Include="Scripting\Properties\HealthProperties.cs" />
<Compile Include="Scripting\Properties\CombatProperties.cs" />
<Compile Include="Scripting\Properties\DiplomacyProperties.cs" />
<Compile Include="Scripting\Properties\PowerProperties.cs" />
<Compile Include="Scripting\Global\MapGlobal.cs" />
<Compile Include="Scripting\Global\PlayerGlobal.cs" />
<Compile Include="Scripting\Global\UtilsGlobal.cs" />

View File

@@ -220,6 +220,68 @@ namespace OpenRA.Mods.RA.Scripting
GetScriptTriggers(a).RegisterCallback(Trigger.OnCapture, func, context);
}
[Desc("Call a function when this actor is killed or captured. " +
"The callback function will be called as func().")]
public void OnKilledOrCaptured(Actor a, LuaFunction func)
{
var called = false;
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnKilledOrCaptured = m =>
{
try
{
if (called)
return;
copy.Call().Dispose();
copy.Dispose();
called = true;
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
GetScriptTriggers(a).OnCapturedInternal += OnKilledOrCaptured;
GetScriptTriggers(a).OnKilledInternal += OnKilledOrCaptured;
}
[Desc("Call a function when all of the actors in a group have been killed or captured. " +
"The callback function will be called as func().")]
public void OnAllKilledOrCaptured(Actor[] actors, LuaFunction func)
{
var group = actors.ToList();
var copy = (LuaFunction)func.CopyReference();
Action<Actor> OnMemberKilledOrCaptured = m =>
{
try
{
if (!group.Contains(m))
return;
group.Remove(m);
if (!group.Any())
{
copy.Call().Dispose();
copy.Dispose();
}
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
foreach (var a in group)
{
GetScriptTriggers(a).OnCapturedInternal += OnMemberKilledOrCaptured;
GetScriptTriggers(a).OnKilledInternal += OnMemberKilledOrCaptured;
}
}
[Desc("Call a function when a ground-based actor enters this cell footprint." +
"Returns the trigger id for later removal using RemoveFootprintTrigger(int id)." +
"The callback function will be called as func(Actor a, int id).")]
@@ -278,6 +340,64 @@ namespace OpenRA.Mods.RA.Scripting
context.World.ActorMap.RemoveCellTrigger(id);
}
[Desc("Call a function when an actor enters this range." +
"Returns the trigger id for later removal using RemoveProximityTrigger(int id)." +
"The callback function will be called as func(Actor a, int id).")]
public int OnEnteredProximityTrigger(WPos pos, WRange range, LuaFunction func)
{
var triggerId = 0;
var onEntry = (LuaFunction)func.CopyReference();
Action<Actor> invokeEntry = a =>
{
try
{
using (var luaActor = a.ToLuaValue(context))
using (var id = triggerId.ToLuaValue(context))
onEntry.Call(luaActor, id).Dispose();
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
triggerId = context.World.ActorMap.AddProximityTrigger(pos, range, invokeEntry, null);
return triggerId;
}
[Desc("Call a function when an actor leaves this range." +
"Returns the trigger id for later removal using RemoveProximityTrigger(int id)." +
"The callback function will be called as func(Actor a, int id).")]
public int OnExitedProximityTrigger(WPos pos, WRange range, LuaFunction func)
{
var triggerId = 0;
var onExit = (LuaFunction)func.CopyReference();
Action<Actor> invokeExit = a =>
{
try
{
using (var luaActor = a.ToLuaValue(context))
using (var id = triggerId.ToLuaValue(context))
onExit.Call(luaActor, id).Dispose();
}
catch (Exception e)
{
context.FatalError(e.Message);
}
};
triggerId = context.World.ActorMap.AddProximityTrigger(pos, range, null, invokeExit);
return triggerId;
}
[Desc("Removes a previously created proximitry trigger.")]
public void RemoveProximityTrigger(int id)
{
context.World.ActorMap.RemoveProximityTrigger(id);
}
[Desc("Call a function when this actor is infiltrated. The callback function " +
"will be called as func(Actor self, Actor infiltrator).")]
public void OnInfiltrated(Actor a, LuaFunction func)

View File

@@ -0,0 +1,73 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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 Eluant;
using OpenRA.Mods.Common.Power;
using OpenRA.Scripting;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Scripting
{
[ScriptPropertyGroup("Power")]
public class PlayerPowerProperties : ScriptPlayerProperties, Requires<PowerManagerInfo>
{
readonly PowerManager pm;
public PlayerPowerProperties(ScriptContext context, Player player)
: base(context, player)
{
pm = player.PlayerActor.Trait<PowerManager>();
}
[Desc("Returns the total of the power the player has.")]
public int PowerProvided
{
get { return pm.PowerProvided; }
}
[Desc("Returns the power used by the player.")]
public int PowerDrained
{
get { return pm.PowerDrained; }
}
[Desc("Returns the player's power state " +
"(\"Normal\", \"Low\" or \"Critical\").")]
public string PowerState
{
get { return pm.PowerState.ToString(); }
}
[Desc("Triggers low power for the chosen amount of ticks.")]
public void TriggerPowerOutage(int ticks)
{
pm.TriggerPowerOutage(ticks);
}
}
[ScriptPropertyGroup("Power")]
public class ActorPowerProperties : ScriptActorProperties, Requires<PowerInfo>
{
readonly PowerInfo pi;
public ActorPowerProperties(ScriptContext context, Actor self)
: base(context, self)
{
pi = self.Info.Traits.GetOrDefault<PowerInfo>();
}
[Desc("Returns the power drained/provided by this actor.")]
public int Power
{
get { return pi.Amount; }
}
}
}

View File

@@ -32,6 +32,7 @@ namespace OpenRA.Mods.RA.Scripting
readonly World world;
public event Action<Actor> OnKilledInternal = _ => { };
public event Action<Actor> OnCapturedInternal = _ => { };
public event Action<Actor> OnRemovedInternal = _ => { };
public event Action<Actor, Actor> OnProducedInternal = (a, b) => { };
public event Action<Actor, Actor> OnOtherProducedInternal = (a, b) => { };
@@ -236,6 +237,9 @@ namespace OpenRA.Mods.RA.Scripting
return;
}
}
// Run any internally bound callbacks
OnCapturedInternal(self);
}
public void Infiltrated(Actor self, Actor infiltrator)

View File

@@ -27,6 +27,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
readonly ScrollPanelWidget descriptionPanel;
readonly LabelWidget description;
readonly SpriteFont descriptionFont;
readonly DropDownButtonWidget difficultyButton;
readonly ButtonWidget startVideoButton;
readonly ButtonWidget stopVideoButton;
readonly VqaPlayerWidget videoPlayer;
@@ -39,6 +40,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
bool showVideoPlayer;
string difficulty;
[ObjectCreator.UseCtor]
public MissionBrowserLogic(Widget widget, Action onStart, Action onExit)
{
@@ -67,6 +70,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
description = descriptionPanel.Get<LabelWidget>("MISSION_DESCRIPTION");
descriptionFont = Game.Renderer.Fonts[description.Font];
difficultyButton = widget.Get<DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");
startVideoButton = widget.Get<ButtonWidget>("START_VIDEO_BUTTON");
stopVideoButton = widget.Get<ButtonWidget>("STOP_VIDEO_BUTTON");
stopVideoButton.IsVisible = () => showVideoPlayer;
@@ -176,6 +181,28 @@ namespace OpenRA.Mods.RA.Widgets.Logic
description.Bounds.Height = descriptionFont.Measure(text).Y;
descriptionPanel.ScrollToTop();
descriptionPanel.Layout.AdjustChildren();
difficultyButton.IsVisible = () => map.Options.Difficulties.Any();
if (!map.Options.Difficulties.Any())
return;
difficulty = map.Options.Difficulties.First();
difficultyButton.OnMouseDown = _ =>
{
var options = map.Options.Difficulties.Select(d => new DropDownOption
{
Title = d,
IsSelected = () => difficulty == d,
OnClick = () => difficulty = d
});
Func<DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
{
var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
item.Get<LabelWidget>("LABEL").GetText = () => option.Title;
return item;
};
difficultyButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
};
}
void StopVideo()
@@ -202,6 +229,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Action lobbyReady = null;
lobbyReady = () =>
{
om.IssueOrder(Order.Command("difficulty {0}".F(difficulty)));
Game.LobbyInfoChanged -= lobbyReady;
onStart();
om.IssueOrder(Order.Command("state {0}".F(Session.ClientState.Ready)));
@@ -210,5 +238,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
om = Game.JoinServer(IPAddress.Loopback.ToString(), Game.CreateLocalServer(selectedMapPreview.Uid), "", false);
}
class DropDownOption
{
public string Title;
public Func<bool> IsSelected;
public Action OnClick;
}
}
}

View File

@@ -49,6 +49,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Red Alert Lua scripts", "Re
mods\ra\maps\intervention\intervention.lua = mods\ra\maps\intervention\intervention.lua
mods\ra\maps\fort-lonestar\fort-lonestar.lua = mods\ra\maps\fort-lonestar\fort-lonestar.lua
mods\ra\maps\monster-tank-madness\monster-tank-madness.lua = mods\ra\maps\monster-tank-madness\monster-tank-madness.lua
mods\ra\maps\survival01\survival01.lua = mods\ra\maps\survival01\survival01.lua
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System Lua scripts", "System Lua scripts", "{A4D6AEA4-8009-4256-903B-8D227E50452B}"

View File

@@ -102,6 +102,13 @@ Container@MISSIONBROWSER_PANEL:
Height: 35
Text: Play
Font: Bold
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
X: PARENT_RIGHT - 290 - 150
Y: 376
Width: 140
Height: 35
Text: Difficulty
Font: Bold
Container@MISSION_BIN:
Children:
VqaPlayer@MISSION_VIDEO:

View File

@@ -98,6 +98,13 @@ Background@MISSIONBROWSER_PANEL:
Text: Back
Font: Bold
Key: escape
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
X: PARENT_RIGHT - 140 - 130 - 150
Y: PARENT_BOTTOM - 45
Width: 140
Height: 25
Text: Difficulty
Font: Bold
Background@MISSION_BIN:
X: 20
Y: 50

View File

@@ -115,6 +115,8 @@ WorldLoaded = function()
ukraine.AddPrimaryObjective("Destroy the convoy.")
end)
Trigger.AfterDelay(DateTime.Seconds(1), function() Media.PlaySpeechNotification(allies, "MissionTimerInitialised") end)
RunInitialActivities()
SendConstructionVehicleReinforcements()

View File

@@ -9,11 +9,21 @@ BeachheadTrigger =
CPos.New(137, 104), CPos.New(137, 105), CPos.New(137, 106), CPos.New(136, 106), CPos.New(136, 107)
}
BaseRaidInterval = DateTime.Minutes(3)
BaseFrontAttackInterval = DateTime.Minutes(3) + DateTime.Seconds(30)
BaseRearAttackInterval = DateTime.Minutes(8)
UBoatPatrolDelay = DateTime.Minutes(2) + DateTime.Seconds(30)
BaseFrontAttackWpts = { PatrolWpt1.Location, BaseRaidWpt1.Location }
Difficulty = Map.Difficulty
if Difficulty == "Medium" then
BaseRaidInterval = DateTime.Minutes(3)
BaseFrontAttackInterval = DateTime.Minutes(3) + DateTime.Seconds(30)
BaseRearAttackInterval = DateTime.Minutes(8)
UBoatPatrolDelay = DateTime.Minutes(2) + DateTime.Seconds(30)
BaseFrontAttackWpts = { PatrolWpt1.Location, BaseRaidWpt1.Location }
else
BaseRaidInterval = DateTime.Minutes(2)
BaseFrontAttackInterval = DateTime.Minutes(2) + DateTime.Seconds(30)
BaseRearAttackInterval = DateTime.Minutes(5)
UBoatPatrolDelay = DateTime.Minutes(2)
BaseFrontAttackWpts = { PatrolWpt1.Location }
end
Village = { FarmHouse1, FarmHouse2, FarmHouse3, FarmHouse4, FarmHouse5, FarmHouse6, FarmHouse7, FarmHouse8, FarmHouse9, Church }
VillageRaidInterval = DateTime.Minutes(3)
@@ -224,7 +234,7 @@ WorldLoaded = function()
sovietObjective = soviets.AddPrimaryObjective("Destroy the village.")
villageObjective = player.AddPrimaryObjective("Save the village.")
beachheadObjective = player.AddSecondaryObjective("Get your MCV to the main island.")
beachheadObjective = player.AddPrimaryObjective("Get your MCV to the main island.")
beachheadTrigger = false
Trigger.OnExitedFootprint(BeachheadTrigger, function(a, id)
@@ -234,6 +244,17 @@ WorldLoaded = function()
player.MarkCompletedObjective(beachheadObjective)
captureObjective = player.AddPrimaryObjective("Locate and capture the enemy's Air Force HQ.")
if AirForceHQ.IsDead then
player.MarkFailedObjective(captureObjective)
return
end
if AirForceHQ.Owner == player then
player.MarkCompletedObjective(captureObjective)
player.MarkCompletedObjective(villageObjective)
return
end
Trigger.OnCapture(AirForceHQ, function()
Trigger.AfterDelay(DateTime.Seconds(3), function()
player.MarkCompletedObjective(captureObjective)
@@ -242,6 +263,8 @@ WorldLoaded = function()
end)
Trigger.OnKilled(AirForceHQ, function() player.MarkFailedObjective(captureObjective) end)
Actor.Create("mainland", true, { Owner = player })
Trigger.AfterDelay(BaseFrontAttackInterval, function()
Build(BaseFrontAttackUnits, BaseFrontAttack)
ParadropSovietUnits()

View File

@@ -2248,10 +2248,23 @@ Rules:
E6:
Buildable:
Prerequisites: ~disabled
HPAD:
TENT:
Buildable:
Prerequisites: anypower, ~structures.allies, ~techlevel.infonly, mainland
DOME:
Buildable:
Prerequisites: proc, ~techlevel.medium, mainland
WEAP:
Buildable:
Prerequisites: proc, ~techlevel.low, mainland
ProvidesCustomPrerequisite:
Prerequisite: givefix
WEAP:
MAINLAND:
Tooltip:
Name: Reach the mainland
ProvidesCustomPrerequisite:
Prerequisite: mainland
HPAD:
ProvidesCustomPrerequisite:
Prerequisite: givefix
FIX:

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,392 @@
Difficulty = Map.Difficulty
if Difficulty == "Easy" then
AttackAtFrameIncrement = DateTime.Seconds(22)
AttackAtFrameIncrementInf = DateTime.Seconds(16)
TimerTicks = DateTime.Minutes(15)
IncrementTurningPoint = TimerTicks / 2
DamageModifier = 0.5
LongBowReinforcements = { "heli", "heli" }
ParadropArtillery = true
elseif Difficulty == "Medium" then
AttackAtFrameIncrement = DateTime.Seconds(18)
AttackAtFrameIncrementInf = DateTime.Seconds(12)
TimerTicks = DateTime.Minutes(20)
IncrementTurningPoint = TimerTicks / 2
MoreParas = true
DamageModifier = 0.75
LongBowReinforcements = { "heli", "heli" }
else --Difficulty == "Hard"
AttackAtFrameIncrement = DateTime.Seconds(14)
AttackAtFrameIncrementInf = DateTime.Seconds(8)
TimerTicks = DateTime.Minutes(25)
IncrementTurningPoint = DateTime.Minutes(10)
MoreParas = true
AttackAtFrameNaval = DateTime.Minutes(3) + DateTime.Seconds(45)
SpawnNavalUnits = true
DamageModifier = 1
LongBowReinforcements = { "heli" }
end
AlliedArtilleryParadrops = { "arty", "arty", "arty" }
AlliedAirReinforcementsWaypoints =
{
{ AirReinforcementsEntry1.Location, AirReinforcementsEntry2.Location },
{ AirReinforcementsRally1.Location, AirReinforcementsRally2.Location }
}
FrenchReinforcements = { "2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "1tnk", "1tnk", "1tnk", "arty", "arty", "arty", "jeep", "jeep" }
SpawningSovietUnits = true
SpawningInfantry = true
AttackAtFrameInf = DateTime.Seconds(12)
AttackAtFrame = DateTime.Seconds(18)
SovietAttackGroupSize = 5
SovietInfantryGroupSize = 7
FactoryClearRange = 10
ParadropTicks = DateTime.Seconds(30)
BadgerPassengers = { "e1", "e1", "e1", "e2", "e2" }
ParadropWaypoints =
{
{ BadgerEntryPoint1.Location, ParaDrop1.Location },
{ BadgerEntryPoint2.Location, ParaDrop2.Location },
{ BadgerEntryPoint1.Location, Alliesbase2.Location },
{ BadgerEntryPoint2.Location, Alliesbase1.Location }
}
NavalTransportPassengers = { "e1", "e1", "e2", "e4", "e4" }
NavalReinforcementsWaypoints = { NavalWaypoint1, NavalWaypoint2, NavalWaypoint2, NavalWaypoint3 }
Squad1 = { "e1", "e1" }
Squad2 = { "e2", "e2" }
SovietVehicles = { "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "v2rl", "v2rl", "ftrk", "ftrk", "ftrk", "apc", "apc" }
SovietInfantry = { "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e4", "e4", "e3" }
SovietEntryPoints = { SovietEntryPoint1, SovietEntryPoint2, SovietEntryPoint3, SovietEntryPoint4, SovietEntryPoint5 }
SovietRallyPoints = { SovietRallyPoint1, SovietRallyPoint2, SovietRallyPoint3, SovietRallyPoint4, SovietRallyPoint5 }
SovietGateRallyPoints = { AlliesBaseGate2, AlliesBaseGate2, AlliesBaseGate1, AlliesBaseGate1, AlliesBaseGate1 }
Airfields = { SovietAirfield1, SovietAirfield2, SovietAirfield3 }
SovietBuildings = { Barrack1, SubPen, RadarDome, AdvancedPowerPlant1, AdvancedPowerPlant2, AdvancedPowerPlant3, WarFactory, Refinery, Silo1, Silo2, FlameTower1, FlameTower2, FlameTower3, Sam1, Sam2, Sam3, Sam4, SovietAirfield1, SovietAirfield2, SovietAirfield3 }
IdleTrigger = function(units, dest)
Utils.Do(units, function(unit)
Trigger.OnIdle(unit, function()
local bool = Utils.All(units, function(unit) return unit.IsIdle end)
if bool then
Utils.Do(units, function(unit)
if not unit.IsDead then
Trigger.ClearAll(unit)
Trigger.AfterDelay(0, function()
if not unit.IsDead then
if dest then unit.AttackMove(dest, 3) end
Trigger.OnIdle(unit, unit.Hunt)
end
end)
end
end)
end
end)
Trigger.OnDamaged(unit, function()
Utils.Do(units, function(unit)
if not unit.IsDead then
Trigger.ClearAll(unit)
Trigger.AfterDelay(0, function()
if not unit.IsDead then Trigger.OnIdle(unit, unit.Hunt) end
end)
end
end)
end)
end)
end
Tick = function()
if KillObj and soviets.HasNoRequiredUnits() then
allies.MarkCompletedObjective(KillObj)
end
if allies.HasNoRequiredUnits() then
soviets.MarkCompletedObjective(SovietObj)
end
if soviets.Resources > soviets.ResourceCapacity / 2 then
soviets.Resources = soviets.ResourceCapacity / 2
end
if DateTime.Minutes(20) == TimerTicks - DateTime.GameTime then
Media.PlaySpeechNotification(allies, "TwentyMinutesRemaining")
elseif DateTime.Minutes(10) == TimerTicks - DateTime.GameTime then
Media.PlaySpeechNotification(allies, "TenMinutesRemaining")
elseif DateTime.Minutes(5) == TimerTicks - DateTime.GameTime then
Media.PlaySpeechNotification(allies, "WarningFiveMinutesRemaining")
InitTimer()
end
end
SendSovietParadrops = function(table)
local plane = Actor.Create("badr", true, { Owner = soviets, Location = table[1] })
Utils.Do(BadgerPassengers, function(type)
local unit = Actor.Create(type, false, { Owner = soviets })
plane.LoadPassenger(unit)
Trigger.OnIdle(unit, unit.Hunt)
end)
plane.Paradrop(table[2])
end
SendSovietNavalReinforcements = function()
if SpawnNavalUnits then
local entry = NavalEntryPoint.Location
local units = Reinforcements.ReinforceWithTransport(soviets, "lst", NavalTransportPassengers, { entry, Utils.Random(NavalReinforcementsWaypoints).Location }, { entry })[2]
Utils.Do(units, function(unit)
Trigger.OnIdle(unit, unit.Hunt)
end)
local delay = Utils.RandomInteger(AttackAtFrameNaval, AttackAtFrameNaval + DateTime.Minutes(2))
Trigger.AfterDelay(delay, SendSovietNavalReinforcements)
end
end
SpawnSovietInfantry = function()
local units = { }
for i = 0, SovietInfantryGroupSize - 1, 1 do
local type = Utils.Random(SovietInfantry)
units[i] = type
end
soviets.Build(units, function(soldiers)
Trigger.AfterDelay(25, function() IdleTrigger(soldiers) end)
end)
end
SpawnSovietUnits = function()
local units = { }
for i = 0, SovietAttackGroupSize - 1, 1 do
local type = Utils.Random(SovietVehicles)
units[i] = type
end
local route = Utils.RandomInteger(1, #SovietEntryPoints + 1)
local attackers = Reinforcements.Reinforce(soviets, units, { SovietEntryPoints[route].Location, SovietRallyPoints[route].Location })
Trigger.AfterDelay(25, function()
IdleTrigger(attackers, SovietGateRallyPoints[route].Location)
end)
end
SendInfantryWave = function()
if SpawningInfantry then
SpawnSovietInfantry()
if DateTime.GameTime < IncrementTurningPoint then
AttackAtFrameIncrementInf = AttackAtFrameIncrementInf + Utils.RandomInteger(DateTime.Seconds(2), DateTime.Seconds(3))
elseif not (AttackAtFrameIncrementInf <= DateTime.Seconds(4)) then
AttackAtFrameIncrementInf = AttackAtFrameIncrementInf - Utils.RandomInteger(DateTime.Seconds(2), DateTime.Seconds(3))
end
Trigger.AfterDelay(AttackAtFrameInf + AttackAtFrameIncrementInf, SendInfantryWave)
end
end
SendVehicleWave = function()
if SpawningSovietUnits then
SpawnSovietUnits()
if DateTime.GameTime < IncrementTurningPoint then
AttackAtFrameIncrement = AttackAtFrameIncrement + Utils.RandomInteger(DateTime.Seconds(4), DateTime.Seconds(6))
elseif not (AttackAtFrameIncrement <= DateTime.Seconds(4)) then
AttackAtFrameIncrement = AttackAtFrameIncrement - Utils.RandomInteger(DateTime.Seconds(4), DateTime.Seconds(6))
end
Trigger.AfterDelay(AttackAtFrame + AttackAtFrameIncrement, SendVehicleWave)
end
end
InitTimer = function()
Trigger.AfterDelay(DateTime.Minutes(1), function()
Media.PlaySpeechNotification(allies, "WarningFourMinutesRemaining")
Trigger.AfterDelay(ParadropTicks, function()
SendSovietParadrops(ParadropWaypoints[3])
SendSovietParadrops(ParadropWaypoints[2])
end)
Trigger.AfterDelay(ParadropTicks * 2, function()
SendSovietParadrops(ParadropWaypoints[4])
SendSovietParadrops(ParadropWaypoints[1])
end)
end)
Trigger.AfterDelay(DateTime.Minutes(2), function() Media.PlaySpeechNotification(allies, "WarningThreeMinutesRemaining") end)
Trigger.AfterDelay(DateTime.Minutes(3), function()
Media.PlaySpeechNotification(allies, "WarningTwoMinutesRemaining")
AttackAtFrameIncrement = DateTime.Seconds(4)
AttackAtFrameIncrementInf = DateTime.Seconds(4)
end)
Trigger.AfterDelay(DateTime.Minutes(4), function() Media.PlaySpeechNotification(allies, "WarningOneMinuteRemaining") end)
Trigger.AfterDelay(DateTime.Minutes(4) + DateTime.Seconds(45), function() Media.PlaySpeechNotification(allies, "AlliedForcesApproaching") end)
Trigger.AfterDelay(DateTime.Minutes(5), TimerExpired)
end
TimerExpired = function()
SpawningSovietUnits = false
SpawningInfantry = false
SpawnNavalUnits = false
Media.PlaySpeechNotification(allies, "AlliedReinforcementsArrived")
Reinforcements.Reinforce(allies, FrenchReinforcements, { SovietEntryPoint7.Location, Alliesbase.Location })
if DestroyObj then
KillObj = allies.AddPrimaryObjective("Take control of French reinforcements and\nkill all remaining soviet forces.")
else
DestroyObj = allies.AddPrimaryObjective("Take control of French reinforcements and\ndismantle the nearby Soviet base.")
end
allies.MarkCompletedObjective(SurviveObj)
if not allies.IsObjectiveCompleted(KillSams) then
allies.MarkFailedObjective(KillSams)
end
end
DropAlliedArtillery = function(table)
local plane = Actor.Create("badr", true, { Owner = allies, Location = table[1] })
Utils.Do(AlliedArtilleryParadrops, function(type)
local unit = Actor.Create(type, false, { Owner = allies })
plane.LoadPassenger(unit)
end)
plane.Paradrop(table[2])
end
SendLongBowReinforcements = function()
Media.PlaySpeechNotification(allies, "AlliedReinforcementsArrived")
Reinforcements.Reinforce(allies, LongBowReinforcements, AlliedAirReinforcementsWaypoints[1])
Reinforcements.Reinforce(allies, LongBowReinforcements, AlliedAirReinforcementsWaypoints[2])
if ParadropArtillery then
DropAlliedArtillery({ Utils.Random(AlliedAirReinforcementsWaypoints)[1], Alliesbase.Location })
end
end
InitObjectives = function()
Trigger.OnObjectiveAdded(allies, function(p, id)
Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective")
end)
SurviveObj = allies.AddPrimaryObjective("Enforce your position and hold-out the onslaught\nuntil reinforcements arrive.")
KillSams = allies.AddSecondaryObjective("Destroy the two SAM Sites before reinforcements\narrive.")
Media.DisplayMessage("The soviets are blocking our GPS. We need to investigate their new technology.")
CaptureAirfields = allies.AddSecondaryObjective("Capture and hold the soviet airbase\nin the north east.")
SovietObj = soviets.AddPrimaryObjective("Eliminate all Allied forces.")
Trigger.OnObjectiveCompleted(allies, function(p, id)
Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed")
end)
Trigger.OnObjectiveFailed(allies, function(p, id)
Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed")
end)
Trigger.OnPlayerLost(allies, function()
Media.PlaySpeechNotification(allies, "Lose")
end)
Trigger.OnPlayerWon(allies, function()
Media.PlaySpeechNotification(allies, "Win")
Media.DisplayMessage("The French forces have survived and dismantled the soviet presence in the area!")
end)
end
InitMission = function()
Camera.Position = Alliesbase.CenterPosition
camera1 = Actor.Create("camera.sam", true, { Owner = allies, Location = Sam1.Location })
camera2 = Actor.Create("camera.sam", true, { Owner = allies, Location = Sam2.Location })
Trigger.OnKilled(Sam1, function()
if camera1.IsInWorld then camera1.Destroy() end
end)
Trigger.OnKilled(Sam2, function()
if camera2.IsInWorld then camera2.Destroy() end
end)
Trigger.OnAllKilledOrCaptured({ Sam1, Sam2 }, function()
if not allies.IsObjectiveFailed(KillSams) then
allies.MarkCompletedObjective(KillSams)
SendLongBowReinforcements()
end
end)
local count = 0
Utils.Do(Airfields, function(field)
Trigger.OnCapture(field, function()
count = count + 1
if count == #Airfields then
allies.MarkCompletedObjective(CaptureAirfields)
local atek = Actor.Create("atek.mission", true, { Owner = allies, Location = HiddenATEK.Location })
Trigger.AfterDelay(DateTime.Seconds(5), atek.Destroy)
end
end)
Trigger.OnKilled(field, function()
allies.MarkFailedObjective(CaptureAirfields)
end)
end)
Trigger.OnAllKilledOrCaptured(SovietBuildings, function()
if DestroyObj then
if not soviets.HasNoRequiredUnits() then
KillObj = allies.AddPrimaryObjective("Kill all remaining soviet forces.")
end
allies.MarkCompletedObjective(DestroyObj)
else
DestroyObj = allies.AddPrimaryObjective("Dismantle the nearby Soviet base.")
allies.MarkCompletedObjective(DestroyObj)
end
end)
Trigger.AfterDelay(DateTime.Seconds(1), function() Media.PlaySpeechNotification(allies, "MissionTimerInitialised") end)
end
SetupSoviets = function()
Barrack1.IsPrimaryBuilding = true
Barrack1.RallyPoint = SovietInfantryRally1.Location
Trigger.OnKilledOrCaptured(Barrack1, function()
SpawningInfantry = false
end)
Trigger.AfterDelay(0, function()
local buildings = Map.ActorsInBox(Map.TopLeft, Map.BottomRight, function(self) return self.Owner == soviets and self.HasProperty("StartBuildingRepairs") end)
Utils.Do(buildings, function(actor)
Trigger.OnDamaged(actor, function(building)
if building.Owner == soviets and building.Health < building.MaxHealth * DamageModifier then
building.StartBuildingRepairs()
end
end)
end)
end)
Reinforcements.Reinforce(soviets, Squad1, { AlliesBaseGate1.Location, Alliesbase1.Location })
Reinforcements.Reinforce(soviets, Squad2, { AlliesBaseGate2.Location, Alliesbase2.Location })
Trigger.AfterDelay(ParadropTicks, function()
SendSovietParadrops(ParadropWaypoints[1])
SendSovietParadrops(ParadropWaypoints[2])
end)
Trigger.AfterDelay(ParadropTicks * 2, function()
SendSovietParadrops(ParadropWaypoints[3])
SendSovietParadrops(ParadropWaypoints[4])
end)
Trigger.AfterDelay(AttackAtFrame, SendVehicleWave)
Trigger.AfterDelay(AttackAtFrameInf, SendInfantryWave)
if MoreParas then
local delay = Utils.RandomInteger(TimerTicks/3, TimerTicks*2/3)
Trigger.AfterDelay(delay, function()
SendSovietParadrops(ParadropWaypoints[Utils.RandomInteger(1,3)])
SendSovietParadrops(ParadropWaypoints[Utils.RandomInteger(3,5)])
end)
end
if SpawnNavalUnits then
Trigger.AfterDelay(AttackAtFrameNaval, SendSovietNavalReinforcements)
end
end
WorldLoaded = function()
allies = Player.GetPlayer("Allies")
soviets = Player.GetPlayer("Soviets")
InitObjectives()
InitMission()
SetupSoviets()
end

View File

@@ -47,6 +47,7 @@ Speech:
WarningFiveMinutesRemaining: 5minr
ControlCenterDeactivated: cntlded1
OperationControlTerminated: opterm1
MissionTimerInitialised: mtimein1
Sounds:
Notifications: