Arcade polish (#2333)

Co-authored-by: Pieter-Jan Briers <pieterjan.briers@gmail.com>
This commit is contained in:
Paul Ritter
2020-10-30 11:25:26 +01:00
committed by GitHub
parent e9df8794da
commit d8f5bffaa0
7 changed files with 266 additions and 139 deletions

View File

@@ -1,7 +1,9 @@
using Content.Client.GameObjects.Components.Arcade; using System.Linq;
using Content.Client.GameObjects.Components.Arcade;
using Content.Shared.GameObjects.Components.Arcade; using Content.Shared.GameObjects.Components.Arcade;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Localization;
using Vector2 = Robust.Shared.Maths.Vector2; using Vector2 = Robust.Shared.Maths.Vector2;
namespace Content.Client.Arcade namespace Content.Client.Arcade
@@ -16,17 +18,17 @@ namespace Content.Client.Arcade
private Label _enemyInfoLabel; private Label _enemyInfoLabel;
private Label _playerActionLabel; private Label _playerActionLabel;
private Label _enemyActionLabel; private Label _enemyActionLabel;
private Button[] _gameButtons = new Button[3]; //used to disable/enable all game buttons
public SpaceVillainArcadeMenu(SpaceVillainArcadeBoundUserInterface owner) public SpaceVillainArcadeMenu(SpaceVillainArcadeBoundUserInterface owner)
{ {
Title = "Space Villain"; Title = Loc.GetString("Space Villain");
Owner = owner; Owner = owner;
GridContainer grid = new GridContainer(); var grid = new GridContainer {Columns = 1};
grid.Columns = 1;
GridContainer infoGrid = new GridContainer(); var infoGrid = new GridContainer {Columns = 3};
infoGrid.Columns = 3; infoGrid.AddChild(new Label{ Text = Loc.GetString("Player"), Align = Label.AlignMode.Center });
infoGrid.AddChild(new Label{ Text = "Player", Align = Label.AlignMode.Center });
infoGrid.AddChild(new Label{ Text = "|", Align = Label.AlignMode.Center }); infoGrid.AddChild(new Label{ Text = "|", Align = Label.AlignMode.Center });
_enemyNameLabel = new Label{ Align = Label.AlignMode.Center}; _enemyNameLabel = new Label{ Align = Label.AlignMode.Center};
infoGrid.AddChild(_enemyNameLabel); infoGrid.AddChild(_enemyNameLabel);
@@ -36,38 +38,35 @@ namespace Content.Client.Arcade
infoGrid.AddChild(new Label{ Text = "|", Align = Label.AlignMode.Center }); infoGrid.AddChild(new Label{ Text = "|", Align = Label.AlignMode.Center });
_enemyInfoLabel = new Label {Align = Label.AlignMode.Center}; _enemyInfoLabel = new Label {Align = Label.AlignMode.Center};
infoGrid.AddChild(_enemyInfoLabel); infoGrid.AddChild(_enemyInfoLabel);
CenterContainer centerContainer = new CenterContainer(); var centerContainer = new CenterContainer();
centerContainer.AddChild(infoGrid); centerContainer.AddChild(infoGrid);
grid.AddChild(centerContainer); grid.AddChild(centerContainer);
_playerActionLabel = new Label(); _playerActionLabel = new Label {Align = Label.AlignMode.Center};
_playerActionLabel.Align = Label.AlignMode.Center;
grid.AddChild(_playerActionLabel); grid.AddChild(_playerActionLabel);
_enemyActionLabel = new Label(); _enemyActionLabel = new Label {Align = Label.AlignMode.Center};
_enemyActionLabel.Align = Label.AlignMode.Center;
grid.AddChild(_enemyActionLabel); grid.AddChild(_enemyActionLabel);
GridContainer buttonGrid = new GridContainer(); var buttonGrid = new GridContainer {Columns = 3};
buttonGrid.Columns = 3; _gameButtons[0] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Attack)
Button attack = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Attack); {Text = Loc.GetString("ATTACK")};
attack.Text = "ATTACK"; buttonGrid.AddChild(_gameButtons[0]);
buttonGrid.AddChild(attack);
Button heal = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Heal); _gameButtons[1] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Heal)
heal.Text = "HEAL"; {Text = Loc.GetString("HEAL")};
buttonGrid.AddChild(heal); buttonGrid.AddChild(_gameButtons[1]);
Button recharge = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Recharge); _gameButtons[2] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Recharge)
recharge.Text = "RECHARGE"; {Text = Loc.GetString("RECHARGE")};
buttonGrid.AddChild(recharge); buttonGrid.AddChild(_gameButtons[2]);
centerContainer = new CenterContainer(); centerContainer = new CenterContainer();
centerContainer.AddChild(buttonGrid); centerContainer.AddChild(buttonGrid);
grid.AddChild(centerContainer); grid.AddChild(centerContainer);
Button newGame = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.NewGame); var newGame = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.NewGame)
newGame.Text = "New Game"; {Text = Loc.GetString("New Game")};
grid.AddChild(newGame); grid.AddChild(newGame);
centerContainer = new CenterContainer(); centerContainer = new CenterContainer();
@@ -79,6 +78,11 @@ namespace Content.Client.Arcade
{ {
Title = message.GameTitle; Title = message.GameTitle;
_enemyNameLabel.Text = message.EnemyName; _enemyNameLabel.Text = message.EnemyName;
foreach (var gameButton in _gameButtons)
{
gameButton.Disabled = message.ButtonsDisabled;
}
} }
public void UpdateInfo(SharedSpaceVillainArcadeComponent.SpaceVillainArcadeDataUpdateMessage message) public void UpdateInfo(SharedSpaceVillainArcadeComponent.SpaceVillainArcadeDataUpdateMessage message)

View File

@@ -13,6 +13,7 @@ using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects; using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.ComponentDependencies;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Random; using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -29,10 +30,11 @@ namespace Content.Server.GameObjects.Components.Arcade
public override string Name => "BlockGameArcade"; public override string Name => "BlockGameArcade";
public override uint? NetID => ContentNetIDs.BLOCKGAME_ARCADE; public override uint? NetID => ContentNetIDs.BLOCKGAME_ARCADE;
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; [ComponentDependency] private PowerReceiverComponent? _powerReceiverComponent = default!;
private bool Powered => _powerReceiverComponent?.Powered ?? false;
private BoundUserInterface? UserInterface => Owner.GetUIOrNull(BlockGameUiKey.Key); private BoundUserInterface? UserInterface => Owner.GetUIOrNull(BlockGameUiKey.Key);
private BlockGame _game = null!; private BlockGame? _game;
private IPlayerSession? _player; private IPlayerSession? _player;
private List<IPlayerSession> _spectators = new List<IPlayerSession>(); private List<IPlayerSession> _spectators = new List<IPlayerSession>();
@@ -47,7 +49,7 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
return; return;
} }
if(!ActionBlockerSystem.CanInteract(Owner)) return; if(!ActionBlockerSystem.CanInteract(actor.playerSession.AttachedEntity)) return;
UserInterface?.Toggle(actor.playerSession); UserInterface?.Toggle(actor.playerSession);
RegisterPlayerSession(actor.playerSession); RegisterPlayerSession(actor.playerSession);
@@ -59,7 +61,7 @@ namespace Content.Server.GameObjects.Components.Arcade
else _spectators.Add(session); else _spectators.Add(session);
UpdatePlayerStatus(session); UpdatePlayerStatus(session);
_game.UpdateNewPlayerUI(session); _game?.UpdateNewPlayerUI(session);
} }
private void DeactivePlayer(IPlayerSession session) private void DeactivePlayer(IPlayerSession session)
@@ -104,38 +106,56 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage; UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
} }
if (_powerReceiverComponent != null)
{
_powerReceiverComponent.OnPowerStateChanged += OnPowerStateChanged;
}
_game = new BlockGame(this); _game = new BlockGame(this);
} }
private void OnPowerStateChanged(object? sender, PowerStateEventArgs e)
{
if (e.Powered) return;
UserInterface?.CloseAll();
_player = null;
_spectators.Clear();
}
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage obj) private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage obj)
{ {
if (obj.Message is BlockGameMessages.BlockGameUserUnregisterMessage unregisterMessage) switch (obj.Message)
{ {
UnRegisterPlayerSession(obj.Session); case BlockGameMessages.BlockGameUserUnregisterMessage unregisterMessage:
return; UnRegisterPlayerSession(obj.Session);
} break;
if (obj.Session != _player) return; case BlockGameMessages.BlockGamePlayerActionMessage playerActionMessage:
if (obj.Session != _player) break;
if (!ActionBlockerSystem.CanInteract(Owner)) if (!ActionBlockerSystem.CanInteract(Owner))
{ {
DeactivePlayer(obj.Session); DeactivePlayer(obj.Session);
} break;
}
if (!(obj.Message is BlockGameMessages.BlockGamePlayerActionMessage message)) return; if (playerActionMessage.PlayerAction == BlockGamePlayerAction.NewGame)
if (message.PlayerAction == BlockGamePlayerAction.NewGame) {
{ if(_game?.Started == true) _game = new BlockGame(this);
if(_game.Started) _game = new BlockGame(this); _game?.StartGame();
_game.StartGame(); }
} else
else {
{ _game?.ProcessInput(playerActionMessage.PlayerAction);
_game.ProcessInput(message.PlayerAction); }
break;
} }
} }
public void DoGameTick(float frameTime) public void DoGameTick(float frameTime)
{ {
_game.GameTick(frameTime); _game?.GameTick(frameTime);
} }
private class BlockGame private class BlockGame
@@ -196,13 +216,12 @@ namespace Content.Server.GameObjects.Components.Arcade
private Vector2i _currentPiecePosition; private Vector2i _currentPiecePosition;
private BlockGamePieceRotation _currentRotation; private BlockGamePieceRotation _currentRotation;
private float _softDropOverride = 0.1f; private float _softDropModifier = 0.1f;
private float Speed => !_softDropPressed private float Speed =>
? -0.03f * Level + 1 -0.03f * Level + 1 * (!_softDropPressed ? 1 : _softDropModifier);
: _softDropOverride;
private float _pressCheckSpeed = 0.08f; private const float _pressCheckSpeed = 0.08f;
private bool _running; private bool _running;
public bool Paused => !(_running && _started); public bool Paused => !(_running && _started);
@@ -278,7 +297,8 @@ namespace Content.Server.GameObjects.Components.Arcade
public BlockGame(BlockGameArcadeComponent component) public BlockGame(BlockGameArcadeComponent component)
{ {
_component = component; _component = component;
_internalNextPiece = BlockGamePiece.GetRandom(_component._random); _allBlockGamePieces = (BlockGamePieceType[]) Enum.GetValues(typeof(BlockGamePieceType));
_internalNextPiece = GetRandomBlockGamePiece(_component._random);
} }
private void SendHighscoreUpdate() private void SendHighscoreUpdate()
@@ -343,7 +363,7 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
_accumulatedLeftPressTime += frameTime; _accumulatedLeftPressTime += frameTime;
if (_accumulatedLeftPressTime >= _pressCheckSpeed) while (_accumulatedLeftPressTime >= _pressCheckSpeed)
{ {
if (_currentPiece.Positions(_currentPiecePosition.AddToX(-1), _currentRotation) if (_currentPiece.Positions(_currentPiecePosition.AddToX(-1), _currentRotation)
@@ -361,7 +381,7 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
_accumulatedRightPressTime += frameTime; _accumulatedRightPressTime += frameTime;
if (_accumulatedRightPressTime >= _pressCheckSpeed) while (_accumulatedRightPressTime >= _pressCheckSpeed)
{ {
if (_currentPiece.Positions(_currentPiecePosition.AddToX(1), _currentRotation) if (_currentPiece.Positions(_currentPiecePosition.AddToX(1), _currentRotation)
.All(MoveCheck)) .All(MoveCheck))
@@ -384,13 +404,14 @@ namespace Content.Server.GameObjects.Components.Arcade
var checkTime = Speed; var checkTime = Speed;
if (_accumulatedFieldFrameTime < checkTime) return; while (_accumulatedFieldFrameTime >= checkTime)
{
if (_softDropPressed) AddPoints(1);
if(_softDropPressed) AddPoints(1); InternalFieldTick();
InternalFieldTick(); _accumulatedFieldFrameTime -= checkTime;
}
_accumulatedFieldFrameTime -= checkTime;
} }
private void InternalFieldTick() private void InternalFieldTick()
@@ -490,7 +511,7 @@ namespace Content.Server.GameObjects.Components.Arcade
private void InitializeNewBlock() private void InitializeNewBlock()
{ {
InitializeNewBlock(_nextPiece); InitializeNewBlock(_nextPiece);
_nextPiece = BlockGamePiece.GetRandom(_component._random); _nextPiece = GetRandomBlockGamePiece(_component._random);
_holdBlock = false; _holdBlock = false;
_component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameVisualUpdateMessage(_nextPiece.BlocksForPreview(), BlockGameMessages.BlockGameVisualType.NextBlock)); _component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameVisualUpdateMessage(_nextPiece.BlocksForPreview(), BlockGameMessages.BlockGameVisualType.NextBlock));
@@ -538,6 +559,7 @@ namespace Content.Server.GameObjects.Components.Arcade
break; break;
case BlockGamePlayerAction.SoftdropStart: case BlockGamePlayerAction.SoftdropStart:
_softDropPressed = true; _softDropPressed = true;
if (_accumulatedFieldFrameTime > Speed) _accumulatedFieldFrameTime = Speed; //to prevent jumps
break; break;
case BlockGamePlayerAction.SoftdropEnd: case BlockGamePlayerAction.SoftdropEnd:
_softDropPressed = false; _softDropPressed = false;
@@ -707,6 +729,22 @@ namespace Content.Server.GameObjects.Components.Arcade
}; };
} }
private readonly BlockGamePieceType[] _allBlockGamePieces;
private List<BlockGamePieceType> _blockGamePiecesBuffer = new List<BlockGamePieceType>();
private BlockGamePiece GetRandomBlockGamePiece(IRobustRandom random)
{
if (_blockGamePiecesBuffer.Count == 0)
{
_blockGamePiecesBuffer = _allBlockGamePieces.ToList();
}
var chosenPiece = random.Pick(_blockGamePiecesBuffer);
_blockGamePiecesBuffer.Remove(chosenPiece);
return BlockGamePiece.GetPiece(chosenPiece);
}
private struct BlockGamePiece private struct BlockGamePiece
{ {
public Vector2i[] Offsets; public Vector2i[] Offsets;
@@ -770,13 +808,6 @@ namespace Content.Server.GameObjects.Components.Arcade
return Blocks(new Vector2i(-xOffset, -yOffset), BlockGamePieceRotation.North); return Blocks(new Vector2i(-xOffset, -yOffset), BlockGamePieceRotation.North);
} }
public static BlockGamePiece GetRandom(IRobustRandom random)
{
var pieces = (BlockGamePieceType[])Enum.GetValues(typeof(BlockGamePieceType));
var choice = random.Pick(pieces);
return GetPiece(choice);
}
public static BlockGamePiece GetPiece(BlockGamePieceType type) public static BlockGamePiece GetPiece(BlockGamePieceType type)
{ {
//switch statement, hardcoded offsets //switch statement, hardcoded offsets

View File

@@ -0,0 +1,34 @@
using System;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
using Robust.Shared.Random;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Arcade
{
[RegisterComponent]
public class RandomArcadeGameComponent : Component, IMapInit
{
public override string Name => "RandomArcade";
public void MapInit()
{
var arcades = new[]
{
"BlockGameArcade",
"SpaceVillainArcade"
};
var entityManager = IoCManager.Resolve<IEntityManager>();
entityManager.SpawnEntity(
IoCManager.Resolve<IRobustRandom>().Pick(arcades),
Owner.Transform.Coordinates);
Owner.Delete();
}
}
}

View File

@@ -5,16 +5,20 @@ using Content.Server.GameObjects.Components.VendingMachines;
using Content.Server.Utility; using Content.Server.Utility;
using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.Components.Arcade; using Content.Shared.GameObjects.Components.Arcade;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.GameObjects.EntitySystems; using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.GameObjects; using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.ComponentDependencies;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Random; using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -27,7 +31,10 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
[Dependency] private IRobustRandom _random = null!; [Dependency] private IRobustRandom _random = null!;
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; [ComponentDependency] private PowerReceiverComponent? _powerReceiverComponent = default!;
[ComponentDependency] private WiresComponent? _wiresComponent = default!;
private bool Powered => _powerReceiverComponent != null && _powerReceiverComponent.Powered;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SpaceVillainArcadeUiKey.Key); [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SpaceVillainArcadeUiKey.Key);
[ViewVariables] private bool _overflowFlag; [ViewVariables] private bool _overflowFlag;
@@ -73,11 +80,11 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
return; return;
} }
if(!ActionBlockerSystem.CanInteract(actor.playerSession.AttachedEntity)) return;
var wires = Owner.GetComponent<WiresComponent>(); if (_wiresComponent?.IsPanelOpen == true)
if (wires.IsPanelOpen)
{ {
wires.OpenInterface(actor.playerSession); _wiresComponent.OpenInterface(actor.playerSession);
} else } else
{ {
UserInterface?.Toggle(actor.playerSession); UserInterface?.Toggle(actor.playerSession);
@@ -92,6 +99,18 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage; UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
} }
if (_powerReceiverComponent != null)
{
_powerReceiverComponent.OnPowerStateChanged += OnOnPowerStateChanged;
}
}
private void OnOnPowerStateChanged(object? sender, PowerStateEventArgs e)
{
if(e.Powered) return;
UserInterface?.CloseAll();
} }
@@ -145,6 +164,10 @@ namespace Content.Server.GameObjects.Components.Arcade
builder.CreateWire(Wires.Overflow); builder.CreateWire(Wires.Overflow);
builder.CreateWire(Wires.PlayerInvincible); builder.CreateWire(Wires.PlayerInvincible);
builder.CreateWire(Wires.EnemyInvincible); builder.CreateWire(Wires.EnemyInvincible);
builder.CreateWire(4);
builder.CreateWire(5);
builder.CreateWire(6);
IndicatorUpdate();
} }
public void WiresUpdate(WiresUpdateEventArgs args) public void WiresUpdate(WiresUpdateEventArgs args)
@@ -163,6 +186,24 @@ namespace Content.Server.GameObjects.Components.Arcade
_enemyInvincibilityFlag = value; _enemyInvincibilityFlag = value;
break; break;
} }
IndicatorUpdate();
}
public void IndicatorUpdate()
{
_wiresComponent?.SetStatus(Indicators.HealthManager,
new SharedWiresComponent.StatusLightData(Color.Purple,
_playerInvincibilityFlag || _enemyInvincibilityFlag
? SharedWiresComponent.StatusLightState.BlinkingSlow
: SharedWiresComponent.StatusLightState.On,
"MNGR"));
_wiresComponent?.SetStatus(Indicators.HealthLimiter,
new SharedWiresComponent.StatusLightData(Color.Red,
_overflowFlag
? SharedWiresComponent.StatusLightState.BlinkingSlow
: SharedWiresComponent.StatusLightState.On,
"LIMT"));
} }
/// <summary> /// <summary>
@@ -257,7 +298,7 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
case PlayerAction.Attack: case PlayerAction.Attack:
var attackAmount = _random.Next(2, 6); var attackAmount = _random.Next(2, 6);
_latestPlayerActionMessage = $"You attack {_enemyName} for {attackAmount}!"; _latestPlayerActionMessage = Loc.GetString("You attack {0} for {1}!", _enemyName, attackAmount);
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_attack.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_attack.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f));
if(!Owner._enemyInvincibilityFlag) _enemyHp -= attackAmount; if(!Owner._enemyInvincibilityFlag) _enemyHp -= attackAmount;
_turtleTracker -= _turtleTracker > 0 ? 1 : 0; _turtleTracker -= _turtleTracker > 0 ? 1 : 0;
@@ -265,24 +306,23 @@ namespace Content.Server.GameObjects.Components.Arcade
case PlayerAction.Heal: case PlayerAction.Heal:
var pointAmount = _random.Next(1, 3); var pointAmount = _random.Next(1, 3);
var healAmount = _random.Next(6, 8); var healAmount = _random.Next(6, 8);
_latestPlayerActionMessage = $"You use {pointAmount} magic to heal for {healAmount} damage!"; _latestPlayerActionMessage = Loc.GetString("You use {0} magic to heal for {1} damage!", pointAmount, healAmount);
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_heal.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_heal.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f));
if(!Owner._playerInvincibilityFlag) _playerMp -= pointAmount; if(!Owner._playerInvincibilityFlag) _playerMp -= pointAmount;
_playerHp += healAmount; _playerHp += healAmount;
_turtleTracker++; _turtleTracker++;
break; break;
case PlayerAction.Recharge: case PlayerAction.Recharge:
var charge_amount = _random.Next(4, 7); var chargeAmount = _random.Next(4, 7);
_latestPlayerActionMessage = $"You regain {charge_amount} points"; _latestPlayerActionMessage = Loc.GetString("You regain {0} points", chargeAmount);
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_charge.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/player_charge.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f));
_playerMp += charge_amount; _playerMp += chargeAmount;
_turtleTracker -= _turtleTracker > 0 ? 1 : 0; _turtleTracker -= _turtleTracker > 0 ? 1 : 0;
break; break;
} }
if (!CheckGameConditions()) if (!CheckGameConditions())
{ {
_running = false;
return; return;
} }
@@ -291,7 +331,6 @@ namespace Content.Server.GameObjects.Components.Arcade
if (!CheckGameConditions()) if (!CheckGameConditions())
{ {
_running = false;
return; return;
} }
ValidateVars(); ValidateVars();
@@ -304,22 +343,28 @@ namespace Content.Server.GameObjects.Components.Arcade
/// <returns>A bool indicating if the game should continue.</returns> /// <returns>A bool indicating if the game should continue.</returns>
private bool CheckGameConditions() private bool CheckGameConditions()
{ {
if ((_enemyHp <= 0 || _enemyMp <= 0) && (_playerHp > 0 && _playerMp > 0)) if ((_playerHp > 0 && _playerMp > 0) && (_enemyHp <= 0 || _enemyMp <= 0))
{ {
UpdateUi("You won!", $"{_enemyName} dies."); _running = false;
UpdateUi(Loc.GetString("You won!"), Loc.GetString("{0} dies.", _enemyName), true);
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/win.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/win.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f));
Owner.ProcessWin(); Owner.ProcessWin();
return false; return false;
} }
if ((_playerHp <= 0 || _playerMp <= 0) && _enemyHp > 0 && _enemyMp > 0)
if (_playerHp > 0 && _playerMp > 0) return true;
if ((_enemyHp > 0 && _enemyMp > 0))
{ {
UpdateUi("You lost!", $"{_enemyName} cheers."); _running = false;
UpdateUi(Loc.GetString("You lost!"), Loc.GetString("{0} cheers.", _enemyName), true);
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/gameover.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/gameover.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f));
return false; return false;
} }
if ((_playerHp <= 0 || _playerMp <= 0) && (_enemyHp <= 0 || _enemyMp <= 0)) if (_enemyHp <= 0 || _enemyMp <= 0)
{ {
UpdateUi("You lost!", $"{_enemyName} dies, but takes you with him."); _running = false;
UpdateUi(Loc.GetString("You lost!"), Loc.GetString("{0} dies, but takes you with him.", _enemyName), true);
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/gameover.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f)); EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/Effects/Arcade/gameover.ogg", Owner.Owner, AudioParams.Default.WithVolume(-4f));
return false; return false;
} }
@@ -330,16 +375,16 @@ namespace Content.Server.GameObjects.Components.Arcade
/// <summary> /// <summary>
/// Updates the UI. /// Updates the UI.
/// </summary> /// </summary>
private void UpdateUi() private void UpdateUi(bool metadata = false)
{ {
Owner.UserInterface?.SendMessage(GenerateUpdateMessage(_latestPlayerActionMessage, _latestEnemyActionMessage)); Owner.UserInterface?.SendMessage(metadata ? GenerateMetaDataMessage() : GenerateUpdateMessage());
} }
private void UpdateUi(string message1, string message2) private void UpdateUi(string message1, string message2, bool metadata = false)
{ {
_latestPlayerActionMessage = message1; _latestPlayerActionMessage = message1;
_latestEnemyActionMessage = message2; _latestEnemyActionMessage = message2;
UpdateUi(); UpdateUi(metadata);
} }
/// <summary> /// <summary>
@@ -351,14 +396,14 @@ namespace Content.Server.GameObjects.Components.Arcade
if (_turtleTracker >= 4) if (_turtleTracker >= 4)
{ {
var boomAmount = _random.Next(5, 10); var boomAmount = _random.Next(5, 10);
_latestEnemyActionMessage = $"{_enemyName} throws a bomb, exploding you for {boomAmount} damage!"; _latestEnemyActionMessage = Loc.GetString("{0} throws a bomb, exploding you for {1} damage!", _enemyName, boomAmount);
if (Owner._playerInvincibilityFlag) return; if (Owner._playerInvincibilityFlag) return;
_playerHp -= boomAmount; _playerHp -= boomAmount;
_turtleTracker--; _turtleTracker--;
}else if (_enemyMp <= 5 && _random.Prob(0.7f)) }else if (_enemyMp <= 5 && _random.Prob(0.7f))
{ {
var stealAmount = _random.Next(2, 3); var stealAmount = _random.Next(2, 3);
_latestEnemyActionMessage = $"{_enemyName} steals {stealAmount} of your power!"; _latestEnemyActionMessage = Loc.GetString("{0} steals {1} of your power!", _enemyName, stealAmount);
if (Owner._playerInvincibilityFlag) return; if (Owner._playerInvincibilityFlag) return;
_playerMp -= stealAmount; _playerMp -= stealAmount;
_enemyMp += stealAmount; _enemyMp += stealAmount;
@@ -366,12 +411,13 @@ namespace Content.Server.GameObjects.Components.Arcade
{ {
_enemyHp += 4; _enemyHp += 4;
_enemyMp -= 4; _enemyMp -= 4;
_latestEnemyActionMessage = $"{_enemyName} heals for 4 health!"; _latestEnemyActionMessage = Loc.GetString("{0} heals for 4 health!", _enemyName);
} }
else else
{ {
var attackAmount = _random.Next(3, 6); var attackAmount = _random.Next(3, 6);
_latestEnemyActionMessage = $"{_enemyName} attacks you for {attackAmount} damage!"; _latestEnemyActionMessage =
Loc.GetString("{0} attacks you for {1} damage!", _enemyName, attackAmount);
if (Owner._playerInvincibilityFlag) return; if (Owner._playerInvincibilityFlag) return;
_playerHp -= attackAmount; _playerHp -= attackAmount;
} }
@@ -383,20 +429,18 @@ namespace Content.Server.GameObjects.Components.Arcade
/// <returns>A Metadata-message.</returns> /// <returns>A Metadata-message.</returns>
public SpaceVillainArcadeMetaDataUpdateMessage GenerateMetaDataMessage() public SpaceVillainArcadeMetaDataUpdateMessage GenerateMetaDataMessage()
{ {
return new SpaceVillainArcadeMetaDataUpdateMessage(_playerHp, _playerMp, _enemyHp, _enemyMp, _latestPlayerActionMessage, _latestEnemyActionMessage, Name, _enemyName); return new SpaceVillainArcadeMetaDataUpdateMessage(_playerHp, _playerMp, _enemyHp, _enemyMp, _latestPlayerActionMessage, _latestEnemyActionMessage, Name, _enemyName, !_running);
} }
/// <summary> /// <summary>
/// Creates an Update-message based on the objects values. /// Creates an Update-message based on the objects values.
/// </summary> /// </summary>
/// <param name="playerAction">Content of the Playeraction-field.</param> /// <returns>An Update-Message.</returns>
/// <param name="enemyAction">Content of the Enemyaction-field.</param>
/// <returns></returns>
public SpaceVillainArcadeDataUpdateMessage public SpaceVillainArcadeDataUpdateMessage
GenerateUpdateMessage(string playerAction = "", string enemyAction = "") GenerateUpdateMessage()
{ {
return new SpaceVillainArcadeDataUpdateMessage(_playerHp, _playerMp, _enemyHp, _enemyMp, playerAction, return new SpaceVillainArcadeDataUpdateMessage(_playerHp, _playerMp, _enemyHp, _enemyMp, _latestPlayerActionMessage,
enemyAction); _latestEnemyActionMessage);
} }
} }
} }

View File

@@ -10,6 +10,19 @@ namespace Content.Shared.GameObjects.Components.Arcade
public override string Name => "SpaceVillainArcade"; public override string Name => "SpaceVillainArcade";
public override uint? NetID => ContentNetIDs.SPACE_VILLAIN_ARCADE; public override uint? NetID => ContentNetIDs.SPACE_VILLAIN_ARCADE;
[Serializable, NetSerializable]
public enum Indicators
{
/// <summary>
/// Blinks when any invincible flag is set
/// </summary>
HealthManager,
/// <summary>
/// Blinks when Overflow flag is set
/// </summary>
HealthLimiter
}
[Serializable, NetSerializable] [Serializable, NetSerializable]
public enum PlayerAction public enum PlayerAction
{ {
@@ -51,10 +64,12 @@ namespace Content.Shared.GameObjects.Components.Arcade
{ {
public readonly string GameTitle; public readonly string GameTitle;
public readonly string EnemyName; public readonly string EnemyName;
public SpaceVillainArcadeMetaDataUpdateMessage(int playerHp, int playerMp, int enemyHp, int enemyMp, string playerActionMessage, string enemyActionMessage, string gameTitle, string enemyName) : base(playerHp, playerMp, enemyHp, enemyMp, playerActionMessage, enemyActionMessage) public readonly bool ButtonsDisabled;
public SpaceVillainArcadeMetaDataUpdateMessage(int playerHp, int playerMp, int enemyHp, int enemyMp, string playerActionMessage, string enemyActionMessage, string gameTitle, string enemyName, bool buttonsDisabled) : base(playerHp, playerMp, enemyHp, enemyMp, playerActionMessage, enemyActionMessage)
{ {
GameTitle = gameTitle; GameTitle = gameTitle;
EnemyName = enemyName; EnemyName = enemyName;
ButtonsDisabled = buttonsDisabled;
} }
} }

View File

@@ -1,5 +1,6 @@
- type: entity - type: entity
id: Arcade abstract: true
id: ArcadeBase
description: An arcade cabinet. description: An arcade cabinet.
name: arcade name: arcade
parent: ComputerBase parent: ComputerBase
@@ -25,15 +26,20 @@
bodyBroken: arcade bodyBroken: arcade
- type: Anchorable - type: Anchorable
- type: Pullable - type: Pullable
- type: entity
id: SpaceVillainArcade
parent: ArcadeBase
components:
- type: SpaceVillainArcade - type: SpaceVillainArcade
- type: Wires - type: Wires
BoardName: "Arcade" BoardName: "Arcade"
- type: UserInterface - type: UserInterface
interfaces: interfaces:
- key: enum.SpaceVillainArcadeUiKey.Key - key: enum.SpaceVillainArcadeUiKey.Key
type: SpaceVillainArcadeBoundUserInterface type: SpaceVillainArcadeBoundUserInterface
- key: enum.WiresUiKey.Key - key: enum.WiresUiKey.Key
type: WiresBoundUserInterface type: WiresBoundUserInterface
- type: Computer - type: Computer
board: SpaceVillainArcadeComputerCircuitboard board: SpaceVillainArcadeComputerCircuitboard
@@ -41,35 +47,28 @@
id: BlockGameArcade id: BlockGameArcade
description: An arcade cabinet with a strangely familiar game. description: An arcade cabinet with a strangely familiar game.
name: NT block game name: NT block game
parent: ComputerBase parent: ArcadeBase
components: components:
- type: PowerReceiver - type: BlockGameArcade
- type: Sprite - type: UserInterface
sprite: Constructible/Power/computers.rsi interfaces:
layers: - key: enum.BlockGameUiKey.Key
- state: arcade type: BlockGameBoundUserInterface
map: ["enum.ComputerVisualizer+Layers.Body"] - key: enum.WiresUiKey.Key
- state: invaders type: WiresBoundUserInterface
shader: unshaded - type: Computer
map: ["enum.ComputerVisualizer+Layers.Screen"] board: BlockGameArcadeComputerCircuitboard
- type: Icon
sprite: Constructible/Power/computers.rsi - type: entity
state: arcade id: RandomArcade
- type: Appearance name: Random Arcade Spawner
visuals: components:
- type: ComputerVisualizer - type: RandomArcade
screen: invaders - type: Sprite
key: "" netsync: false
body: arcade visible: false
bodyBroken: arcade sprite: Interface/Misc/markers.rsi
- type: Anchorable state: cross_blue
- type: Pullable - type: Marker
- type: BlockGameArcade - type: Clickable
- type: UserInterface - type: InteractionOutline
interfaces:
- key: enum.BlockGameUiKey.Key
type: BlockGameBoundUserInterface
- key: enum.WiresUiKey.Key
type: WiresBoundUserInterface
- type: Computer
board: BlockGameArcadeComputerCircuitboard

View File

@@ -71,7 +71,7 @@
name: space villain arcade computer circuit board name: space villain arcade computer circuit board
components: components:
- type: ComputerBoard - type: ComputerBoard
prototype: Arcade prototype: SpaceVillainArcade
- type: entity - type: entity
id: BlockGameArcadeComputerCircuitboard id: BlockGameArcadeComputerCircuitboard