Skip to content

Commit

Permalink
Merge pull request Simple-Station#208 from Memeji/Nikko-Species
Browse files Browse the repository at this point in the history
Rodentia Species
  • Loading branch information
FoxxoTrystan authored Sep 27, 2024
2 parents a9de443 + 7f354a5 commit 003066d
Show file tree
Hide file tree
Showing 122 changed files with 2,530 additions and 41 deletions.
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.Mousetrap;
using Content.Shared.StepTrigger.Systems;
Expand Down Expand Up @@ -35,6 +36,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;
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;
33 changes: 33 additions & 0 deletions Content.Shared/DeltaV/Storage/Components/MouthStorageComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using Content.Shared.Actions;
using Content.Shared.CombatMode;
using Content.Shared.Damage;
using Content.Shared.DeltaV.Storage.Components;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Content.Shared.Standing;
using Content.Shared.Storage;
using Content.Shared.Storage.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.Map;

namespace Content.Shared.DeltaV.Storage.EntitySystems;

public abstract class SharedMouthStorageSystem : EntitySystem
{
[Dependency] private readonly DumpableSystem _dumpableSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;

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

SubscribeLocalEvent<MouthStorageComponent, MapInitEvent>(OnMouthStorageInit);
SubscribeLocalEvent<MouthStorageComponent, DownedEvent>(DropAllContents);
SubscribeLocalEvent<MouthStorageComponent, DisarmedEvent>(DropAllContents);
SubscribeLocalEvent<MouthStorageComponent, DamageChangedEvent>(OnDamageModified);
SubscribeLocalEvent<MouthStorageComponent, ExaminedEvent>(OnExamined);
}

protected bool IsMouthBlocked(MouthStorageComponent component)
{
if (!TryComp<StorageComponent>(component.MouthId, out var storage))
return false;

return storage.Container.ContainedEntities.Count > 0;
}

private void OnMouthStorageInit(EntityUid uid, MouthStorageComponent component, MapInitEvent args)
{
if (string.IsNullOrWhiteSpace(component.MouthProto))
return;

component.Mouth = _containerSystem.EnsureContainer<Container>(uid, MouthStorageComponent.MouthContainerId);
component.Mouth.ShowContents = false;
component.Mouth.OccludesLight = false;

var mouth = Spawn(component.MouthProto, new EntityCoordinates(uid, 0, 0));
_containerSystem.Insert(mouth, component.Mouth);
component.MouthId = mouth;

if (!string.IsNullOrWhiteSpace(component.OpenStorageAction) && component.Action == null)
_actionsSystem.AddAction(uid, ref component.Action, component.OpenStorageAction, mouth);
}

private void DropAllContents(EntityUid uid, MouthStorageComponent component, EntityEventArgs args)
{
if (component.MouthId == null)
return;

_dumpableSystem.DumpContents(component.MouthId.Value, uid, uid);
}

private void OnDamageModified(EntityUid uid, MouthStorageComponent component, DamageChangedEvent args)
{
if (args.DamageDelta == null
|| !args.DamageIncreased
|| args.DamageDelta.GetTotal() < component.SpitDamageThreshold)
return;

DropAllContents(uid, component, args);
}

// Other people can see if this person has items in their mouth.
private void OnExamined(EntityUid uid, MouthStorageComponent component, ExaminedEvent args)
{
if (IsMouthBlocked(component))
{
var subject = Identity.Entity(uid, EntityManager);
args.PushMarkup(Loc.GetString("mouth-storage-examine-condition-occupied", ("entity", subject)));
}
}
}
3 changes: 3 additions & 0 deletions Content.Shared/Humanoid/NamingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ public string GetName(string species, Gender? gender = null)
case SpeciesNaming.FirstDashFirst:
return Loc.GetString("namepreset-firstdashfirst",
("first1", GetFirstName(speciesProto, gender)), ("first2", GetFirstName(speciesProto, gender)));
case SpeciesNaming.LastFirst: // DeltaV: Rodentia name scheme
return Loc.GetString("namepreset-lastfirst",
("last", GetLastName(speciesProto)), ("first", GetFirstName(speciesProto, gender)));
case SpeciesNaming.FirstDashLast:
return Loc.GetString("namepreset-firstdashlast",
("first", GetFirstName(speciesProto, gender)), ("last", GetLastName(speciesProto)));
Expand Down
1 change: 1 addition & 0 deletions Content.Shared/Humanoid/Prototypes/SpeciesPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,5 @@ public enum SpeciesNaming : byte
//End of Nyano - Summary: for Oni naming
TheFirstofLast,
FirstDashLast,
LastFirst, // DeltaV
}
14 changes: 13 additions & 1 deletion Content.Shared/RatKing/RatKingRummageableComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Content.Shared.Random;
using Content.Shared.Random;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
Expand All @@ -20,6 +20,18 @@ public sealed partial class RatKingRummageableComponent : Component
[AutoNetworkedField]
public bool Looted;

/// <summary>
/// DeltaV: Last time the object was looted, used to check if cooldown has expired
/// </summary>
[ViewVariables]
public TimeSpan? LastLooted;

/// <summary>
/// DeltaV: Minimum time between rummage attempts
/// </summary>
[DataField, AutoNetworkedField]
public TimeSpan RummageCooldown = TimeSpan.FromMinutes(5);

/// <summary>
/// How long it takes to rummage through a rummageable container.
/// </summary>
Expand Down
20 changes: 16 additions & 4 deletions Content.Shared/RatKing/SharedRatKingSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Shared.Actions;
using Content.Shared.Actions;
using Content.Shared.Abilities; // DeltavV
using Content.Shared.DoAfter;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
Expand All @@ -9,11 +10,13 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;

namespace Content.Shared.RatKing;

public abstract class SharedRatKingSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!; // DeltaV - Used for rummage cooldown
[Dependency] private readonly INetManager _net = default!;
[Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
[Dependency] protected readonly IRobustRandom Random = default!;
Expand Down Expand Up @@ -105,7 +108,10 @@ private void UpdateActions(EntityUid uid, RatKingComponent? component = null)

private void OnGetVerb(EntityUid uid, RatKingRummageableComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!HasComp<RatKingComponent>(args.User) || component.Looted)
// DeltaV - Use RummagerComponent instead of RatKingComponent
// (This is so we can give Rodentia rummage abilities)
// Additionally, adds a cooldown check
if (!HasComp<RummagerComponent>(args.User) || component.Looted || _gameTiming.CurTime < component.LastLooted + component.RummageCooldown)
return;

args.Verbs.Add(new AlternativeVerb
Expand All @@ -128,10 +134,16 @@ private void OnGetVerb(EntityUid uid, RatKingRummageableComponent component, Get

private void OnDoAfterComplete(EntityUid uid, RatKingRummageableComponent component, RatKingRummageDoAfterEvent args)
{
if (args.Cancelled || component.Looted)
// DeltaV - Rummaging an object updates the looting cooldown rather than a "previously looted" check.
// Note that the "Looted" boolean can still be checked (by mappers/admins)
// to disable rummaging on the object indefinitely, but rummaging will no
// longer permanently prevent future rummaging.
var time = _gameTiming.CurTime;
if (args.Cancelled || component.Looted || time < component.LastLooted + component.RummageCooldown)
return;

component.Looted = true;
component.LastLooted = time;
// End DeltaV change
Dirty(uid, component);
_audio.PlayPredicted(component.Sound, uid, args.User);

Expand Down
26 changes: 20 additions & 6 deletions Content.Shared/Storage/EntitySystems/DumpableSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Content.Shared.Placeable;
using Content.Shared.Storage.Components;
using Content.Shared.Verbs;
using JetBrains.Annotations;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
Expand Down Expand Up @@ -140,27 +141,40 @@ private void StartDoAfter(EntityUid storageUid, EntityUid targetUid, EntityUid u

private void OnDoAfter(EntityUid uid, DumpableComponent component, DumpableDoAfterEvent args)
{
if (args.Handled || args.Cancelled || !TryComp<StorageComponent>(uid, out var storage) || storage.Container.ContainedEntities.Count == 0)
if (args.Handled || args.Cancelled)
return;

DumpContents(uid, args.Args.Target, args.Args.User, component);
}

// DeltaV: Refactor to allow dumping that doesn't require a verb
[PublicAPI]
public void DumpContents(EntityUid uid, EntityUid? target, EntityUid user, DumpableComponent? component = null)
{
if (!TryComp<StorageComponent>(uid, out var storage) || !Resolve(uid, ref component))
return;

if (storage.Container.ContainedEntities.Count == 0)
return;

var dumpQueue = new Queue<EntityUid>(storage.Container.ContainedEntities);

var dumped = false;

if (_disposalUnitSystem.HasDisposals(args.Args.Target))
if (_disposalUnitSystem.HasDisposals(target))
{
dumped = true;

foreach (var entity in dumpQueue)
{
_disposalUnitSystem.DoInsertDisposalUnit(args.Args.Target.Value, entity, args.Args.User);
_disposalUnitSystem.DoInsertDisposalUnit(target.Value, entity, user);
}
}
else if (HasComp<PlaceableSurfaceComponent>(args.Args.Target))
else if (HasComp<PlaceableSurfaceComponent>(target))
{
dumped = true;

var (targetPos, targetRot) = _transformSystem.GetWorldPositionRotation(args.Args.Target.Value);
var (targetPos, targetRot) = _transformSystem.GetWorldPositionRotation(target.Value);

foreach (var entity in dumpQueue)
{
Expand All @@ -180,7 +194,7 @@ private void OnDoAfter(EntityUid uid, DumpableComponent component, DumpableDoAft

if (dumped)
{
_audio.PlayPredicted(component.DumpSound, uid, args.User);
_audio.PlayPredicted(component.DumpSound, uid, user);
}
}
}
2 changes: 2 additions & 0 deletions Resources/Locale/en-US/deltav/actions/crawl-under-objects.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
crawl-under-objects-toggle-on = Now sneaking
crawl-under-objects-toggle-off = Now standing
6 changes: 6 additions & 0 deletions Resources/Locale/en-US/deltav/chat/managers/chat_manager.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ chat-speech-verb-harpy-1 = chirps
chat-speech-verb-harpy-2 = tweets
chat-speech-verb-harpy-3 = caws
chat-speech-verb-harpy-4 = trills
chat-speech-verb-name-rodentia = Rodentia
chat-speech-verb-rodentia-1 = squeaks
chat-speech-verb-rodentia-2 = pieps
chat-speech-verb-rodentia-3 = chatters
chat-speech-verb-rodentia-4 = squeals
Loading

0 comments on commit 003066d

Please sign in to comment.