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

Blob gamemode, Vampirs mid round #484

Merged
merged 3 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Content.Server/Backmen/Arrivals/CentcommSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ private void OnShuttleConsoleEmaged(Entity<ShuttleConsoleComponent> ent, ref Got
return;

_audio.PlayPvs(SparkSound, ent);
_popupSystem.PopupEntity(Loc.GetString("cloning-pod-component-upgrade-emag-requirement"), ent);
_popupSystem.PopupEntity(Loc.GetString("shuttle-console-component-upgrade-emag-requirement"), ent);
args.Handled = true;
EnsureComp<EmaggedComponent>(ent); // для обновления консоли нужно чтобы компонент был до вызыва RefreshShuttleConsoles
_console.RefreshShuttleConsoles();
Expand Down
2 changes: 2 additions & 0 deletions Content.Server/Backmen/Blob/BlobCarrierSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ private void OnStartup(EntityUid uid, BlobCarrierComponent component, ComponentS
ghostRole.RoleName = Loc.GetString("blob-carrier-role-name");
ghostRole.RoleDescription = Loc.GetString("blob-carrier-role-desc");
ghostRole.RoleRules = Loc.GetString("blob-carrier-role-rules");

EnsureComp<BlobSpeakComponent>(uid);
}

private void OnShutdown(EntityUid uid, BlobCarrierComponent component, ComponentShutdown args)
Expand Down
67 changes: 67 additions & 0 deletions Content.Server/Backmen/Blob/BlobMobSystem.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
using Content.Server.Chat.Systems;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Fluids.EntitySystems;
using Content.Server.Popups;
using Content.Server.Radio.Components;
using Content.Server.Radio.EntitySystems;
using Content.Shared.Backmen.Blob;
using Content.Shared.Backmen.Blob.Chemistry;
using Content.Shared.Chemistry.Components;
using Content.Shared.Damage;
using Content.Shared.Interaction.Events;
using Content.Shared.Popups;
using Content.Shared.Speech;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;

namespace Content.Server.Backmen.Blob;

Expand All @@ -18,15 +24,76 @@ public sealed class BlobMobSystem : EntitySystem
//[Dependency] private readonly SmokeSystem _smokeSystem = default!;
//[Dependency] private readonly SharedAudioSystem _audioSystem = default!;

[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly RadioSystem _radioSystem = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<BlobMobComponent, BlobMobGetPulseEvent>(OnPulsed);
SubscribeLocalEvent<BlobMobComponent, AttackAttemptEvent>(OnBlobAttackAttempt);
SubscribeLocalEvent<BlobSpeakComponent, EntitySpokeEvent>(OnSpoke, before: new []{ typeof(RadioSystem) });
SubscribeLocalEvent<BlobSpeakComponent, ComponentStartup>(OnSpokeAdd);
SubscribeLocalEvent<BlobSpeakComponent, ComponentShutdown>(OnSpokeRemove);
SubscribeLocalEvent<BlobSpeakComponent, TransformSpeakerNameEvent>(OnSpokeName);
SubscribeLocalEvent<BlobSpeakComponent, SpeakAttemptEvent>(OnSpokeCan, after: new []{ typeof(SpeechSystem) });
//SubscribeLocalEvent<SmokeOnTriggerComponent, TriggerEvent>(HandleSmokeTrigger);
}

private void OnSpokeName(Entity<BlobSpeakComponent> ent, ref TransformSpeakerNameEvent args)
{
args.Name = "Блоб";

}

private void OnSpokeCan(Entity<BlobSpeakComponent> ent, ref SpeakAttemptEvent args)
{
args.Uncancel();
}

private void OnSpokeRemove(Entity<BlobSpeakComponent> ent, ref ComponentShutdown args)
{
var radio = EnsureComp<ActiveRadioComponent>(ent);
radio.Channels.Remove(ent.Comp.Channel);
var snd = EnsureComp<IntrinsicRadioTransmitterComponent>(ent);
snd.Channels.Remove(ent.Comp.Channel);
}

private void OnSpokeAdd(Entity<BlobSpeakComponent> ent, ref ComponentStartup args)
{
EnsureComp<IntrinsicRadioReceiverComponent>(ent);
var radio = EnsureComp<ActiveRadioComponent>(ent);
radio.Channels.Add(ent.Comp.Channel);
var snd = EnsureComp<IntrinsicRadioTransmitterComponent>(ent);
snd.Channels.Add(ent.Comp.Channel);
}


private void OnSpoke(Entity<BlobSpeakComponent> ent, ref EntitySpokeEvent args)
{
if (args.Channel == null)
args.Channel = _prototypeManager.Index(ent.Comp.Channel);

if (!TryComp<IntrinsicRadioTransmitterComponent>(ent, out var component) ||
!component.Channels.Contains(args.Channel.ID) ||
args.Channel.ID != ent.Comp.Channel)
{
return;
}

if (TryComp<BlobObserverComponent>(ent, out var blobObserverComponent) && blobObserverComponent.Core.HasValue)
{
_radioSystem.SendRadioMessage(blobObserverComponent.Core.Value, args.OriginalMessage, args.Channel, blobObserverComponent.Core.Value);
}
else
{
_radioSystem.SendRadioMessage(ent, args.OriginalMessage, args.Channel, ent);
}

args.Channel = null; // prevent duplicate messages from other listeners.
}

private void OnPulsed(EntityUid uid, BlobMobComponent component, BlobMobGetPulseEvent args)
{
_damageableSystem.TryChangeDamage(uid, component.HealthOfPulse);
Expand Down
10 changes: 10 additions & 0 deletions Content.Server/Backmen/Blob/BlobSpeakComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Content.Shared.Radio;
using Robust.Shared.Prototypes;

namespace Content.Server.Backmen.Blob;

[RegisterComponent]
public sealed partial class BlobSpeakComponent : Component
{
public ProtoId<RadioChannelPrototype> Channel = "Hivemind";
}
7 changes: 7 additions & 0 deletions Content.Server/Backmen/Blob/Rule/BlobGameRuleComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Content.Server.Backmen.Blob.Rule;

[RegisterComponent]
public sealed partial class BlobGameRuleComponent : Component
{
public int TotalBlobs = 0;
}
162 changes: 162 additions & 0 deletions Content.Server/Backmen/Blob/Rule/BlobRuleSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
using System.Linq;
using Content.Server.Antag;
using Content.Server.Backmen.Vampiric;
using Content.Server.Bible.Components;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Mind;
using Content.Shared.Backmen.Blob;
using Content.Shared.Backmen.CCVar;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Shared.Configuration;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;

namespace Content.Server.Backmen.Blob.Rule;

public sealed class BlobGameRuleSystem : GameRuleSystem<BlobGameRuleComponent>
{
private ISawmill _sawmill = default!;


private int PlayersPerBlob => _cfg.GetCVar(CCVars.BlobPlayersPer);
private int MaxBlob => _cfg.GetCVar(CCVars.BlobMax);

[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly AntagSelectionSystem _antagSelection = default!;
[Dependency] private readonly IRobustRandom _random = default!;


public override void Initialize()
{
base.Initialize();

_sawmill = Logger.GetSawmill("preset");

SubscribeLocalEvent<RoundStartAttemptEvent>(OnStartAttempt);
SubscribeLocalEvent<RulePlayerJobsAssignedEvent>(OnPlayersSpawned);
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(HandleLatejoin);
}

private void HandleLatejoin(PlayerSpawnCompleteEvent ev)
{
var query = EntityQueryEnumerator<BlobGameRuleComponent, GameRuleComponent>();
while (query.MoveNext(out var uid, out var blob, out var gameRule))
{
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
continue;

if (blob.TotalBlobs >= MaxBlob)
continue;

if (!ev.LateJoin)
continue;

if (!ev.Profile.AntagPreferences.Contains(Blob))
continue;

if (ev.JobId == null || !_prototypeManager.TryIndex<JobPrototype>(ev.JobId, out var job))
continue;

if (!job.CanBeAntag)
continue;

// the nth player we adjust our probabilities around
var target = PlayersPerBlob * blob.TotalBlobs + 1;

var chance = 1f / PlayersPerBlob;

// If we have too many traitors, divide by how many players below target for next traitor we are.
if (ev.JoinOrder < target)
{
chance /= (target - ev.JoinOrder);
}
else // Tick up towards 100% chance.
{
chance *= ((ev.JoinOrder + 1) - target);
}

if (chance > 1)
chance = 1;

// Now that we've calculated our chance, roll and make them a traitor if we roll under.
// You get one shot.
if (_random.Prob(chance) && ev.Player.AttachedEntity.HasValue)
{
MakeBlob(blob, ev.Player);
}
}
}

private void MakeBlob(BlobGameRuleComponent blob, ICommonSession player)
{
if (!player.AttachedEntity.HasValue)
return;

blob.TotalBlobs++;
EnsureComp<BlobCarrierComponent>(player.AttachedEntity.Value).HasMind = true;
}

private void OnPlayersSpawned(RulePlayerJobsAssignedEvent ev)
{
var query = EntityQueryEnumerator<BlobGameRuleComponent, GameRuleComponent>();
while (query.MoveNext(out var uid, out var blob, out var gameRule))
{
var plr = new Dictionary<ICommonSession, HumanoidCharacterProfile>();

if (!GameTicker.IsGameRuleAdded(uid, gameRule))
continue;

foreach (var player in ev.Players)
{
if (!ev.Profiles.ContainsKey(player.UserId))
continue;

plr.Add(player, ev.Profiles[player.UserId]);
}

DoBlobStart(blob, plr);
}
}

private void DoBlobStart(BlobGameRuleComponent blob,
Dictionary<ICommonSession, HumanoidCharacterProfile> startCandidates)
{
var numTraitors = MathHelper.Clamp(startCandidates.Count / PlayersPerBlob, 1, MaxBlob);
var traitorPool = _antagSelection.FindPotentialAntags(startCandidates, Blob);
var selectedTraitors = _antagSelection.PickAntag(numTraitors, traitorPool);

foreach (var traitor in selectedTraitors)
{
if (!traitor.AttachedEntity.HasValue)
continue;

MakeBlob(blob, traitor);
}
}

private void OnStartAttempt(RoundStartAttemptEvent ev)
{
var query = EntityQueryEnumerator<BlobGameRuleComponent, GameRuleComponent>();
while (query.MoveNext(out var uid, out _, out var gameRule))
{
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
continue;

if (ev.Players.Length == 0)
{
_chatManager.DispatchServerAnnouncement(Loc.GetString("blob-no-one-ready"));
ev.Cancel();
}
}
}

[ValidatePrototypeId<AntagPrototype>]
private const string Blob = "Blob";
}
6 changes: 6 additions & 0 deletions Content.Server/Backmen/Blob/ZombieBlobSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ private void ReplaceFixtures(EntityUid uid, ZombieBlobComponent climbingComp, Fi
private void OnStartup(EntityUid uid, ZombieBlobComponent component, ComponentStartup args)
{
EnsureComp<BlobMobComponent>(uid);
EnsureComp<BlobSpeakComponent>(uid);

var oldFactions = new List<string>();
var factionComp = EnsureComp<NpcFactionMemberComponent>(uid);
Expand Down Expand Up @@ -114,6 +115,11 @@ private void OnShutdown(EntityUid uid, ZombieBlobComponent component, ComponentS
return;
}

if (HasComp<BlobSpeakComponent>(uid))
{
RemComp<BlobSpeakComponent>(uid);
}

if (HasComp<BlobMobComponent>(uid))
{
RemComp<BlobMobComponent>(uid);
Expand Down
Loading
Loading