Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gamemodes #23

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Content.Server.GameTicking.Rules.Components;

[RegisterComponent, Access(typeof(LockdownRuleSystem))]
public sealed partial class LockdownRuleComponent : Component
{
/// <summary>
/// The gamerules that get added by lockdown.
/// </summary>
[DataField("additionalGameRules")]
public HashSet<EntityUid> AdditionalGameRules = new();
}
172 changes: 172 additions & 0 deletions Content.Server/GameTicking/Rules/SP14/LockdownRuleSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking.Presets;
using Content.Server.GameTicking.Rules.Components;
using Content.Shared.GameTicking.Components;
using Content.Shared.Random;
using Content.Shared.CCVar;
using Content.Shared.Database;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Configuration;
using Robust.Shared.Utility;

namespace Content.Server.GameTicking.Rules;

public sealed class LockdownRuleSystem : GameRuleSystem<LockdownRuleComponent>
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly IComponentFactory _compFact = default!;

private string _ruleCompName = default!;

public override void Initialize()
{
base.Initialize();
_ruleCompName = _compFact.GetComponentName(typeof(GameRuleComponent));
}

protected override void Added(EntityUid uid, LockdownRuleComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args)
{
base.Added(uid, component, gameRule, args);
var weights = _configurationManager.GetCVar(CCVars.LockdownWeightPrototype);

if (!TryPickPreset(weights, out var preset))
{
Log.Error($"{ToPrettyString(uid)} failed to pick any preset. Removing rule.");
Del(uid);
return;
}

Log.Info($"Selected {preset.ID} as the lockdown preset.");
_adminLogger.Add(LogType.EventStarted, $"Selected {preset.ID} as the lockdown preset.");

foreach (var rule in preset.Rules)
{
EntityUid ruleEnt;

// if we're pre-round (i.e. will only be added)
// then just add rules. if we're added in the middle of the round (or at any other point really)
// then we want to start them as well
if (GameTicker.RunLevel <= GameRunLevel.InRound)
ruleEnt = GameTicker.AddGameRule(rule);
else
GameTicker.StartGameRule(rule, out ruleEnt);

component.AdditionalGameRules.Add(ruleEnt);
}
}

protected override void Ended(EntityUid uid, LockdownRuleComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
{
base.Ended(uid, component, gameRule, args);

foreach (var rule in component.AdditionalGameRules)
{
GameTicker.EndGameRule(rule);
}
}

private bool TryPickPreset(ProtoId<WeightedRandomPrototype> weights, [NotNullWhen(true)] out GamePresetPrototype? preset)
{
var options = _prototypeManager.Index(weights).Weights.ShallowClone();
var players = GameTicker.ReadyPlayerCount();

GamePresetPrototype? selectedPreset = null;
var sum = options.Values.Sum();
while (options.Count > 0)
{
var accumulated = 0f;
var rand = _random.NextFloat(sum);
foreach (var (key, weight) in options)
{
accumulated += weight;
if (accumulated < rand)
continue;

if (!_prototypeManager.TryIndex(key, out selectedPreset))
Log.Error($"Invalid preset {selectedPreset} in lockdown rule weights: {weights}");

options.Remove(key);
sum -= weight;
break;
}

if (CanPick(selectedPreset, players))
{
preset = selectedPreset;
return true;
}

if (selectedPreset != null)
Log.Info($"Excluding {selectedPreset.ID} from lockdown preset selection.");
}

preset = null;
return false;
}

public bool CanPickAny()
{
var secretPresetId = _configurationManager.GetCVar(CCVars.SecretWeightPrototype);
return CanPickAny(secretPresetId);
}

/// <summary>
/// Can any of the given presets be picked, taking into account the currently available player count?
/// </summary>
public bool CanPickAny(ProtoId<WeightedRandomPrototype> weightedPresets)
{
var ids = _prototypeManager.Index(weightedPresets).Weights.Keys
.Select(x => new ProtoId<GamePresetPrototype>(x));

return CanPickAny(ids);
}

/// <summary>
/// Can any of the given presets be picked, taking into account the currently available player count?
/// </summary>
public bool CanPickAny(IEnumerable<ProtoId<GamePresetPrototype>> protos)
{
var players = GameTicker.ReadyPlayerCount();
foreach (var id in protos)
{
if (!_prototypeManager.TryIndex(id, out var selectedPreset))
Log.Error($"Invalid preset {selectedPreset} in lockdown rule weights: {id}");

if (CanPick(selectedPreset, players))
return true;
}

return false;
}

/// <summary>
/// Can the given preset be picked, taking into account the currently available player count?
/// </summary>
private bool CanPick([NotNullWhen(true)] GamePresetPrototype? selected, int players)
{
if (selected == null)
return false;

foreach (var ruleId in selected.Rules)
{
if (!_prototypeManager.TryIndex(ruleId, out EntityPrototype? rule)
|| !rule.TryGetComponent(_ruleCompName, out GameRuleComponent? ruleComp))
{
Log.Error($"Encountered invalid rule {ruleId} in preset {selected.ID}");
return false;
}

if (ruleComp.MinPlayers > players && ruleComp.CancelPresetOnTooFewPlayers)
return false;
}

return true;
}
}
19 changes: 19 additions & 0 deletions Content.Server/_SP14/Liberators/LiberatorConvertSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Content.Shared.Liberator;

namespace Content.Server.Liberator;

/// <summary>
/// System used for checking if the implanted is a Rev or Head Rev.
/// </summary>
public sealed class LiberatorConvertSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LiberatorConvertEvent>(ConvertActor);
}
private void ConvertActor(LiberatorConvertEvent args)
{
Logger.Info("Event handled!");
}
}
8 changes: 6 additions & 2 deletions Content.Shared/CCVar/CCVars.Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ public static readonly CVarDef<int>
public static readonly CVarDef<bool>
GameDisallowLateJoins = CVarDef.Create("game.disallowlatejoins", false, CVar.ARCHIVE | CVar.SERVERONLY);

/// !!!REDEFINED BY SP14!!!

/// <summary>
/// Controls the default game preset.
/// </summary>
public static readonly CVarDef<string>
GameLobbyDefaultPreset = CVarDef.Create("game.defaultpreset", "secret", CVar.ARCHIVE);
/// public static readonly CVarDef<string>
/// GameLobbyDefaultPreset = CVarDef.Create("game.defaultpreset", "secret", CVar.ARCHIVE);

/// !!! !!!

/// <summary>
/// Controls if the game can force a different preset if the current preset's criteria are not met.
Expand Down
8 changes: 6 additions & 2 deletions Content.Shared/CCVar/CCVars.Shuttle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,16 @@ public sealed partial class CCVars
public static readonly CVarDef<float> FTLCooldown =
CVarDef.Create("shuttle.cooldown", 10f, CVar.SERVERONLY);

/// !!!REDEFINED BY SP14!!!

/// <summary>
/// The maximum <see cref="PhysicsComponent.Mass"/> a grid can have before it becomes unable to FTL.
/// Any value equal to or less than zero will disable this check.
/// </summary>
public static readonly CVarDef<float> FTLMassLimit =
CVarDef.Create("shuttle.mass_limit", 300f, CVar.SERVERONLY);
///public static readonly CVarDef<float> FTLMassLimit =
/// CVarDef.Create("shuttle.mass_limit", 300f, CVar.SERVERONLY);

/// !!! !!!

/// <summary>
/// How long to knock down entities for if they aren't buckled when FTL starts and stops.
Expand Down
19 changes: 19 additions & 0 deletions Content.Shared/CCVar/SP14/CCVars.Game.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Content.Shared.Roles;
using Robust.Shared.Configuration;

namespace Content.Shared.CCVar;

public sealed partial class CCVars
{
/// <summary>
/// The prototype to use for lockdown weights.
/// </summary>
public static readonly CVarDef<string> LockdownWeightPrototype =
CVarDef.Create("game.lockdown_weight_prototype", "Lockdown", CVar.SERVERONLY);

/// <summary>
/// The default loaded preset.
/// </summary>
public static readonly CVarDef<string>
GameLobbyDefaultPreset = CVarDef.Create("game.defaultpreset", "lockdown", CVar.ARCHIVE);
}
13 changes: 13 additions & 0 deletions Content.Shared/CCVar/SP14/CCVars.Shuttle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Robust.Shared.Configuration;

namespace Content.Shared.CCVar;

public sealed partial class CCVars
{
/// <summary>
/// The maximum <see cref="PhysicsComponent.Mass"/> a grid can have before it becomes unable to FTL.
/// Any value equal to or less than zero will disable this check.
/// </summary>
public static readonly CVarDef<float> FTLMassLimit =
CVarDef.Create("shuttle.mass_limit", 700f, CVar.SERVERONLY);
}
8 changes: 8 additions & 0 deletions Content.Shared/_SP14/Liberators/LiberatorConvertEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Robust.Shared.Serialization;

namespace Content.Shared.Liberator;

[Serializable, NetSerializable]
public sealed class LiberatorConvertEvent : EntityEventArgs
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Liberator-title = Liberation
Liberator-description = Liberators have been called in to extract inmates. stage your escape or defend the prison.

Liberator-welcome =
You are a liberator. Your goal is to extract any and all prisoners from {$station}. ensure minimal harm comes to any inmates. Your benefactors, the Syndicate, have provided you with the tools you'll need for the task.
Free the people! Death to Nanotrasen!

Liberator-opsmajor = [color=crimson]Liberator major victory![/color]
Liberator-opsminor = [color=crimson]Liberator minor victory![/color]
Liberator-neutral = [color=yellow]Neutral outcome![/color]
Liberator-crewminor = [color=green]Crew minor victory![/color]
Liberator-crewmajor = [color=green]Crew major victory![/color]

Liberator-role-commander = Commander
Liberator-role-agent = Agent
Liberator-role-operator = Operator
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
lockdown-title = Lockdown
lockdown-description = It's a secret to everyone. The threats you encounter are randomized.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ghost-role-information-liberator-rules = You are a [color=red][bold]Team Antagonist[/bold][/color] with all other liberators. Prisoners are not guaranteed to help you.
11 changes: 11 additions & 0 deletions Resources/Locale/en-US/prototypes/roles/antags.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,14 @@ roles-antag-thief-objective = Add some NT property to your personal collection w

roles-antag-dragon-name = Space Dragon
roles-antag-dragon-objective = Create a carp army to take over this quadrant.

#sp14

roles-antag-liberator-commander-name = Liberaton commander
roles-antag-liberator-commander-objective = Lead the liberation. Ensure resources are properly allocated and the operation is not at risk.

roles-antag-liberator-agent-name = Liberaton agent
roles-antag-liberator-agent-objective = The liberation efforts finest medic, keep your teammates in the fight.

roles-antag-liberator-name = Liberator
roles-antag-liberator-objective = break into the prison, break others out.
Loading
Loading