Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Content.Server._Maid.Terminator.EntitySystems;
using Robust.Shared.Serialization.TypeSerializers.Implementations;

namespace Content.Server._Maid.Terminator.Components;

[RegisterComponent, Access(typeof(HeatOverTimeSystem))]
public sealed partial class HeatOverTimeComponent : Component
{
[DataField(required: true)]
public float Heat { get; set; }

[DataField]
public float FireStacks { get; set; }

[DataField(customTypeSerializer: typeof(TimespanSerializer))]
public TimeSpan Interval = TimeSpan.FromSeconds(1);

[DataField]
public TimeSpan NextTickTime = TimeSpan.Zero;

[DataField]
public bool IgnoreHeatResistance { get; set; } = false;

[DataField]
public float MultiplierIncrease { get; set; }

[DataField]
public float Multiplier { get; set; } = 1f;

[DataField]
public float FireProtectionPenetration { get; set; }
}
10 changes: 10 additions & 0 deletions Content.Server/_Maid/Terminator/Components/SpawnOnGibComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Robust.Shared.Prototypes;

namespace Content.Server._Maid.Terminator.Components;

[RegisterComponent]
public sealed partial class SpawnOnGibComponent : Component
{
[DataField] public EntProtoId? Prototype;
[DataField] public bool TransferMind = false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

using Content.Server._Maid.Terminator.Components;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Temperature.Systems;
using Content.Shared.Atmos.Components;
using Robust.Shared.Timing;

namespace Content.Server._Maid.Terminator.EntitySystems;

public sealed class HeatOverTimeSystem : EntitySystem
{
[Dependency] private readonly FlammableSystem _flammable = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly TemperatureSystem _temperature = default!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HeatOverTimeComponent, ComponentStartup>(OnStartup);
}

private void OnStartup(EntityUid uid, HeatOverTimeComponent component, ref ComponentStartup args)
{
if (component.NextTickTime == TimeSpan.Zero)
component.NextTickTime = _timing.CurTime;
}

public override void Update(float frameTime)
{
var currentTime = _timing.CurTime;
var query = EntityQueryEnumerator<HeatOverTimeComponent, FlammableComponent>();

while (query.MoveNext(out var uid, out var heatOverTimeComponent, out var flammableComponent))
{
if (heatOverTimeComponent.Interval <= TimeSpan.Zero)
continue;

while (currentTime >= heatOverTimeComponent.NextTickTime)
{
_temperature.ChangeHeat(uid, heatOverTimeComponent.Heat * heatOverTimeComponent.Multiplier, heatOverTimeComponent.IgnoreHeatResistance);
if (heatOverTimeComponent.FireStacks > 0f)
{
_flammable.AdjustFireStacks(uid,
heatOverTimeComponent.FireStacks * heatOverTimeComponent.Multiplier,
null,
true,
heatOverTimeComponent.FireProtectionPenetration);
}

heatOverTimeComponent.Multiplier += heatOverTimeComponent.MultiplierIncrease;
heatOverTimeComponent.NextTickTime += heatOverTimeComponent.Interval;
}
}
}
}
32 changes: 32 additions & 0 deletions Content.Server/_Maid/Terminator/EntitySystems/SpawnOnGibSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Content.Server._Maid.Terminator.Components;
using Content.Server.Mind;
using Content.Shared.Body.Events;

namespace Content.Server._Maid.Terminator.EntitySystems;

// SpawnOnDespawnSystem will not do the trick cause no easy way to transfer mind without changing SpawnOnDespawnSystem itself
public sealed class SpawnOnGibSystem : EntitySystem
{
[Dependency] private MindSystem _mindSystem = default!;

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

SubscribeLocalEvent<SpawnOnGibComponent, BeingGibbedEvent>(OnGibbed);
}

private void OnGibbed(Entity<SpawnOnGibComponent> ent, ref BeingGibbedEvent args)
{
if (!TryComp(ent, out TransformComponent? xform)) return;

if (ent.Comp.Prototype == null) return;

var spawned = Spawn(ent.Comp.Prototype, xform.Coordinates);

if (ent.Comp.TransferMind && _mindSystem.TryGetMind(ent, out var mindId, out var mindComponent))
{
_mindSystem.TransferTo(mindId, spawned);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Content.Shared.Whitelist;
using Robust.Shared.Audio;

namespace Content.Server._Maid.Terminator.GameTicking.Rules;

[RegisterComponent]
public sealed partial class TerminatorRuleComponent : Component
{
[DataField]
public SoundSpecifier? BriefingSound;

[DataField]
public EntityWhitelist? TargetBlacklist;

[DataField]
public EntityUid? Target;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Content.Server._Maid.Terminator.Roles;
using Content.Server.Antag;
using Content.Server.Body.Components;
using Content.Server.GameTicking.Rules;
using Content.Server.Mind;
using Content.Server.Objectives.Components;
using Content.Server.Roles;
using Content.Shared.GameTicking.Components;
using Content.Shared.Roles;
using Content.Shared.Roles.Jobs;
using Content.Shared.Whitelist;
using Robust.Shared.Random;

namespace Content.Server._Maid.Terminator.GameTicking.Rules;

public sealed class TerminatorRuleSystem : GameRuleSystem<TerminatorRuleComponent>
{
[Dependency] private readonly AntagSelectionSystem _antag = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly SharedJobSystem _jobs = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedRoleSystem _role = default!;

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

SubscribeLocalEvent<TerminatorRuleComponent, AntagSelectEntityEvent>(OnAntagSelectEntity);
SubscribeLocalEvent<TerminatorRuleComponent, AfterAntagEntitySelectedEvent>(AfterAntagSelected);
}

private void OnAntagSelectEntity(Entity<TerminatorRuleComponent> ent, ref AntagSelectEntityEvent args)
{
var allAliveHumanoids = _mind.GetAliveHumans();
allAliveHumanoids.RemoveWhere(human => _whitelist.IsBlacklistPass(ent.Comp.TargetBlacklist, human));

if (allAliveHumanoids.Count == 0)
{
Log.Warning("Could not find any alive players to create a terminator for!");
return;
}

// pick a random player
var randomHumanoidMind = _random.Pick(allAliveHumanoids);

ent.Comp.Target = randomHumanoidMind;
}

private void AfterAntagSelected(Entity<TerminatorRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
{
var targetComp = EnsureComp<TargetOverrideComponent>(args.EntityUid);
targetComp.Target = ent.Comp.Target;

RemComp<RespiratorComponent>(args.EntityUid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Content.Shared.Roles;

namespace Content.Server._Maid.Terminator.Roles;

[RegisterComponent]
public sealed partial class TerminatorRoleComponent : BaseMindRoleComponent
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Content.Shared.Popups;

namespace Content.Server._Maid.Triggers.Components;

/// <summary>
/// Displays a popup on a target entity when this entity is triggered.
/// </summary>
[RegisterComponent]
public sealed partial class PopupOnTriggerComponent : Component
{
[DataField(required: true)]
public string Popup = string.Empty;

[DataField]
public PopupType PopupType = PopupType.MediumCaution;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Content.Server.Explosion.EntitySystems;
using Content.Shared.Implants.Components;
using Content.Shared.Popups;
using Content.Shared.Trigger;

namespace Content.Server._Maid.Triggers.EntitySystems;

public sealed class PopupOnTriggerSystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popup = default!;

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

SubscribeLocalEvent<Components.PopupOnTriggerComponent, TriggerEvent>(OnPopupTrigger);
}

private void OnPopupTrigger(EntityUid uid, Components.PopupOnTriggerComponent component, ref TriggerEvent args)
{
if (!TryComp(uid, out SubdermalImplantComponent? implant) || implant.ImplantedEntity is null)
return;

_popup.PopupEntity(Loc.GetString(component.Popup), implant.ImplantedEntity.Value, component.PopupType);
args.Handled = true;
}
}
23 changes: 23 additions & 0 deletions Resources/Locale/en-US/_Maid/Terminator/terminator.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
terminator-round-end-agent-name = nt-800

objective-issuer-susnet = [color=#d64119]Susnet[/color]

terminator-role-greeting =
You are the Terminator, a relentless assassin sent into the past to secure our future.
Eliminate the target while minimizing changes to the timeline.

terminator-role-briefing = Kill the target at all costs.

terminator-endoskeleton-gib-popup = All the battered flesh falls apart, revealing a titanium endoskeleton!
terminator-endoskeleton-burn-popup = The seared flesh is burned to a crisp, revealing a titanium endoskeleton!

ghost-role-information-exterminator-name = Terminator
ghost-role-information-exterminator-description = You have been sent back in time to terminate a target with high importance to the future.
ghost-role-information-exterminator-rules =
You are an antagonist who must kill your target to preserve the future.
You must also minimize changes to the timeline by avoiding unnecessary casualties and station damage.

roles-antag-terminator-name = Terminator
roles-antag-terminator-objective = Kill the target while minimizing changes to the timeline. The future depends on it.

terminator-overheat-popup = Your internal systems start to overheat!
1 change: 1 addition & 0 deletions Resources/Locale/en-US/_Maid/mind/role-types.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
role-subtype-terminator = Terminator
1 change: 1 addition & 0 deletions Resources/Locale/en-US/objectives/conditions/terminate.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
objective-terminate-title = Terminate {$targetName}, {CAPITALIZE($job)}
23 changes: 23 additions & 0 deletions Resources/Locale/ru-RU/_Maid/Terminator/terminator.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
terminator-round-end-agent-name = nt-800

objective-issuer-susnet = [color=#d64119]Susnet[/color]

terminator-role-greeting =
Вы - терминатор, безжалостный убийца, отправленный в прошлое, чтобы обеспечить наше будущее.
Устраните цель минимизируя изменения таймлайна.
Comment thread
CREAsTIVE marked this conversation as resolved.

terminator-role-briefing = Убейте цель любой ценой.

terminator-endoskeleton-gib-popup = Избитая плоть разваливается, обнажая титановый эндоскелет!
terminator-endoskeleton-burn-popup = Обугленная плоть сгорает дотла, обнажая титановый эндоскелет!

ghost-role-information-exterminator-name = Терминатор
ghost-role-information-exterminator-description = Вас отправили назад во времени, чтобы устранить цель, крайне важную для будущего.
ghost-role-information-exterminator-rules =
Вы антагонист, которому необходимо убить вашу цель для сохранения будущего.
Вам также необходимо минимизировать изменения таймлайна, избегая лишних жертв и порчи станции.

roles-antag-terminator-name = Терминатор
roles-antag-terminator-objective = Убейте цель, минимизируя изменения в таймлайне, от этого зависит будущее.

terminator-overheat-popup = Ваши внутренности начинают нагреваться!
Comment thread
CREAsTIVE marked this conversation as resolved.
1 change: 1 addition & 0 deletions Resources/Locale/ru-RU/_Maid/mind/role-types.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
role-subtype-terminator = Терминатор
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ent-ActionActivateTerminatorOverheat = Активировать имплант перегрева
.desc = Активирует ваш внутренний имплант перегрева, быстро повышая внутреннюю температуру тела сверх безопасных пределов.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ent-PartTerminatorBase = часть тела nt-800
ent-ChestTerminator = грудная клетка nt-800
ent-GroinTerminator = пах nt-800
ent-HeadTerminator = череп nt-800
.desc = Его красные глаза погасли... пока что.
ent-LeftArmTerminator = левая рука nt-800
ent-RightArmTerminator = правая рука nt-800
ent-LeftHandTerminator = левая кисть nt-800
ent-RightHandTerminator = правая кисть nt-800
ent-LeftLegTerminator = левая нога nt-800
ent-RightLegTerminator = правая нога nt-800
ent-LeftFootTerminator = левая стопа nt-800
ent-RightFootTerminator = правая стопа nt-800
ent-MobTerminatorEndoskeleton = эндоскелет nt-800 «Терминатор»
.desc = Внутреннее ядро андроидов-инфильтраторов Susnet.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ent-TerminatorOverheatImplant = имплант перегрева
.desc = Этот имплант быстро перегревает тело пользователя при активации.
ent-TerminatorSelfExplodeImplant = имплант микробомбы
.desc = Этот имплант взрывает пользователя при активации или после смерти.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ent-TerminateObjective = { ent-BaseObjective }
.desc = Следуйте своей программе и устраните цель.
ent-ShutDownObjective = Отключение.
.desc = После завершения миссии умрите, чтобы экипаж не смог завладеть технологиями будущего.
1 change: 1 addition & 0 deletions Resources/Locale/ru-RU/objectives/conditions/terminate.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
objective-terminate-title = Устранить {$targetName}, {CAPITALIZE($job)}
2 changes: 2 additions & 0 deletions Resources/Prototypes/GameRules/events.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@
# - id: SlasherSpawn # Goobstation - The Slasher #Maid
- id: SpacePirates # Goobstation - you probably can read whom this rule spawns
#- id: WraithMidround # Goobstation - Wraith
- id: TerminatorSpawn # Maid - Terminator
#TODO When Slasher is Ready - id: SlasherSpawn # Goobstation - The Slasher
#TODO when midrounds are "reviewed" by the chudmins add them back

- type: entity
Expand Down
Loading
Loading