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

Rodentia Code #2009

Merged
merged 13 commits into from
Sep 30, 2024
44 changes: 44 additions & 0 deletions Content.Client/DeltaV/Abilities/CrawlUnderObjectsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Content.Shared.DeltaV.Abilities;
using Content.Shared.Popups;
using Robust.Client.GameObjects;
using DrawDepth = Content.Shared.DrawDepth.DrawDepth;

namespace Content.Client.DeltaV.Abilities;

public sealed partial class HideUnderTableAbilitySystem : SharedCrawlUnderObjectsSystem
{
[Dependency] private readonly AppearanceSystem _appearance = default!;

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

SubscribeLocalEvent<CrawlUnderObjectsComponent, AppearanceChangeEvent>(OnAppearanceChange);
}

private void OnAppearanceChange(EntityUid uid,
CrawlUnderObjectsComponent component,
AppearanceChangeEvent args)
{
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;

_appearance.TryGetData(uid, SneakMode.Enabled, out bool enabled);
if (enabled)
{
if (component.OriginalDrawDepth != null)
return;

component.OriginalDrawDepth = sprite.DrawDepth;
sprite.DrawDepth = (int) DrawDepth.SmallMobs;
}
else
{
if (component.OriginalDrawDepth == null)
return;

sprite.DrawDepth = (int) component.OriginalDrawDepth;
component.OriginalDrawDepth = null;
}
}
}
140 changes: 140 additions & 0 deletions Content.Server/DeltaV/Abilities/CrawlUnderObjectsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
using Content.Shared.Actions;
using Content.Shared.Climbing.Components;
using Content.Shared.Climbing.Events;
using Content.Shared.DeltaV.Abilities;
using Content.Shared.Maps;
using Content.Shared.Movement.Systems;
using Content.Shared.Physics;
using Robust.Server.GameObjects;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Systems;

namespace Content.Server.DeltaV.Abilities;

public sealed partial class CrawlUnderObjectsSystem : SharedCrawlUnderObjectsSystem
{
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movespeed = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly TurfSystem _turf = default!;

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

SubscribeLocalEvent<CrawlUnderObjectsComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<CrawlUnderObjectsComponent, ToggleCrawlingStateEvent>(OnAbilityToggle);
SubscribeLocalEvent<CrawlUnderObjectsComponent, AttemptClimbEvent>(OnAttemptClimb);
SubscribeLocalEvent<CrawlUnderObjectsComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
}

private bool IsOnCollidingTile(EntityUid uid)
{
var xform = Transform(uid);
var tile = xform.Coordinates.GetTileRef();
if (tile == null)
return false;

return _turf.IsTileBlocked(tile.Value, CollisionGroup.MobMask);
}

private void OnInit(EntityUid uid, CrawlUnderObjectsComponent component, ComponentInit args)
{
if (component.ToggleHideAction != null)
return;

_actionsSystem.AddAction(uid, ref component.ToggleHideAction, component.ActionProto);
}

private bool EnableSneakMode(EntityUid uid, CrawlUnderObjectsComponent component)
{
if (component.Enabled
|| (TryComp<ClimbingComponent>(uid, out var climbing)
&& climbing.IsClimbing == true))
return false;

component.Enabled = true;
Dirty(uid, component);
RaiseLocalEvent(uid, new CrawlingUpdatedEvent(component.Enabled));

if (TryComp(uid, out FixturesComponent? fixtureComponent))
{
foreach (var (key, fixture) in fixtureComponent.Fixtures)
{
var newMask = (fixture.CollisionMask
& (int)~CollisionGroup.HighImpassable
& (int)~CollisionGroup.MidImpassable)
| (int)CollisionGroup.InteractImpassable;
if (fixture.CollisionMask == newMask)
continue;

component.ChangedFixtures.Add((key, fixture.CollisionMask));
_physics.SetCollisionMask(uid,
key,
fixture,
newMask,
manager: fixtureComponent);
}
}
return true;
}

private bool DisableSneakMode(EntityUid uid, CrawlUnderObjectsComponent component)
{
if (!component.Enabled
|| IsOnCollidingTile(uid)
|| (TryComp<ClimbingComponent>(uid, out var climbing)
&& climbing.IsClimbing == true))
return false;

component.Enabled = false;
Dirty(uid, component);
RaiseLocalEvent(uid, new CrawlingUpdatedEvent(component.Enabled));

// Restore normal collision masks
if (TryComp(uid, out FixturesComponent? fixtureComponent))
foreach (var (key, originalMask) in component.ChangedFixtures)
if (fixtureComponent.Fixtures.TryGetValue(key, out var fixture))
_physics.SetCollisionMask(uid, key, fixture, originalMask, fixtureComponent);

component.ChangedFixtures.Clear();
return true;
}

private void OnAbilityToggle(EntityUid uid,
CrawlUnderObjectsComponent component,
ToggleCrawlingStateEvent args)
{
if (args.Handled)
return;

bool result;

if (component.Enabled)
result = DisableSneakMode(uid, component);
else
result = EnableSneakMode(uid, component);

if (TryComp<AppearanceComponent>(uid, out var app))
_appearance.SetData(uid, SneakMode.Enabled, component.Enabled, app);

_movespeed.RefreshMovementSpeedModifiers(uid);

args.Handled = result;
}

private void OnAttemptClimb(EntityUid uid,
CrawlUnderObjectsComponent component,
AttemptClimbEvent args)
{
if (component.Enabled == true)
args.Cancelled = true;
}

private void OnRefreshMovespeed(EntityUid uid, CrawlUnderObjectsComponent component, RefreshMovementSpeedModifiersEvent args)
{
if (component.Enabled)
args.ModifySpeed(component.SneakSpeedModifier, component.SneakSpeedModifier);
}
}
41 changes: 41 additions & 0 deletions Content.Server/DeltaV/Storage/EntitySystems/MouthStorageSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Content.Server.Nutrition;
using Content.Server.Speech;
using Content.Server.Speech.EntitySystems;
using Content.Shared.DeltaV.Storage.Components;
using Content.Shared.DeltaV.Storage.EntitySystems;
using Content.Shared.Storage;

namespace Content.Server.DeltaV.Storage.EntitySystems;

public sealed class MouthStorageSystem : SharedMouthStorageSystem
{
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<MouthStorageComponent, AccentGetEvent>(OnAccent);
SubscribeLocalEvent<MouthStorageComponent, IngestionAttemptEvent>(OnIngestAttempt);
}

// Force you to mumble if you have items in your mouth
private void OnAccent(EntityUid uid, MouthStorageComponent component, AccentGetEvent args)
{
if (IsMouthBlocked(component))
args.Message = _replacement.ApplyReplacements(args.Message, "mumble");
}

// Attempting to eat or drink anything with items in your mouth won't work
private void OnIngestAttempt(EntityUid uid, MouthStorageComponent component, IngestionAttemptEvent args)
{
if (!IsMouthBlocked(component))
return;

if (!TryComp<StorageComponent>(component.MouthId, out var storage))
return;

var firstItem = storage.Container.ContainedEntities[0];
args.Blocker = firstItem;
args.Cancel();
}
}
5 changes: 5 additions & 0 deletions Content.Server/Mousetrap/MousetrapSystem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Content.Server.Damage.Systems;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Popups;
using Content.Shared.Abilities;
using Content.Shared.Interaction.Events;
using Content.Shared.Inventory;
using Content.Shared.Mousetrap;
Expand Down Expand Up @@ -39,6 +40,10 @@ private void OnUseInHand(EntityUid uid, MousetrapComponent component, UseInHandE

private void OnStepTriggerAttempt(EntityUid uid, MousetrapComponent component, ref StepTriggerAttemptEvent args)
{
// DeltaV: Entities with this component always trigger mouse traps, even if wearing shoes
if (HasComp<AlwaysTriggerMousetrapComponent>(args.Tripper))
args.Cancelled = false;

args.Continue |= component.IsActive;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Abilities;

[RegisterComponent, NetworkedComponent]
public sealed partial class AlwaysTriggerMousetrapComponent : Component;
47 changes: 47 additions & 0 deletions Content.Shared/DeltaV/Abilities/CrawlUnderObjectsComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Content.Shared.Actions;
using DrawDepth = Content.Shared.DrawDepth.DrawDepth;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;

namespace Content.Shared.DeltaV.Abilities;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class CrawlUnderObjectsComponent : Component
{
[DataField]
public EntityUid? ToggleHideAction;

[DataField]
public EntProtoId? ActionProto;

[DataField]
public bool Enabled = false;

/// <summary>
/// List of fixtures that had their collision mask changed.
/// Required for re-adding the collision mask.
/// </summary>
[DataField, AutoNetworkedField]
public List<(string key, int originalMask)> ChangedFixtures = new();

[DataField]
public int? OriginalDrawDepth;

[DataField]
public float SneakSpeedModifier = 0.7f;
}

[Serializable, NetSerializable]
public enum SneakMode : byte
{
Enabled
}

public sealed partial class ToggleCrawlingStateEvent : InstantActionEvent { }

[Serializable, NetSerializable]
public sealed partial class CrawlingUpdatedEvent(bool enabled = false) : EventArgs
{
public readonly bool Enabled = enabled;
}
5 changes: 5 additions & 0 deletions Content.Shared/DeltaV/Abilities/RummagerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Abilities;

[RegisterComponent, NetworkedComponent]
public sealed partial class RummagerComponent : Component;
25 changes: 25 additions & 0 deletions Content.Shared/DeltaV/Abilities/SharedCrawlUnderObjectsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

using Content.Shared.Popups;

namespace Content.Shared.DeltaV.Abilities;
public abstract class SharedCrawlUnderObjectsSystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popup = default!;

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

SubscribeLocalEvent<CrawlUnderObjectsComponent, CrawlingUpdatedEvent>(OnCrawlingUpdated);
}

private void OnCrawlingUpdated(EntityUid uid,
CrawlUnderObjectsComponent component,
CrawlingUpdatedEvent args)
{
if (args.Enabled)
_popup.PopupEntity(Loc.GetString("crawl-under-objects-toggle-on"), uid);
else
_popup.PopupEntity(Loc.GetString("crawl-under-objects-toggle-off"), uid);
}
}
32 changes: 32 additions & 0 deletions Content.Shared/DeltaV/Storage/Components/MouthStorageComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Content.Shared.DeltaV.Storage.EntitySystems;
using Content.Shared.FixedPoint;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared.DeltaV.Storage.Components;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedMouthStorageSystem))]
public sealed partial class MouthStorageComponent : Component
{
public const string MouthContainerId = "mouth";

[DataField, AutoNetworkedField]
public EntProtoId? OpenStorageAction;

[DataField, AutoNetworkedField]
public EntityUid? Action;

[DataField]
public EntProtoId MouthProto = "ActionOpenMouthStorage";

[ViewVariables]
public Container Mouth = default!;

[DataField]
public EntityUid? MouthId;

// Mimimum inflicted damage on hit to spit out items
[DataField]
public FixedPoint2 SpitDamageThreshold = FixedPoint2.New(2);
}
Loading
Loading