using static Content.Shared.Arcade.SharedSpaceVillainArcadeComponent;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Random;
namespace Content.Server.Arcade.SpaceVillain;
///
/// A Class to handle all the game-logic of the SpaceVillain-game.
///
public sealed partial class SpaceVillainGame
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
private readonly SharedAudioSystem _audioSystem = default!;
private readonly UserInterfaceSystem _uiSystem = default!;
private readonly SpaceVillainArcadeSystem _svArcade = default!;
[ViewVariables]
private readonly EntityUid _owner = default!;
[ViewVariables]
private bool _running = true;
[ViewVariables]
public string Name => $"{_fightVerb} {_villainName}";
[ViewVariables]
private readonly string _fightVerb;
[ViewVariables]
public readonly Fighter PlayerChar;
[ViewVariables]
private readonly string _villainName;
[ViewVariables]
public readonly Fighter VillainChar;
[ViewVariables]
private int _turtleTracker = 0;
[ViewVariables]
private string _latestPlayerActionMessage = "";
[ViewVariables]
private string _latestEnemyActionMessage = "";
public SpaceVillainGame(EntityUid owner, SpaceVillainArcadeComponent arcade, SpaceVillainArcadeSystem arcadeSystem)
: this(owner, arcade, arcadeSystem, arcadeSystem.GenerateFightVerb(arcade), arcadeSystem.GenerateEnemyName(arcade))
{
}
public SpaceVillainGame(EntityUid owner, SpaceVillainArcadeComponent arcade, SpaceVillainArcadeSystem arcadeSystem, string fightVerb, string enemyName)
{
IoCManager.InjectDependencies(this);
_audioSystem = _entityManager.System();
_uiSystem = _entityManager.System();
_svArcade = _entityManager.System();
_owner = owner;
//todo defeat the curse secret game mode
_fightVerb = fightVerb;
_villainName = enemyName;
PlayerChar = new()
{
HpMax = 30,
Hp = 30,
MpMax = 10,
Mp = 10
};
VillainChar = new()
{
HpMax = 45,
Hp = 45,
MpMax = 20,
Mp = 20
};
}
///
/// Called by the SpaceVillainArcadeComponent when Userinput is received.
///
/// The action the user picked.
/// The action the user picked.
/// The action the user picked.
public void ExecutePlayerAction(EntityUid uid, PlayerAction action, SpaceVillainArcadeComponent arcade)
{
if (!_running)
return;
switch (action)
{
case PlayerAction.Attack:
var attackAmount = _random.Next(2, 6);
_latestPlayerActionMessage = Loc.GetString(
"space-villain-game-player-attack-message",
("enemyName", _villainName),
("attackAmount", attackAmount)
);
_audioSystem.PlayPvs(arcade.PlayerAttackSound, uid, AudioParams.Default.WithVolume(-4f));
if (!VillainChar.Invincible)
VillainChar.Hp -= attackAmount;
_turtleTracker -= _turtleTracker > 0 ? 1 : 0;
break;
case PlayerAction.Heal:
var pointAmount = _random.Next(1, 3);
var healAmount = _random.Next(6, 8);
_latestPlayerActionMessage = Loc.GetString(
"space-villain-game-player-heal-message",
("magicPointAmount", pointAmount),
("healAmount", healAmount)
);
_audioSystem.PlayPvs(arcade.PlayerHealSound, uid, AudioParams.Default.WithVolume(-4f));
if (!PlayerChar.Invincible)
PlayerChar.Mp -= pointAmount;
PlayerChar.Hp += healAmount;
_turtleTracker++;
break;
case PlayerAction.Recharge:
var chargeAmount = _random.Next(4, 7);
_latestPlayerActionMessage = Loc.GetString(
"space-villain-game-player-recharge-message",
("regainedPoints", chargeAmount)
);
_audioSystem.PlayPvs(arcade.PlayerChargeSound, uid, AudioParams.Default.WithVolume(-4f));
PlayerChar.Mp += chargeAmount;
_turtleTracker -= _turtleTracker > 0 ? 1 : 0;
break;
}
if (!CheckGameConditions(uid, arcade))
return;
ExecuteAiAction();
if (!CheckGameConditions(uid, arcade))
return;
UpdateUi(uid);
}
///
/// Handles the logic of the AI
///
private void ExecuteAiAction()
{
if (_turtleTracker >= 4)
{
var boomAmount = _random.Next(5, 10);
_latestEnemyActionMessage = Loc.GetString(
"space-villain-game-enemy-throws-bomb-message",
("enemyName", _villainName),
("damageReceived", boomAmount)
);
if (PlayerChar.Invincible)
return;
PlayerChar.Hp -= boomAmount;
_turtleTracker--;
return;
}
if (VillainChar.Mp <= 5 && _random.Prob(0.7f))
{
var stealAmount = _random.Next(2, 3);
_latestEnemyActionMessage = Loc.GetString(
"space-villain-game-enemy-steals-player-power-message",
("enemyName", _villainName),
("stolenAmount", stealAmount)
);
if (PlayerChar.Invincible)
return;
PlayerChar.Mp -= stealAmount;
VillainChar.Mp += stealAmount;
return;
}
if (VillainChar.Hp <= 10 && VillainChar.Mp > 4)
{
VillainChar.Hp += 4;
VillainChar.Mp -= 4;
_latestEnemyActionMessage = Loc.GetString(
"space-villain-game-enemy-heals-message",
("enemyName", _villainName),
("healedAmount", 4)
);
return;
}
var attackAmount = _random.Next(3, 6);
_latestEnemyActionMessage =
Loc.GetString(
"space-villain-game-enemy-attacks-message",
("enemyName", _villainName),
("damageDealt", attackAmount)
);
if (PlayerChar.Invincible)
return;
PlayerChar.Hp -= attackAmount;
}
///
/// Checks the Game conditions and Updates the Ui & Plays a sound accordingly.
///
/// A bool indicating if the game should continue.
private bool CheckGameConditions(EntityUid uid, SpaceVillainArcadeComponent arcade)
{
switch (
PlayerChar.Hp > 0 && PlayerChar.Mp > 0,
VillainChar.Hp > 0 && VillainChar.Mp > 0
)
{
case (true, true):
return true;
case (true, false):
_running = false;
UpdateUi(
uid,
Loc.GetString("space-villain-game-player-wins-message"),
Loc.GetString("space-villain-game-enemy-dies-message", ("enemyName", _villainName)),
true
);
_audioSystem.PlayPvs(arcade.WinSound, uid, AudioParams.Default.WithVolume(-4f));
_svArcade.ProcessWin(uid, arcade);
return false;
case (false, true):
_running = false;
UpdateUi(
uid,
Loc.GetString("space-villain-game-player-loses-message"),
Loc.GetString("space-villain-game-enemy-cheers-message", ("enemyName", _villainName)),
true
);
_audioSystem.PlayPvs(arcade.GameOverSound, uid, AudioParams.Default.WithVolume(-4f));
return false;
case (false, false):
_running = false;
UpdateUi(
uid,
Loc.GetString("space-villain-game-player-loses-message"),
Loc.GetString("space-villain-game-enemy-dies-with-player-message", ("enemyName", _villainName)),
true
);
_audioSystem.PlayPvs(arcade.GameOverSound, uid, AudioParams.Default.WithVolume(-4f));
return false;
}
}
}