Merge pull request #6552 from abcdefg30/monstertankmadness

Ported monster tank madness to lua
This commit is contained in:
obrakmann
2014-10-19 13:44:00 +02:00
14 changed files with 2856 additions and 16 deletions

View File

@@ -60,6 +60,7 @@ Also thanks to:
* Kyrre Soerensen (zypres)
* Lawrence Wang
* Lesueur Benjamin (Valkirie)
* Lukas Franke (abcdefg30)
* Maarten Meuris (Nyerguds)
* Mark Olson (markolson)
* Matija Hustic (matija-hustic)

View File

@@ -239,7 +239,7 @@ namespace OpenRA.Network
var targetPlayer = order.Player.World.Players.FirstOrDefault(p => p.InternalName == order.TargetString);
var newStance = (Stance)order.ExtraData;
SetPlayerStance(world, order.Player, targetPlayer, newStance);
order.Player.SetStance(targetPlayer, newStance);
Game.Debug("{0} has set diplomatic stance vs {1} to {2}",
order.Player.PlayerName, targetPlayer.PlayerName, newStance);
@@ -247,7 +247,7 @@ namespace OpenRA.Network
// automatically declare war reciprocally
if (newStance == Stance.Enemy && targetPlayer.Stances[order.Player] == Stance.Ally)
{
SetPlayerStance(world, targetPlayer, order.Player, newStance);
targetPlayer.SetStance(order.Player, newStance);
Game.Debug("{0} has reciprocated",targetPlayer.PlayerName);
}
@@ -275,17 +275,6 @@ namespace OpenRA.Network
}
}
static void SetPlayerStance(World w, Player p, Player target, Stance s)
{
var oldStance = p.Stances[target];
p.Stances[target] = s;
target.Shroud.UpdatePlayerStance(w, p, oldStance, s);
p.Shroud.UpdatePlayerStance(w, target, oldStance, s);
foreach (var nsc in w.ActorsWithTrait<INotifyStanceChanged>())
nsc.Trait.StanceChanged(nsc.Actor, p, target, oldStance, s);
}
static void SetOrderLag(OrderManager o)
{
if (o.FramesAhead != o.LobbyInfo.GlobalSettings.OrderLatency && !o.GameStarted)

View File

@@ -111,6 +111,17 @@ namespace OpenRA
return p == null || Stances[p] == Stance.Ally;
}
public void SetStance(Player target, Stance s)
{
var oldStance = Stances[target];
Stances[target] = s;
target.Shroud.UpdatePlayerStance(World, this, oldStance, s);
Shroud.UpdatePlayerStance(World, target, oldStance, s);
foreach (var nsc in World.ActorsWithTrait<INotifyStanceChanged>())
nsc.Trait.StanceChanged(nsc.Actor, this, target, oldStance, s);
}
#region Scripting interface
Lazy<ScriptPlayerInterface> luaInterface;

View File

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

View File

@@ -278,6 +278,13 @@ namespace OpenRA.Mods.RA.Scripting
context.World.ActorMap.RemoveCellTrigger(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)
{
GetScriptTriggers(a).RegisterCallback(Trigger.OnInfiltrated, func, context);
}
[Desc("Removes all triggers from this actor.")]
public void ClearAll(Actor a)
{

View File

@@ -0,0 +1,39 @@
#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.Network;
using OpenRA.Scripting;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Scripting
{
[ScriptPropertyGroup("Diplomacy")]
public class DiplomacyProperties : ScriptPlayerProperties
{
public DiplomacyProperties(ScriptContext context, Player player)
: base(context, player) { }
[Desc("Returns true if the player is allied with the other player.")]
public bool IsAlliedWith(Player targetPlayer)
{
return player.IsAlliedWith(targetPlayer);
}
[Desc("Changes the current stance of the player against the target player. " +
"Allowed keywords for new stance: Ally, Neutral, Enemy.")]
public void SetStance(Player targetPlayer, string newStance)
{
var emergingStance = Enum<Stance>.Parse(newStance);
player.SetStance(targetPlayer, emergingStance);
}
}
}

View File

@@ -33,6 +33,12 @@ namespace OpenRA.Mods.RA.Scripting
[Desc("Maximum health of the actor.")]
public int MaxHealth { get { return health.MaxHP; } }
[Desc("Kill the actor.")]
public void Kill()
{
health.InflictDamage(self, self, health.MaxHP, null, true);
}
}
[ScriptPropertyGroup("General")]

View File

@@ -19,7 +19,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Scripting
{
public enum Trigger { OnIdle, OnDamaged, OnKilled, OnProduction, OnOtherProduction, OnPlayerWon, OnPlayerLost,
OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed, OnCapture, OnAddedToWorld, OnRemovedFromWorld };
OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed, OnCapture, OnInfiltrated, OnAddedToWorld, OnRemovedFromWorld };
[Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")]
public class ScriptTriggersInfo : ITraitInfo
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA.Scripting
public object Create(ActorInitializer init) { return new ScriptTriggers(init.world); }
}
public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyOtherProduction, INotifyObjectivesUpdated, INotifyCapture, INotifyAddedToWorld, INotifyRemovedFromWorld, IDisposable
public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyOtherProduction, INotifyObjectivesUpdated, INotifyCapture, INotifyInfiltrated, INotifyAddedToWorld, INotifyRemovedFromWorld, IDisposable
{
readonly World world;
@@ -238,6 +238,24 @@ namespace OpenRA.Mods.RA.Scripting
}
}
public void Infiltrated(Actor self, Actor infiltrator)
{
foreach (var f in Triggers[Trigger.OnInfiltrated])
{
try
{
using (var a = self.ToLuaValue(f.Second))
using (var b = infiltrator.ToLuaValue(f.Second))
f.First.Call(a, b).Dispose();
}
catch (Exception ex)
{
f.Second.FatalError(ex.Message);
return;
}
}
}
public void AddedToWorld(Actor self)
{
foreach (var f in Triggers[Trigger.OnAddedToWorld])

View File

@@ -61,6 +61,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Red Alert Lua scripts", "Re
mods\ra\maps\desert-shellmap\desert-shellmap.lua = mods\ra\maps\desert-shellmap\desert-shellmap.lua
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
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System Lua scripts", "System Lua scripts", "{A4D6AEA4-8009-4256-903B-8D227E50452B}"

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,361 @@
AlliedUnits =
{
{ 0, { "1tnk", "1tnk", "2tnk", "2tnk" } },
{ Utils.Seconds(3), { "e1", "e1", "e1", "e3", "e3" } },
{ Utils.Seconds(7), { "e6" } }
}
ReinforceBaseUnits = { "1tnk", "1tnk", "2tnk", "arty", "arty" }
CivilianEvacuees = { "c1", "c2", "c5", "c7", "c8" }
USSROutpostFlameTurrets = { FlameTurret1, FlameTurret2 }
ExplosiveBarrels = { ExplosiveBarrel1, ExplosiveBarrel2 }
SuperTanks = { stnk1, stnk2, stnk3 }
SuperTankMoveWaypoints = { HospitalSuperTankPoint, AlliedBaseBottomRight, DemitriTriggerAreaCenter, DemitriLZ }
SuperTankMove = 1
SuperTankHuntWaypoints = { SuperTankHuntWaypoint1, SuperTankHuntWaypoint2, SuperTankHuntWaypoint3, SuperTankHuntWaypoint4 }
SuperTankHunt = 1
SuperTankHuntCounter = 1
ExtractionHeli = "tran"
ExtractionWaypoint = CPos.New(DemitriLZ.Location.X, 0)
ExtractionLZ = DemitriLZ.Location
BeachTrigger = { CPos.New(19, 44), CPos.New(20, 44), CPos.New(21, 44), CPos.New(22, 44), CPos.New(22, 45), CPos.New(23, 45), CPos.New(22, 44), CPos.New(24, 45), CPos.New(24, 46), CPos.New(24, 47), CPos.New(25, 47), CPos.New(25, 48) }
SetupAlliedBaseTrigger = { CPos.New(19, 33), CPos.New(20, 33), CPos.New(21, 33), CPos.New(22, 33), CPos.New(23, 33), CPos.New(24, 33), CPos.New(25, 33), CPos.New(26, 33), CPos.New(27, 33), CPos.New(28, 33) }
DemitriAreaTrigger = { CPos.New(32, 98), CPos.New(32, 99), CPos.New(33, 99), CPos.New(33, 100), CPos.New(33, 101), CPos.New(33, 102), CPos.New(32, 102), CPos.New(32, 103) }
HospitalAreaTrigger = { CPos.New(43, 41), CPos.New(44, 41), CPos.New(45, 41), CPos.New(46, 41), CPos.New(46, 42), CPos.New(46, 43), CPos.New(46, 44), CPos.New(46, 45), CPos.New(46, 46), CPos.New(45, 46), CPos.New(44, 46), CPos.New(43, 46) }
EvacuateCivilians = function()
local evacuees = Reinforcements.Reinforce(neutral, CivilianEvacuees, { HospitalCivilianSpawnPoint.Location }, 0)
Trigger.OnAnyKilled(evacuees, function()
player.MarkFailedObjective(RescueCivilians)
end)
Trigger.OnAllRemovedFromWorld(evacuees, function()
player.MarkCompletedObjective(RescueCivilians)
end)
Utils.Do(evacuees, function(civ)
Trigger.OnIdle(civ, function()
if civ.Location == AlliedBaseEntryPoint.Location then
civ.Destroy()
else
civ.Move(AlliedBaseEntryPoint.Location)
end
end)
end)
end
SpawnAndMoveAlliedBaseUnits = function()
Media.PlaySpeechNotification(player, "ReinforcementsArrived")
Reinforcements.Reinforce(player, ReinforceBaseUnits, { AlliedBaseEntryPoint.Location, AlliedBaseMovePoint.Location }, 18)
end
SetupAlliedBase = function()
local alliedOutpost = Map.ActorsInBox(AlliedBaseTopLeft.CenterPosition, AlliedBaseBottomRight.CenterPosition,
function(self) return self.Owner == outpost end)
Media.PlaySoundNotification(player, "BaseSetup")
Utils.Do(alliedOutpost, function(building)
building.Owner = player
end)
AlliedBaseHarv.Owner = player
AlliedBaseHarv.FindResources()
FindDemitri = player.AddPrimaryObjective("Find Dr. Demitri. He is likely hiding in the village\n to the far south.")
InfiltrateRadarDome = player.AddPrimaryObjective("Reprogram the super tanks by sending a spy into\n the Soviet radar dome.")
DefendOutpost = player.AddSecondaryObjective("Defend and repair our outpost.")
player.MarkCompletedObjective(FindOutpost)
Trigger.AfterDelay(Utils.Seconds(1), function() -- don't fail the Objective instantly
Trigger.OnAllRemovedFromWorld(alliedOutpost, function() player.MarkFailedObjective(DefendOutpost) end)
end)
Trigger.AfterDelay(Utils.Minutes(1) + Utils.Seconds(40), function()
if not SuperTankDomeIsInfiltrated then
SuperTankAttack = true
Utils.Do(SuperTanks, function(tnk)
if not tnk.IsDead then
Trigger.ClearAll(tnk)
Trigger.OnIdle(tnk, function()
if SuperTankAttack then
if tnk.Location == SuperTankMoveWaypoints[SuperTankMove].Location then
SuperTankMove = SuperTankMove + 1
if SuperTankMove == 5 then
SuperTankAttack = false
end
else
tnk.AttackMove(SuperTankMoveWaypoints[SuperTankMove].Location, 2)
end
end
end)
end
end)
end
end)
end
SendAlliedUnits = function()
Camera.Position = StartEntryPoint.CenterPosition
Actor.Create("camera" ,true , { Owner = player, Location = ProvingGroundsCameraPoint.Location })
Actor.Create("camera" ,true , { Owner = ussr, Location = USSRSpen.Location })
Trigger.AfterDelay(Utils.Seconds(1), function() Media.PlaySpeechNotification(player, "ReinforcementsArrived") end)
--To avoid overlapping "battlecontrol initialized" and "reinforcements have arrived"
Utils.Do(AlliedUnits, function(table)
Trigger.AfterDelay(table[1], function()
Reinforcements.Reinforce(player, table[2], { StartEntryPoint.Location, StartMovePoint.Location }, 18)
end)
end)
Trigger.AfterDelay(Utils.Seconds(1), function() InitialUnitsArrived = true end)
end
SuperTankDomeInfiltrated = function()
turkey.SetStance(player, "Ally")
turkey.SetStance(neutral, "Ally")
SuperTankAttack = true
Utils.Do(SuperTanks, function(tnk)
if not tnk.IsDead then
Trigger.ClearAll(tnk)
tnk.Stop()
if tnk.Location.Y > 61 then
SuperTankHunt = 4
SuperTankHuntCounter = -1
end
Trigger.OnIdle(tnk, function()
if SuperTankAttack then
if tnk.Location == SuperTankHuntWaypoints[SuperTankHunt].Location then
SuperTankHunt = SuperTankHunt + SuperTankHuntCounter
if SuperTankHunt == 0 or SuperTankHunt == 5 then
SuperTankAttack = false
end
else
tnk.AttackMove(SuperTankHuntWaypoints[SuperTankHunt].Location, 2)
end
else
tnk.Hunt()
end
end)
end
end)
player.MarkCompletedObjective(InfiltrateRadarDome)
Trigger.AfterDelay(Utils.Minutes(3), SuperTanksDestruction)
Trigger.AfterDelay(Utils.Seconds(2), function()
Media.PlaySpeechNotification(player, "ControlCenterDeactivated")
Trigger.AfterDelay(Utils.Seconds(3), function()
Media.DisplayMessage("In 3 minutes the super tanks will self destruct.")
Media.PlaySpeechNotification(player, "WarningThreeMinutesRemaining")
end)
end)
end
SuperTanksDestruction = function()
local badGuys = Map.ActorsInBox(Map.TopLeft, Map.BottomRight,
function(self) return self.Owner == badguy and self.HasProperty("Health") end)
Utils.Do(badGuys, function(unit)
unit.Kill()
end)
Utils.Do(SuperTanks, function(tnk)
if not tnk.IsDead then
Trigger.ClearAll(tnk)
tnk.Kill()
end
end)
player.MarkCompletedObjective(DefendOutpost)
end
CreateDemitri = function()
local demitri = Actor.Create("demitri", true, { Owner = player, Location = DemitriChurchSpawnPoint.Location })
demitri.Move(DemitriTriggerAreaCenter.Location)
Media.PlaySpeechNotification(player, "TargetFreed")
EvacuateDemitri = player.AddPrimaryObjective("Evacuate Dr. Demitri with the helicopter waiting\n at our outpost.")
player.MarkCompletedObjective(FindDemitri)
local flarepos = CPos.New(DemitriLZ.Location.X, DemitriLZ.Location.Y - 1)
local demitriLZFlare = Actor.Create("flare", true, { Owner = player, Location = flarepos })
Trigger.AfterDelay(Utils.Seconds(3), function() Media.PlaySpeechNotification(player, "SignalFlareNorth") end)
local demitriChinook = Reinforcements.ReinforceWithTransport(player, ExtractionHeli, nil, { ExtractionWaypoint, ExtractionLZ })[1]
Trigger.OnAnyKilled({ demitri, demitriChinook }, function()
player.MarkFailedObjective(EvacuateDemitri)
end)
Trigger.OnRemovedFromWorld(demitriChinook, function()
if not demitriChinook.IsDead then
Media.PlaySpeechNotification(player, "TargetRescued")
Trigger.AfterDelay(Utils.Seconds(1), function() player.MarkCompletedObjective(EvacuateDemitri) end)
Trigger.AfterDelay(Utils.Seconds(3), SpawnAndMoveAlliedBaseUnits)
end
end)
Trigger.OnRemovedFromWorld(demitri, function()
if not demitriChinook.IsDead and demitriChinook.HasPassengers then
demitriChinook.Move(ExtractionWaypoint)
Trigger.OnIdle(demitriChinook, demitriChinook.Destroy)
demitriLZFlare.Destroy()
end
end)
end
Tick = function()
ussr.Resources = ussr.Resources - (0.01 * ussr.ResourceCapacity / 25)
if InitialUnitsArrived then -- don't fail the mission straight at the beginning
if not DemitriFound or not SuperTankDomeIsInfiltrated then
if player.HasNoRequiredUnits() then
player.MarkFailedObjective(EliminateSuperTanks)
end
end
end
end
InitPlayers = function()
player = Player.GetPlayer("Greece")
neutral = Player.GetPlayer("Neutral")
outpost = Player.GetPlayer("Outpost")
badguy = Player.GetPlayer("BadGuy")
ussr = Player.GetPlayer("USSR")
ukraine = Player.GetPlayer("Ukraine")
turkey = Player.GetPlayer("Turkey")
player.Cash = 0
ussr.Cash = 2000
--badguy.Resources = badguy.ResourceCapacity -- doesn't work, workaround below
Trigger.OnCapture(Actor479, function()
player.Cash = player.Cash + Utils.RandomInteger(1200, 1300)
end)
end
InitObjectives = function()
Trigger.OnObjectiveAdded(player, function(p, id)
Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective")
end)
EliminateSuperTanks = player.AddPrimaryObjective("Eliminate these super tanks.")
CrossRiver = player.AddPrimaryObjective("Find a way to transport your forces to the mainland")
FindOutpost = player.AddPrimaryObjective("Find our outpost and start repairs on it.")
RescueCivilians = player.AddSecondaryObjective("Evacuate all civilians from the hospital.")
BadGuyObj = badguy.AddPrimaryObjective("Deny the destruction of the super tanks.")
USSRObj = ussr.AddPrimaryObjective("Deny the destruction of the super tanks.")
UkraineObj = ukraine.AddPrimaryObjective("Survive.")
TurkeyObj = turkey.AddPrimaryObjective("Destroy.")
Trigger.OnObjectiveCompleted(player, function(p, id)
Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed")
end)
Trigger.OnObjectiveFailed(player, function(p, id)
Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed")
end)
Trigger.OnPlayerLost(player, function()
Media.PlaySpeechNotification(player, "Lose")
ussr.MarkCompletedObjective(USSRObj)
badguy.MarkCompletedObjective(BadGuyObj)
ukraine.MarkCompletedObjective(UkraineObj)
turkey.MarkCompletedObjective(TurkeyObj)
end)
Trigger.OnPlayerWon(player, function()
Media.PlaySpeechNotification(player, "Win")
Media.DisplayMessage("Dr. Demitri has been extracted and the super tanks have been dealt with.")
ussr.MarkFailedObjective(USSRObj)
badguy.MarkFailedObjective(BadGuyObj)
ukraine.MarkFailedObjective(UkraineObj)
turkey.MarkFailedObjective(TurkeyObj)
end)
end
InitTriggers = function()
Trigger.OnAllKilled(SuperTanks, function()
Trigger.AfterDelay(Utils.Seconds(3), function() player.MarkCompletedObjective(EliminateSuperTanks) end)
end)
Trigger.OnKilled(SuperTankDome, function()
if not SuperTankDomeIsInfiltrated then
player.MarkFailedObjective(InfiltrateRadarDome)
end
end)
Trigger.OnInfiltrated(SuperTankDome, function()
if not SuperTankDomeIsInfiltrated then
SuperTankDomeIsInfiltrated = true
SuperTankDomeInfiltrated()
end
end)
Trigger.OnCapture(SuperTankDome, function()
if not SuperTankDomeIsInfiltrated then
SuperTankDomeIsInfiltrated = true
SuperTankDomeInfiltrated()
end
end)
Trigger.OnAnyKilled(USSROutpostFlameTurrets, function()
Utils.Do(ExplosiveBarrels, function(barrel)
if not barrel.IsDead then barrel.Kill() end
end)
end)
Trigger.OnKilled(DemitriChurch, function()
if not DemitriFound then
player.MarkFailedObjective(FindDemitri)
end
end)
Trigger.OnKilled(Hospital, function()
if not HospitalEvacuated then
HospitalEvacuated = true
player.MarkFailedObjective(RescueCivilians)
end
end)
beachReached = false
Trigger.OnEnteredFootprint(BeachTrigger, function(a, id)
if not beachReached and a.Owner == player then
beachReached = true
Trigger.RemoveFootprintTrigger(id)
player.MarkCompletedObjective(CrossRiver)
end
end)
Trigger.OnEnteredFootprint(SetupAlliedBaseTrigger, function(a, id)
if not outpostReached and a.Owner == player then
outpostReached = true
Trigger.RemoveFootprintTrigger(id)
SetupAlliedBase()
end
end)
Trigger.OnEnteredFootprint(DemitriAreaTrigger, function(a, id)
if not DemitriFound and a.Owner == player then
DemitriFound = true
Trigger.RemoveFootprintTrigger(id)
CreateDemitri()
end
end)
Trigger.OnEnteredFootprint(HospitalAreaTrigger, function(a, id)
if not HospitalEvacuated and a.Owner == player then
HospitalEvacuated = true
Trigger.RemoveFootprintTrigger(id)
EvacuateCivilians()
end
end)
end
WorldLoaded = function()
InitPlayers()
InitObjectives()
InitTriggers()
SendAlliedUnits()
end

View File

@@ -27,6 +27,7 @@ Speech:
ReinforcementsArrived: reinfor1
SignalFlareNorth: flaren1
AlliedReinforcementsArrived: aarrive1
AlliedForcesApproaching: aappro1
ConvoyApproaching: convyap1
ConvoyUnitLost: convlst1
TargetFreed: targfre1
@@ -44,6 +45,8 @@ Speech:
WarningThreeMinutesRemaining: 3minr
WarningFourMinutesRemaining: 4minr
WarningFiveMinutesRemaining: 5minr
ControlCenterDeactivated: cntlded1
OperationControlTerminated: opterm1
Sounds:
Notifications:
@@ -59,4 +62,5 @@ Sounds:
ClickDisabledSound:
Beacon: beepslct
AlertBuzzer: buzzy1
AlertBleep: bleep6
AlertBleep: bleep6
BaseSetup: bleep9