Merge pull request #4386 from Mailaender/gdi01-lua

Ported first GDI mission to Lua
This commit is contained in:
Paul Chote
2013-12-30 19:19:24 -08:00
7 changed files with 126 additions and 270 deletions

View File

@@ -1,221 +0,0 @@
#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 System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Mods.RA;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Move;
using OpenRA.Scripting;
using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Missions
{
class Gdi01ScriptInfo : TraitInfo<Gdi01Script> { }
class Gdi01Script : IWorldLoaded, ITick
{
Dictionary<string, Actor> actors;
Dictionary<string, Player> players;
public void WorldLoaded(World w, WorldRenderer wr)
{
players = w.Players.ToDictionary(p => p.InternalName);
actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
var b = w.Map.Bounds;
wr.Viewport.Center(new CPos(b.Left + b.Width / 2, b.Top + b.Height / 2).CenterPosition);
Action afterFMV = () =>
{
Sound.PlayMusic(Rules.Music["aoi"]);
started = true;
};
Game.RunAfterDelay(0, () => Media.PlayFMVFullscreen(w, "gdi1.vqa", () =>
Media.PlayFMVFullscreen(w, "landing.vqa", afterFMV)));
}
public void OnVictory(World w)
{
Action afterFMV = () =>
{
players["GoodGuy"].WinState = WinState.Won;
started = false;
Sound.StopMusic();
Sound.PlayToPlayer(players["GoodGuy"], "accom1.aud");
};
Game.RunAfterDelay(0, () => Media.PlayFMVFullscreen(w, "consyard.vqa", afterFMV));
}
public void OnLose(World w)
{
Action afterFMV = () =>
{
players["GoodGuy"].WinState = WinState.Lost;
started = false;
Sound.StopMusic();
Sound.PlayToPlayer(players["GoodGuy"], "fail1.aud");
};
Game.RunAfterDelay(0, () => Media.PlayFMVFullscreen(w, "gameover.vqa", afterFMV));
}
int ticks = 0;
bool started = false;
int lastBadCount = -1;
public void Tick(Actor self)
{
if (!started)
return;
if (ticks == 0)
{
SetGunboatPath();
self.World.AddFrameEndTask(w =>
{
// Initial Nod reinforcements
foreach (var i in new[] { "e1", "e1" })
{
var a = self.World.CreateActor(i.ToLowerInvariant(), new TypeDictionary
{
new OwnerInit(players["BadGuy"]),
new FacingInit(0),
new LocationInit(actors["nod0"].Location),
});
var mobile = a.Trait<Mobile>();
a.QueueActivity(mobile.MoveTo(actors["nod1"].Location, 2));
a.QueueActivity(mobile.MoveTo(actors["nod2"].Location, 2));
a.QueueActivity(mobile.MoveTo(actors["nod3"].Location, 2));
// TODO: Queue hunt order
}
});
}
// GoodGuy win conditions
// BadGuy is dead
var badcount = self.World.Actors.Count(a => a != a.Owner.PlayerActor &&
a.Owner == players["BadGuy"] && !a.IsDead());
if (badcount != lastBadCount)
{
Game.Debug("{0} badguys remain".F(badcount));
lastBadCount = badcount;
if (badcount == 0)
OnVictory(self.World);
}
// GoodGuy lose conditions: MCV/cyard must survive
var hasAnything = self.World.ActorsWithTrait<MustBeDestroyed>()
.Any(a => a.Actor.Owner == players["GoodGuy"]);
if (!hasAnything)
OnLose(self.World);
// GoodGuy reinforcements
if (ticks == 25 * 5)
{
ReinforceFromSea(self.World,
actors["lstStart"].Location,
actors["lstEnd"].Location,
new CPos(53, 53),
new string[] { "e1", "e1", "e1" },
players["GoodGuy"]);
}
if (ticks == 25 * 15)
{
ReinforceFromSea(self.World,
actors["lstStart"].Location,
actors["lstEnd"].Location,
new CPos(53, 53),
new string[] { "e1", "e1", "e1" },
players["GoodGuy"]);
}
if (ticks == 25 * 30)
{
ReinforceFromSea(self.World,
actors["lstStart"].Location,
actors["lstEnd"].Location,
new CPos(53, 53),
new string[] { "jeep" },
players["GoodGuy"]);
}
if (ticks == 25 * 60)
{
ReinforceFromSea(self.World,
actors["lstStart"].Location,
actors["lstEnd"].Location,
new CPos(53, 53),
new string[] { "jeep" },
players["GoodGuy"]);
}
ticks++;
}
void SetGunboatPath()
{
var self = actors["Gunboat"];
var mobile = self.Trait<Mobile>();
self.Trait<AutoTarget>().stance = UnitStance.AttackAnything; // TODO: this is ignored
self.QueueActivity(mobile.ScriptedMove(actors["gunboatLeft"].Location));
self.QueueActivity(mobile.ScriptedMove(actors["gunboatRight"].Location));
self.QueueActivity(new CallFunc(() => SetGunboatPath()));
}
void ReinforceFromSea(World world, CPos startPos, CPos endPos, CPos unload, string[] items, Player player)
{
world.AddFrameEndTask(w =>
{
Sound.PlayToPlayer(w.LocalPlayer, "reinfor1.aud");
var a = w.CreateActor("lst", new TypeDictionary
{
new LocationInit(startPos),
new OwnerInit(player),
new FacingInit(0),
});
var mobile = a.Trait<Mobile>();
var cargo = a.Trait<Cargo>();
foreach (var i in items)
cargo.Load(a, world.CreateActor(false, i.ToLowerInvariant(), new TypeDictionary
{
new OwnerInit(player),
new FacingInit(0),
}));
a.CancelActivity();
a.QueueActivity(mobile.ScriptedMove(endPos));
a.QueueActivity(new CallFunc(() =>
{
while (!cargo.IsEmpty(a))
{
var b = cargo.Unload(a);
world.AddFrameEndTask(w2 =>
{
if (b.Destroyed) return;
w2.Add(b);
b.TraitsImplementing<IPositionable>().FirstOrDefault().SetPosition(b, a.Location);
b.QueueActivity(mobile.MoveTo(unload, 2));
});
}
}));
a.QueueActivity(new Wait(25));
a.QueueActivity(mobile.ScriptedMove(startPos));
a.QueueActivity(new RemoveSelf());
});
}
}
}

View File

@@ -77,7 +77,6 @@
<Compile Include="CncMenuPaletteEffect.cs" /> <Compile Include="CncMenuPaletteEffect.cs" />
<Compile Include="Effects\IonCannon.cs" /> <Compile Include="Effects\IonCannon.cs" />
<Compile Include="IonCannonPower.cs" /> <Compile Include="IonCannonPower.cs" />
<Compile Include="Missions\Gdi01Script.cs" />
<Compile Include="Missions\Nod01Script.cs" /> <Compile Include="Missions\Nod01Script.cs" />
<Compile Include="PoisonedByTiberium.cs" /> <Compile Include="PoisonedByTiberium.cs" />
<Compile Include="ProductionAirdrop.cs" /> <Compile Include="ProductionAirdrop.cs" />

View File

@@ -26,18 +26,18 @@ Options:
Shroud: True Shroud: True
AllyBuildRadius: False AllyBuildRadius: False
FragileAlliances: False FragileAlliances: False
StartingCash: 500 StartingCash: 5000
ConfigurableStartingUnits: False ConfigurableStartingUnits: False
Players: Players:
PlayerReference@BadGuy: PlayerReference@Nod:
Name: BadGuy Name: Nod
Race: nod Race: nod
ColorRamp: 3,255,127 ColorRamp: 3,255,127
Allies: BadGuy Allies: Nod
Enemies: GoodGuy,Creeps Enemies: GDI,Creeps
PlayerReference@GoodGuy: PlayerReference@GDI:
Name: GoodGuy Name: GDI
Playable: True Playable: True
AllowBots: False AllowBots: False
Required: True Required: True
@@ -47,8 +47,8 @@ Players:
ColorRamp: 31,222,183 ColorRamp: 31,222,183
LockSpawn: True LockSpawn: True
LockTeam: True LockTeam: True
Allies: GoodGuy Allies: GDI
Enemies: BadGuy,Creeps Enemies: Nod,Creeps
PlayerReference@Neutral: PlayerReference@Neutral:
Name: Neutral Name: Neutral
OwnsWorld: True OwnsWorld: True
@@ -58,7 +58,7 @@ Players:
Name: Creeps Name: Creeps
NonCombatant: True NonCombatant: True
Race: Random Race: Random
Enemies: BadGuy,GoodGuy Enemies: Nod,GDI
Actors: Actors:
Actor0: sbag Actor0: sbag
@@ -312,110 +312,110 @@ Actors:
Owner: Neutral Owner: Neutral
Actor83: gun Actor83: gun
Location: 46,55 Location: 46,55
Owner: BadGuy Owner: Nod
Health: 0.5 Health: 0.5
Facing: 160 Facing: 160
Actor84: gun Actor84: gun
Location: 41,55 Location: 41,55
Owner: BadGuy Owner: Nod
Health: 0.5 Health: 0.5
Facing: 160 Facing: 160
Actor85: gun Actor85: gun
Location: 49,55 Location: 49,55
Owner: BadGuy Owner: Nod
Health: 0.1875 Health: 0.1875
Facing: 160 Facing: 160
mcv: mcv mcv: mcv
Location: 56,53 Location: 56,53
Owner: GoodGuy Owner: GDI
Health: 1 Health: 1
Facing: 0 Facing: 0
Gunboat: boat Gunboat: boat
Location: 53,59 Location: 53,59
Owner: GoodGuy Owner: GDI
Health: 1 Health: 1
Facing: 64 Facing: 64
Actor88: e1 Actor88: e1
Location: 56,55 Location: 56,55
Owner: GoodGuy Owner: GDI
Health: 1 Health: 1
Facing: 0 Facing: 0
SubCell: 2 SubCell: 2
Actor89: e1 Actor89: e1
Location: 56,55 Location: 56,55
Owner: GoodGuy Owner: GDI
Health: 1 Health: 1
Facing: 0 Facing: 0
SubCell: 4 SubCell: 4
Actor90: e1 Actor90: e1
Location: 56,55 Location: 56,55
Owner: GoodGuy Owner: GDI
Health: 1 Health: 1
Facing: 0 Facing: 0
SubCell: 3 SubCell: 3
Actor91: e1 Actor91: e1
Location: 56,55 Location: 56,55
Owner: GoodGuy Owner: GDI
Health: 1 Health: 1
Facing: 0 Facing: 0
SubCell: 1 SubCell: 1
Actor92: e1 Actor92: e1
Location: 57,45 Location: 57,45
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 160 Facing: 160
SubCell: 2 SubCell: 2
Actor93: e1 Actor93: e1
Location: 56,41 Location: 56,41
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 192 Facing: 192
SubCell: 2 SubCell: 2
Actor94: e1 Actor94: e1
Location: 48,41 Location: 48,41
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 96 Facing: 96
SubCell: 3 SubCell: 3
Actor95: e1 Actor95: e1
Location: 59,45 Location: 59,45
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 160 Facing: 160
SubCell: 1 SubCell: 1
Actor96: e1 Actor96: e1
Location: 46,50 Location: 46,50
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 96 Facing: 96
SubCell: 3 SubCell: 3
Actor97: e1 Actor97: e1
Location: 48,47 Location: 48,47
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 96 Facing: 96
SubCell: 1 SubCell: 1
Actor98: e1 Actor98: e1
Location: 38,43 Location: 38,43
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 128 Facing: 128
SubCell: 4 SubCell: 4
Actor99: e1 Actor99: e1
Location: 38,43 Location: 38,43
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 128 Facing: 128
SubCell: 1 SubCell: 1
Actor100: e1 Actor100: e1
Location: 48,41 Location: 48,41
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 96 Facing: 96
SubCell: 2 SubCell: 2
Actor101: e1 Actor101: e1
Location: 41,39 Location: 41,39
Owner: BadGuy Owner: Nod
Health: 1 Health: 1
Facing: 96 Facing: 96
SubCell: 4 SubCell: 4
@@ -454,9 +454,15 @@ Rules:
-SpawnMPUnits: -SpawnMPUnits:
-MPStartLocations: -MPStartLocations:
-CrateSpawner: -CrateSpawner:
Gdi01Script: PlayMusicOnMapLoad:
Music: aoi
Loop: false
LuaScriptInterface:
LuaScripts: mission.lua
Player: Player:
-ConquestVictoryConditions: -ConquestVictoryConditions:
^Infantry:
MustBeDestroyed:
PROC: PROC:
-Buildable: -Buildable:
SILO: SILO:
@@ -475,6 +481,7 @@ Rules:
-Buildable: -Buildable:
GUN: GUN:
-Buildable: -Buildable:
MustBeDestroyed:
GTWR: GTWR:
-Buildable: -Buildable:
ATWR: ATWR:
@@ -488,10 +495,24 @@ Rules:
RMBO: RMBO:
-Buildable: -Buildable:
BOAT: BOAT:
Mobile: Health:
OnRails: false HP: 1000
AutoTarget:
InitialStance: AttackAnything
RejectsOrders:
Except: Attack
OLDLST:
Inherits: LST
-WithRoof:
Sequences: Sequences:
oldlst:
idle: lst
Start: 0
Facings: 1
unload: lst
Start: 0
Facings: 1
VoxelSequences: VoxelSequences:

View File

@@ -0,0 +1,59 @@
InfantryReinforcements = { "e1", "e1", "e1" }
VehicleReinforcements = { "jeep" }
NodPatrol = { "e1", "e1" }
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Media.PlayMovieFullscreen("consyard.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Media.PlayMovieFullscreen("gameover.vqa")
end
SendNodPatrol = function()
local patrol = Reinforcements.Reinforce(enemy, NodPatrol, nod0.Location, nod1.Location, 0)
Utils.Do(patrol, function(soldier)
Actor.Move(soldier, nod2.Location)
Actor.Move(soldier, nod3.Location)
Actor.Hunt(soldier)
end)
end
SetGunboatPath = function()
Actor.AttackMove(Gunboat, gunboatLeft.Location)
Actor.AttackMove(Gunboat, gunboatRight.Location)
end
ReinforceFromSea = function(passengers)
local hovercraft, troops = Reinforcements.Insert(player, "oldlst", passengers, { lstStart.Location, lstEnd.Location }, { lstStart.Location })
Media.PlaySpeechNotification("Reinforce")
end
WorldLoaded = function()
player = OpenRA.GetPlayer("GDI")
enemy = OpenRA.GetPlayer("Nod")
Media.PlayMovieFullscreen("gdi1.vqa", function() Media.PlayMovieFullscreen("landing.vqa") end)
SendNodPatrol()
OpenRA.RunAfterDelay(25 * 5, function() ReinforceFromSea(InfantryReinforcements) end)
OpenRA.RunAfterDelay(25 * 15, function() ReinforceFromSea(InfantryReinforcements) end)
OpenRA.RunAfterDelay(25 * 30, function() ReinforceFromSea(VehicleReinforcements) end)
OpenRA.RunAfterDelay(25 * 60, function() ReinforceFromSea(VehicleReinforcements) end)
end
Tick = function()
if Actor.IsIdle(Gunboat) then
SetGunboatPath()
end
if Mission.RequiredUnitsAreDestroyed(player) then
MissionFailed()
end
if Mission.RequiredUnitsAreDestroyed(enemy) then
MissionAccomplished()
end
end

View File

@@ -284,7 +284,7 @@
Water: 100 Water: 100
SelectionDecorations: SelectionDecorations:
Selectable: Selectable:
Voice: GenericVoice Voice: VehicleVoice
TargetableUnit: TargetableUnit:
TargetTypes: Ground, Water TargetTypes: Ground, Water
HiddenUnderFog: HiddenUnderFog:

View File

@@ -1,4 +1,4 @@
GenericVoice: GenericVoice:
Variants: Variants:
nod: .v01,.v03 nod: .v01,.v03
gdi: .v01,.v03 gdi: .v01,.v03
@@ -8,27 +8,27 @@ GenericVoice:
Die: nuyell1,nuyell3,nuyell4,nuyell5 Die: nuyell1,nuyell3,nuyell4,nuyell5
DisableVariants: Die DisableVariants: Die
VehicleVoice: VehicleVoice:
Variants: Variants:
nod: .v00,.v02 nod: .v00,.v02
gdi: .v00,.v02 gdi: .v00,.v02
Voices: Voices:
Select: vehic1,yessir1,report1,await1,unit1 Select: vehic1,yessir1,report1,await1,unit1
Move: ackno,affirm1,movout1 Move: ackno,affirm1,movout1
CivilianMaleVoice: CivilianMaleVoice:
Voices: Voices:
Select: guyyeah1 Select: guyyeah1
Move: guyokay1 Move: guyokay1
Die: nuyell1,nuyell3,nuyell4,nuyell5 Die: nuyell1,nuyell3,nuyell4,nuyell5
CivilianFemaleVoice: CivilianFemaleVoice:
Voices: Voices:
Select: girlyeah Select: girlyeah
Move: girlokay Move: girlokay
Die: nuyell1,nuyell3,nuyell4,nuyell5 Die: nuyell1,nuyell3,nuyell4,nuyell5
CommandoVoice: CommandoVoice:
Voices: Voices:
Select: yeah1,yes1,yo1 Select: yeah1,yes1,yo1
Move: cmon1,onit1,gotit1 Move: cmon1,onit1,gotit1

View File

@@ -34,15 +34,13 @@ end
Tick = function() Tick = function()
Mission.TickTakeOre(ussr) Mission.TickTakeOre(ussr)
if not Mission.MissionIsOver then if Mission.RequiredUnitsAreDestroyed(player) then
if Mission.RequiredUnitsAreDestroyed(player) then MissionFailed()
MissionFailed() end
end if not trucksSent and Mission.RequiredUnitsAreDestroyed(ussr) and Mission.RequiredUnitsAreDestroyed(badGuy) then
if not trucksSent and Mission.RequiredUnitsAreDestroyed(ussr) and Mission.RequiredUnitsAreDestroyed(badGuy) then SendTrucks()
SendTrucks() trucksSent = true
trucksSent = true
end
end end
end end