Files
wwdpublic/Content.Server/_Goobstation/Blob/BlobCarrierSystem.cs
Kyoth25f ed2301f840 Port Blob (#2441)
Ports Blob from https://github.com/Goob-Station/Goob-Station/pull/975
that was ported from https://github.com/Rxup/space-station-14.

Credit to VigersRay for original code, Roudenn and Rxup for maintaining
and jorgun for the Goob port.

---

- [X] Port https://github.com/Goob-Station/Goob-Station/pull/975;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/1209;
- [X] Port Blob related code from
https://github.com/Goob-Station/Goob-Station/pull/1262;
- [X] Port Blob related code from
https://github.com/Goob-Station/Goob-Station/pull/1340;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/1408;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/1419;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/1440;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/1817;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/2077;
- [ ] ~Port https://github.com/Goob-Station/Goob-Station/pull/1916~;
- [ ] ~Port https://github.com/Goob-Station/Goob-Station/pull/1917~;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/2077;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/2092;
- [X] Port https://github.com/Goob-Station/Goob-Station/pull/2546;
- [X] Port https://github.com/Rxup/space-station-14/pull/963;
- [X] Port https://github.com/Rxup/space-station-14/pull/998;
- [ ] ~Port https://github.com/Goob-Station/Goob-Station/pull/2563~.

- [X] Enable Blob and Blob gamemode;
- [X] Add `StationGlobConfig` to all stations;
- [X] Use `AnnouncerSystem` in `BlobRuleSystem.cs`;
- [X] Blob language and Hivemind (from
https://github.com/Rxup/space-station-14/pull/176);
- [x] Change CVars location;
- [X] Add media.

---

<details><summary><h1>Media</h1></summary>
<p>
https://youtu.be/-WtMQwRcmrU?si=su3An6RtiCTZg-DV
</p>
</details>

---

🆑 VigersRay, Roudenn, Rxup, vladospupuos, fishbait and Kyoth25f
- add: Added a new antagonist: Blob

---------

Co-authored-by: fishbait <gnesse@gmail.com>
Co-authored-by: Fishbait <Fishbait@git.ml>
Co-authored-by: Aiden <aiden@djkraz.com>
Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com>
Co-authored-by: lanse12 <cloudability.ez@gmail.com>
Co-authored-by: BombasterDS <deniskaporoshok@gmail.com>
Co-authored-by: Aviu00 <93730715+Aviu00@users.noreply.github.com>
Co-authored-by: Piras314 <p1r4s@proton.me>
Co-authored-by: shibe <95730644+shibechef@users.noreply.github.com>
Co-authored-by: Ilya246 <57039557+Ilya246@users.noreply.github.com>
Co-authored-by: JohnOakman <sremy2012@hotmail.fr>
Co-authored-by: Fat Engineer Gaming <159075414+Fat-Engineer-Gaming@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Rouden <149893554+Roudenn@users.noreply.github.com>
2025-07-12 12:20:25 +10:00

121 lines
4.7 KiB
C#

using Content.Server.Actions;
using Content.Server.Language;
using Content.Server.Body.Systems;
using Content.Server.Ghost.Roles;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Mind;
using Content.Shared._Goobstation.Blob;
using Content.Shared._Goobstation.Blob.Components;
using Content.Shared.Language;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs;
using Robust.Shared.Map.Components;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Content.Shared.Language.Events;
using Content.Server._Goobstation.Blob.Systems;
namespace Content.Server._Goobstation.Blob;
public sealed class BlobCarrierSystem : SharedBlobCarrierSystem
{
[Dependency] private readonly BlobCoreSystem _blobCoreSystem = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly GhostRoleSystem _ghost = default!;
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly ActionsSystem _action = default!;
[Dependency] private readonly LanguageSystem _language = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BlobCarrierComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<BlobCarrierComponent, TransformToBlobActionEvent>(OnTransformToBlobChanged);
SubscribeLocalEvent<BlobCarrierComponent, MapInitEvent>(OnStartup);
SubscribeLocalEvent<BlobCarrierComponent, DetermineEntityLanguagesEvent>(OnApplyLang);
SubscribeLocalEvent<BlobCarrierComponent, ComponentRemove>(OnRemove);
SubscribeLocalEvent<BlobCarrierComponent, MindAddedMessage>(OnMindAdded);
SubscribeLocalEvent<BlobCarrierComponent, MindRemovedMessage>(OnMindRemove);
}
[ValidatePrototypeId<EntityPrototype>]
private const string ActionTransformToBlob = "ActionTransformToBlob";
[ValidatePrototypeId<LanguagePrototype>]
private const string BlobLang = "Blob";
private void OnApplyLang(Entity<BlobCarrierComponent> ent, ref DetermineEntityLanguagesEvent args)
{
if(ent.Comp.LifeStage is
ComponentLifeStage.Removing
or ComponentLifeStage.Stopping
or ComponentLifeStage.Stopped)
return;
args.SpokenLanguages.Add(BlobLang);
args.UnderstoodLanguages.Add(BlobLang);
}
private void OnRemove(Entity<BlobCarrierComponent> ent, ref ComponentRemove args) => _language.UpdateEntityLanguages(ent.Owner);
private void OnMindAdded(EntityUid uid, BlobCarrierComponent component, MindAddedMessage args) => component.HasMind = true;
private void OnMindRemove(EntityUid uid, BlobCarrierComponent component, MindRemovedMessage args) => component.HasMind = false;
private void OnTransformToBlobChanged(Entity<BlobCarrierComponent> uid, ref TransformToBlobActionEvent args) => TransformToBlob(uid);
private void OnStartup(EntityUid uid, BlobCarrierComponent component, MapInitEvent args)
{
_language.UpdateEntityLanguages(uid);
_action.AddAction(uid, ref component.TransformToBlob, ActionTransformToBlob);
//EnsureComp<BlobSpeakComponent>(uid).OverrideName = false;
if (HasComp<ActorComponent>(uid))
return;
var ghostRole = EnsureComp<GhostRoleComponent>(uid);
EnsureComp<GhostTakeoverAvailableComponent>(uid);
ghostRole.RoleName = Loc.GetString("blob-carrier-role-name");
ghostRole.RoleDescription = Loc.GetString("blob-carrier-role-desc");
ghostRole.RoleRules = Loc.GetString("blob-carrier-role-rules");
}
private void OnMobStateChanged(Entity<BlobCarrierComponent> uid, ref MobStateChangedEvent args)
{
if (args.NewMobState == MobState.Dead)
{
TransformToBlob(uid);
}
}
protected override void TransformToBlob(Entity<BlobCarrierComponent> ent)
{
var xform = Transform(ent);
if (!HasComp<MapGridComponent>(xform.GridUid))
return;
if (_mind.TryGetMind(ent, out _, out var mind) && mind.UserId != null)
{
var core = Spawn(ent.Comp.CoreBlobPrototype, xform.Coordinates);
var ghostRoleComp = EnsureComp<GhostRoleComponent>(core);
// Unfortunately we have to manually turn this off so we don't need to make more prototypes.
_ghost.UnregisterGhostRole((core, ghostRoleComp));
if (!TryComp<BlobCoreComponent>(core, out var blobCoreComponent))
return;
_blobCoreSystem.CreateBlobObserver(core, mind.UserId.Value, blobCoreComponent);
}
else
{
Spawn(ent.Comp.CoreBlobPrototype, xform.Coordinates);
}
_bodySystem.GibBody(ent);
}
}