Core: Added basic support for Spectators
TODO: Someone modify the files for cnc (chrome / rules)
This commit is contained in:
@@ -56,7 +56,7 @@ namespace OpenRA.Network
|
||||
public string Bot; // trait name of the bot to initialize in this slot, or null otherwise.
|
||||
public bool Closed; // host has explicitly closed this slot.
|
||||
public string MapPlayer; // playerReference to bind against.
|
||||
|
||||
public bool Spectator = false; // Spectating or not
|
||||
// todo: more stuff?
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace OpenRA
|
||||
PlayerName = client.Name;
|
||||
InternalName = pr.Name;
|
||||
Country = world.GetCountries()
|
||||
.FirstOrDefault(c => client != null && client.Country == c.Race)
|
||||
.FirstOrDefault(c => client != null && client.Country == c.Race )
|
||||
?? world.GetCountries().Random(world.SharedRandom);
|
||||
|
||||
ClientIndex = client.Index;
|
||||
|
||||
@@ -40,6 +40,9 @@ namespace OpenRA.Server
|
||||
|
||||
const int MasterPingInterval = 60 * 3; // 3 minutes. server has a 5 minute TTL for games, so give ourselves a bit
|
||||
// of leeway.
|
||||
|
||||
public static int MaxSpectators = 4; // How many spectators to allow // @todo Expose this as an option
|
||||
|
||||
static int lastPing = 0;
|
||||
static bool isInternetServer;
|
||||
static string masterServerUrl;
|
||||
@@ -135,6 +138,12 @@ namespace OpenRA.Server
|
||||
.Where(s => s != null)
|
||||
.Select((s, i) => { s.Index = i; return s; })
|
||||
.ToList();
|
||||
|
||||
// Generate slots for spectators
|
||||
for (int i = 0; i < MaxSpectators; i++)
|
||||
{
|
||||
lobbyInfo.Slots.Add(new Session.Slot { Spectator = true, Index = lobbyInfo.Slots.Count(), MapPlayer = null, Bot = null});
|
||||
}
|
||||
}
|
||||
|
||||
/* lobby rework todo:
|
||||
@@ -283,6 +292,8 @@ namespace OpenRA.Server
|
||||
|
||||
static void SyncClientToPlayerReference(Session.Client c, PlayerReference pr)
|
||||
{
|
||||
if (pr == null)
|
||||
return;
|
||||
if (pr.LockColor)
|
||||
{
|
||||
c.Color1 = pr.Color;
|
||||
@@ -358,6 +369,13 @@ namespace OpenRA.Server
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "spectator",
|
||||
s =>
|
||||
{
|
||||
// GetClient(conn).Slot = -1; /* observer */
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "team",
|
||||
s =>
|
||||
{
|
||||
@@ -411,7 +429,7 @@ namespace OpenRA.Server
|
||||
var cl = GetClient(conn);
|
||||
cl.Slot = slot;
|
||||
|
||||
SyncClientToPlayerReference(cl, Map.Players[slotData.MapPlayer]);
|
||||
SyncClientToPlayerReference(cl, slotData.MapPlayer != null ? Map.Players[slotData.MapPlayer] : null);
|
||||
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace OpenRA.Traits
|
||||
|
||||
void DrawUnitPath(Actor self)
|
||||
{
|
||||
if (!self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
|
||||
if (self.World.LocalPlayer == null ||!self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
|
||||
|
||||
var activity = self.GetCurrentActivity();
|
||||
var mobile = self.TraitOrDefault<IMove>();
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace OpenRA.Widgets.Delegates
|
||||
{
|
||||
public class LobbyDelegate : IWidgetDelegate
|
||||
{
|
||||
Widget Players, LocalPlayerTemplate, RemotePlayerTemplate, EmptySlotTemplate, EmptySlotTemplateHost;
|
||||
Widget Players, LocalPlayerTemplate, RemotePlayerTemplate, EmptySlotTemplate, EmptySlotTemplateHost, EmptySpectatorSlotTemplateHost;
|
||||
|
||||
Dictionary<string, string> CountryNames;
|
||||
string MapUid;
|
||||
@@ -44,6 +44,7 @@ namespace OpenRA.Widgets.Delegates
|
||||
RemotePlayerTemplate = Players.GetWidget("TEMPLATE_REMOTE");
|
||||
EmptySlotTemplate = Players.GetWidget("TEMPLATE_EMPTY");
|
||||
EmptySlotTemplateHost = Players.GetWidget("TEMPLATE_EMPTY_HOST");
|
||||
EmptySpectatorSlotTemplateHost = Players.GetWidget("TEMPLATE_EMPTY_SPECTATOR");
|
||||
|
||||
var mapPreview = lobby.GetWidget<MapPreviewWidget>("LOBBY_MAP_PREVIEW");
|
||||
mapPreview.Map = () => Map;
|
||||
@@ -71,6 +72,7 @@ namespace OpenRA.Widgets.Delegates
|
||||
};
|
||||
|
||||
CountryNames = Rules.Info["world"].Traits.WithInterface<OpenRA.Traits.CountryInfo>().ToDictionary(a => a.Race, a => a.Name);
|
||||
|
||||
CountryNames.Add("random", "Random");
|
||||
|
||||
var mapButton = lobby.GetWidget("CHANGEMAP_BUTTON");
|
||||
@@ -231,10 +233,32 @@ namespace OpenRA.Widgets.Delegates
|
||||
if (c == null)
|
||||
{
|
||||
if (Game.IsHost)
|
||||
{
|
||||
if (slot.Spectator)
|
||||
{
|
||||
template = EmptySlotTemplateHost.Clone();
|
||||
var btn = template.GetWidget<ButtonWidget>("JOIN");
|
||||
var name = template.GetWidget<ButtonWidget>("NAME");
|
||||
btn.GetText = () => "Spectate in this slot";
|
||||
name.GetText = () => s.Closed ? "Closed" : "Open";
|
||||
name.OnMouseUp = _ =>
|
||||
{
|
||||
if (s.Closed)
|
||||
{
|
||||
orderManager.IssueOrder(Order.Command("slot_open " + s.Index));
|
||||
}
|
||||
else
|
||||
{
|
||||
orderManager.IssueOrder(Order.Command("slot_close " + s.Index));
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
template = EmptySlotTemplateHost.Clone();
|
||||
var name = template.GetWidget<ButtonWidget>("NAME");
|
||||
name.GetText = () => s.Closed ? "Closed" : (s.Bot == null)? "Open" : "Bot: " + s.Bot;
|
||||
name.GetText = () => s.Closed ? "Closed" : (s.Bot == null) ? "Open" : "Bot: " + s.Bot;
|
||||
name.OnMouseUp = _ =>
|
||||
{
|
||||
if (s.Closed)
|
||||
@@ -252,6 +276,7 @@ namespace OpenRA.Widgets.Delegates
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
template = EmptySlotTemplate.Clone();
|
||||
@@ -330,6 +355,14 @@ namespace OpenRA.Widgets.Delegates
|
||||
var status = template.GetWidget<CheckboxWidget>("STATUS");
|
||||
status.Checked = () => c.State == Session.ClientState.Ready;
|
||||
status.OnMouseDown = CycleReady;
|
||||
|
||||
Session.Slot slot1 = slot;
|
||||
color.IsVisible = () => !slot1.Spectator;
|
||||
colorBlock.IsVisible = () => !slot1.Spectator;
|
||||
faction.IsVisible = () => !slot1.Spectator;
|
||||
factionname.IsVisible = () => !slot1.Spectator;
|
||||
factionflag.IsVisible = () => !slot1.Spectator;
|
||||
team.IsVisible = () => !slot1.Spectator;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace OpenRA
|
||||
|
||||
public void AddPlayer(Player p) { players[p.Index] = p; }
|
||||
|
||||
int localPlayerIndex;
|
||||
int localPlayerIndex = -999;
|
||||
public Player LocalPlayer
|
||||
{
|
||||
get { return players.ContainsKey(localPlayerIndex) ? players[localPlayerIndex] : null; }
|
||||
|
||||
@@ -103,6 +103,7 @@ namespace OpenRA
|
||||
|
||||
public static bool IsVisible(this Actor a, Player byPlayer) /* must never be relied on in synced code! */
|
||||
{
|
||||
if (byPlayer == null) return true; // Observer
|
||||
if (a.World.LocalPlayer != null && a.World.LocalPlayer.Shroud.Disabled)
|
||||
return true;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA
|
||||
// create the players which are bound through slots.
|
||||
foreach (var slot in w.LobbyInfo.Slots)
|
||||
{
|
||||
var client = w.LobbyInfo.Clients.FirstOrDefault(c => c.Slot == slot.Index);
|
||||
var client = w.LobbyInfo.Clients.FirstOrDefault(c => c.Slot == slot.Index && slot.MapPlayer != null);
|
||||
if (client != null)
|
||||
{
|
||||
/* spawn a real player in this slot. */
|
||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA
|
||||
if (client.Index == Game.LocalClientId)
|
||||
w.SetLocalPlayer(player.Index); // bind this one to the local player.
|
||||
}
|
||||
else if (slot.Bot != null)
|
||||
else if (slot.Bot != null && slot.MapPlayer != null)
|
||||
{
|
||||
/* spawn a bot in this slot, "owned" by the host */
|
||||
|
||||
@@ -80,6 +80,14 @@ namespace OpenRA.Mods.RA
|
||||
static Stance ChooseInitialStance(Player p, Player q)
|
||||
{
|
||||
if (p == q) return Stance.Ally;
|
||||
var pc = GetClientForPlayer(p);
|
||||
var qc = GetClientForPlayer(q);
|
||||
|
||||
if (p.World.LobbyInfo.Slots.Count > 0)
|
||||
{
|
||||
if (p.World.LobbyInfo.Slots[pc.Slot].Spectator) return Stance.Ally;
|
||||
if (p.World.LobbyInfo.Slots[qc.Slot].Spectator) return Stance.Ally;
|
||||
}
|
||||
|
||||
if (p.PlayerRef.Allies.Contains(q.InternalName))
|
||||
return Stance.Ally;
|
||||
@@ -92,8 +100,6 @@ namespace OpenRA.Mods.RA
|
||||
if (p.IsBot ^ q.IsBot)
|
||||
return Stance.Enemy; // bots and humans hate each other
|
||||
|
||||
var pc = GetClientForPlayer(p);
|
||||
var qc = GetClientForPlayer(q);
|
||||
|
||||
return pc.Team != 0 && pc.Team == qc.Team
|
||||
? Stance.Ally : Stance.Enemy;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
using XRandom = OpenRA.Thirdparty.Random;
|
||||
using OpenRA.FileFormats;
|
||||
@@ -232,6 +233,10 @@ namespace OpenRA.Mods.RA
|
||||
return !hackyAI.enabled;
|
||||
}
|
||||
|
||||
bool HasHumanPlayers()
|
||||
{
|
||||
return p.World.players.Any(a => !a.Value.IsBot && !a.Value.NonCombatant);
|
||||
}
|
||||
int2? ChooseEnemyTarget()
|
||||
{
|
||||
// Criteria for picking an enemy:
|
||||
@@ -240,7 +245,7 @@ namespace OpenRA.Mods.RA
|
||||
// 3. not dead.
|
||||
|
||||
var possibleTargets = world.WorldActor.Trait<MPStartLocations>().Start
|
||||
.Where(kv => kv.Key != p && IsHumanPlayer(kv.Key)
|
||||
.Where(kv => kv.Key != p && (!HasHumanPlayers()|| IsHumanPlayer(kv.Key))
|
||||
&& p.WinState == WinState.Undefined)
|
||||
.Select(kv => kv.Value);
|
||||
|
||||
|
||||
@@ -28,13 +28,15 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public void WorldLoaded(World world)
|
||||
{
|
||||
var taken = world.LobbyInfo.Clients.Where(c => c.SpawnPoint != 0)
|
||||
var taken = world.LobbyInfo.Clients.Where(c => c.SpawnPoint != 0 && c.Slot != -1)
|
||||
.Select(c => world.Map.SpawnPoints.ElementAt(c.SpawnPoint - 1)).ToList();
|
||||
var available = world.Map.SpawnPoints.Except(taken).ToList();
|
||||
|
||||
// Set spawn
|
||||
foreach (var slot in world.LobbyInfo.Slots)
|
||||
{
|
||||
if (slot.Spectator)
|
||||
continue; // Skip spectator slots
|
||||
var client = world.LobbyInfo.Clients.FirstOrDefault(c => c.Slot == slot.Index);
|
||||
var player = FindPlayerInSlot(world, slot);
|
||||
|
||||
@@ -49,7 +51,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
// Explore allied shroud
|
||||
foreach (var p in Start)
|
||||
if (p.Key == world.LocalPlayer || p.Key.Stances[world.LocalPlayer] == Stance.Ally)
|
||||
if ((world.LocalPlayer != null ) &&(p.Key == world.LocalPlayer || p.Key.Stances[world.LocalPlayer] == Stance.Ally))
|
||||
world.WorldActor.Trait<Shroud>().Explore(world, p.Value,
|
||||
world.WorldActor.Info.Traits.Get<MPStartLocationsInfo>().InitialExploreRange);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{4A8A43B5-A9EF-4ED0-99DD-4BAB10A0DB6E}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
@@ -230,6 +230,7 @@
|
||||
<Compile Include="WaterPaletteRotation.cs" />
|
||||
<Compile Include="Weapon.cs" />
|
||||
<Compile Include="Widgets\BuildPaletteWidget.cs" />
|
||||
<Compile Include="Widgets\Delegates\IngameObserverChromeDelegate.cs" />
|
||||
<Compile Include="Widgets\Delegates\IngameChromeDelegate.cs" />
|
||||
<Compile Include="Widgets\MoneyBinWidget.cs" />
|
||||
<Compile Include="Widgets\OrderButtonWidget.cs" />
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace OpenRA.Mods.RA
|
||||
public class OpenWidgetAtGameStartInfo : ITraitInfo
|
||||
{
|
||||
public readonly string Widget = "INGAME_ROOT";
|
||||
public readonly string ObserverWidget = "";
|
||||
|
||||
public object Create(ActorInitializer init) { return new OpenWidgetAtGameStart(this); }
|
||||
}
|
||||
@@ -29,9 +30,10 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public void WorldLoaded(World world)
|
||||
{
|
||||
// Todo: custom observer ui?
|
||||
if (world.LocalPlayer != null)
|
||||
world.OpenWindow(Info.Widget);
|
||||
else if (Info.ObserverWidget != null)
|
||||
world.OpenWindow(Info.ObserverWidget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA
|
||||
void SpawnUnitsForPlayer(Player p, int2 sp)
|
||||
{
|
||||
if (!p.PlayerRef.DefaultStartingUnits)
|
||||
return; /* they don't want an mcv, the map provides something else for them. */
|
||||
return; /* they don't want an mcv, the map provides something else for them OR it is a spectator. */
|
||||
|
||||
p.World.CreateActor("mcv", new TypeDictionary
|
||||
{
|
||||
|
||||
@@ -71,6 +71,8 @@ Player:
|
||||
|
||||
World:
|
||||
OpenWidgetAtGameStart:
|
||||
Widget: INGAME_ROOT
|
||||
# ObserverWidget:
|
||||
ScreenShaker:
|
||||
NukePaletteEffect:
|
||||
WaterPaletteRotation:
|
||||
|
||||
@@ -193,6 +193,7 @@
|
||||
<image name="allies" x="30" y="84" width="30" height="15" />
|
||||
<image name="soviet" x="0" y="84" width="30" height="15" />
|
||||
<image name="random" x="60" y="84" width="30" height="15" />
|
||||
<image name="spectator" x="60" y="84" width="30" height="15" />
|
||||
</collection>
|
||||
<collection name="music" src="musicplayer.png">
|
||||
<image name="pause" x="0" y="0" width="25" height="25" />
|
||||
|
||||
@@ -29,18 +29,25 @@ Background@SERVER_LOBBY:
|
||||
Y:4
|
||||
Width:244
|
||||
Height:244
|
||||
Container@PLAYERS:
|
||||
Id:PLAYERS
|
||||
ListBox@PLAYERSX:
|
||||
Id:PLAYERSX
|
||||
X:20
|
||||
Y:75
|
||||
Width:500
|
||||
Height:200
|
||||
Height:227
|
||||
Children:
|
||||
Container@PLAYERS:
|
||||
Id:PLAYERS
|
||||
X:2
|
||||
Y:1
|
||||
Width:500
|
||||
Height:2270
|
||||
Children:
|
||||
Container@TEMPLATE_LOCAL:
|
||||
Id:TEMPLATE_LOCAL
|
||||
X:0
|
||||
Y:0
|
||||
Width:500
|
||||
Width:400
|
||||
Height:30
|
||||
Visible:false
|
||||
Children:
|
||||
@@ -94,7 +101,7 @@ Background@SERVER_LOBBY:
|
||||
Y:0
|
||||
Checkbox@STATUS:
|
||||
Id:STATUS
|
||||
X:455
|
||||
X:450
|
||||
Y:2
|
||||
Width:20
|
||||
Height:20
|
||||
@@ -102,7 +109,7 @@ Background@SERVER_LOBBY:
|
||||
Id:TEMPLATE_REMOTE
|
||||
X:0
|
||||
Y:0
|
||||
Width:500
|
||||
Width:400
|
||||
Height:30
|
||||
Visible:false
|
||||
Children:
|
||||
@@ -154,11 +161,33 @@ Background@SERVER_LOBBY:
|
||||
Y:2
|
||||
Width:20
|
||||
Height:20
|
||||
Container@TEMPLATE_EMPTY_SPECTATOR:
|
||||
Id:TEMPLATE_EMPTY_SPECTATOR
|
||||
X:0
|
||||
Y:0
|
||||
Width:400
|
||||
Height:30
|
||||
Visible:false
|
||||
Children:
|
||||
Button@NAME:
|
||||
Id:NAME
|
||||
Text:Name
|
||||
Width:139
|
||||
Height:25
|
||||
X:0
|
||||
Y:0
|
||||
Button@JOIN:
|
||||
Id:JOIN
|
||||
Text:Spectate this match
|
||||
Width:PARENT_RIGHT - 90
|
||||
Height:25
|
||||
X:160
|
||||
Y:0
|
||||
Container@TEMPLATE_EMPTY:
|
||||
Id:TEMPLATE_EMPTY
|
||||
X:0
|
||||
Y:0
|
||||
Width:500
|
||||
Width:400
|
||||
Height:30
|
||||
Visible:false
|
||||
Children:
|
||||
@@ -172,7 +201,7 @@ Background@SERVER_LOBBY:
|
||||
Button@JOIN:
|
||||
Id:JOIN
|
||||
Text:Play in this slot
|
||||
Width:PARENT_RIGHT - 160
|
||||
Width:PARENT_RIGHT - 90
|
||||
Height:25
|
||||
X:160
|
||||
Y:0
|
||||
@@ -180,7 +209,7 @@ Background@SERVER_LOBBY:
|
||||
Id:TEMPLATE_EMPTY_HOST
|
||||
X:0
|
||||
Y:0
|
||||
Width:500
|
||||
Width:400
|
||||
Height:30
|
||||
Visible:false
|
||||
Children:
|
||||
@@ -194,7 +223,7 @@ Background@SERVER_LOBBY:
|
||||
Button@JOIN:
|
||||
Id:JOIN
|
||||
Text:Play in this slot
|
||||
Width:PARENT_RIGHT - 160
|
||||
Width:PARENT_RIGHT - 90
|
||||
Height:25
|
||||
X:160
|
||||
Y:0
|
||||
@@ -240,7 +269,7 @@ Background@SERVER_LOBBY:
|
||||
Bold:True
|
||||
Label@LABEL_LOBBY_STATUS:
|
||||
Id:LABEL_LOBBY_STATUS
|
||||
X:432
|
||||
X:420
|
||||
Y:0
|
||||
Width:70
|
||||
Height:25
|
||||
|
||||
@@ -284,3 +284,133 @@ Container@INGAME_ROOT:
|
||||
Width:200
|
||||
Height:20
|
||||
Text: Give Exploration
|
||||
Container@OBSERVER_ROOT:
|
||||
Id:OBSERVER_ROOT
|
||||
Visible:true
|
||||
Delegate:IngameObserverChromeDelegate
|
||||
Children:
|
||||
WorldInteractionController:
|
||||
X:0
|
||||
Y:0
|
||||
Width:WINDOW_RIGHT
|
||||
Height:WINDOW_BOTTOM
|
||||
ViewportScrollController:
|
||||
X:0
|
||||
Y:0
|
||||
Width:WINDOW_RIGHT
|
||||
Height:WINDOW_BOTTOM
|
||||
Timer@GAME_TIMER:
|
||||
Id:GAME_TIMER
|
||||
X: WINDOW_RIGHT/2
|
||||
Y: 10
|
||||
Background@POSTGAME_BG:
|
||||
Id:POSTGAME_BG
|
||||
X:(WINDOW_RIGHT - WIDTH)/2
|
||||
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
||||
Width:400
|
||||
Height:100
|
||||
Background:dialog4
|
||||
Visible:false
|
||||
Children:
|
||||
Label@TEXT:
|
||||
Id:TEXT
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:(PARENT_BOTTOM - HEIGHT)/2
|
||||
Width:200
|
||||
Height:40
|
||||
Align:Center
|
||||
Bold:True
|
||||
SpecialPowerBin@INGAME_POWERS_BIN:
|
||||
Id:INGAME_POWERS_BIN
|
||||
X:0
|
||||
Y:25
|
||||
Button@INGAME_OPTIONS_BUTTON:
|
||||
Id:INGAME_OPTIONS_BUTTON
|
||||
X:0
|
||||
Y:0
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Options
|
||||
Bold:True
|
||||
WorldTooltip:
|
||||
Background@INGAME_OPTIONS_BG:
|
||||
Id:INGAME_OPTIONS_BG
|
||||
X:(WINDOW_RIGHT - WIDTH)/2
|
||||
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
||||
Width:300
|
||||
Height:320
|
||||
Visible:false
|
||||
Children:
|
||||
Label@LABEL_TITLE:
|
||||
Id:LABEL_TITLE
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:20
|
||||
Width:250
|
||||
Height:25
|
||||
Text:Options
|
||||
Align:Center
|
||||
Bold:True
|
||||
Button@RESUME:
|
||||
Id:RESUME
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:60
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Resume
|
||||
Bold:True
|
||||
Button@SETTINGS:
|
||||
Id:SETTINGS
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:100
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Settings
|
||||
Bold:True
|
||||
Button@MUSIC:
|
||||
Id:MUSIC
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:140
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Music
|
||||
Bold:True
|
||||
Button@SURRENDER:
|
||||
Id:SURRENDER
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:180
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Surrender
|
||||
Bold:True
|
||||
Button@DISCONNECT:
|
||||
Id:DISCONNECT
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:220
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Disconnect
|
||||
Bold:True
|
||||
Button@QUIT:
|
||||
Id:QUIT
|
||||
X:(PARENT_RIGHT - WIDTH)/2
|
||||
Y:260
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Quit
|
||||
Bold:True
|
||||
ChatDisplay@CHAT_DISPLAY:
|
||||
Id:CHAT_DISPLAY
|
||||
X:250
|
||||
Y:WINDOW_BOTTOM - HEIGHT - 30
|
||||
Width: 760
|
||||
Height: 200
|
||||
ClickThrough: True
|
||||
DrawBackground: False
|
||||
RemoveTime:250
|
||||
ChatEntry@CHAT_ENTRY:
|
||||
Id:CHAT_ENTRY
|
||||
X:250
|
||||
Y:WINDOW_BOTTOM - HEIGHT
|
||||
Width: 760
|
||||
Height: 30
|
||||
ClickThrough: True
|
||||
|
||||
@@ -127,6 +127,8 @@ Player:
|
||||
|
||||
World:
|
||||
OpenWidgetAtGameStart:
|
||||
Widget: INGAME_ROOT
|
||||
ObserverWidget: OBSERVER_ROOT
|
||||
ScreenShaker:
|
||||
WaterPaletteRotation:
|
||||
ChronoshiftPaletteEffect:
|
||||
|
||||
Reference in New Issue
Block a user