Merge pull request #6059 from obrakmann/mission-objectives

Mission objectives
This commit is contained in:
Paul Chote
2014-08-09 12:39:12 +12:00
98 changed files with 2415 additions and 1041 deletions

View File

@@ -271,7 +271,16 @@ namespace OpenRA.Traits
public interface ILintPass { void Run(Action<string> emitError, Action<string> emitWarning, Map map); }
public interface IObjectivesPanel { string ObjectivesPanel { get; } }
public interface IObjectivesPanel { string PanelName { get; } }
public interface INotifyObjectivesUpdated
{
void OnPlayerWon(Player winner);
void OnPlayerLost(Player loser);
void OnObjectiveAdded(Player player, int objectiveID);
void OnObjectiveCompleted(Player player, int objectiveID);
void OnObjectiveFailed(Player player, int objectiveID);
}
public static class DisableExts
{

View File

@@ -50,7 +50,8 @@ namespace OpenRA.Widgets
var colordisabled = GetColorDisabled();
var contrast = GetContrastColor();
var rect = RenderBounds;
var textSize = font.Measure(Text);
var text = GetText();
var textSize = font.Measure(text);
var check = new Rectangle(rect.Location, new Size(Bounds.Height, Bounds.Height));
var state = disabled ? "checkbox-disabled" :
highlighted ? "checkbox-highlighted" :
@@ -62,10 +63,10 @@ namespace OpenRA.Widgets
var position = new float2(rect.Left + rect.Height * 1.5f, RenderOrigin.Y - BaseLine + (Bounds.Height - textSize.Y)/2);
if (Contrast)
font.DrawTextWithContrast(Text, position,
font.DrawTextWithContrast(text, position,
disabled ? colordisabled : color, contrast, 2);
else
font.DrawText(Text, position,
font.DrawText(text, position,
disabled ? colordisabled : color);
if (IsChecked() || (Depressed && HasPressedState && !disabled))

View File

@@ -51,6 +51,11 @@ namespace OpenRA.Widgets
return window;
}
public static Widget CurrentWindow()
{
return WindowList.Count > 0 ? WindowList.Peek() : null;
}
public static T LoadWidget<T>(string id, Widget parent, WidgetArgs args) where T : Widget
{
var widget = LoadWidget(id, parent, args) as T;

View File

@@ -42,8 +42,19 @@ namespace OpenRA
public void AddPlayer(Player p) { Players.Add(p); }
public Player LocalPlayer { get; private set; }
Player renderPlayer;
public event Action GameOver = () => { };
bool gameOver;
public void EndGame()
{
if (!gameOver)
{
gameOver = true;
GameOver();
}
}
public bool ObserveAfterWinOrLose;
Player renderPlayer;
public Player RenderPlayer
{
get { return renderPlayer == null || (ObserveAfterWinOrLose && renderPlayer.WinState != WinState.Undefined) ? null : renderPlayer; }

View File

@@ -75,8 +75,6 @@
<Compile Include="RenderGunboat.cs" />
<Compile Include="SpawnViceroid.cs" />
<Compile Include="TiberiumRefinery.cs" />
<Compile Include="Widgets\Logic\CncConquestObjectivesLogic.cs" />
<Compile Include="Widgets\Logic\CncIngameMenuLogic.cs" />
<Compile Include="Widgets\Logic\CncMainMenuLogic.cs" />
<Compile Include="WithFire.cs" />
<Compile Include="WithRoof.cs" />

View File

@@ -1,131 +0,0 @@
#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 System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.RA;
using OpenRA.Mods.RA.Widgets;
using OpenRA.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.Cnc.Widgets.Logic
{
public class CncIngameMenuLogic
{
Widget menu;
enum PanelType { Objectives, Debug }
[ObjectCreator.UseCtor]
public CncIngameMenuLogic(Widget widget, World world, Action onExit, WorldRenderer worldRenderer)
{
var resumeDisabled = false;
menu = widget.Get("INGAME_MENU");
var mpe = world.WorldActor.Trait<MenuPaletteEffect>();
mpe.Fade(MenuPaletteEffect.EffectType.Desaturated);
menu.Get<LabelWidget>("VERSION_LABEL").Text = Game.modData.Manifest.Mod.Version;
var hideButtons = false;
menu.Get("MENU_BUTTONS").IsVisible = () => !hideButtons;
// TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions
Action onQuit = () =>
{
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", null);
resumeDisabled = true;
Game.RunAfterDelay(1200, () => mpe.Fade(MenuPaletteEffect.EffectType.Black));
Game.RunAfterDelay(1200 + 40 * mpe.Info.FadeLength, () =>
{
Game.Disconnect();
Ui.ResetAll();
Game.LoadShellMap();
});
};
Action doNothing = () => { };
menu.Get<ButtonWidget>("QUIT_BUTTON").OnClick = () =>
ConfirmationDialogs.PromptConfirmAction("Abort Mission", "Leave this game and return to the menu?", onQuit, doNothing);
Action onSurrender = () => world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false));
var surrenderButton = menu.Get<ButtonWidget>("SURRENDER_BUTTON");
surrenderButton.IsDisabled = () => (world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined);
surrenderButton.OnClick = () =>
ConfirmationDialogs.PromptConfirmAction("Surrender", "Are you sure you want to surrender?", onSurrender, doNothing);
menu.Get<ButtonWidget>("MUSIC_BUTTON").OnClick = () =>
{
hideButtons = true;
Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs()
{
{ "onExit", () => hideButtons = false },
{ "world", world }
});
};
menu.Get<ButtonWidget>("SETTINGS_BUTTON").OnClick = () =>
{
hideButtons = true;
Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs()
{
{ "world", world },
{ "worldRenderer", worldRenderer },
{ "onExit", () => hideButtons = false },
});
};
var resumeButton = menu.Get<ButtonWidget>("RESUME_BUTTON");
resumeButton.IsDisabled = () => resumeDisabled;
resumeButton.OnClick = () =>
{
Ui.CloseWindow();
Ui.Root.RemoveChild(menu);
world.WorldActor.Trait<MenuPaletteEffect>().Fade(MenuPaletteEffect.EffectType.None);
onExit();
};
// Menu panels - ordered from lowest to highest priority
var panelParent = Game.OpenWindow(world, "INGAME_MENU_PANEL");
var panelType = PanelType.Objectives;
var visibleButtons = 0;
// Debug / Cheats panel
var debugButton = panelParent.Get<ButtonWidget>("DEBUG_BUTTON");
debugButton.OnClick = () => panelType = PanelType.Debug;
debugButton.IsHighlighted = () => panelType == PanelType.Debug;
if (world.LocalPlayer != null && world.LobbyInfo.GlobalSettings.AllowCheats)
{
panelType = PanelType.Debug;
visibleButtons++;
var debugPanel = Game.LoadWidget(world, "DEBUG_PANEL", panelParent, new WidgetArgs() { { "onExit", doNothing }, { "transient", true } });
debugPanel.IsVisible = () => panelType == PanelType.Debug;
debugButton.IsVisible = () => visibleButtons > 1;
}
// Mission objectives
var iop = world.WorldActor.TraitsImplementing<IObjectivesPanel>().FirstOrDefault();
var objectivesButton = panelParent.Get<ButtonWidget>("OBJECTIVES_BUTTON");
objectivesButton.OnClick = () => panelType = PanelType.Objectives;
objectivesButton.IsHighlighted = () => panelType == PanelType.Objectives;
if (iop != null && iop.ObjectivesPanel != null)
{
panelType = PanelType.Objectives;
visibleButtons++;
var objectivesPanel = Game.LoadWidget(world, iop.ObjectivesPanel, panelParent, new WidgetArgs());
objectivesPanel.IsVisible = () => panelType == PanelType.Objectives;
objectivesButton.IsVisible = () => visibleButtons > 1;
}
}
}
}

View File

@@ -8,11 +8,14 @@
*/
#endregion
using System;
using System.Drawing;
using System.Linq;
using OpenRA.Mods.RA;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Widgets;
using OpenRA.Mods.RA.Widgets.Logic;
using OpenRA.Mods.D2k.Widgets;
using OpenRA.Traits;
using OpenRA.Widgets;
@@ -40,54 +43,19 @@ namespace OpenRA.Mods.D2k.Widgets.Logic
void InitRootWidgets()
{
var cachedPause = false;
Widget optionsBG = null;
optionsBG = Game.LoadWidget(world, "INGAME_OPTIONS_BG", Ui.Root, new WidgetArgs
{
{ "transient", false },
{ "onExit", () =>
{
optionsBG.Visible = false;
if (world.LobbyInfo.IsSinglePlayer)
world.SetPauseState(cachedPause);
}
}
});
optionsBG.Visible = false;
gameRoot.Get<ButtonWidget>("INGAME_OPTIONS_BUTTON").OnClick = () =>
{
optionsBG.Visible ^= true;
if (optionsBG.Visible)
{
cachedPause = world.PredictedPaused;
if (world.LobbyInfo.IsSinglePlayer)
world.SetPauseState(true);
}
else
world.SetPauseState(cachedPause);
};
Game.LoadWidget(world, "CHAT_PANEL", gameRoot, new WidgetArgs());
Action ShowLeaveRestartDialog = () =>
{
gameRoot.IsVisible = () => false;
Game.LoadWidget(world, "LEAVE_RESTART_WIDGET", Ui.Root, new WidgetArgs());
};
world.GameOver += ShowLeaveRestartDialog;
}
void InitObserverWidgets()
{
var observerWidgets = Game.LoadWidget(world, "OBSERVER_WIDGETS", playerRoot, new WidgetArgs());
Widget observerstats = null;
observerstats = Game.LoadWidget(world, "INGAME_OBSERVERSTATS_BG", observerWidgets, new WidgetArgs
{
{ "transient", false },
{ "onExit", () => observerstats.Visible = false }
});
observerstats.Visible = false;
var statsButton = observerWidgets.Get<ButtonWidget>("OBSERVER_STATS_BUTTON");
statsButton.OnClick = () => observerstats.Visible ^= true;
Game.LoadWidget(world, "OBSERVER_WIDGETS", playerRoot, new WidgetArgs());
}
enum RadarBinState { Closed, BinAnimating, RadarAnimating, Open };
@@ -95,41 +63,6 @@ namespace OpenRA.Mods.D2k.Widgets.Logic
{
var playerWidgets = Game.LoadWidget(world, "PLAYER_WIDGETS", playerRoot, new WidgetArgs());
Widget diplomacy = null;
diplomacy = Game.LoadWidget(world, "INGAME_DIPLOMACY_BG", playerWidgets, new WidgetArgs
{
{ "transient", false },
{ "onExit", () => diplomacy.Visible = false }
});
diplomacy.Visible = false;
var diplomacyButton = playerWidgets.Get<ButtonWidget>("INGAME_DIPLOMACY_BUTTON");
diplomacyButton.OnClick = () => diplomacy.Visible ^= true;
var validPlayers = 0;
validPlayers = world.Players.Where(a => a != world.LocalPlayer && !a.NonCombatant).Count();
diplomacyButton.IsVisible = () => validPlayers > 0;
Widget cheats = null;
cheats = Game.LoadWidget(world, "INGAME_DEBUG_BG", playerWidgets, new WidgetArgs
{
{ "transient", false },
{ "onExit", () => cheats.Visible = false }
});
cheats.Visible = false;
var cheatsButton = playerWidgets.Get<ButtonWidget>("INGAME_DEBUG_BUTTON");
cheatsButton.OnClick = () => cheats.Visible ^= true;
cheatsButton.IsVisible = () => world.LobbyInfo.GlobalSettings.AllowCheats;
var iop = world.WorldActor.TraitsImplementing<IObjectivesPanel>().FirstOrDefault();
if (iop != null && iop.ObjectivesPanel != null)
{
var objectivesButton = playerWidgets.Get<ButtonWidget>("OBJECTIVES_BUTTON");
var objectivesWidget = Game.LoadWidget(world, iop.ObjectivesPanel, playerWidgets, new WidgetArgs());
objectivesButton.Visible = true;
objectivesButton.OnClick += () => objectivesWidget.Visible ^= true;
}
var radarActive = false;
var binState = RadarBinState.Closed;
var radarBin = playerWidgets.Get<SlidingContainerWidget>("INGAME_RADAR_BIN");

View File

@@ -13,98 +13,82 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class ConquestVictoryConditionsInfo : ITraitInfo
public class ConquestVictoryConditionsInfo : ITraitInfo, Requires<MissionObjectivesInfo>
{
[Desc("Milliseconds")]
[Desc("Delay for the end game notification in milliseconds.")]
public int NotificationDelay = 1500;
public object Create(ActorInitializer init) { return new ConquestVictoryConditions(init.world, this); }
public object Create(ActorInitializer init) { return new ConquestVictoryConditions(init.self, this); }
}
public class ConquestVictoryConditions : ITick, IResolveOrder
public class ConquestVictoryConditions : ITick, INotifyObjectivesUpdated
{
ConquestVictoryConditionsInfo Info;
public ConquestVictoryConditions(World world, ConquestVictoryConditionsInfo info)
readonly ConquestVictoryConditionsInfo info;
readonly MissionObjectives mo;
int objectiveID = -1;
public ConquestVictoryConditions(Actor self, ConquestVictoryConditionsInfo cvcInfo)
{
world.ObserveAfterWinOrLose = true;
Info = info;
info = cvcInfo;
mo = self.Trait<MissionObjectives>();
}
public void Tick(Actor self)
{
if (self.Owner.WinState != WinState.Undefined || self.Owner.NonCombatant) return;
var hasAnything = self.World.ActorsWithTrait<MustBeDestroyed>()
.Any(a => a.Actor.Owner == self.Owner);
if (objectiveID < 0)
objectiveID = mo.Add(self.Owner, "Destroy all opposition!");
if (!hasAnything && !self.Owner.NonCombatant)
Lose(self);
if (!self.Owner.NonCombatant && self.Owner.HasNoRequiredUnits())
mo.MarkFailed(self.Owner, objectiveID);
var others = self.World.Players.Where(p => !p.NonCombatant
&& p != self.Owner && p.Stances[self.Owner] != Stance.Ally);
&& !p.IsAlliedWith(self.Owner));
if (!others.Any()) return;
if (others.All(p => p.WinState == WinState.Lost))
Win(self);
mo.MarkCompleted(self.Owner, objectiveID);
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Surrender")
Lose(self);
mo.MarkFailed(self.Owner, objectiveID);
}
public void Lose(Actor self)
public void OnPlayerLost(Player player)
{
if (self.Owner.WinState == WinState.Lost) return;
self.Owner.WinState = WinState.Lost;
self.World.OnPlayerWinStateChanged(self.Owner);
Game.Debug("{0} is defeated.".F(player.PlayerName));
Game.Debug("{0} is defeated.".F(self.Owner.PlayerName));
foreach (var a in self.World.Actors.Where(a => a.Owner == self.Owner))
foreach (var a in player.World.Actors.Where(a => a.Owner == player))
a.Kill(a);
if (self.Owner == self.World.LocalPlayer)
if (player == player.World.LocalPlayer)
{
Game.RunAfterDelay(Info.NotificationDelay, () =>
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(self.World))
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "Lose", self.Owner.Country.Race);
if (Game.IsCurrentWorld(player.World))
Sound.PlayNotification(player.World.Map.Rules, player, "Speech", "Lose", player.Country.Race);
});
}
}
public void Win(Actor self)
public void OnPlayerWon(Player player)
{
if (self.Owner.WinState == WinState.Won) return;
self.Owner.WinState = WinState.Won;
self.World.OnPlayerWinStateChanged(self.Owner);
Game.Debug("{0} is victorious.".F(player.PlayerName));
Game.Debug("{0} is victorious.".F(self.Owner.PlayerName));
if (self.Owner == self.World.LocalPlayer)
Game.RunAfterDelay(Info.NotificationDelay, () => Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "Win", self.Owner.Country.Race));
if (player == player.World.LocalPlayer)
Game.RunAfterDelay(info.NotificationDelay, () => Sound.PlayNotification(player.World.Map.Rules, player, "Speech", "Win", player.Country.Race));
}
public void OnObjectiveAdded(Player player, int id) {}
public void OnObjectiveCompleted(Player player, int id) {}
public void OnObjectiveFailed(Player player, int id) {}
}
[Desc("Tag trait for things that must be destroyed for a short game to end.")]
public class MustBeDestroyedInfo : TraitInfo<MustBeDestroyed> { }
public class MustBeDestroyed { }
[Desc("Provides game mode information for players/observers.",
"Goes on WorldActor - observers don't have a player it can live on.")]
public class ConquestObjectivesPanelInfo : ITraitInfo
{
public string ObjectivesPanel = null;
public object Create(ActorInitializer init) { return new ConquestObjectivesPanel(this); }
}
public class ConquestObjectivesPanel : IObjectivesPanel
{
ConquestObjectivesPanelInfo info;
public ConquestObjectivesPanel(ConquestObjectivesPanelInfo info) { this.info = info; }
public string ObjectivesPanel { get { return info.ObjectivesPanel; } }
}
}

View File

@@ -21,9 +21,12 @@ namespace OpenRA.Mods.RA
[Desc("Time (in ticks) to fade between states")]
public readonly int FadeLength = 10;
[Desc("Effect style to fade to. Accepts values of None or Desaturated")]
[Desc("Effect style to fade to during gameplay. Accepts values of None or Desaturated.")]
public readonly MenuPaletteEffect.EffectType Effect = MenuPaletteEffect.EffectType.None;
[Desc("Effect style to fade to when opening the in-game menu. Accepts values of None, Black or Desaturated.")]
public readonly MenuPaletteEffect.EffectType MenuEffect = MenuPaletteEffect.EffectType.None;
public object Create(ActorInitializer init) { return new MenuPaletteEffect(this); }
}

View File

@@ -284,6 +284,7 @@
<Compile Include="Player\PlaceBuilding.cs" />
<Compile Include="Player\ProductionQueue.cs" />
<Compile Include="Player\ProvidesTechPrerequisite.cs" />
<Compile Include="Player\MissionObjectives.cs" />
<Compile Include="PortableChrono.cs" />
<Compile Include="Warheads\DestroyResourceWarhead.cs" />
<Compile Include="Warheads\CreateEffectWarhead.cs" />
@@ -372,6 +373,11 @@
<Compile Include="Widgets\Logic\KickSpectatorsLogic.cs" />
<Compile Include="Widgets\Logic\MissionBrowserLogic.cs" />
<Compile Include="Widgets\Logic\IngameMenuLogic.cs" />
<Compile Include="Widgets\Logic\Ingame\GameInfoLogic.cs" />
<Compile Include="Widgets\Logic\Ingame\GameInfoBriefingLogic.cs" />
<Compile Include="Widgets\Logic\Ingame\GameInfoObjectivesLogic.cs" />
<Compile Include="Widgets\Logic\Ingame\GameInfoStatsLogic.cs" />
<Compile Include="Widgets\Logic\Ingame\LeaveMapLogic.cs" />
<Compile Include="Widgets\Logic\IrcLogic.cs" />
<Compile Include="Widgets\Logic\KickClientLogic.cs" />
<Compile Include="Widgets\Logic\ModBrowserLogic.cs" />
@@ -484,6 +490,7 @@
<Compile Include="Scripting\Global\CoordinateGlobals.cs" />
<Compile Include="Scripting\Properties\ResourceProperties.cs" />
<Compile Include="Scripting\Properties\ProductionProperties.cs" />
<Compile Include="Scripting\Properties\MissionObjectiveProperties.cs" />
<Compile Include="Scripting\Properties\MobileProperties.cs" />
<Compile Include="Scripting\Properties\GeneralProperties.cs" />
<Compile Include="Scripting\Properties\HealthProperties.cs" />
@@ -551,6 +558,7 @@
<Compile Include="GlobalUpgradable.cs" />
<Compile Include="Player\GlobalUpgradeManager.cs" />
<Compile Include="GainsStatUpgrades.cs" />
<Compile Include="Player\Extensions.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj">

View File

@@ -0,0 +1,23 @@
#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.Linq;
using OpenRA.Mods.RA;
namespace OpenRA
{
public static class Extensions
{
public static bool HasNoRequiredUnits(this Player player)
{
return player.World.ActorsWithTrait<MustBeDestroyed>().All(p => p.Actor.Owner != player);
}
}
}

View File

@@ -0,0 +1,229 @@
#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 System.Collections.Generic;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public enum ObjectiveType { Primary, Secondary };
public enum ObjectiveState { Incomplete, Completed, Failed };
public class MissionObjective
{
public readonly ObjectiveType Type;
public readonly string Description;
public ObjectiveState State;
public MissionObjective(ObjectiveType type, string description)
{
Type = type;
Description = description;
State = ObjectiveState.Incomplete;
}
}
public class MissionObjectivesInfo : ITraitInfo
{
[Desc("Set this to true if multiple cooperative players have a distinct set of " +
"objectives that each of them has to complete to win the game. This is mainly " +
"useful for multiplayer coop missions. Do not use this for skirmish team games.")]
public readonly bool Cooperative = false;
[Desc("If set to true, this setting causes the game to end immediately once the first " +
"player (or team of cooperative players) fails or completes his objectives. If " +
"set to false, players that fail their objectives will stick around and become observers.")]
public readonly bool EarlyGameOver = false;
[Desc("Delay between the game over condition being met, and the game actually ending, in milliseconds.")]
public readonly int GameOverDelay = 1500;
public object Create(ActorInitializer init) { return new MissionObjectives(init.world, this); }
}
public class MissionObjectives : INotifyObjectivesUpdated, ISync, IResolveOrder
{
readonly MissionObjectivesInfo info;
readonly List<MissionObjective> objectives = new List<MissionObjective>();
public ReadOnlyList<MissionObjective> Objectives;
[Sync]
public int ObjectivesHash { get { return Objectives.Aggregate(0, (code, objective) => code ^ Sync.hash(objective.State)); } }
// This property is used as a flag in 'Cooperative' games to mark that the player has completed all his objectives.
// The player's WinState is only updated when his allies have all completed their objective as well.
public WinState WinStateCooperative { get; private set; }
public MissionObjectives(World world, MissionObjectivesInfo moInfo)
{
info = moInfo;
Objectives = new ReadOnlyList<MissionObjective>(objectives);
world.ObserveAfterWinOrLose = !info.EarlyGameOver;
}
public int Add(Player player, string description, ObjectiveType type = ObjectiveType.Primary)
{
var newID = objectives.Count;
objectives.Insert(newID, new MissionObjective(type, description));
ObjectiveAdded(player);
foreach (var imo in player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>())
imo.OnObjectiveAdded(player, newID);
return newID;
}
public void MarkCompleted(Player player, int objectiveID)
{
if (objectiveID >= objectives.Count || objectives[objectiveID].State == ObjectiveState.Completed)
return;
objectives[objectiveID].State = ObjectiveState.Completed;
if (objectives[objectiveID].Type == ObjectiveType.Primary)
{
var playerWon = objectives.Where(o => o.Type == ObjectiveType.Primary).All(o => o.State == ObjectiveState.Completed);
foreach (var imo in player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>())
{
imo.OnObjectiveCompleted(player, objectiveID);
if (playerWon)
imo.OnPlayerWon(player);
}
if (playerWon)
CheckIfGameIsOver(player);
}
}
public void MarkFailed(Player player, int objectiveID)
{
if (objectiveID >= objectives.Count || objectives[objectiveID].State == ObjectiveState.Failed)
return;
objectives[objectiveID].State = ObjectiveState.Failed;
if (objectives[objectiveID].Type == ObjectiveType.Primary)
{
var playerLost = objectives.Where(o => o.Type == ObjectiveType.Primary).Any(o => o.State == ObjectiveState.Failed);
foreach (var imo in player.PlayerActor.TraitsImplementing<INotifyObjectivesUpdated>())
{
imo.OnObjectiveFailed(player, objectiveID);
if (playerLost)
imo.OnPlayerLost(player);
}
if (playerLost)
CheckIfGameIsOver(player);
}
}
void CheckIfGameIsOver(Player player)
{
var players = player.World.Players.Where(p => !p.NonCombatant);
var allies = players.Where(p => p.IsAlliedWith(player));
var gameOver = ((info.EarlyGameOver && !info.Cooperative && player.WinState != WinState.Undefined) ||
(info.EarlyGameOver && info.Cooperative && allies.All(p => p.WinState != WinState.Undefined)) ||
players.All(p => p.WinState != WinState.Undefined));
if (gameOver)
{
Game.RunAfterDelay(info.GameOverDelay, () =>
{
player.World.EndGame();
player.World.SetPauseState(true);
player.World.PauseStateLocked = true;
});
}
}
public void OnPlayerWon(Player player)
{
if (info.Cooperative)
{
WinStateCooperative = WinState.Won;
var players = player.World.Players.Where(p => !p.NonCombatant);
var allies = players.Where(p => p.IsAlliedWith(player));
if (allies.All(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Won))
foreach (var p in allies)
{
p.WinState = WinState.Won;
p.World.OnPlayerWinStateChanged(p);
}
}
else
{
player.WinState = WinState.Won;
player.World.OnPlayerWinStateChanged(player);
}
}
public void OnPlayerLost(Player player)
{
if (info.Cooperative)
{
WinStateCooperative = WinState.Lost;
var players = player.World.Players.Where(p => !p.NonCombatant);
var allies = players.Where(p => p.IsAlliedWith(player));
if (allies.Any(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Lost))
foreach (var p in allies)
{
p.WinState = WinState.Lost;
p.World.OnPlayerWinStateChanged(p);
}
}
else
{
player.WinState = WinState.Lost;
player.World.OnPlayerWinStateChanged(player);
}
}
public event Action<Player> ObjectiveAdded = player => { };
public void OnObjectiveAdded(Player player, int id) {}
public void OnObjectiveCompleted(Player player, int id) {}
public void OnObjectiveFailed(Player player, int id) {}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Surrender")
for (var id = 0; id < objectives.Count; id++)
MarkFailed(self.Owner, id);
}
}
[Desc("Provides game mode progress information for players.",
"Goes on WorldActor - observers don't have a player it can live on.",
"Current options for PanelName are 'SKIRMISH_STATS' and 'MISSION_OBJECTIVES'.")]
public class ObjectivesPanelInfo : ITraitInfo
{
public string PanelName = null;
public object Create(ActorInitializer init) { return new ObjectivesPanel(this); }
}
public class ObjectivesPanel : IObjectivesPanel
{
ObjectivesPanelInfo info;
public ObjectivesPanel(ObjectivesPanelInfo info) { this.info = info; }
public string PanelName { get { return info.PanelName; } }
}
}

View File

@@ -8,14 +8,58 @@
*/
#endregion
using System;
using System.Drawing;
using Eluant;
using OpenRA.Scripting;
namespace OpenRA.Scripting
{
[ScriptGlobal("Media")]
public class MediaGlobal : ScriptGlobal
{
public MediaGlobal(ScriptContext context) : base(context) { }
World world;
public MediaGlobal(ScriptContext context) : base(context)
{
world = context.World;
}
[Desc("Play an announcer voice listed in notifications.yaml")]
public void PlaySpeechNotification(Player player, string notification)
{
Sound.PlayNotification(world.Map.Rules, player, "Speech", notification, player != null ? player.Country.Race : null);
}
[Desc("Play a sound listed in notifications.yaml")]
public void PlaySoundNotification(Player player, string notification)
{
Sound.PlayNotification(world.Map.Rules, player, "Sounds", notification, player != null ? player.Country.Race : null);
}
Action onComplete;
[Desc("Play a VQA video including the file extension.")]
public void PlayMovieFullscreen(string movie, LuaFunction func = null)
{
if (func != null)
{
var f = func.CopyReference() as LuaFunction;
onComplete = () =>
{
try
{
using (f)
f.Call();
}
catch (LuaException e)
{
context.FatalError(e.Message);
}
};
}
else
onComplete = () => { };
Media.PlayFMVFullscreen(world, movie, onComplete);
}
[Desc("Display a text message to the player.")]
public void DisplayMessage(string text, string prefix = "Mission") // TODO: expose HSLColor to Lua and add as parameter

View File

@@ -56,21 +56,21 @@ namespace OpenRA.Mods.RA.Scripting
"The callback function will be called as func(Actor self).")]
public void OnIdle(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterIdleCallback(func, context);
GetScriptTriggers(a).RegisterCallback(Trigger.OnIdle, func, context);
}
[Desc("Call a function when the actor is damaged. The callback " +
"function will be called as func(Actor self, Actor attacker).")]
public void OnDamaged(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterDamagedCallback(func, context);
GetScriptTriggers(a).RegisterCallback(Trigger.OnDamaged, func, context);
}
[Desc("Call a function when the actor is killed. The callback " +
"function will be called as func(Actor self, Actor killer).")]
public void OnKilled(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterKilledCallback(func, context);
GetScriptTriggers(a).RegisterCallback(Trigger.OnKilled, func, context);
}
[Desc("Call a function when all of the actors in a group are killed. The callback " +
@@ -106,7 +106,56 @@ namespace OpenRA.Mods.RA.Scripting
"The callback function will be called as func(Actor producer, Actor produced).")]
public void OnProduction(Actor a, LuaFunction func)
{
GetScriptTriggers(a).RegisterProductionCallback(func, context);
GetScriptTriggers(a).RegisterCallback(Trigger.OnProduction, func, context);
}
[Desc("Call a function when this player completes all primary objectives. " +
"The callback function will be called as func(Player player).")]
public void OnPlayerWon(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnPlayerWon, func, context);
}
[Desc("Call a function when this player fails any primary objective. " +
"The callback function will be called as func(Player player).")]
public void OnPlayerLost(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnPlayerLost, func, context);
}
[Desc("Call a function when this player is assigned a new objective. " +
"The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveAdded(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveAdded, func, context);
}
[Desc("Call a function when this player completes an objective " +
"The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveCompleted(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveCompleted, func, context);
}
[Desc("Call a function when this player fails an objective " +
"The callback function will be called as func(Player player, int objectiveID).")]
public void OnObjectiveFailed(Player player, LuaFunction func)
{
GetScriptTriggers(player.PlayerActor).RegisterCallback(Trigger.OnObjectiveFailed, func, context);
}
[Desc("Removes all triggers from this actor")]
public void ClearAll(Actor a)
{
GetScriptTriggers(a).ClearAll();
}
[Desc("Removes the specified trigger from this actor")]
public void Clear(Actor a, string triggerName)
{
var trigger = (Trigger)Enum.Parse(typeof(Trigger), triggerName);
GetScriptTriggers(a).Clear(trigger);
}
}
}

View File

@@ -319,7 +319,7 @@ namespace OpenRA.Mods.RA.Scripting
[LuaGlobal]
public bool RequiredUnitsAreDestroyed(Player player)
{
return world.ActorsWithTrait<MustBeDestroyed>().All(p => p.Actor.Owner != player);
return player.HasNoRequiredUnits();
}
[LuaGlobal]

View File

@@ -0,0 +1,70 @@
#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 OpenRA.Traits;
using OpenRA.Scripting;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Scripting
{
[ScriptPropertyGroup("MissionObjectives")]
public class MissionObjectiveProperties : ScriptPlayerProperties
{
readonly MissionObjectives mo;
public MissionObjectiveProperties(Player player)
: base(player)
{
mo = player.PlayerActor.Trait<MissionObjectives>();
}
[ScriptActorPropertyActivity]
[Desc("Add a primary mission objective for this player. The function returns the " +
"ID of the newly created objective, so that it can be referred to later.")]
public int AddPrimaryObjective(string description)
{
return mo.Add(player, description, ObjectiveType.Primary);
}
[ScriptActorPropertyActivity]
[Desc("Add a secondary mission objective for this player. The function returns the " +
"ID of the newly created objective, so that it can be referred to later.")]
public int AddSecondaryObjective(string description)
{
return mo.Add(player, description, ObjectiveType.Secondary);
}
[ScriptActorPropertyActivity]
[Desc("Mark an objective as completed. This needs the objective ID returned " +
"by AddObjective as argument. When the player has completed all primary " +
"objectives, (s)he has won the game.")]
public void MarkCompletedObjective(int id)
{
mo.MarkCompleted(player, id);
}
[ScriptActorPropertyActivity]
[Desc("Mark an objective as failed. This needs the objective ID returned " +
"by AddObjective as argument. Secondary objectives do not have any " +
"influence whatsoever on the outcome of the game.")]
public void MarkFailedObjective(int id)
{
mo.MarkFailed(player, id);
}
[ScriptActorPropertyActivity]
[Desc("Returns true if 'player' has lost all units/actors that have the 'MustBeDestroyed' trait.")]
public bool HasNoRequiredUnits()
{
return player.HasNoRequiredUnits();
}
}
}

View File

@@ -18,41 +18,31 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Scripting
{
public enum Trigger { OnIdle, OnDamaged, OnKilled, OnProduction, OnPlayerWon, OnPlayerLost, OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed };
[Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")]
public class ScriptTriggersInfo : TraitInfo<ScriptTriggers> { }
public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, IDisposable
public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyObjectivesUpdated, IDisposable
{
public event Action<Actor> OnKilledInternal = _ => {};
List<Pair<LuaFunction, ScriptContext>> onIdle = new List<Pair<LuaFunction, ScriptContext>>();
List<Pair<LuaFunction, ScriptContext>> onDamaged = new List<Pair<LuaFunction, ScriptContext>>();
List<Pair<LuaFunction, ScriptContext>> onKilled = new List<Pair<LuaFunction, ScriptContext>>();
List<Pair<LuaFunction, ScriptContext>> onProduction = new List<Pair<LuaFunction, ScriptContext>>();
public Dictionary<Trigger, List<Pair<LuaFunction, ScriptContext>>> Triggers = new Dictionary<Trigger, List<Pair<LuaFunction, ScriptContext>>>();
public void RegisterIdleCallback(LuaFunction func, ScriptContext context)
public ScriptTriggers()
{
onIdle.Add(Pair.New((LuaFunction)func.CopyReference(), context));
foreach (var t in Enum.GetValues(typeof(Trigger)).Cast<Trigger>())
Triggers.Add(t, new List<Pair<LuaFunction, ScriptContext>>());
}
public void RegisterDamagedCallback(LuaFunction func, ScriptContext context)
public void RegisterCallback(Trigger trigger, LuaFunction func, ScriptContext context)
{
onDamaged.Add(Pair.New((LuaFunction)func.CopyReference(), context));
}
public void RegisterKilledCallback(LuaFunction func, ScriptContext context)
{
onKilled.Add(Pair.New((LuaFunction)func.CopyReference(), context));
}
public void RegisterProductionCallback(LuaFunction func, ScriptContext context)
{
onProduction.Add(Pair.New((LuaFunction)func.CopyReference(), context));
Triggers[trigger].Add(Pair.New((LuaFunction)func.CopyReference(), context));
}
public void TickIdle(Actor self)
{
foreach (var f in onIdle)
foreach (var f in Triggers[Trigger.OnIdle])
{
var a = self.ToLuaValue(f.Second);
f.First.Call(a).Dispose();
@@ -62,7 +52,7 @@ namespace OpenRA.Mods.RA.Scripting
public void Damaged(Actor self, AttackInfo e)
{
foreach (var f in onDamaged)
foreach (var f in Triggers[Trigger.OnDamaged])
{
var a = self.ToLuaValue(f.Second);
var b = e.Attacker.ToLuaValue(f.Second);
@@ -75,7 +65,7 @@ namespace OpenRA.Mods.RA.Scripting
public void Killed(Actor self, AttackInfo e)
{
// Run lua callbacks
foreach (var f in onKilled)
foreach (var f in Triggers[Trigger.OnKilled])
{
var a = self.ToLuaValue(f.Second);
var b = e.Attacker.ToLuaValue(f.Second);
@@ -90,7 +80,7 @@ namespace OpenRA.Mods.RA.Scripting
public void UnitProduced(Actor self, Actor other, CPos exit)
{
foreach (var f in onProduction)
foreach (var f in Triggers[Trigger.OnProduction])
{
var a = self.ToLuaValue(f.Second);
var b = other.ToLuaValue(f.Second);
@@ -100,9 +90,76 @@ namespace OpenRA.Mods.RA.Scripting
}
}
public void OnPlayerWon(Player player)
{
foreach (var f in Triggers[Trigger.OnPlayerWon])
{
var a = player.ToLuaValue(f.Second);
f.First.Call(a).Dispose();
a.Dispose();
}
}
public void OnPlayerLost(Player player)
{
foreach (var f in Triggers[Trigger.OnPlayerLost])
{
var a = player.ToLuaValue(f.Second);
f.First.Call(a).Dispose();
a.Dispose();
}
}
public void OnObjectiveAdded(Player player, int id)
{
foreach (var f in Triggers[Trigger.OnObjectiveAdded])
{
var a = player.ToLuaValue(f.Second);
var b = id.ToLuaValue(f.Second);
f.First.Call(a, b).Dispose();
a.Dispose();
b.Dispose();
}
}
public void OnObjectiveCompleted(Player player, int id)
{
foreach (var f in Triggers[Trigger.OnObjectiveCompleted])
{
var a = player.ToLuaValue(f.Second);
var b = id.ToLuaValue(f.Second);
f.First.Call(a, b).Dispose();
a.Dispose();
b.Dispose();
}
}
public void OnObjectiveFailed(Player player, int id)
{
foreach (var f in Triggers[Trigger.OnObjectiveFailed])
{
var a = player.ToLuaValue(f.Second);
var b = id.ToLuaValue(f.Second);
f.First.Call(a, b).Dispose();
a.Dispose();
b.Dispose();
}
}
public void Clear(Trigger trigger)
{
Triggers[trigger].Clear();
}
public void ClearAll()
{
foreach (var trigger in Triggers)
trigger.Value.Clear();
}
public void Dispose()
{
var pairs = new[] { onIdle, onDamaged, onKilled, onProduction };
var pairs = Triggers.Values;
pairs.SelectMany(l => l).Select(p => p.First).Do(f => f.Dispose());
pairs.Do(l => l.Clear());
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* 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,
@@ -17,41 +17,68 @@ namespace OpenRA.Mods.RA
public class StrategicPointInfo : TraitInfo<StrategicPoint> {}
public class StrategicPoint {}
public class StrategicVictoryConditionsInfo : ITraitInfo, Requires<ConquestVictoryConditionsInfo>
public class StrategicVictoryConditionsInfo : ITraitInfo, Requires<MissionObjectivesInfo>
{
[Desc("Amount of time (in game ticks) that the player has to hold all the strategic points.")]
public readonly int TicksToHold = 25 * 60 * 5; // ~5 minutes
[Desc("Should the timer reset when the player loses hold of a strategic point.")]
public readonly bool ResetOnHoldLost = true;
[Desc("Percentage of strategic points the player has to hold to win.")]
public readonly float RatioRequired = 0.5f; // 50% required of all koth locations
[Desc("Delay for the end game notification in milliseconds.")]
public int NotificationDelay = 1500;
public object Create(ActorInitializer init) { return new StrategicVictoryConditions(init.self, this); }
}
public class StrategicVictoryConditions : ITick, ISync
public class StrategicVictoryConditions : ITick, ISync, INotifyObjectivesUpdated
{
Actor self;
StrategicVictoryConditionsInfo info;
readonly StrategicVictoryConditionsInfo info;
[Sync] public int TicksLeft = 0;
[Sync] public int TicksLeft;
readonly Player player;
readonly MissionObjectives mo;
int objectiveID = -1;
public StrategicVictoryConditions(Actor self, StrategicVictoryConditionsInfo info)
public StrategicVictoryConditions(Actor self, StrategicVictoryConditionsInfo svcInfo)
{
this.self = self;
this.info = info;
info = svcInfo;
TicksLeft = info.TicksToHold;
player = self.Owner;
mo = self.Trait<MissionObjectives>();
}
public IEnumerable<TraitPair<StrategicPoint>> AllPoints
{
get { return self.World.ActorsWithTrait<StrategicPoint>(); }
get { return player.World.ActorsWithTrait<StrategicPoint>(); }
}
public int Total { get { return AllPoints.Count(); } }
int Owned { get { return AllPoints.Count( a => WorldUtils.AreMutualAllies( self.Owner, a.Actor.Owner )); } }
int Owned { get { return AllPoints.Count(a => WorldUtils.AreMutualAllies(player, a.Actor.Owner)); } }
public bool Holding { get { return Owned >= info.RatioRequired * Total; } }
public void Tick(Actor self)
{
if (self.Owner.WinState != WinState.Undefined || self.Owner.NonCombatant) return;
if (player.WinState != WinState.Undefined || player.NonCombatant) return;
if (objectiveID < 0)
objectiveID = mo.Add(player, "Hold all the strategic positions for a specified time!");
if (!self.Owner.NonCombatant && self.Owner.HasNoRequiredUnits())
mo.MarkFailed(self.Owner, objectiveID);
var others = self.World.Players.Where(p => !p.NonCombatant
&& !p.IsAlliedWith(self.Owner));
if (others.All(p => p.WinState == WinState.Lost))
mo.MarkCompleted(player, objectiveID);
if (others.Any(p => p.WinState == WinState.Won))
mo.MarkFailed(player, objectiveID);
// See if any of the conditions are met to increase the count
if (Total > 0)
@@ -59,10 +86,8 @@ namespace OpenRA.Mods.RA
if (Holding)
{
// Hah! We met ths critical owned condition
if (TicksLeft == 0)
TicksLeft = info.TicksToHold; // first tick -- this is crap.
else if (--TicksLeft == 0)
Won();
if (--TicksLeft == 0)
mo.MarkCompleted(player, objectiveID);
}
else if (TicksLeft != 0)
if (info.ResetOnHoldLost)
@@ -70,18 +95,33 @@ namespace OpenRA.Mods.RA
}
}
void Won()
public void OnPlayerLost(Player player)
{
// Player has won
foreach (var p in self.World.Players)
{
var cvc = p.PlayerActor.Trait<ConquestVictoryConditions>();
Game.Debug("{0} is defeated.".F(player.PlayerName));
if (p.WinState == WinState.Undefined && WorldUtils.AreMutualAllies(self.Owner, p))
cvc.Win(p.PlayerActor);
else if (p.WinState == WinState.Undefined)
cvc.Lose(p.PlayerActor);
foreach (var a in player.World.Actors.Where(a => a.Owner == player))
a.Kill(a);
if (player == player.World.LocalPlayer)
{
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World))
Sound.PlayNotification(player.World.Map.Rules, player, "Speech", "Lose", player.Country.Race);
});
}
}
public void OnPlayerWon(Player player)
{
Game.Debug("{0} is victorious.".F(player.PlayerName));
if (player == player.World.LocalPlayer)
Game.RunAfterDelay(info.NotificationDelay, () => Sound.PlayNotification(player.World.Map.Rules, player, "Speech", "Win", player.Country.Race));
}
public void OnObjectiveAdded(Player player, int id) {}
public void OnObjectiveCompleted(Player player, int id) {}
public void OnObjectiveFailed(Player player, int id) {}
}
}

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
public class DebugMenuLogic
{
[ObjectCreator.UseCtor]
public DebugMenuLogic(Widget widget, Action onExit, World world, bool transient)
public DebugMenuLogic(Widget widget, World world)
{
var devTrait = world.LocalPlayer.PlayerActor.Trait<DeveloperMode>();
@@ -112,21 +112,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
showAstarCostCheckbox.IsChecked = () => dbgOverlay != null ? dbgOverlay.Visible : false;
showAstarCostCheckbox.OnClick = () => { if (dbgOverlay != null) dbgOverlay.Visible ^= true; };
}
var close = widget.GetOrNull<ButtonWidget>("CLOSE");
if (close != null)
{
close.OnClick = () =>
{
if (transient)
{
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
}
onExit();
};
}
}
public void Order(World world, string order)

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
ScrollPanelWidget diplomacyPanel;
[ObjectCreator.UseCtor]
public DiplomacyLogic(Widget widget, Action onExit, World world, bool transient)
public DiplomacyLogic(Widget widget, Action onExit, World world)
{
this.world = world;
@@ -33,18 +33,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var close = widget.GetOrNull<ButtonWidget>("CLOSE");
if (close != null)
{
close.OnClick = () =>
{
if (transient)
{
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
}
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
onExit();
};
}
}
void LayoutPlayers()

View File

@@ -0,0 +1,38 @@
#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 System.Linq;
using OpenRA.Widgets;
using OpenRA.Traits;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Widgets.Logic
{
class GameInfoBriefingLogic
{
[ObjectCreator.UseCtor]
public GameInfoBriefingLogic(Widget widget, World world)
{
var previewWidget = widget.Get<MapPreviewWidget>("MAP_PREVIEW");
previewWidget.Preview = () => Game.modData.MapCache[world.Map.Uid];
var mapDescriptionPanel = widget.Get<ScrollPanelWidget>("MAP_DESCRIPTION_PANEL");
var mapDescription = widget.Get<LabelWidget>("MAP_DESCRIPTION");
var mapFont = Game.Renderer.Fonts[mapDescription.Font];
var text = world.Map.Description != null ? world.Map.Description.Replace("\\n", "\n") : "";
text = WidgetUtils.WrapText(text, mapDescription.Bounds.Width, mapFont);
mapDescription.Text = text;
mapDescription.Bounds.Height = mapFont.Measure(text).Y;
mapDescriptionPanel.ScrollToTop();
mapDescriptionPanel.Layout.AdjustChildren();
}
}
}

View File

@@ -0,0 +1,109 @@
#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 System.Linq;
using OpenRA.Widgets;
using OpenRA.Traits;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Widgets.Logic
{
public enum IngameInfoPanel { AutoSelect, Map, Objectives, Debug };
class GameInfoLogic
{
[ObjectCreator.UseCtor]
public GameInfoLogic(Widget widget, World world, IngameInfoPanel activePanel)
{
var lp = world.LocalPlayer;
var numTabs = 0;
widget.IsVisible = () => activePanel != IngameInfoPanel.AutoSelect;
// Objectives/Stats tab
var iop = world.WorldActor.TraitsImplementing<IObjectivesPanel>().FirstOrDefault();
if (lp != null && iop != null && iop.PanelName != null)
{
numTabs++;
var objectivesTabButton = widget.Get<ButtonWidget>(string.Concat("BUTTON", numTabs.ToString()));
objectivesTabButton.GetText = () => "Objectives";
objectivesTabButton.IsVisible = () => lp != null && numTabs > 1;
objectivesTabButton.OnClick = () => activePanel = IngameInfoPanel.Objectives;
objectivesTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Objectives;
var objectivesPanel = widget.Get<ContainerWidget>("OBJECTIVES_PANEL");
objectivesPanel.IsVisible = () => activePanel == IngameInfoPanel.Objectives;
Game.LoadWidget(world, iop.PanelName, objectivesPanel, new WidgetArgs());
if (activePanel == IngameInfoPanel.AutoSelect)
activePanel = IngameInfoPanel.Objectives;
}
// Briefing tab
if (world.Map.CustomPreview != null)
{
numTabs++;
var mapTabButton = widget.Get<ButtonWidget>(string.Concat("BUTTON", numTabs.ToString()));
mapTabButton.Text = "Briefing";
mapTabButton.IsVisible = () => numTabs > 1;
mapTabButton.OnClick = () => activePanel = IngameInfoPanel.Map;
mapTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Map;
var mapPanel = widget.Get<ContainerWidget>("MAP_PANEL");
mapPanel.IsVisible = () => activePanel == IngameInfoPanel.Map;
Game.LoadWidget(world, "MAP_PANEL", mapPanel, new WidgetArgs());
if (activePanel == IngameInfoPanel.AutoSelect)
activePanel = IngameInfoPanel.Map;
}
// Debug/Cheats tab
if (lp != null && world.LobbyInfo.GlobalSettings.AllowCheats)
{
numTabs++;
var debugTabButton = widget.Get<ButtonWidget>(string.Concat("BUTTON", numTabs.ToString()));
debugTabButton.Text = "Debug";
debugTabButton.IsVisible = () => lp != null && world.LobbyInfo.GlobalSettings.AllowCheats && numTabs > 1;
debugTabButton.OnClick = () => activePanel = IngameInfoPanel.Debug;
debugTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Debug;
var debugPanelContainer = widget.Get<ContainerWidget>("DEBUG_PANEL");
debugPanelContainer.IsVisible = () => activePanel == IngameInfoPanel.Debug;
Game.LoadWidget(world, "DEBUG_PANEL", debugPanelContainer, new WidgetArgs());
if (activePanel == IngameInfoPanel.AutoSelect)
activePanel = IngameInfoPanel.Debug;
}
// Handle empty space when tabs aren't displayed
var titleText = widget.Get<LabelWidget>("TITLE");
var titleTextNoTabs = widget.GetOrNull<LabelWidget>("TITLE_NO_TABS");
titleText.IsVisible = () => numTabs > 1 || (numTabs == 1 && titleTextNoTabs == null);
titleText.GetText = () => string.Concat(world.Map.Type, ": ", world.Map.Title);
if (titleTextNoTabs != null)
{
titleTextNoTabs.IsVisible = () => numTabs == 1;
titleTextNoTabs.GetText = () => string.Concat(world.Map.Type, ": ", world.Map.Title);
}
var bg = widget.Get<BackgroundWidget>("BACKGROUND");
var bgNoTabs = widget.GetOrNull<BackgroundWidget>("BACKGROUND_NO_TABS");
bg.IsVisible = () => numTabs > 1 || (numTabs == 1 && bgNoTabs == null);
if (bgNoTabs != null)
bgNoTabs.IsVisible = () => numTabs == 1;
}
}
}

View File

@@ -0,0 +1,72 @@
#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 System.Linq;
using System.Drawing;
using OpenRA.Widgets;
using OpenRA.Traits;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Widgets.Logic
{
class GameInfoObjectivesLogic
{
ContainerWidget template;
[ObjectCreator.UseCtor]
public GameInfoObjectivesLogic(Widget widget, World world)
{
var lp = world.LocalPlayer;
var missionStatus = widget.Get<LabelWidget>("MISSION_STATUS");
missionStatus.GetText = () => lp.WinState == WinState.Undefined ? "In progress" :
lp.WinState == WinState.Won ? "Accomplished" : "Failed";
missionStatus.GetColor = () => lp.WinState == WinState.Undefined ? Color.White :
lp.WinState == WinState.Won ? Color.LimeGreen : Color.Red;
var mo = lp.PlayerActor.TraitOrDefault<MissionObjectives>();
if (mo == null)
return;
var objectivesPanel = widget.Get<ScrollPanelWidget>("OBJECTIVES_PANEL");
template = objectivesPanel.Get<ContainerWidget>("OBJECTIVE_TEMPLATE");
PopulateObjectivesList(mo, objectivesPanel, template);
Action<Player> RedrawObjectives = player =>
{
if (player == lp)
PopulateObjectivesList(mo, objectivesPanel, template);
};
mo.ObjectiveAdded += RedrawObjectives;
}
void PopulateObjectivesList(MissionObjectives mo, ScrollPanelWidget parent, ContainerWidget template)
{
parent.RemoveChildren();
foreach (var objective in mo.Objectives.OrderBy(o => o.Type))
{
var widget = template.Clone();
var label = widget.Get<LabelWidget>("OBJECTIVE_TYPE");
label.GetText = () => objective.Type == ObjectiveType.Primary ? "Primary" : "Secondary";
var checkbox = widget.Get<CheckboxWidget>("OBJECTIVE_STATUS");
checkbox.IsChecked = () => objective.State != ObjectiveState.Incomplete;
checkbox.GetCheckType = () => objective.State == ObjectiveState.Completed ? "checked" : "crossed";
checkbox.GetText = () => objective.Description;
parent.AddChild(widget);
}
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* 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,
@@ -8,46 +8,42 @@
*/
#endregion
using System;
using System.Drawing;
using System.Linq;
using OpenRA.Mods.RA;
using OpenRA.Widgets;
using OpenRA.Traits;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.Cnc.Widgets.Logic
namespace OpenRA.Mods.RA.Widgets.Logic
{
public class CncConquestObjectivesLogic
class GameInfoStatsLogic
{
[ObjectCreator.UseCtor]
public CncConquestObjectivesLogic(Widget widget, World world)
public GameInfoStatsLogic(Widget widget, World world)
{
var panel = widget.Get("CONQUEST_OBJECTIVES");
panel.Get<LabelWidget>("TITLE").GetText = () => "Conquest: " + world.Map.Title;
var lp = world.LocalPlayer;
var statusLabel = panel.Get<LabelWidget>("STATUS");
statusLabel.IsVisible = () => world.LocalPlayer != null;
var checkbox = widget.Get<CheckboxWidget>("STATS_CHECKBOX");
checkbox.IsChecked = () => lp.WinState != WinState.Undefined;
checkbox.GetCheckType = () => lp.WinState == WinState.Won ?
"checked" : "crossed";
if (world.LocalPlayer != null)
{
var lp = world.LocalPlayer;
var objectiveCheckbox = panel.Get<CheckboxWidget>("1");
objectiveCheckbox.IsChecked = () => lp.WinState != WinState.Undefined;
objectiveCheckbox.GetCheckType = () => lp.WinState == WinState.Won ?
"checked" : "crossed";
var statusLabel = widget.Get<LabelWidget>("STATS_STATUS");
statusLabel.GetText = () => lp.WinState == WinState.Won ? "Complete" :
lp.WinState == WinState.Lost ? "Failed" : "Incomplete";
statusLabel.GetColor = () => lp.WinState == WinState.Won ? Color.Green :
lp.WinState == WinState.Lost ? Color.Red : Color.White;
}
statusLabel.GetText = () => lp.WinState == WinState.Won ? "Accomplished" :
lp.WinState == WinState.Lost ? "Failed" : "In progress";
statusLabel.GetColor = () => lp.WinState == WinState.Won ? Color.LimeGreen :
lp.WinState == WinState.Lost ? Color.Red : Color.White;
var scrollpanel = panel.Get<ScrollPanelWidget>("PLAYER_LIST");
var itemTemplate = scrollpanel.Get("PLAYER_TEMPLATE");
scrollpanel.RemoveChildren();
var playerPanel = widget.Get<ScrollPanelWidget>("PLAYER_LIST");
var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE");
playerPanel.RemoveChildren();
foreach (var p in world.Players.Where(a => !a.NonCombatant))
{
var pp = p;
var item = itemTemplate.Clone();
var item = playerTemplate.Clone();
var nameLabel = item.Get<LabelWidget>("NAME");
nameLabel.GetText = () => pp.WinState == WinState.Lost ? pp.PlayerName + " (Dead)" : pp.PlayerName;
nameLabel.GetColor = () => pp.Color.RGB;
@@ -61,7 +57,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex);
var teamNumber = (client == null) ? 0 : client.Team;
team.GetText = () => (teamNumber == 0) ? "-" : teamNumber.ToString();
scrollpanel.AddChild(item);
playerPanel.AddChild(item);
var stats = pp.PlayerActor.TraitOrDefault<PlayerStatistics>();
if (stats == null)

View File

@@ -0,0 +1,70 @@
#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.Linq;
using OpenRA.Network;
using OpenRA.Traits;
using OpenRA.Widgets;
using OpenRA.Mods.RA;
namespace OpenRA.Mods.RA.Widgets
{
class LeaveMapLogic
{
[ObjectCreator.UseCtor]
public LeaveMapLogic(Widget widget, OrderManager orderManager, World world)
{
widget.Get<LabelWidget>("VERSION_LABEL").Text = Game.modData.Manifest.Mod.Version;
var panelName = "LEAVE_RESTART_SIMPLE";
var iop = world.WorldActor.TraitsImplementing<IObjectivesPanel>().FirstOrDefault();
var showObjectives = iop != null && iop.PanelName != null && world.LocalPlayer != null;
if (showObjectives)
panelName = "LEAVE_RESTART_FULL";
var dialog = widget.Get<ContainerWidget>(panelName);
var fmvPlayer = Ui.Root.GetOrNull<BackgroundWidget>("FMVPLAYER");
dialog.IsVisible = () => true;
widget.IsVisible = () => fmvPlayer == null || fmvPlayer != Ui.CurrentWindow();
var leaveButton = dialog.Get<ButtonWidget>("LEAVE_BUTTON");
leaveButton.OnClick = () =>
{
leaveButton.Disabled = true;
var mpe = world.WorldActor.TraitOrDefault<MenuPaletteEffect>();
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave",
world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
var exitDelay = 1200;
if (mpe != null)
{
Game.RunAfterDelay(exitDelay, () => mpe.Fade(MenuPaletteEffect.EffectType.Black));
exitDelay += 40 * mpe.Info.FadeLength;
}
Game.RunAfterDelay(exitDelay, () =>
{
Game.Disconnect();
Ui.ResetAll();
Game.LoadShellMap();
});
};
if (showObjectives)
{
var objectivesContainer = dialog.Get<ContainerWidget>("OBJECTIVES");
Game.LoadWidget(world, iop.PanelName, objectivesContainer, new WidgetArgs());
}
}
}
}

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System;
using OpenRA.Widgets;
namespace OpenRA.Mods.RA.Widgets.Logic
@@ -26,6 +27,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Game.LoadWidget(world, "PLAYER_WIDGETS", playerRoot, new WidgetArgs());
Game.LoadWidget(world, "CHAT_PANEL", ingameRoot, new WidgetArgs());
Action ShowLeaveRestartDialog = () =>
{
ingameRoot.IsVisible = () => false;
Game.LoadWidget(world, "LEAVE_RESTART_WIDGET", Ui.Root, new WidgetArgs());
};
world.GameOver += ShowLeaveRestartDialog;
}
}
}

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#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
@@ -9,19 +9,34 @@
#endregion
using System;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.RA;
using OpenRA.Mods.RA.Widgets;
using OpenRA.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.RA.Widgets.Logic
{
class IngameMenuLogic
public class IngameMenuLogic
{
Widget menu;
[ObjectCreator.UseCtor]
public IngameMenuLogic(Widget widget, World world, Action onExit, WorldRenderer worldRenderer, bool transient)
public IngameMenuLogic(Widget widget, World world, Action onExit, WorldRenderer worldRenderer, IngameInfoPanel activePanel)
{
var resumeDisabled = false;
menu = widget.Get("INGAME_MENU");
var mpe = world.WorldActor.TraitOrDefault<MenuPaletteEffect>();
if (mpe != null)
mpe.Fade(mpe.Info.MenuEffect);
menu.Get<LabelWidget>("VERSION_LABEL").Text = Game.modData.Manifest.Mod.Version;
var hideMenu = false;
menu.Get("MENU_BUTTONS").IsVisible = () => !hideMenu;
// TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions
Action onQuit = () =>
{
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
@@ -33,7 +48,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Game.RunAfterDelay(exitDelay, () => mpe.Fade(MenuPaletteEffect.EffectType.Black));
exitDelay += 40 * mpe.Info.FadeLength;
}
Game.RunAfterDelay(exitDelay, () =>
{
Game.Disconnect();
@@ -42,62 +56,69 @@ namespace OpenRA.Mods.RA.Widgets.Logic
});
};
Action onSurrender = () =>
Action closeMenu = () =>
{
world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false));
Ui.CloseWindow();
Ui.Root.RemoveChild(menu);
if (mpe != null)
mpe.Fade(MenuPaletteEffect.EffectType.None);
onExit();
};
widget.Get<ButtonWidget>("DISCONNECT").OnClick = () =>
Action showMenu = () => hideMenu = false;
menu.Get<ButtonWidget>("ABORT_MISSION").OnClick = () =>
{
widget.Visible = false;
ConfirmationDialogs.PromptConfirmAction("Abort Mission", "Leave this game and return to the menu?", onQuit, () => widget.Visible = true);
hideMenu = true;
ConfirmationDialogs.PromptConfirmAction("Abort Mission", "Leave this game and return to the menu?", onQuit, showMenu);
};
widget.Get<ButtonWidget>("SETTINGS").OnClick = () =>
Action onSurrender = () =>
{
widget.Visible = false;
Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs()
{
{ "onExit", () => widget.Visible = true },
{ "worldRenderer", worldRenderer },
});
world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false));
closeMenu();
};
widget.Get<ButtonWidget>("MUSIC").OnClick = () =>
var surrenderButton = menu.Get<ButtonWidget>("SURRENDER");
surrenderButton.IsDisabled = () => (world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined);
surrenderButton.OnClick = () =>
{
widget.Visible = false;
Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
hideMenu = true;
ConfirmationDialogs.PromptConfirmAction("Surrender", "Are you sure you want to surrender?", onSurrender, showMenu);
};
surrenderButton.IsDisabled = () => world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined;
menu.Get<ButtonWidget>("MUSIC").OnClick = () =>
{
hideMenu = true;
Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs()
{
{ "onExit", () => { widget.Visible = true; } },
{ "onExit", () => hideMenu = false },
{ "world", world }
});
};
var resumeButton = widget.Get<ButtonWidget>("RESUME");
resumeButton.IsDisabled = () => resumeDisabled;
resumeButton.OnClick = () =>
var settingsButton = widget.Get<ButtonWidget>("SETTINGS");
settingsButton.OnClick = () =>
{
if (transient)
hideMenu = true;
Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs()
{
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
}
onExit();
{ "world", world },
{ "worldRenderer", worldRenderer },
{ "onExit", () => hideMenu = false },
});
};
widget.Get<ButtonWidget>("SURRENDER").OnClick = () =>
var resumeButton = menu.Get<ButtonWidget>("RESUME");
resumeButton.IsDisabled = () => resumeDisabled;
resumeButton.OnClick = closeMenu;
// Game info panel
var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", menu, new WidgetArgs()
{
widget.Visible = false;
ConfirmationDialogs.PromptConfirmAction(
"Surrender",
"Are you sure you want to surrender?",
onSurrender,
() => widget.Visible = true,
"Surrender");
};
widget.Get("SURRENDER").IsVisible = () => world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Undefined;
{ "activePanel", activePanel }
});
gameInfoPanel.IsVisible = () => !hideMenu;
}
}
}

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
WorldRenderer worldRenderer;
[ObjectCreator.UseCtor]
public ObserverStatsLogic(World world, WorldRenderer worldRenderer, Widget widget, Action onExit, bool transient)
public ObserverStatsLogic(World world, WorldRenderer worldRenderer, Widget widget, Action onExit)
{
this.world = world;
this.worldRenderer = worldRenderer;
@@ -139,18 +139,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var close = widget.GetOrNull<ButtonWidget>("CLOSE");
if (close != null)
{
close.OnClick = () =>
{
if (transient)
{
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
}
Ui.CloseWindow();
Ui.Root.RemoveChild(widget);
onExit();
};
}
}
void ClearStats()

View File

@@ -8,9 +8,11 @@
*/
#endregion
using System;
using System.Linq;
using OpenRA.Mods.RA.Orders;
using OpenRA.Widgets;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Widgets.Logic
{
@@ -59,8 +61,32 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var options = widget.GetOrNull<MenuButtonWidget>("OPTIONS_BUTTON");
if (options != null)
{
var blinking = false;
var lp = world.LocalPlayer;
options.IsDisabled = () => disableSystemButtons;
options.OnClick = () => OpenMenuPanel(options);
options.OnClick = () =>
{
blinking = false;
OpenMenuPanel(options, new WidgetArgs()
{
{ "activePanel", IngameInfoPanel.AutoSelect }
});
};
options.IsHighlighted = () => blinking && Game.LocalTick % 50 < 25;
if (lp != null)
{
Action<Player> StartBlinking = player =>
{
if (player == world.LocalPlayer)
blinking = true;
};
var mo = lp.PlayerActor.TraitOrDefault<MissionObjectives>();
if (mo != null)
mo.ObjectiveAdded += StartBlinking;
}
}
var diplomacy = widget.GetOrNull<MenuButtonWidget>("DIPLOMACY_BUTTON");
@@ -76,7 +102,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
debug.IsVisible = () => world.LobbyInfo.GlobalSettings.AllowCheats;
debug.IsDisabled = () => disableSystemButtons;
debug.OnClick = () => OpenMenuPanel(debug);
debug.OnClick = () => OpenMenuPanel(debug, new WidgetArgs()
{
{ "activePanel", IngameInfoPanel.Debug }
});
}
var stats = widget.GetOrNull<MenuButtonWidget>("OBSERVER_STATS_BUTTON");
@@ -87,7 +116,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
}
}
void OpenMenuPanel(MenuButtonWidget button)
void OpenMenuPanel(MenuButtonWidget button, WidgetArgs widgetArgs = null)
{
disableSystemButtons = true;
var cachedPause = world.PredictedPaused;
@@ -98,21 +127,19 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (button.Pause && world.LobbyInfo.IsSinglePlayer)
world.SetPauseState(true);
Game.LoadWidget(world, button.MenuContainer, Ui.Root, new WidgetArgs()
widgetArgs = widgetArgs ?? new WidgetArgs();
widgetArgs.Add("onExit", () =>
{
{ "transient", true },
{ "onExit", () =>
{
if (button.HideIngameUI)
ingameRoot.IsVisible = () => true;
if (button.HideIngameUI)
ingameRoot.IsVisible = () => true;
if (button.Pause && world.LobbyInfo.IsSinglePlayer)
world.SetPauseState(cachedPause);
if (button.Pause && world.LobbyInfo.IsSinglePlayer)
world.SetPauseState(cachedPause);
disableSystemButtons = false;
}
}
disableSystemButtons = false;
});
Game.LoadWidget(world, button.MenuContainer, Ui.Root, widgetArgs);
}
static void BindOrderButton<T>(World world, ButtonWidget w, string icon)

View File

@@ -364,6 +364,22 @@ namespace OpenRA.Utility
}
}
if (engineVersion < 20140806)
{
// remove ConquestVictoryConditions when StrategicVictoryConditions is set
if (depth == 0 && node.Key == "Player" && node.Value.Nodes.Any(n => n.Key == "StrategicVictoryConditions"))
node.Value.Nodes.Add(new MiniYamlNode("-ConquestVictoryConditions", ""));
// the objectives panel trait and its properties have been renamed
if (depth == 1 && node.Key == "ConquestObjectivesPanel")
{
node.Key = "ObjectivesPanel";
node.Value.Nodes.RemoveAll(_ => true);
node.Value.Nodes.Add(new MiniYamlNode("PanelName", new MiniYaml("SKIRMISH_STATS")));
}
}
// Veterancy was changed to use the upgrades system
if (engineVersion < 20140807)
{

View File

@@ -3,122 +3,110 @@ Container@DEBUG_PANEL:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
Label@TITLE:
Width: PARENT_RIGHT
Y: 0-25
Font: BigBold
Contrast: true
Label@CHEATS_TITLE:
Y: 25
Font: Bold
Text: Cheats
Align: Center
Text: Debug Options
Background@bg:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Background: panel-black
Children:
Label@CHEATS_TITLE:
Y: 25
Font: Bold
Text: Cheats
Align: Center
Width: PARENT_RIGHT
Checkbox@INSTANT_BUILD:
X: 45
Y: 45
Width: 200
Height: 20
Font: Regular
Text: Instant Build Speed
Checkbox@ENABLE_TECH:
X: 45
Y: 75
Width: 200
Height: 20
Font: Regular
Text: Build Everything
Checkbox@BUILD_ANYWHERE:
X: 45
Y: 105
Width: 200
Height: 20
Font: Regular
Text: Build Anywhere
Checkbox@UNLIMITED_POWER:
X: 290
Y: 45
Width: 200
Height: 20
Font: Regular
Text: Unlimited Power
Checkbox@INSTANT_CHARGE:
X: 290
Y: 75
Width: 200
Height: 20
Font: Regular
Text: Instant Charge Time
Checkbox@DISABLE_SHROUD:
X: 290
Y: 105
Height: 20
Width: 200
Font: Regular
Text: Disable Shroud & Fog
Button@GIVE_CASH:
X: 90
Y: 145
Width: 140
Height: 35
Text: Give $20,000
Button@GROW_RESOURCES:
X: 271
Y: 145
Width: 140
Height: 35
Text: Grow Resources
Button@GIVE_EXPLORATION:
X: 90
Y: 195
Width: 140
Height: 35
Text: Clear Shroud
Button@RESET_EXPLORATION:
X: 271
Y: 195
Width: 140
Height: 35
Text: Reset Shroud
Label@VISUALIZATIONS_TITLE:
Y: 255
Font: Bold
Text: Visualizations
Align: Center
Width: PARENT_RIGHT
Checkbox@SHOW_UNIT_PATHS:
X: 45
Y: 285
Width: 200
Height: 20
Font: Regular
Text: Show Unit Paths
Checkbox@SHOW_ASTAR:
X: 45
Y: 315
Height: 20
Width: 200
Font: Regular
Text: Show A* Cost
Checkbox@SHOW_COMBATOVERLAY:
X: 290
Y: 285
Height: 20
Width: 200
Font: Regular
Text: Show Combat Geometry
Checkbox@SHOW_GEOMETRY:
X: 290
Y: 315
Height: 20
Width: 200
Font: Regular
Text: Show Render Geometry
Checkbox@INSTANT_BUILD:
X: 45
Y: 45
Width: 200
Height: 20
Font: Regular
Text: Instant Build Speed
Checkbox@ENABLE_TECH:
X: 45
Y: 75
Width: 200
Height: 20
Font: Regular
Text: Build Everything
Checkbox@BUILD_ANYWHERE:
X: 45
Y: 105
Width: 200
Height: 20
Font: Regular
Text: Build Anywhere
Checkbox@UNLIMITED_POWER:
X: 290
Y: 45
Width: 200
Height: 20
Font: Regular
Text: Unlimited Power
Checkbox@INSTANT_CHARGE:
X: 290
Y: 75
Width: 200
Height: 20
Font: Regular
Text: Instant Charge Time
Checkbox@DISABLE_SHROUD:
X: 290
Y: 105
Height: 20
Width: 200
Font: Regular
Text: Disable Shroud & Fog
Button@GIVE_CASH:
X: 90
Y: 145
Width: 140
Height: 35
Text: Give $20,000
Button@GROW_RESOURCES:
X: 271
Y: 145
Width: 140
Height: 35
Text: Grow Resources
Button@GIVE_EXPLORATION:
X: 90
Y: 195
Width: 140
Height: 35
Text: Clear Shroud
Button@RESET_EXPLORATION:
X: 271
Y: 195
Width: 140
Height: 35
Text: Reset Shroud
Label@VISUALIZATIONS_TITLE:
Y: 255
Font: Bold
Text: Visualizations
Align: Center
Width: PARENT_RIGHT
Checkbox@SHOW_UNIT_PATHS:
X: 45
Y: 285
Width: 200
Height: 20
Font: Regular
Text: Show Unit Paths
Checkbox@SHOW_ASTAR:
X: 45
Y: 315
Height: 20
Width: 200
Font: Regular
Text: Show A* Cost
Checkbox@SHOW_COMBATOVERLAY:
X: 290
Y: 285
Height: 20
Width: 200
Font: Regular
Text: Show Combat Geometry
Checkbox@SHOW_GEOMETRY:
X: 290
Y: 315
Height: 20
Width: 200
Font: Regular
Text: Show Render Geometry

View File

@@ -0,0 +1,55 @@
Container@GAME_INFO_PANEL:
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 512
Height: 375
Logic: GameInfoLogic
Visible: False
Children:
Label@TITLE:
Width: PARENT_RIGHT
Y: 0 - 20
Text: Game Information
Align: Center
Font: BigBold
Contrast: true
Label@TITLE_NO_TABS:
Width: PARENT_RIGHT
Y: 15
Text: Game Information
Align: Center
Font: BigBold
Contrast: true
Container@TAB_CONTAINER:
Children:
Button@BUTTON1:
Y: 5
Width: 140
Height: 35
Visible: False
Button@BUTTON2:
X: 150
Y: 5
Width: 140
Height: 35
Visible: False
Button@BUTTON3:
X: 300
Y: 5
Width: 140
Height: 35
Visible: False
Background@BACKGROUND:
Y: 39
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Background: panel-black
Children:
Container@STATS_PANEL:
Container@MAP_PANEL:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Container@OBJECTIVES_PANEL:
Container@DEBUG_PANEL:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM

View File

@@ -0,0 +1,32 @@
Container@MAP_PANEL:
Height: PARENT_BOTTOM
Width: PARENT_RIGHT
Logic: GameInfoBriefingLogic
Children:
Background@PREVIEW_BG:
X: (PARENT_RIGHT - WIDTH) / 2
Y: 15
Width: 324
Height: 160
Background: panel-gray
Children:
MapPreview@MAP_PREVIEW:
Width: 320
Height: 156
X: 2
Y: 2
IgnoreMouseOver: True
IgnoreMouseInput: True
ShowSpawnPoints: False
ScrollPanel@MAP_DESCRIPTION_PANEL:
X: 15
Y: 190
Width: 482
Height: 170
Children:
Label@MAP_DESCRIPTION:
X: 5
Y: 195
Width: 452
Height: 160

View File

@@ -0,0 +1,40 @@
Container@MISSION_OBJECTIVES:
Height: PARENT_BOTTOM
Width: PARENT_RIGHT
Logic: GameInfoObjectivesLogic
Children:
Label@MISSION:
X: 15
Y: 15
Width: 80
Height: 20
Font: MediumBold
Text: Mission:
Label@MISSION_STATUS:
X: 95
Y: 15
Width: PARENT_RIGHT - 110
Height: 20
Font: MediumBold
ScrollPanel@OBJECTIVES_PANEL:
X: 15
Y: 50
Width: 482
Height: 310
ItemSpacing: 35
Children:
Container@OBJECTIVE_TEMPLATE:
Children:
Label@OBJECTIVE_TYPE:
X: 10
Y: 0 - 20
Height: 20
Width: 70
Align: Center
Checkbox@OBJECTIVE_STATUS:
X: 90
Y: 0 - 20
Width: PARENT_RIGHT - 100
Height: 20
Disabled: True
TextColorDisabled: 255,255,255

View File

@@ -0,0 +1,108 @@
Container@SKIRMISH_STATS:
Height: PARENT_BOTTOM
Width: PARENT_RIGHT
Logic: GameInfoStatsLogic
Children:
Label@STATS_OBJECTIVE:
X: 15
Y: 10
Width: 85
Height: 25
Font: MediumBold
Text: Mission:
Label@STATS_STATUS:
X: 100
Y: 10
Width: PARENT_RIGHT - 10
Height: 25
Font: MediumBold
Checkbox@STATS_CHECKBOX:
X: 15
Y: 45
Width: 482
Height: 20
Font: Bold
Text: Destroy all opposition!
Disabled: yes
TextColorDisabled: 255,255,255
Container@STATS_HEADERS:
X: 17
Y: 80
Width: 393
Children:
Label@NAME:
X: 10
Width: 150
Height: 25
Text: Player
Font: Bold
Label@RACE:
X: 150
Width: 80
Height: 25
Text: Faction
Font: Bold
Align: Center
Label@STANCE:
X: 240
Width: 70
Height: 25
Text: Team
Font: Bold
Align: Center
Label@KILLS:
X: 310
Width: 70
Height: 25
Text: Kills
Font: Bold
Align: Center
Label@DEATHS:
X: 380
Width: 70
Height: 25
Text: Deaths
Font: Bold
Align: Center
ScrollPanel@PLAYER_LIST:
X: 15
Y: 105
Width: 482
Height: 250
ItemSpacing: 5
Children:
Container@PLAYER_TEMPLATE:
Width: PARENT_RIGHT-27
Height: 25
X: 2
Y: 0
Children:
Label@NAME:
X: 10
Width: 150
Height: 25
Image@FACTIONFLAG:
X: 159
Y: 6
Width: 32
Height: 16
Label@FACTION:
X: 195
Width: 40
Height: 25
Label@TEAM:
X: 240
Width: 70
Height: 25
Align: Center
Label@KILLS:
X: 310
Width: 70
Height: 25
Align: Center
Label@DEATHS:
X: 380
Width: 70
Height: 25
Align: Center

View File

@@ -0,0 +1,98 @@
Container@LEAVE_RESTART_WIDGET:
Logic: LeaveMapLogic
Children:
Image@EVA:
X: WINDOW_RIGHT-128-43
Y: 43
Width: 128
Height: 64
ImageCollection: logos
ImageName: eva
Label@VERSION_LABEL:
X: WINDOW_RIGHT-128-43
Y: 115
Width: 128
Align: Center
Contrast: true
Background@BORDER:
Width: WINDOW_RIGHT
Height: WINDOW_BOTTOM
Background: shellmapborder
Container@LEAVE_RESTART_SIMPLE
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 370
Height: 125
Visible: False
Children:
Background@LEAVE_RESTART_SIMPLE_BG:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM - 35
Background: panel-black
Children:
Label@GAME_ENDED_LABEL:
X: 0
Y: 0 - 25
Width: PARENT_RIGHT
Font: BigBold
Align: Center
Text: The game has ended
Contrast: True
Label@BLURB:
X: 15
Y: (PARENT_BOTTOM - HEIGHT) / 2
Width: PARENT_RIGHT - 30
Text: Press 'Leave' to return to the main menu.
Align: Center
Button@LEAVE_BUTTON:
X: 0
Y: PARENT_BOTTOM - 1
Width: 140
Height: 35
Font: Bold
Text: Leave
Button@RESTART_BUTTON:
X: 150
Y: PARENT_BOTTOM - 1
Width: 140
Height: 35
Font: Bold
Text: Restart
Visible: false
Container@LEAVE_RESTART_FULL:
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 512
Height: 410
Visible: False
Children:
Background@LEAVE_RESTART_BG:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM - 35
Background: panel-black
Children:
Label@GAME_ENDED_LABEL:
X: 0
Y: 0 - 25
Width: PARENT_RIGHT
Font: BigBold
Align: Center
Text: The game has ended
Contrast: True
Button@LEAVE_BUTTON:
X: 0
Y: PARENT_BOTTOM - 1
Width: 140
Height: 35
Font: Bold
Text: Leave
Button@RESTART_BUTTON:
X: 150
Y: PARENT_BOTTOM - 1
Width: 140
Height: 35
Font: Bold
Text: Restart
Visible: false
Container@OBJECTIVES:

View File

@@ -1,27 +1,7 @@
Container@INGAME_MENU_PANEL:
X: (WINDOW_RIGHT - WIDTH)/2
Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 512
Height: 370
Children:
Button@OBJECTIVES_BUTTON:
Y: PARENT_BOTTOM - 1
Width: 140
Height: 35
Text: Objectives
Visible: false
Button@DEBUG_BUTTON:
X: 150
Y: PARENT_BOTTOM - 1
Width: 140
Height: 35
Text: Debug
Visible: false
Container@INGAME_MENU:
Width: WINDOW_RIGHT
Height: WINDOW_BOTTOM
Logic: CncIngameMenuLogic
Logic: IngameMenuLogic
Children:
Image@EVA:
X: WINDOW_RIGHT-128-43
@@ -46,31 +26,31 @@ Container@INGAME_MENU:
Width: 740
Height: 35
Children:
Button@QUIT_BUTTON:
Button@ABORT_MISSION:
X: 0
Y: 0
Width: 140
Height: 35
Text: Abort Mission
Button@SURRENDER_BUTTON:
Button@SURRENDER:
X: 150
Y: 0
Width: 140
Height: 35
Text: Surrender
Button@MUSIC_BUTTON:
Button@MUSIC:
X: 300
Y: 0
Width: 140
Height: 35
Text: Music
Button@SETTINGS_BUTTON:
Button@SETTINGS:
X: 450
Y: 0
Width: 140
Height: 35
Text: Settings
Button@RESUME_BUTTON:
Button@RESUME:
Key: escape
X: 600
Y: 0

View File

@@ -1,120 +0,0 @@
Container@CONQUEST_OBJECTIVES:
Logic: CncConquestObjectivesLogic
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
Label@TITLE:
Width: PARENT_RIGHT
Y: 0-25
Font: BigBold
Contrast: true
Align: Center
Background@bg:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Background: panel-black
Children:
Label@PRIMARY:
X: 15
Y: 10
Width: 482
Height: 25
Font: MediumBold
Text: Primary Objectives:
Label@STATUS:
X: 190
Y: 10
Width: 482
Height: 25
Font: MediumBold
Text: Incomplete
Checkbox@1:
X: 25
Y: 45
Width: 482
Height: 20
Font: Bold
Text: Crush all opposition!
Disabled: yes
Container@LABEL_CONTAINER:
X: 17
Y: 80
Width: 393
Children:
Label@NAME:
X: 10
Width: 150
Height: 25
Text: Player
Align: Center
Font: Bold
Label@RACE:
X: 150
Width: 80
Height: 25
Text: Faction
Font: Bold
Align: Center
Label@STANCE:
X: 240
Width: 70
Height: 25
Text: Team
Font: Bold
Align: Center
Label@KILLS:
X: 310
Width: 70
Height: 25
Text: Kills
Font: Bold
Align: Center
Label@DEATHS:
X: 380
Width: 70
Height: 25
Text: Deaths
Font: Bold
Align: Center
ScrollPanel@PLAYER_LIST:
X: 15
Y: 105
Width: 482
Height: 250
ItemSpacing: 5
Children:
Container@PLAYER_TEMPLATE:
Width: PARENT_RIGHT-27
Height: 25
X: 2
Y: 0
Children:
Label@NAME:
X: 10
Width: 150
Height: 25
Image@FACTIONFLAG:
X: 159
Y: 6
Width: 32
Height: 16
Label@FACTION:
X: 195
Width: 40
Height: 25
Label@TEAM:
X: 240
Width: 70
Height: 25
Align: Center
Label@KILLS:
X: 310
Width: 70
Height: 25
Align: Center
Label@DEATHS:
X: 380
Width: 70
Height: 25
Align: Center

View File

@@ -2,58 +2,76 @@ 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)
Utils.Do(NodPatrol, function(type)
local soldier = Actor.Create(type, true, { Location = nod0.Location, Owner = enemy })
soldier.Move(nod1.Location)
soldier.AttackMove(nod2.Location)
soldier.Move(nod3.Location)
soldier.Hunt()
end)
end
SetGunboatPath = function()
Actor.AttackMove(Gunboat, gunboatLeft.Location)
Actor.AttackMove(Gunboat, gunboatRight.Location)
SetGunboatPath = function(gunboat)
gunboat.AttackMove(gunboatLeft.Location)
gunboat.AttackMove(gunboatRight.Location)
end
ReinforceFromSea = function(passengers)
local hovercraft, troops = Reinforcements.Insert(player, "oldlst", passengers, { lstStart.Location, lstEnd.Location }, { lstStart.Location })
Media.PlaySpeechNotification("Reinforce")
local transport = Actor.Create("oldlst", true, { Location = lstStart.Location, Owner = player })
Utils.Do(passengers, function(actorType)
local passenger = Actor.Create(actorType, false, { Owner = player })
transport.LoadPassenger(passenger)
end)
transport.Move(lstEnd.Location)
transport.UnloadPassengers()
transport.Wait(50)
transport.Move(lstStart.Location)
transport.Destroy()
Media.PlaySpeechNotification(player, "Reinforce")
end
WorldLoaded = function()
player = OpenRA.GetPlayer("GDI")
enemy = OpenRA.GetPlayer("Nod")
Media.PlayMovieFullscreen("gdi1.vqa", function() Media.PlayMovieFullscreen("landing.vqa") end)
player = Player.GetPlayer("GDI")
enemy = Player.GetPlayer("Nod")
gdiObjective = player.AddPrimaryObjective("Destroy all Nod forces in the area!")
Trigger.OnPlayerWon(player, function()
Media.PlaySpeechNotification(player, "Win")
Trigger.AfterDelay(25, function()
Media.PlayMovieFullscreen("consyard.vqa")
end)
end)
Trigger.OnPlayerLost(player, function()
Media.PlaySpeechNotification(player, "Lose")
Trigger.AfterDelay(25, function()
Media.PlayMovieFullscreen("gameover.vqa")
end)
end)
Trigger.OnIdle(Gunboat, function() SetGunboatPath(Gunboat) 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)
Trigger.AfterDelay(25 * 5, function() ReinforceFromSea(InfantryReinforcements) end)
Trigger.AfterDelay(25 * 15, function() ReinforceFromSea(InfantryReinforcements) end)
Trigger.AfterDelay(25 * 30, function() ReinforceFromSea(VehicleReinforcements) end)
Trigger.AfterDelay(25 * 60, function() ReinforceFromSea(VehicleReinforcements) end)
end
Tick = function()
if Actor.IsIdle(Gunboat) then
SetGunboatPath()
if enemy.HasNoRequiredUnits() then
player.MarkCompletedObjective(gdiObjective)
end
if Mission.RequiredUnitsAreDestroyed(player) then
MissionFailed()
if player.HasNoRequiredUnits() then
player.MarkFailedObjective(gdiObjective)
end
if Mission.RequiredUnitsAreDestroyed(enemy) then
MissionAccomplished()
end
end
end

View File

@@ -457,10 +457,14 @@ Rules:
PlayMusicOnMapLoad:
Music: aoi
Loop: false
LuaScriptInterface:
LuaScripts: gdi01.lua
LuaScript:
Scripts: gdi01.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
^Infantry:
MustBeDestroyed:
PROC:

View File

@@ -5,12 +5,12 @@ VehicleReinforcements = { "jeep" }
AttackerSquadSize = 3
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
Media.PlayMovieFullscreen("flag.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("gameover.vqa")
end

View File

@@ -736,8 +736,12 @@ Rules:
-CrateSpawner:
LuaScriptInterface:
LuaScripts: gdi02.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
PROC:
Buildable:
Prerequisites: ~disabled

View File

@@ -1,10 +1,10 @@
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
Media.PlayMovieFullscreen("bombaway.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("gameover.vqa")
end

View File

@@ -897,8 +897,12 @@ Rules:
-CrateSpawner:
LuaScriptInterface:
LuaScripts: gdi03.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
^Infantry:
MustBeDestroyed:
WEAP:

View File

@@ -127,11 +127,11 @@ WorldLoaded = function()
end
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
Media.PlayMovieFullscreen("burdet1.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("gameover.vqa")
end

View File

@@ -546,8 +546,12 @@ Rules:
-CrateSpawner:
LuaScriptInterface:
LuaScripts: gdi04a.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
^Infantry:
MustBeDestroyed:
^Vehicle:

View File

@@ -162,11 +162,11 @@ WorldLoaded = function()
end
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
Media.PlayMovieFullscreen("burdet1.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("gameover.vqa")
end

View File

@@ -625,8 +625,12 @@ Rules:
-CrateSpawner:
LuaScriptInterface:
LuaScripts: gdi04b.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
^Infantry:
MustBeDestroyed:
^Vehicle:

View File

@@ -109,11 +109,11 @@ WorldLoaded = function()
end
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
Media.PlayMovieFullscreen("burdet1.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("gameover.vqa")
end

View File

@@ -895,8 +895,12 @@ Rules:
-CrateSpawner:
LuaScriptInterface:
LuaScripts: gdi04c.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
^Infantry:
MustBeDestroyed:
^Vehicle:

View File

@@ -299,12 +299,16 @@ Smudges:
Rules:
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
World:
-CrateSpawner:
-SpawnMPUnits:
-MPStartLocations:
LuaScriptInterface:
LuaScripts: nod01.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
C10:
Tooltip:
Name: Nikoomba

View File

@@ -2,11 +2,11 @@ RifleInfantryReinforcements = { "e1", "e1", }
RocketInfantryReinforcements = { "e3", "e3", "e3" }
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("nodlose.vqa")
end

View File

@@ -565,12 +565,16 @@ Smudges:
Rules:
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
World:
-CrateSpawner:
-SpawnMPUnits:
-MPStartLocations:
LuaScriptInterface:
LuaScripts: nod03a.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
NUK2:
Buildable:
Prerequisites: ~disabled

View File

@@ -2,12 +2,12 @@ FirstAttackWave = { "e1", "e1", "e1", "e2", }
SecondThirdAttackWave = { "e1", "e1", "e2", }
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
Media.PlayMovieFullscreen("desflees.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("flag.vqa")
end

View File

@@ -634,12 +634,16 @@ Smudges:
Rules:
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
World:
-CrateSpawner:
-SpawnMPUnits:
-MPStartLocations:
LuaScriptInterface:
LuaScripts: nod03b.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
NUK2:
Buildable:
Prerequisites: ~disabled

View File

@@ -3,12 +3,12 @@ SecondAttackWave = { "e1", "e1", "e1", }
ThirdAttackWave = { "e1", "e1", "e1", "e2", }
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
Media.PlayMovieFullscreen("desflees.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("flag.vqa")
end

View File

@@ -88,13 +88,17 @@ ChromeLayout:
mods/cnc/chrome/replaybrowser.yaml
mods/cnc/chrome/ingame.yaml
mods/cnc/chrome/ingame-chat.yaml
mods/cnc/chrome/ingame-debug.yaml
mods/cnc/chrome/ingame-menu.yaml
mods/cnc/chrome/ingame-debug.yaml
mods/cnc/chrome/ingame-info.yaml
mods/cnc/chrome/ingame-infobriefing.yaml
mods/cnc/chrome/ingame-infoobjectives.yaml
mods/cnc/chrome/ingame-infostats.yaml
mods/cnc/chrome/ingame-leavemap.yaml
mods/cnc/chrome/music.yaml
mods/cnc/chrome/settings.yaml
mods/cnc/chrome/credits.yaml
mods/cnc/chrome/dialogs.yaml
mods/cnc/chrome/objectives.yaml
mods/cnc/chrome/tooltips.yaml
mods/cnc/chrome/irc.yaml
mods/cnc/chrome/assetbrowser.yaml

View File

@@ -2,6 +2,8 @@ Player:
PlaceBuilding:
TechTree:
SupportPowerManager:
ScriptTriggers:
MissionObjectives:
ConquestVictoryConditions:
PowerManager:
AllyRepair:

View File

@@ -8,6 +8,7 @@ World:
LoadWidgetAtGameStart:
Widget: INGAME_ROOT
MenuPaletteEffect:
MenuEffect: Desaturated
CloakPaletteEffect:
ScreenShaker:
NukePaletteEffect:
@@ -185,7 +186,7 @@ World:
PathFinder:
ValidateOrder:
DebugPauseState:
ConquestObjectivesPanel:
ObjectivesPanel: CONQUEST_OBJECTIVES
ObjectivesPanel:
PanelName: SKIRMISH_STATS
RadarPings:

View File

@@ -521,7 +521,10 @@ checkbox: dialog.png
corner-br: 767,127,1,1
checkbox-bits: buttons.png
checked: 0,140,16,16
checked: 0,157,16,16
checked-disabled: 0,173,16,16
crossed: 16,157,16,16
crossed-disabled: 16,173,16,16
checkbox-hover: dialog.png
background: 641,129,126,126

View File

@@ -0,0 +1,92 @@
Container@LEAVE_RESTART_WIDGET:
Logic: LeaveMapLogic
Children:
Background@BORDER:
X: 0 - 15
Y: 0 - 15
Width: WINDOW_RIGHT + 30
Height: WINDOW_BOTTOM + 30
Background: mainmenu-border
Label@VERSION_LABEL:
X: WINDOW_RIGHT - 10
Y: WINDOW_BOTTOM - 20
Align: Right
Font: Regular
Contrast: True
Container@LEAVE_RESTART_SIMPLE
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 370
Height: 175
Visible: False
Children:
Background@LEAVE_RESTART_SIMPLE_BG:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
Label@GAME_ENDED_LABEL:
Y: 20
Width: PARENT_RIGHT
Height: 25
Font: Bold
Align: Center
Text: The game has ended
Label@BLURB:
X: 15
Y: 50
Width: PARENT_RIGHT - 30
Height: 65
Text: Press 'Leave' to return to the main menu.
Align: Center
Button@RESTART_BUTTON:
X: 20
Y: PARENT_BOTTOM - 45
Width: 140
Height: 25
Font: Bold
Text: Restart
Visible: false
Button@LEAVE_BUTTON:
X: (PARENT_RIGHT - WIDTH) / 2
Y: PARENT_BOTTOM - 45
Width: 140
Height: 25
Font: Bold
Text: Leave
Container@LEAVE_RESTART_FULL:
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 522
Height: 470
Visible: False
Children:
Background@LEAVE_RESTART_BG:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
Label@GAME_ENDED_LABEL:
X: 20
Y: 20
Width: PARENT_RIGHT - 40
Height: 25
Font: Bold
Align: Center
Text: The game has ended
Button@RESTART_BUTTON:
X: PARENT_RIGHT - 2 * (WIDTH + 20)
Y: PARENT_BOTTOM - 45
Width: 120
Height: 25
Font: Bold
Text: Restart
Visible: false
Button@LEAVE_BUTTON:
X: PARENT_RIGHT - WIDTH - 20
Y: PARENT_BOTTOM - 45
Width: 120
Height: 25
Font: Bold
Text: Leave
Container@OBJECTIVES:
Y: 40

View File

@@ -0,0 +1,61 @@
Container@INGAME_MENU:
Width: WINDOW_RIGHT
Height: WINDOW_BOTTOM
Logic: IngameMenuLogic
Children:
Label@VERSION_LABEL:
X: WINDOW_RIGHT - 10
Y: WINDOW_BOTTOM - 20
Align: Right
Font: Regular
Contrast: True
Background@MENU_BUTTONS:
X: 100
Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 200
Height: 295
Children:
Label@LABEL_TITLE:
X: (PARENT_RIGHT - WIDTH)/2
Y: 20
Width: 200
Height: 30
Text: Options
Align: Center
Font: Bold
Button@RESUME:
X: (PARENT_RIGHT - WIDTH)/2
Y: 60
Width: 140
Height: 30
Text: Resume
Font: Bold
Key: escape
Button@SETTINGS:
X: (PARENT_RIGHT - WIDTH)/2
Y: 100
Width: 140
Height: 30
Text: Settings
Font: Bold
Button@MUSIC:
X: (PARENT_RIGHT - WIDTH)/2
Y: 140
Width: 140
Height: 30
Text: Music
Font: Bold
Button@SURRENDER:
X: (PARENT_RIGHT - WIDTH)/2
Y: 180
Width: 140
Height: 30
Text: Surrender
Font: Bold
Button@ABORT_MISSION:
X: (PARENT_RIGHT - WIDTH)/2
Y: 220
Width: 140
Height: 30
Text: Abort Mission
Font: Bold

View File

@@ -1,6 +1,10 @@
Container@OBSERVER_WIDGETS:
Children:
Button@OBSERVER_STATS_BUTTON:
MenuButton@OBSERVER_STATS_BUTTON:
Logic: OrderButtonsChromeLogic
MenuContainer: INGAME_OBSERVERSTATS_BG
HideIngameUI: False
Pause: False
X: 162
Y: 0
Width: 160

View File

@@ -3,7 +3,10 @@ Container@PLAYER_WIDGETS:
LogicKeyListener@CONTROLGROUP_KEYHANDLER:
Logic: ControlGroupLogic
LogicTicker@SIDEBAR_TICKER:
Button@INGAME_DIPLOMACY_BUTTON:
MenuButton@DIPLOMACY_BUTTON:
Logic: OrderButtonsChromeLogic
MenuContainer: INGAME_DIPLOMACY_BG
HideIngameUI: False
X: 162
Y: 0
Width: 160
@@ -11,24 +14,16 @@ Container@PLAYER_WIDGETS:
Text: Diplomacy (P)
Font: Bold
Key: p
Button@INGAME_DEBUG_BUTTON:
MenuButton@DEBUG_BUTTON:
Logic: OrderButtonsChromeLogic
MenuContainer: INGAME_MENU
X: 324
Y: 0
Width: 160
Height: 25
Text: Debug (Shift + Esc)
Visible: false
Font: Bold
Key: escape Shift
Button@OBJECTIVES_BUTTON:
X: 486
Y: 0
Width: 160
Height: 25
Text: Objectives (O)
Visible: false
Font: Bold
Key: o
SlidingContainer@INGAME_RADAR_BIN:
X: WINDOW_RIGHT-215
Y: 0

View File

@@ -46,7 +46,8 @@ Container@INGAME_ROOT:
Y: 34
Order: Descending
Container@PLAYER_ROOT:
Button@INGAME_OPTIONS_BUTTON:
MenuButton@OPTIONS_BUTTON:
Logic: OrderButtonsChromeLogic
X: 0
Y: 0
Width: 160

View File

@@ -61,11 +61,16 @@ ChromeLayout:
mods/ra/chrome/ingame-chat.yaml
mods/ra/chrome/ingame-diplomacy.yaml
mods/ra/chrome/ingame-fmvplayer.yaml
mods/ra/chrome/ingame-menu.yaml
mods/d2k/chrome/ingame-menu.yaml
mods/ra/chrome/ingame-info.yaml
mods/ra/chrome/ingame-infobriefing.yaml
mods/ra/chrome/ingame-infoobjectives.yaml
mods/ra/chrome/ingame-infostats.yaml
mods/d2k/chrome/ingame-observer.yaml
mods/ra/chrome/ingame-observerstats.yaml
mods/d2k/chrome/ingame-player.yaml
mods/ra/chrome/ingame-debug.yaml
mods/d2k/chrome/ingame-leavemap.yaml
mods/d2k/chrome/mainmenu.yaml
mods/ra/chrome/settings.yaml
mods/ra/chrome/credits.yaml
@@ -152,6 +157,9 @@ Fonts:
Title:
Font:mods/d2k/Dune2k.ttf
Size:32
MediumBold:
Font:FreeSansBold.ttf
Size:18
BigBold:
Font:FreeSansBold.ttf
Size:24

View File

@@ -34,6 +34,8 @@ Player:
BlockedAudio: NoRoom
PlaceBuilding:
SupportPowerManager:
ScriptTriggers:
MissionObjectives:
ConquestVictoryConditions:
PowerManager:
AdviceInterval: 650

View File

@@ -189,4 +189,6 @@ World:
ValidateOrder:
DebugPauseState:
RadarPings:
ObjectivesPanel:
PanelName: SKIRMISH_STATS

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -427,7 +427,10 @@ checkbox: dialog.png
corner-br: 767,127,1,1
checkbox-bits: buttons.png
checked: 0,140,16,16
checked: 0,157,16,16
checked-disabled: 0,173,16,16
crossed: 16,157,16,16
crossed-disabled: 16,173,16,16
checkbox-hover: dialog.png
background: 641,129,126,126

View File

@@ -1,110 +1,117 @@
Background@INGAME_DEBUG_BG:
Container@DEBUG_PANEL:
Logic: DebugMenuLogic
X: (WINDOW_RIGHT - WIDTH)/2
Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 350
Height: 475
Y: 20
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
Label@LABEL_TITLE:
X: (PARENT_RIGHT - WIDTH)/2
Y: 20
Width: 250
Height: 25
Label@LABLE_TITLE:
Y: 25
Font: Bold
Text: Debug Options
Align: Center
Font: Bold
Checkbox@DISABLE_SHROUD:
X: 30
Y: 50
Height: 20
Width: PARENT_RIGHT - 30
Text: Disable Shroud & Fog
Button@GIVE_EXPLORATION:
X: 30
Y: 80
Width: 120
Height: 25
Text: Give Exploration
Button@RESET_EXPLORATION:
X: 200
Y: 80
Width: 120
Height: 25
Text: Reset Exploration
Checkbox@SHOW_UNIT_PATHS:
X: 30
Y: 110
Width: PARENT_RIGHT - 30
Height: 20
Text: Show Unit Paths
Button@GIVE_CASH:
X: 30
Y: 140
Width: 135
Height: 20
Text: Give $20000 Cash
Height: 25
Button@GROW_RESOURCES:
X: 185
Y: 140
Width: 135
Height: 20
Text: Grow Resources
Height: 25
Width: PARENT_RIGHT
Checkbox@INSTANT_BUILD:
X: 30
Y: 170
Width: PARENT_RIGHT - 30
X: 45
Y: 45
Width: 200
Height: 20
Font: Regular
Text: Instant Build Speed
Checkbox@INSTANT_CHARGE:
X: 30
Y: 200
Width: PARENT_RIGHT - 30
Height: 20
Text: Support Powers Charge Instantly
Checkbox@ENABLE_TECH:
X: 30
Y: 230
Width: PARENT_RIGHT - 30
X: 45
Y: 75
Width: 200
Height: 20
Font: Regular
Text: Build Everything
Checkbox@UNLIMITED_POWER:
X: 30
Y: 260
Width: PARENT_RIGHT - 30
Height: 20
Text: Unlimited Power
Checkbox@BUILD_ANYWHERE:
X: 30
Y: 290
Width: PARENT_RIGHT - 30
X: 45
Y: 105
Width: 200
Height: 20
Font: Regular
Text: Build Anywhere
Checkbox@SHOW_ASTAR:
X: 30
Y: 320
Width: PARENT_RIGHT - 30
Checkbox@UNLIMITED_POWER:
X: 290
Y: 45
Width: 200
Height: 20
Font: Regular
Text: Unlimited Power
Checkbox@INSTANT_CHARGE:
X: 290
Y: 75
Width: 200
Height: 20
Font: Regular
Text: Instant Charge Time
Checkbox@DISABLE_SHROUD:
X: 290
Y: 105
Height: 20
Width: 200
Font: Regular
Text: Disable Shroud & Fog
Button@GIVE_CASH:
X: 90
Y: 150
Width: 140
Height: 30
Font: Bold
Text: Give $20,000
Button@GROW_RESOURCES:
X: 271
Y: 150
Width: 140
Height: 30
Font: Bold
Text: Grow Resources
Button@GIVE_EXPLORATION:
X: 90
Y: 200
Width: 140
Height: 30
Font: Bold
Text: Clear Shroud
Button@RESET_EXPLORATION:
X: 271
Y: 200
Width: 140
Height: 30
Font: Bold
Text: Reset Shroud
Label@VISUALIZATIONS_TITLE:
Y: 255
Font: Bold
Text: Visualizations
Align: Center
Width: PARENT_RIGHT
Checkbox@SHOW_UNIT_PATHS:
X: 45
Y: 285
Width: 200
Height: 20
Font: Regular
Text: Show Unit Paths
Checkbox@SHOW_ASTAR:
X: 45
Y: 315
Height: 20
Width: 200
Font: Regular
Text: Show A* Cost
Checkbox@SHOW_COMBATOVERLAY:
X: 30
Y: 350
X: 290
Y: 285
Height: 20
Width: 200
Font: Regular
Text: Show Combat Geometry
Checkbox@SHOW_GEOMETRY:
X: 30
Y: 380
X: 290
Y: 315
Height: 20
Width: 200
Font: Regular
Text: Show Render Geometry
Button@CLOSE:
X: 30
Y: 420
Width: PARENT_RIGHT - 60
Height: 25
Text: Close
Key: escape
Font: Bold

View File

@@ -0,0 +1,64 @@
Container@GAME_INFO_PANEL:
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 522
Height: 455
Logic: GameInfoLogic
Visible: False
Children:
Background@BACKGROUND:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Background@BACKGROUND_NO_TABS:
Y: 25
Width: PARENT_RIGHT
Height: PARENT_BOTTOM - 25
Label@TITLE:
Y: 20
Width: PARENT_RIGHT
Height: 25
Align: Center
Font: Bold
Label@TITLE_NO_TABS:
Y: 45
Width: PARENT_RIGHT
Height: 25
Align: Center
Font: Bold
Container@TAB_CONTAINER:
X: (PARENT_RIGHT - WIDTH) / 2
Width: 360
Height: 25
Children:
Button@BUTTON1:
Y: 50
Width: 120
Height: 25
Font: Bold
Visible: False
Button@BUTTON2:
X: 120
Y: 50
Width: 120
Height: 25
Font: Bold
Visible: False
Button@BUTTON3:
X: 240
Y: 50
Width: 120
Height: 25
Font: Bold
Visible: False
Container@STATS_PANEL:
Y: 65
Container@MAP_PANEL:
Y: 65
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Container@OBJECTIVES_PANEL:
Y: 65
Container@DEBUG_PANEL:
Y: 65
Width: PARENT_RIGHT
Height: PARENT_BOTTOM

View File

@@ -0,0 +1,32 @@
Container@MAP_PANEL:
Height: PARENT_BOTTOM
Width: PARENT_RIGHT
Logic: GameInfoBriefingLogic
Children:
Background@PREVIEW_BG:
X: (PARENT_RIGHT - WIDTH) / 2
Y: 20
Width: 324
Height: 160
Background: panel-gray
Children:
MapPreview@MAP_PREVIEW:
Width: 320
Height: 156
X: 2
Y: 2
IgnoreMouseOver: True
IgnoreMouseInput: True
ShowSpawnPoints: False
ScrollPanel@MAP_DESCRIPTION_PANEL:
X: 20
Y: 195
Width: 482
Height: 175
Children:
Label@MAP_DESCRIPTION:
X: 5
Y: 180
Width: 452
Height: 145

View File

@@ -0,0 +1,40 @@
Container@MISSION_OBJECTIVES:
Height: PARENT_BOTTOM
Width: PARENT_RIGHT
Logic: GameInfoObjectivesLogic
Children:
Label@MISSION:
X: 20
Y: 20
Width: 80
Height: 25
Font: MediumBold
Text: Mission:
Label@MISSION_STATUS:
X: 100
Y: 20
Width: PARENT_RIGHT - 120
Height: 25
Font: MediumBold
ScrollPanel@OBJECTIVES_PANEL:
X: 20
Y: 60
Width: 482
Height: 310
ItemSpacing: 35
Children:
Container@OBJECTIVE_TEMPLATE:
Children:
Label@OBJECTIVE_TYPE:
X: 10
Y: 0 - 20
Height: 20
Width: 70
Align: Center
Checkbox@OBJECTIVE_STATUS:
X: 90
Y: 0 - 20
Width: PARENT_RIGHT - 100
Height: 20
Disabled: True
TextColorDisabled: 255,255,255

View File

@@ -0,0 +1,108 @@
Container@SKIRMISH_STATS:
Height: PARENT_BOTTOM
Width: PARENT_RIGHT
Logic: GameInfoStatsLogic
Children:
Label@MISSION:
X: 20
Y: 20
Width: 482
Height: 25
Font: MediumBold
Text: Mission:
Label@STATS_STATUS:
X: 100
Y: 20
Width: PARENT_RIGHT - 10
Height: 25
Font: MediumBold
Checkbox@STATS_CHECKBOX:
X: 20
Y: 55
Width: 482
Height: 20
Font: Bold
Text: Destroy all opposition!
Disabled: yes
TextColorDisabled: 255,255,255
Container@STATS_HEADERS:
X: 22
Y: 80
Width: 393
Children:
Label@NAME:
X: 10
Width: 150
Height: 25
Text: Player
Font: Bold
Label@RACE:
X: 150
Width: 80
Height: 25
Text: Faction
Font: Bold
Align: Center
Label@STANCE:
X: 240
Width: 70
Height: 25
Text: Team
Font: Bold
Align: Center
Label@KILLS:
X: 310
Width: 70
Height: 25
Text: Kills
Font: Bold
Align: Center
Label@DEATHS:
X: 380
Width: 70
Height: 25
Text: Deaths
Font: Bold
Align: Center
ScrollPanel@PLAYER_LIST:
X: 20
Y: 105
Width: 482
Height: 265
ItemSpacing: 5
Children:
Container@PLAYER_TEMPLATE:
Width: PARENT_RIGHT-27
Height: 25
X: 2
Y: 0
Children:
Label@NAME:
X: 10
Width: 150
Height: 25
Image@FACTIONFLAG:
X: 159
Y: 6
Width: 32
Height: 16
Label@FACTION:
X: 195
Width: 40
Height: 25
Label@TEAM:
X: 240
Width: 70
Height: 25
Align: Center
Label@KILLS:
X: 310
Width: 70
Height: 25
Align: Center
Label@DEATHS:
X: 380
Width: 70
Height: 25
Align: Center

View File

@@ -0,0 +1,99 @@
Container@LEAVE_RESTART_WIDGET:
Logic: LeaveMapLogic
Children:
Background@BORDER:
X: 0 - 15
Y: 0 - 15
Width: WINDOW_RIGHT + 30
Height: WINDOW_BOTTOM + 30
Background: mainmenu-border
Image@LOGO:
X: WINDOW_RIGHT - 296
Y: 30
ImageCollection: logos
ImageName: logo
Label@VERSION_LABEL:
X: WINDOW_RIGHT - 296
Y: 296 - 20
Width: 296 - 20
Height: 25
Align: Center
Font: Regular
Contrast: True
Container@LEAVE_RESTART_SIMPLE
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 370
Height: 175
Visible: False
Children:
Background@LEAVE_RESTART_SIMPLE_BG:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
Label@GAME_ENDED_LABEL:
Y: 20
Width: PARENT_RIGHT
Height: 25
Font: Bold
Align: Center
Text: The game has ended
Label@BLURB:
X: 15
Y: 50
Width: PARENT_RIGHT - 30
Height: 65
Text: Press 'Leave' to return to the main menu.
Align: Center
Button@RESTART_BUTTON:
X: 20
Y: PARENT_BOTTOM - 45
Width: 140
Height: 25
Font: Bold
Text: Restart
Visible: false
Button@LEAVE_BUTTON:
X: (PARENT_RIGHT - WIDTH) / 2
Y: PARENT_BOTTOM - 45
Width: 140
Height: 25
Font: Bold
Text: Leave
Container@LEAVE_RESTART_FULL:
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 522
Height: 470
Visible: False
Children:
Background@LEAVE_RESTART_BG:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
Label@GAME_ENDED_LABEL:
X: 20
Y: 20
Width: PARENT_RIGHT - 40
Height: 25
Font: Bold
Align: Center
Text: The game has ended
Button@RESTART_BUTTON:
X: PARENT_RIGHT - 2 * (WIDTH + 20)
Y: PARENT_BOTTOM - 45
Width: 120
Height: 25
Font: Bold
Text: Restart
Visible: false
Button@LEAVE_BUTTON:
X: PARENT_RIGHT - WIDTH - 20
Y: PARENT_BOTTOM - 45
Width: 120
Height: 25
Font: Bold
Text: Leave
Container@OBJECTIVES:
Y: 40

View File

@@ -1,52 +1,74 @@
Background@INGAME_OPTIONS_BG:
X: (WINDOW_RIGHT - WIDTH)/2
Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 300
Height: 295
Container@INGAME_MENU:
Width: WINDOW_RIGHT
Height: WINDOW_BOTTOM
Logic: IngameMenuLogic
Children:
Label@LABEL_TITLE:
X: (PARENT_RIGHT - WIDTH)/2
Y: 20
Width: 250
Background@BORDER:
X: 0 - 15
Y: 0 - 15
Width: WINDOW_RIGHT + 30
Height: WINDOW_BOTTOM + 30
Background: mainmenu-border
Image@LOGO:
X: WINDOW_RIGHT - 296
Y: 30
ImageCollection: logos
ImageName: logo
Label@VERSION_LABEL:
X: WINDOW_RIGHT - 296
Y: 296 - 20
Width: 296 - 20
Height: 25
Text: Options
Align: Center
Font: Bold
Button@RESUME:
X: (PARENT_RIGHT - WIDTH)/2
Y: 60
Width: 160
Height: 25
Text: Resume
Font: Bold
Key: escape
Button@SETTINGS:
X: (PARENT_RIGHT - WIDTH)/2
Y: 100
Width: 160
Height: 25
Text: Settings
Font: Bold
Button@MUSIC:
X: (PARENT_RIGHT - WIDTH)/2
Y: 140
Width: 160
Height: 25
Text: Music
Font: Bold
Button@SURRENDER:
X: (PARENT_RIGHT - WIDTH)/2
Y: 180
Width: 160
Height: 25
Text: Surrender
Font: Bold
Button@DISCONNECT:
X: (PARENT_RIGHT - WIDTH)/2
Y: 220
Width: 160
Height: 25
Text: Abort Mission
Font: Bold
Font: Regular
Contrast: True
Background@MENU_BUTTONS:
X: 100
Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 200
Height: 295
Children:
Label@LABEL_TITLE:
X: (PARENT_RIGHT - WIDTH)/2
Y: 20
Width: 200
Height: 30
Text: Options
Align: Center
Font: Bold
Button@RESUME:
X: (PARENT_RIGHT - WIDTH)/2
Y: 60
Width: 140
Height: 30
Text: Resume
Font: Bold
Key: escape
Button@SETTINGS:
X: (PARENT_RIGHT - WIDTH)/2
Y: 100
Width: 140
Height: 30
Text: Settings
Font: Bold
Button@MUSIC:
X: (PARENT_RIGHT - WIDTH)/2
Y: 140
Width: 140
Height: 30
Text: Music
Font: Bold
Button@SURRENDER:
X: (PARENT_RIGHT - WIDTH)/2
Y: 180
Width: 140
Height: 30
Text: Surrender
Font: Bold
Button@ABORT_MISSION:
X: (PARENT_RIGHT - WIDTH)/2
Y: 220
Width: 140
Height: 30
Text: Abort Mission
Font: Bold

View File

@@ -1,98 +0,0 @@
Background@MISSION_OBJECTIVES:
Logic: MissionObjectivesLogic
X: 25
Y: 50
Width: 512
Height: 530
Visible: false
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: 20
Children:
Container@PRIMARY_OBJECTIVE_TEMPLATE:
X: 15
Y: 0
Width: PARENT_RIGHT
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: 20
Children:
Container@SECONDARY_OBJECTIVE_TEMPLATE:
X: 15
Y: 0
Width: PARENT_RIGHT
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

View File

@@ -21,8 +21,8 @@ Container@OBSERVER_WIDGETS:
Font: Bold
Contrast: true
MenuButton@OPTIONS_BUTTON:
MenuContainer: INGAME_OPTIONS_BG
HideIngameUI: false
MenuContainer: INGAME_MENU
HideIngameUI: true
Pause: false
X: 0
Y: 0

View File

@@ -3,15 +3,6 @@ Container@PLAYER_WIDGETS:
LogicKeyListener@CONTROLGROUP_KEYHANDLER:
Logic: ControlGroupLogic
LogicTicker@SIDEBAR_TICKER:
Button@OBJECTIVES_BUTTON:
X: 486
Y: 0
Width: 160
Height: 25
Text: Objectives (O)
Visible: false
Font: Bold
Key: o
Container@SUPPORT_POWERS:
Logic: SupportPowerBinLogic
X: 10
@@ -106,9 +97,6 @@ Container@PLAYER_WIDGETS:
ImageCollection: order-icons
MenuButton@DEBUG_BUTTON:
Logic: AddRaceSuffixLogic
MenuContainer: INGAME_DEBUG_BG
HideIngameUI: false
Pause: false
Key: escape Shift
X: 128
Width: 28
@@ -144,8 +132,6 @@ Container@PLAYER_WIDGETS:
ImageName: diplomacy
MenuButton@OPTIONS_BUTTON:
Logic: AddRaceSuffixLogic
MenuContainer: INGAME_OPTIONS_BG
HideIngameUI: false
Key: escape
X: 192
Width: 28

View File

@@ -105,12 +105,12 @@ CreateEinstein = function()
end
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
--Media.PlayMovieFullscreen("snowbomb.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("bmap.vqa")
end

View File

@@ -574,12 +574,16 @@ Smudges:
Rules:
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
World:
-CrateSpawner:
-SpawnMPUnits:
-MPStartLocations:
LuaScriptInterface:
LuaScripts: allies01.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
TRAN.Extraction:
Inherits: TRAN
RenderUnit:

View File

@@ -23,12 +23,12 @@ RunInitialActivities = function()
end
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
Media.PlayMovieFullscreen("montpass.vqa")
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
Media.PlayMovieFullscreen("frozen.vqa")
end

View File

@@ -869,12 +869,16 @@ Smudges:
Rules:
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
World:
-CrateSpawner:
-SpawnMPUnits:
-MPStartLocations:
LuaScriptInterface:
LuaScripts: allies02.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
^Infantry:
MustBeDestroyed:
^Tank:

View File

@@ -2214,12 +2214,16 @@ Smudges:
Rules:
Player:
-ConquestVictoryConditions:
MissionObjectives:
EarlyGameOver: true
World:
-CrateSpawner:
-SpawnMPUnits:
-MPStartLocations:
LuaScriptInterface:
LuaScripts: mission.lua
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
CAMERA:
RevealsShroud:
Range: 18c0

View File

@@ -264,9 +264,9 @@ WorldLoaded = function()
end
MissionFailed = function()
Mission.MissionOver(nil, { player }, false)
Mission.MissionOver(nil, { player }, true)
end
MissionAccomplished = function()
Mission.MissionOver({ player }, nil, false)
Mission.MissionOver({ player }, nil, true)
end

View File

@@ -2113,11 +2113,15 @@ Rules:
-Selectable:
-TargetableBuilding:
Player:
-ConquestVictoryConditions:
StrategicVictoryConditions:
TicksToHold: 4500
ResetOnHoldLost: true
RatioRequired: 1
CriticalRatioRequired: 1
World:
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
Sequences:

View File

@@ -264,11 +264,15 @@ Rules:
-Selectable:
-TargetableBuilding:
Player:
-ConquestVictoryConditions:
StrategicVictoryConditions:
TicksToHold: 3000
ResetOnHoldLost: true
RatioRequired: 1
CriticalRatioRequired: 1
World:
ObjectivesPanel:
PanelName: MISSION_OBJECTIVES
Sequences:

View File

@@ -74,8 +74,12 @@ ChromeLayout:
mods/ra/chrome/ingame-chat.yaml
mods/ra/chrome/ingame-diplomacy.yaml
mods/ra/chrome/ingame-fmvplayer.yaml
mods/ra/chrome/ingame-info.yaml
mods/ra/chrome/ingame-infobriefing.yaml
mods/ra/chrome/ingame-infoobjectives.yaml
mods/ra/chrome/ingame-infostats.yaml
mods/ra/chrome/ingame-leavemap.yaml
mods/ra/chrome/ingame-menu.yaml
mods/ra/chrome/ingame-objectives.yaml
mods/ra/chrome/ingame-observer.yaml
mods/ra/chrome/ingame-observerstats.yaml
mods/ra/chrome/ingame-player.yaml
@@ -169,6 +173,9 @@ Fonts:
Title:
Font:mods/ra/ZoodRangmah.ttf
Size:48
MediumBold:
Font:FreeSansBold.ttf
Size:18
BigBold:
Font:FreeSansBold.ttf
Size:24

View File

@@ -42,6 +42,8 @@ Player:
RequireOwner: false
PlaceBuilding:
SupportPowerManager:
ScriptTriggers:
MissionObjectives:
ConquestVictoryConditions:
PowerManager:
AllyRepair:

View File

@@ -174,4 +174,6 @@ World:
DebugPauseState:
RadarPings:
StartGameNotification:
ObjectivesPanel:
PanelName: SKIRMISH_STATS

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -465,7 +465,10 @@ checkbox: dialog.png
corner-br: 767,127,1,1
checkbox-bits: buttons.png
checked: 0,140,16,16
checked: 0,157,16,16
checked-disabled: 0,173,16,16
crossed: 16,157,16,16
crossed-disabled: 16,173,16,16
checkbox-hover: dialog.png
background: 641,129,126,126

View File

@@ -3,7 +3,10 @@ Container@PLAYER_WIDGETS:
LogicKeyListener@CONTROLGROUP_KEYHANDLER:
Logic: ControlGroupLogic
LogicTicker@SIDEBAR_TICKER:
Button@INGAME_DIPLOMACY_BUTTON:
MenuButton@DIPLOMACY_BUTTON:
Logic: OrderButtonsChromeLogic
MenuContainer: INGAME_DIPLOMACY_BG
HideIngameUI: False
X: 162
Y: 0
Width: 160
@@ -11,7 +14,9 @@ Container@PLAYER_WIDGETS:
Text: Diplomacy (P)
Font: Bold
Key: p
Button@INGAME_DEBUG_BUTTON:
MenuButton@DEBUG_BUTTON:
Logic: OrderButtonsChromeLogic
MenuContainer: INGAME_MENU
X: 324
Y: 0
Width: 160
@@ -20,15 +25,6 @@ Container@PLAYER_WIDGETS:
Visible: false
Font: Bold
Key: escape Shift
Button@OBJECTIVES_BUTTON:
X: 486
Y: 0
Width: 160
Height: 25
Text: Objectives (O)
Visible: false
Font: Bold
Key: o
SlidingContainer@INGAME_RADAR_BIN:
X: WINDOW_RIGHT-215
Y: 0

View File

@@ -46,7 +46,9 @@ Container@INGAME_ROOT:
Y: 34
Order: Descending
Container@PLAYER_ROOT:
Button@INGAME_OPTIONS_BUTTON:
MenuButton@OPTIONS_BUTTON:
Logic: OrderButtonsChromeLogic
MenuContainer: INGAME_MENU
X: 0
Y: 0
Width: 160

View File

@@ -104,11 +104,15 @@ ChromeLayout:
mods/ra/chrome/ingame-diplomacy.yaml
mods/ra/chrome/ingame-fmvplayer.yaml
mods/ra/chrome/ingame-menu.yaml
mods/ra/chrome/ingame-objectives.yaml
mods/ra/chrome/ingame-info.yaml
mods/ra/chrome/ingame-infobriefing.yaml
mods/ra/chrome/ingame-infoobjectives.yaml
mods/ra/chrome/ingame-infostats.yaml
mods/ra/chrome/ingame-observer.yaml
mods/ra/chrome/ingame-observerstats.yaml
mods/ts/chrome/ingame-player.yaml
mods/ra/chrome/ingame-debug.yaml
mods/ra/chrome/ingame-leavemap.yaml
mods/ra/chrome/mainmenu.yaml
mods/ra/chrome/settings.yaml
mods/ra/chrome/credits.yaml

View File

@@ -26,6 +26,8 @@ Player:
LowPowerSlowdown: 3
PlaceBuilding:
SupportPowerManager:
ScriptTriggers:
MissionObjectives:
ConquestVictoryConditions:
PowerManager:
AllyRepair:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB