Skip to content

Commit

Permalink
Merge branch 'master' into showers
Browse files Browse the repository at this point in the history
  • Loading branch information
SleepyScarecrow authored Aug 6, 2024
2 parents 0fe7bc0 + 5fcec47 commit 8cca382
Show file tree
Hide file tree
Showing 132 changed files with 3,374 additions and 1,002 deletions.
72 changes: 0 additions & 72 deletions Content.IntegrationTests/Tests/Nyanotrasen/Oracle/OracleTest.cs

This file was deleted.

231 changes: 231 additions & 0 deletions Content.Server/Arachne/ArachneSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
using Content.Shared.Arachne;
using Content.Shared.Actions;
using Content.Shared.IdentityManagement;
using Content.Shared.Verbs;
using Content.Shared.Buckle.Components;
using Content.Shared.DoAfter;
using Content.Shared.Stunnable;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Damage;
using Content.Shared.Inventory;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.Humanoid;
using Content.Shared.Nutrition.EntitySystems;
using Content.Server.Buckle.Systems;
using Content.Server.Popups;
using Content.Server.DoAfter;
using Content.Server.Body.Components;
using Content.Server.Vampiric;
using Content.Server.Speech.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Containers;
using Robust.Shared.Map;
using Robust.Shared.Utility;
using Robust.Server.Console;

namespace Content.Server.Arachne
{
public sealed class ArachneSystem : EntitySystem
{
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly BuckleSystem _buckleSystem = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly BlindableSystem _blindableSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;

[Dependency] private readonly IServerConsoleHost _host = default!;
[Dependency] private readonly BloodSuckerSystem _bloodSuckerSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;

private const string BodySlot = "body_slot";

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ArachneComponent, GetVerbsEvent<InnateVerb>>(AddCocoonVerb);

SubscribeLocalEvent<CocoonComponent, EntInsertedIntoContainerMessage>(OnCocEntInserted);
SubscribeLocalEvent<CocoonComponent, EntRemovedFromContainerMessage>(OnCocEntRemoved);
SubscribeLocalEvent<CocoonComponent, DamageChangedEvent>(OnDamageChanged);
SubscribeLocalEvent<CocoonComponent, GetVerbsEvent<AlternativeVerb>>(AddSuccVerb);
SubscribeLocalEvent<ArachneComponent, ArachneCocoonDoAfterEvent>(OnCocoonDoAfter);
}

private void AddCocoonVerb(EntityUid uid, ArachneComponent component, GetVerbsEvent<InnateVerb> args)
{
if (!args.CanAccess || !args.CanInteract)
return;

if (args.Target == uid)
return;

if (!TryComp<BloodstreamComponent>(args.Target, out var bloodstream))
return;

if (bloodstream.BloodReagent != component.WebBloodReagent)
return;

InnateVerb verb = new()
{
Act = () =>
{
StartCocooning(uid, component, args.Target);
},
Text = Loc.GetString("cocoon"),
Priority = 2
};
args.Verbs.Add(verb);
}

private void OnCocEntInserted(EntityUid uid, CocoonComponent component, EntInsertedIntoContainerMessage args)
{
_blindableSystem.UpdateIsBlind(args.Entity);
EnsureComp<StunnedComponent>(args.Entity);

if (TryComp<ReplacementAccentComponent>(args.Entity, out var currentAccent))
{
component.WasReplacementAccent = true;
component.OldAccent = currentAccent.Accent;
currentAccent.Accent = "mumble";
} else
{
component.WasReplacementAccent = false;
var replacement = EnsureComp<ReplacementAccentComponent>(args.Entity);
replacement.Accent = "mumble";
}
}

private void OnCocEntRemoved(EntityUid uid, CocoonComponent component, EntRemovedFromContainerMessage args)
{
if (component.WasReplacementAccent && TryComp<ReplacementAccentComponent>(args.Entity, out var replacement))
{
replacement.Accent = component.OldAccent;
} else
{
RemComp<ReplacementAccentComponent>(args.Entity);
}

RemComp<StunnedComponent>(args.Entity);
_blindableSystem.UpdateIsBlind(args.Entity);
}

private void OnDamageChanged(EntityUid uid, CocoonComponent component, DamageChangedEvent args)
{
if (!args.DamageIncreased)
return;

if (args.DamageDelta == null)
return;

var body = _itemSlots.GetItemOrNull(uid, BodySlot);

if (body == null)
return;

var damage = args.DamageDelta * component.DamagePassthrough;
_damageableSystem.TryChangeDamage(body, damage);
}

private void AddSuccVerb(EntityUid uid, CocoonComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanAccess || !args.CanInteract)
return;

if (!TryComp<BloodSuckerComponent>(args.User, out var sucker))
return;

if (!sucker.WebRequired)
return;

var victim = _itemSlots.GetItemOrNull(uid, BodySlot);

if (victim == null)
return;

if (!TryComp<BloodstreamComponent>(victim, out var stream))
return;

AlternativeVerb verb = new()
{
Act = () =>
{
_bloodSuckerSystem.StartSuccDoAfter(args.User, victim.Value, sucker, stream, false); // start doafter
},
Text = Loc.GetString("action-name-suck-blood"),
Icon = new SpriteSpecifier.Texture(new ("/Textures/Nyanotrasen/Icons/verbiconfangs.png")),
Priority = 2
};
args.Verbs.Add(verb);
}

private void OnEntRemoved(EntityUid uid, WebComponent web, EntRemovedFromContainerMessage args)
{
if (!TryComp<StrapComponent>(uid, out var strap))
return;

if (HasComp<ArachneComponent>(args.Entity))
_buckleSystem.StrapSetEnabled(uid, false, strap);
}

private void StartCocooning(EntityUid uid, ArachneComponent component, EntityUid target)
{
_popupSystem.PopupEntity(Loc.GetString("cocoon-start-third-person", ("target", Identity.Entity(target, EntityManager)), ("spider", Identity.Entity(uid, EntityManager))), uid,
Shared.Popups.PopupType.MediumCaution);

_popupSystem.PopupEntity(Loc.GetString("cocoon-start-second-person", ("target", Identity.Entity(target, EntityManager))), uid, uid, Shared.Popups.PopupType.Medium);

var delay = component.CocoonDelay;

if (HasComp<KnockedDownComponent>(target))
delay *= component.CocoonKnockdownMultiplier;

// Is it good practice to use empty data just to disambiguate doafters
// Who knows, there's no docs!
var ev = new ArachneCocoonDoAfterEvent();

var args = new DoAfterArgs(EntityManager, uid, delay, ev, uid, target: target)
{
BreakOnUserMove = true,
BreakOnTargetMove = true,
};

_doAfter.TryStartDoAfter(args);
}

private void OnCocoonDoAfter(EntityUid uid, ArachneComponent component, ArachneCocoonDoAfterEvent args)
{
if (args.Handled || args.Cancelled || args.Args.Target == null)
return;

var spawnProto = HasComp<HumanoidAppearanceComponent>(args.Args.Target) ? "CocoonedHumanoid" : "CocoonSmall";
Transform(args.Args.Target.Value).AttachToGridOrMap();
var cocoon = Spawn(spawnProto, Transform(args.Args.Target.Value).Coordinates);

if (!TryComp<ItemSlotsComponent>(cocoon, out var slots))
return;

// todo: our species should use scale visuals probably...
// TODO: We need a client-accessible notion of scale influence here.
/* if (spawnProto == "CocoonedHumanoid" && TryComp<SpriteComponent>(args.Args.Target.Value, out var sprite)) */
/* { */
/* // why the fuck is this only available as a console command. */
/* _host.ExecuteCommand(null, "scale " + cocoon + " " + sprite.Scale.Y); */
if (TryComp<PhysicsComponent>(args.Args.Target.Value, out var physics))
{
var scale = Math.Clamp(1 / (35 / physics.FixturesMass), 0.35, 2.5);
_host.ExecuteCommand(null, "scale " + cocoon + " " + scale);
}
_itemSlots.SetLock(cocoon, BodySlot, false, slots);
_itemSlots.TryInsert(cocoon, BodySlot, args.Args.Target.Value, args.Args.User);
_itemSlots.SetLock(cocoon, BodySlot, true, slots);

var impact = (spawnProto == "CocoonedHumanoid") ? LogImpact.High : LogImpact.Medium;

_adminLogger.Add(LogType.Action, impact, $"{ToPrettyString(args.Args.User):player} cocooned {ToPrettyString(args.Args.Target.Value):target}");
args.Handled = true;
}
}
}
13 changes: 13 additions & 0 deletions Content.Server/Arachne/CocoonComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Content.Server.Arachne
{
[RegisterComponent]
public sealed partial class CocoonComponent : Component
{
public bool WasReplacementAccent = false;

public string OldAccent = "";

[DataField("damagePassthrough")]
public float DamagePassthrough = 0.5f;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Content.Shared.Database;
using Content.Shared.Interaction;
using Content.Shared.Lock;
using Content.Server.Silicons.Borgs.Components;
using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
Expand Down Expand Up @@ -91,6 +92,10 @@ private void DirtyUI(EntityUid uid,
if (canister.GasTankSlot.Item != null)
{
var tank = canister.GasTankSlot.Item.Value;
if (TryComp<BorgJetpackComponent>(tank, out var jetpack) && jetpack.JetpackUid.HasValue)
{
tank = jetpack.JetpackUid.Value;
}
var tankComponent = Comp<GasTankComponent>(tank);
tankLabel = Name(tank);
tankPressure = tankComponent.Air.Pressure;
Expand Down Expand Up @@ -163,7 +168,12 @@ private void OnCanisterUpdated(EntityUid uid, GasCanisterComponent canister, ref
{
if (canister.GasTankSlot.Item != null)
{
var gasTank = Comp<GasTankComponent>(canister.GasTankSlot.Item.Value);
var tank = canister.GasTankSlot.Item;
if (TryComp<BorgJetpackComponent>(tank, out var jetpack) && jetpack.JetpackUid.HasValue)
{
tank = jetpack.JetpackUid.Value;
}
var gasTank = Comp<GasTankComponent>(tank.Value);
_atmos.ReleaseGasTo(canister.Air, gasTank.Air, canister.ReleasePressure);
}
else
Expand Down Expand Up @@ -233,7 +243,19 @@ private void OnCanisterInsertAttempt(EntityUid uid, GasCanisterComponent compone
if (args.Slot.ID != component.ContainerName || args.User == null)
return;

if (!TryComp<GasTankComponent>(args.Item, out var gasTank) || gasTank.IsValveOpen)
var tank = args.Item;

if (TryComp<BorgJetpackComponent>(tank, out var jetpack))
{
if (!jetpack.JetpackUid.HasValue)
{
args.Cancelled = true;
return;
}
tank = jetpack.JetpackUid.Value;
}

if (!TryComp<GasTankComponent>(tank, out var gasTank) || gasTank.IsValveOpen)
{
args.Cancelled = true;
return;
Expand Down
Loading

0 comments on commit 8cca382

Please sign in to comment.