This commit is contained in:
Rane
2022-07-27 00:46:24 -04:00
committed by GitHub
parent 963ddd507b
commit 1c8bdaf7c4
53 changed files with 698 additions and 36 deletions

View File

@@ -45,7 +45,8 @@ namespace Content.Server.Atmos.Miasma
"VanAusdallsRobovirus",
"BleedersBite",
"Plague",
"TongueTwister"
"TongueTwister",
"MemeticAmirmir"
};
/// <summary>

View File

@@ -28,7 +28,8 @@ namespace Content.Server.Atmos.Portable
Gas.Plasma,
Gas.Tritium,
Gas.WaterVapor,
Gas.Miasma
Gas.Miasma,
Gas.NitrousOxide
};
/// <summary>

View File

@@ -5,17 +5,26 @@ using Content.Server.Body.Systems;
using Content.Shared.Buckle.Components;
using Content.Shared.Body.Components;
using Content.Shared.Bed;
using Content.Shared.Bed.Sleep;
using Content.Server.Bed.Sleep;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Emag.Systems;
using Content.Shared.MobState.Components;
using Content.Server.Actions;
using Content.Server.MobState;
using Content.Shared.Actions.ActionTypes;
using Robust.Shared.Prototypes;
namespace Content.Server.Bed
{
public sealed class BedSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly ActionsSystem _actionsSystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly SleepingSystem _sleepingSystem = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
public override void Initialize()
{
base.Initialize();
@@ -27,12 +36,19 @@ namespace Content.Server.Bed
private void ManageUpdateList(EntityUid uid, HealOnBuckleComponent component, BuckleChangeEvent args)
{
_prototypeManager.TryIndex<InstantActionPrototype>("Sleep", out var sleepAction);
if (args.Buckling)
{
AddComp<HealOnBuckleHealingComponent>(uid);
if (sleepAction != null)
_actionsSystem.AddAction(args.BuckledEntity, new InstantAction(sleepAction), null);
return;
}
if (sleepAction != null)
_actionsSystem.RemoveAction(args.BuckledEntity, sleepAction, null);
_sleepingSystem.TryWaking(args.BuckledEntity);
RemComp<HealOnBuckleHealingComponent>(uid);
component.Accumulator = 0;
}
@@ -52,13 +68,16 @@ namespace Content.Server.Bed
if (strapComponent.BuckledEntities.Count == 0) continue;
var mobStateQuery = GetEntityQuery<MobStateComponent>();
foreach (var healedEntity in strapComponent.BuckledEntities)
{
if (mobStateQuery.TryGetComponent(healedEntity, out var state) && state.IsDead())
if (_mobStateSystem.IsDead(healedEntity))
continue;
var damage = bedComponent.Damage;
if (HasComp<SleepingComponent>(healedEntity))
damage *= bedComponent.SleepMultiplier;
_damageableSystem.TryChangeDamage(healedEntity, bedComponent.Damage, true);
}
}

View File

@@ -12,6 +12,9 @@ namespace Content.Server.Bed.Components
[DataField("healTime", required: false)]
[ViewVariables(VVAccess.ReadWrite)]
public float HealTime = 1f; // How often the bed applies the damage
[DataField("sleepMultiplier")]
public float SleepMultiplier = 3f;
public float Accumulator = 0f; //Time accumulated
}
}

View File

@@ -0,0 +1,198 @@
using Content.Shared.Stunnable;
using Content.Shared.MobState.Components;
using Content.Shared.Bed.Sleep;
using Content.Shared.Damage;
using Content.Server.Actions;
using Content.Shared.Actions.ActionTypes;
using Robust.Shared.Prototypes;
using Content.Shared.Sound;
using Robust.Shared.Timing;
using Content.Shared.MobState;
using Content.Server.MobState;
using Content.Server.Sound.Components;
using Content.Shared.Verbs;
using Content.Shared.Interaction;
using Robust.Shared.Audio;
using Robust.Shared.Player;
using Content.Shared.Audio;
using Content.Server.Popups;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Robust.Shared.Random;
namespace Content.Server.Bed.Sleep
{
public sealed class SleepingSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly ActionsSystem _actionsSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MobStateComponent, SleepStateChangedEvent>(OnSleepStateChanged);
SubscribeLocalEvent<SleepingComponent, DamageChangedEvent>(OnDamageChanged);
SubscribeLocalEvent<MobStateComponent, SleepActionEvent>(OnSleepAction);
SubscribeLocalEvent<MobStateComponent, WakeActionEvent>(OnWakeAction);
SubscribeLocalEvent<SleepingComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<SleepingComponent, GetVerbsEvent<AlternativeVerb>>(AddWakeVerb);
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
SubscribeLocalEvent<SleepingComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<ForcedSleepingComponent, ComponentInit>(OnInit);
}
/// <summary>
/// when sleeping component is added or removed, we do some stuff with other components.
/// </summary>
private void OnSleepStateChanged(EntityUid uid, MobStateComponent component, SleepStateChangedEvent args)
{
_prototypeManager.TryIndex<InstantActionPrototype>("Wake", out var wakeAction);
if (args.FellAsleep)
{
EnsureComp<StunnedComponent>(uid);
EnsureComp<KnockedDownComponent>(uid);
var emitSound = EnsureComp<SpamEmitSoundComponent>(uid);
emitSound.Sound = new SoundCollectionSpecifier("Snores");
emitSound.PlayChance = 0.33f;
emitSound.RollInterval = 5f;
emitSound.PopUp = "sleep-onomatopoeia";
emitSound.PitchVariation = 0.2f;
if (wakeAction != null)
{
var wakeInstance = new InstantAction(wakeAction);
wakeInstance.Cooldown = (_gameTiming.CurTime, _gameTiming.CurTime + TimeSpan.FromSeconds(15));
_actionsSystem.AddAction(uid, wakeInstance, null);
}
return;
}
if (wakeAction != null)
_actionsSystem.RemoveAction(uid, wakeAction);
RemComp<StunnedComponent>(uid);
RemComp<KnockedDownComponent>(uid);
RemComp<SpamEmitSoundComponent>(uid);
}
/// <summary>
/// Wake up if we take an instance of more than 2 damage.
/// </summary>
private void OnDamageChanged(EntityUid uid, SleepingComponent component, DamageChangedEvent args)
{
if (!args.DamageIncreased || args.DamageDelta == null)
return;
if (args.DamageDelta.Total >= component.WakeThreshold)
TryWaking(uid);
}
private void OnSleepAction(EntityUid uid, MobStateComponent component, SleepActionEvent args)
{
TrySleeping(uid);
}
private void OnWakeAction(EntityUid uid, MobStateComponent component, WakeActionEvent args)
{
TryWaking(uid);
}
/// <summary>
/// In crit, we wake up if we are not being forced to sleep.
/// And, you can't sleep when dead...
/// </summary>
private void OnMobStateChanged(EntityUid uid, SleepingComponent component, MobStateChangedEvent args)
{
if (_mobStateSystem.IsCritical(uid) && !HasComp<ForcedSleepingComponent>(uid))
{
RemComp<SleepingComponent>(uid);
return;
}
if (_mobStateSystem.IsDead(uid))
RemComp<SleepingComponent>(uid);
}
private void AddWakeVerb(EntityUid uid, SleepingComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
AlternativeVerb verb = new()
{
Act = () =>
{
TryWaking(args.Target, user: args.User);
},
Text = Loc.GetString("action-name-wake"),
Priority = 2
};
args.Verbs.Add(verb);
}
/// <summary>
/// When you click on a sleeping person with an empty hand, try to wake them.
/// </summary>
private void OnInteractHand(EntityUid uid, SleepingComponent component, InteractHandEvent args)
{
args.Handled = true;
TryWaking(args.Target, user: args.User);
}
private void OnExamined(EntityUid uid, SleepingComponent component, ExaminedEvent args)
{
if (args.IsInDetailsRange)
{
args.PushMarkup(Loc.GetString("sleep-examined", ("target", Identity.Entity(uid, EntityManager))));
}
}
private void OnInit(EntityUid uid, ForcedSleepingComponent component, ComponentInit args)
{
TrySleeping(uid);
}
/// <summary>
/// Try sleeping. Only mobs can sleep.
/// </summary>
public bool TrySleeping(EntityUid uid)
{
if (!HasComp<MobStateComponent>(uid))
return false;
if (_prototypeManager.TryIndex<InstantActionPrototype>("Sleep", out var sleepAction))
_actionsSystem.RemoveAction(uid, sleepAction);
EnsureComp<SleepingComponent>(uid);
return true;
}
/// <summary>
/// Try to wake up.
/// </summary>
public bool TryWaking(EntityUid uid, bool force = false, EntityUid? user = null)
{
if (!force && HasComp<ForcedSleepingComponent>(uid))
{
if (user != null)
{
SoundSystem.Play("/Audio/Effects/thudswoosh.ogg", Filter.Pvs(uid), uid, AudioHelpers.WithVariation(0.05f, _robustRandom));
_popupSystem.PopupEntity(Loc.GetString("wake-other-failure", ("target", Identity.Entity(uid, EntityManager))), uid, Filter.Entities(user.Value), Shared.Popups.PopupType.SmallCaution);
}
return false;
}
if (user != null)
{
SoundSystem.Play("/Audio/Effects/thudswoosh.ogg", Filter.Pvs(uid), uid, AudioHelpers.WithVariation(0.05f, _robustRandom));
_popupSystem.PopupEntity(Loc.GetString("wake-other-success", ("target", Identity.Entity(uid, EntityManager))), uid, Filter.Entities(user.Value));
}
RemComp<SleepingComponent>(uid);
return true;
}
}
}

View File

@@ -18,6 +18,7 @@ using Robust.Shared.Containers;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Content.Shared.IdentityManagement;
using Content.Shared.Bed.Sleep;
namespace Content.Server.Buckle.Components
{
@@ -264,6 +265,9 @@ namespace Content.Server.Buckle.Components
{
return false;
}
if (EntMan.TryGetComponent<SleepingComponent>(Owner, out var sleeping) && Owner == user)
return false;
// If the strap is a vehicle and the rider is not the person unbuckling, return.
if (EntMan.TryGetComponent<VehicleComponent>(oldBuckledTo.Owner, out var vehicle) &&
vehicle.Rider != user)

View File

@@ -1,6 +1,7 @@
using Content.Shared.Disease;
using Content.Server.Buckle.Components;
using Content.Server.Bed.Components;
using Content.Shared.Bed.Sleep;
namespace Content.Server.Disease.Cures
{
@@ -12,6 +13,11 @@ namespace Content.Server.Disease.Cures
{
[ViewVariables(VVAccess.ReadWrite)]
public int Ticker = 0;
/// How many extra ticks you get for sleeping.
[DataField("sleepMultiplier")]
public int SleepMultiplier = 3;
[DataField("maxLength", required: true)]
[ViewVariables(VVAccess.ReadWrite)]
public int MaxLength = 60;
@@ -21,14 +27,19 @@ namespace Content.Server.Disease.Cures
if (!args.EntityManager.TryGetComponent<BuckleComponent>(args.DiseasedEntity, out var buckle) ||
!args.EntityManager.HasComponent<HealOnBuckleComponent>(buckle.BuckledTo?.Owner))
return false;
var ticks = 1;
if (args.EntityManager.HasComponent<SleepingComponent>(args.DiseasedEntity))
ticks *= SleepMultiplier;
if (buckle.Buckled)
Ticker++;
Ticker += ticks;
return Ticker >= MaxLength;
}
public override string CureText()
{
return (Loc.GetString("diagnoser-cure-bedrest", ("time", MaxLength)));
return (Loc.GetString("diagnoser-cure-bedrest", ("time", MaxLength), ("sleep", (MaxLength / SleepMultiplier))));
}
}
}

View File

@@ -1,5 +1,4 @@
using System.Threading;
using Content.Server.Chat;
using Content.Shared.Disease;
using Content.Shared.Disease.Components;
using Content.Server.Disease.Components;
@@ -20,6 +19,8 @@ using Content.Shared.Inventory.Events;
using Content.Server.Nutrition.EntitySystems;
using Robust.Shared.Utility;
using Content.Shared.IdentityManagement;
using Content.Shared.Item;
using Content.Server.MobState;
namespace Content.Server.Disease
{
@@ -37,14 +38,14 @@ namespace Content.Server.Disease
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DiseaseCarrierComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<DiseaseCarrierComponent, CureDiseaseAttemptEvent>(OnTryCureDisease);
SubscribeLocalEvent<DiseasedComponent, InteractHandEvent>(OnInteractDiseasedHand);
SubscribeLocalEvent<DiseasedComponent, InteractUsingEvent>(OnInteractDiseasedUsing);
SubscribeLocalEvent<DiseasedComponent, UserInteractedWithItemEvent>(OnUserInteractDiseased);
SubscribeLocalEvent<DiseasedComponent, ItemInteractedWithEvent>(OnTargetInteractDiseased);
SubscribeLocalEvent<DiseasedComponent, EntitySpokeEvent>(OnEntitySpeak);
SubscribeLocalEvent<DiseaseProtectionComponent, GotEquippedEvent>(OnEquipped);
SubscribeLocalEvent<DiseaseProtectionComponent, GotUnequippedEvent>(OnUnequipped);
@@ -88,7 +89,7 @@ namespace Content.Server.Disease
{
DebugTools.Assert(carrierComp.Diseases.Count > 0);
if (mobState.IsDead())
if (_mobStateSystem.IsDead(mobState.Owner, mobState))
{
if (_random.Prob(0.005f * frameTime)) //Mean time to remove is 200 seconds per disease
CureDisease(carrierComp, _random.Pick(carrierComp.Diseases));
@@ -246,21 +247,19 @@ namespace Content.Server.Disease
}
/// <summary>
/// Called when someone interacts with a diseased person with an empty hand
/// to check if they get infected
/// When a diseased person interacts with something, check infection.
/// </summary>
private void OnInteractDiseasedHand(EntityUid uid, DiseasedComponent component, InteractHandEvent args)
private void OnUserInteractDiseased(EntityUid uid, DiseasedComponent component, UserInteractedWithItemEvent args)
{
InteractWithDiseased(args.Target, args.User);
InteractWithDiseased(args.User, args.Item);
}
/// <summary>
/// Called when someone interacts with a diseased person with any object
/// to check if they get infected
/// When a diseased person is interacted with, check infection.
/// </summary>
private void OnInteractDiseasedUsing(EntityUid uid, DiseasedComponent component, InteractUsingEvent args)
private void OnTargetInteractDiseased(EntityUid uid, DiseasedComponent component, ItemInteractedWithEvent args)
{
InteractWithDiseased(args.Target, args.User);
InteractWithDiseased(args.Item, args.User);
}
private void OnEntitySpeak(EntityUid uid, DiseasedComponent component, EntitySpokeEvent args)

View File

@@ -7,7 +7,7 @@ using Robust.Shared.Audio;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Random;
using Content.Shared.Bed.Sleep;
namespace Content.Server.Interaction;
@@ -28,6 +28,10 @@ public sealed class InteractionPopupSystem : EntitySystem
if (args.Handled || args.User == args.Target)
return;
//Handling does nothing and this thing annoyingly plays way too often.
if (HasComp<SleepingComponent>(uid))
return;
var curTime = _gameTiming.CurTime;
if (curTime < component.LastInteractTime + component.InteractDelay)

View File

@@ -14,5 +14,9 @@ namespace Content.Server.Sound.Components
[DataField("playChance")]
public float PlayChance = 0.5f;
// Always Pvs.
[DataField("popUp")]
public string? PopUp;
}
}

View File

@@ -12,6 +12,7 @@ using Robust.Shared.Audio;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Content.Server.Popups;
namespace Content.Server.Sound
{
@@ -24,6 +25,7 @@ namespace Content.Server.Sound
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefMan = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
/// <inheritdoc />
@@ -41,6 +43,8 @@ namespace Content.Server.Sound
if (_random.Prob(soundSpammer.PlayChance))
{
if (soundSpammer.PopUp != null)
_popupSystem.PopupEntity(Loc.GetString(soundSpammer.PopUp), soundSpammer.Owner, Filter.Pvs(soundSpammer.Owner));
TryEmitSound(soundSpammer);
}
}

View File

@@ -28,6 +28,7 @@ public sealed class GasArtifactComponent : Component
Gas.CarbonDioxide,
Gas.Tritium,
Gas.Miasma,
Gas.NitrousOxide,
};
/// <summary>

View File

@@ -28,6 +28,7 @@ namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems
"OwOnavirus",
"BleedersBite",
"Ultragigacancer",
"MemeticAmirmir",
"AMIV"
};

View File

@@ -18,7 +18,8 @@ public sealed class ArtifactGasTriggerComponent : Component
Gas.Plasma,
Gas.Nitrogen,
Gas.CarbonDioxide,
Gas.Miasma
Gas.Miasma,
Gas.NitrousOxide,
};
/// <summary>

View File

@@ -181,8 +181,10 @@ namespace Content.Shared.ActionBlocker
private void InteractWithItem(EntityUid user, EntityUid item)
{
var itemEvent = new UserInteractedWithItemEvent(user, item);
RaiseLocalEvent(user, itemEvent);
var userEvent = new UserInteractedWithItemEvent(user, item);
RaiseLocalEvent(user, userEvent);
var itemEvent = new ItemInteractedWithEvent(user, item);
RaiseLocalEvent(item, itemEvent);
}
}
}

View File

@@ -168,7 +168,7 @@ namespace Content.Shared.Atmos
/// <summary>
/// Total number of gases. Increase this if you want to add more!
/// </summary>
public const int TotalNumberOfGases = 7;
public const int TotalNumberOfGases = 8;
/// <summary>
/// This is the actual length of the gases arrays in mixtures.
@@ -285,6 +285,7 @@ namespace Content.Shared.Atmos
Plasma = 3,
Tritium = 4,
WaterVapor = 5,
Miasma = 6
Miasma = 6,
NitrousOxide = 7
}
}

View File

@@ -20,7 +20,8 @@ namespace Content.Shared.Atmos.Piping.Unary.Components
Gas.Plasma,
Gas.Tritium,
Gas.WaterVapor,
Gas.Miasma
Gas.Miasma,
Gas.NitrousOxide
};
// Presets for 'dumb' air alarm modes

View File

@@ -0,0 +1,11 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Bed.Sleep
{
[NetworkedComponent, RegisterComponent]
/// <summary>
/// Prevents waking up. Use as a status effect.
/// </summary>
public sealed class ForcedSleepingComponent : Component
{}
}

View File

@@ -0,0 +1,56 @@
using Content.Shared.Eye.Blinding;
using Content.Shared.Speech;
using Content.Shared.Actions;
using Content.Shared.Bed.Sleep;
namespace Content.Server.Bed.Sleep
{
public sealed class SharedSleepingSystem : EntitySystem
{
[Dependency] private readonly SharedBlindingSystem _blindingSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SleepingComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<SleepingComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<SleepingComponent, SpeakAttemptEvent>(OnSpeakAttempt);
}
private void OnInit(EntityUid uid, SleepingComponent component, ComponentInit args)
{
var ev = new SleepStateChangedEvent(true);
RaiseLocalEvent(uid, ev, false);
_blindingSystem.AdjustBlindSources(uid, true);
}
private void OnShutdown(EntityUid uid, SleepingComponent component, ComponentShutdown args)
{
var ev = new SleepStateChangedEvent(false);
RaiseLocalEvent(uid, ev, false);
_blindingSystem.AdjustBlindSources(uid, false);
}
private void OnSpeakAttempt(EntityUid uid, SleepingComponent component, SpeakAttemptEvent args)
{
args.Cancel();
}
}
}
public sealed class SleepActionEvent : InstantActionEvent {}
public sealed class WakeActionEvent : InstantActionEvent {}
/// <summary>
/// Raised on an entity when they fall asleep or wake up.
/// </summary>
public sealed class SleepStateChangedEvent : EntityEventArgs
{
public bool FellAsleep = false;
public SleepStateChangedEvent(bool fellAsleep)
{
FellAsleep = fellAsleep;
}
}

View File

@@ -0,0 +1,14 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Bed.Sleep;
[NetworkedComponent, RegisterComponent]
/// <summary>
/// Added to entities when they go to sleep.
/// </summary>
public sealed class SleepingComponent : Component
{
// How much damage of any type it takes to wake this entity.
[DataField("wakeThreshold")]
public float WakeThreshold = 2;
}

View File

@@ -0,0 +1,17 @@
namespace Content.Shared.Item;
/// <summary>
/// Raised on the item after they do any sort of interaction with an item,
/// useful for when you want a component on the user to do something to the user
/// E.g. forensics, disease, etc.
/// </summary>
public sealed class ItemInteractedWithEvent : EntityEventArgs
{
public EntityUid User;
public EntityUid Item;
public ItemInteractedWithEvent(EntityUid user, EntityUid item)
{
User = user;
Item = item;
}
}

View File

@@ -5,7 +5,7 @@ using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.Inventory.Events;
using Content.Shared.Item;
using Content.Shared.Movement;
using Content.Shared.Bed.Sleep;
using Content.Shared.Movement.Events;
using Content.Shared.Movement.Systems;
using Content.Shared.Standing;
@@ -198,6 +198,9 @@ namespace Content.Shared.Stunnable
if (args.Handled || knocked.HelpTimer > 0f)
return;
if (HasComp<SleepingComponent>(uid))
return;
// Set it to half the help interval so helping is actually useful...
knocked.HelpTimer = knocked.HelpInterval/2f;

View File

@@ -6,3 +6,6 @@ monkey1.ogg taken from https://freesound.org/people/TRAVELcandies/sounds/423396/
monkey2.ogg taken from https://freesound.org/people/Archeos/sounds/325549/
sneeze2.ogg taken from https://freesound.org/people/InspectorJ/sounds/352177/
vomiting.ogg taken from https://freesound.org/people/vikuserro/sounds/246308/
yawn1.ogg taken from https://freesound.org/people/ckvoiceover/sounds/401338/ user ckvoiceover CC-3.0
yawn2.ogg taken from https://freesound.org/people/Reitanna/sounds/252239/ user reitanna CC-0
snore1, snore2, snore3.ogg taken from https://freesound.org/people/mattyharm/sounds/432995/ user mattyharm CC-0

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,9 @@
action-name-sleep = Sleep
action-desc-sleep = Go to sleep.
action-name-wake = Wake up
action-desc-wake = Stop sleeping.
sleep-onomatopoeia = Zzz...
sleep-examined = [color=lightblue]{CAPITALIZE(SUBJECT($target))} {CONJUGATE-BE($target)} asleep.[/color]
wake-other-success = You shake {THE($target)} awake.
wake-other-failure = You shake {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} not waking up.

View File

@@ -0,0 +1 @@
effect-sleepy = You feel a bit sleepy.

View File

@@ -12,7 +12,7 @@ diagnoser-disease-report-cureresist-medium = Spaceacillin Resistance: [color=ora
diagnoser-disease-report-cureresist-high = Spaceacillin Resistance: [color=red]High[/color]
diagnoser-cure-none = The disease has no specific cures.
diagnoser-cure-has = The disease has the following cures:
diagnoser-cure-bedrest = Rest in bed for {$time} seconds.
diagnoser-cure-bedrest = Rest in bed for {$time} seconds, or {$sleep} seconds if sleeping.
diagnoser-cure-reagent = Consume at least {$units}u of {$reagent}.
diagnoser-cure-wait = It will go away on its own after {$time} seconds.
diagnoser-cure-temp = Reach a body temperature below {$max}°K or above {$min}°K.

View File

@@ -3,6 +3,7 @@ disease-sick-generic = You feel sick.
disease-sneeze = {CAPITALIZE($person)} sneezes.
disease-cough = {CAPITALIZE($person)} coughs.
disease-screech = {CAPITALIZE($person)} screeches.
disease-yawn = {CAPITALIZE($person)} yawns.
disease-meow = {CAPITALIZE($person)} meows.
disease-hiss = {CAPITALIZE($person)} hisses.
disease-beep= {CAPITALIZE($person)} beeps.
@@ -11,4 +12,4 @@ disease-banana-compulsion = You really want to eat some bananas.
disease-beat-chest-compulsion = {CAPITALIZE(THE($person))} beats {POSS-ADJ($person)} chest.
disease-vomit = {CAPITALIZE(THE($person))} vomits.
disease-think = You feel like you can't think straight.
disease-polymorph = You feel your body twist and change form!
disease-polymorph = You feel your body twist and change form!

View File

@@ -15,3 +15,6 @@ reagent-desc-nitrogen = A colorless, odorless unreactive gas. Highly stable.
reagent-name-miasma = miasma
reagent-desc-miasma = Uh oh, stinky!
reagent-name-nitrous-oxide = nitrous oxide
reagent-desc-nitrous-oxide = You know how everything seems funnier when you're tired? Well...

View File

@@ -10,6 +10,9 @@ reagent-desc-mold = Often found in dark, humid places or on old bread.
reagent-name-polytrinic-acid = polytrinic acid
reagent-desc-polytrinic-acid = An extremely corrosive chemical substance. The slightest touch of it will melt off most masks and headgear, and it deals extreme damage to anyone who comes directly into contact with it.
reagent-name-chloral-hydrate = chloral hydrate
reagent-desc-chloral-hydrate = In low doses, makes you drowsy. In higher doses, puts you to sleep. Overdoses deal toxin damage.
reagent-name-fluorosulfuric-acid = fluorosulfuric acid
reagent-desc-fluorosulfuric-acid = An extremely corrosive chemical substance.

View File

@@ -77,3 +77,19 @@
icon: Objects/Consumable/Food/egg.rsi/icon.png
useDelay: 60
serverEvent: !type:EggLayInstantActionEvent
- type: instantAction
id: Sleep
name: action-name-sleep
description: action-desc-sleep
checkCanInteract: false
icon: Objects/Consumable/Food/egg.rsi/icon.png
event: !type:SleepActionEvent
- type: instantAction
id: Wake
name: action-name-wake
description: action-desc-wake
icon: Objects/Consumable/Food/egg.rsi/icon.png
checkCanInteract: false
event: !type:WakeActionEvent

View File

@@ -68,3 +68,12 @@
gasOverlayState: miasma
color: 56941E
reagent: Miasma
- type: gas
id: 7
name: NitrousOxide
specificHeat: 40
heatCapacityRatio: 1.3
molarMass: 44
color: 2887E8
reagent: NitrousOxide

View File

@@ -75,7 +75,7 @@
- 4.75217098 # oxygen
- 17.8772147 # nitrogen
temperature: 293.15
- type: entity
id: NitrogenTankFilled
parent: RedOxygenTankFilled
@@ -91,6 +91,27 @@
- 22.6293856 # nitrogen
temperature: 293.15
- type: entity
id: NitrousOxideTankFilled
parent: NitrousOxideTank
suffix: Filled
name: nitrous oxide tank
components:
- type: GasTank
outputPressure: 101.325
air:
volume: 70
moles:
- 20.5 # oxygen
- 0 # CO2
- 0 # Plasma
- 0 # Tritium
- 0 # Water vapor
- 0 # Miasma
- 2 # N2O
temperature: 293.15
- type: entity
id: PlasmaTankFilled
parent: PlasmaTank

View File

@@ -47,6 +47,8 @@
- id: UniformScrubsColorPurple
prob: 0.05
orGroup: Surgshrubs
- id: NitrousOxideTankFilled
prob: 0.3
- id: ClothingMaskSterile
- type: entity

View File

@@ -190,7 +190,7 @@
probability: 0.000427 ## ~5% chance over 120 secs
polymorphId: AMIVMorph
polymorphMessage: disease-polymorph
polymorphSound:
polymorphSound:
path: /Audio/Animals/monkey_scream.ogg
stages:
- 2
@@ -208,6 +208,22 @@
- 1
- 2
- type: disease
id: MemeticAmirmir
name: Memetic Amirmir
effects:
- !type:DiseaseGenericStatusEffect
probability: 0.015
key: ForcedSleep
component: ForcedSleeping
time: 3
type: Add
- !type:DiseaseSnough
probability: 0.025
snoughMessage: disease-yawn
snoughSound:
collection: Yawns
- type: disease
id: BleedersBite
name: Bleeder's Bite

View File

@@ -111,6 +111,7 @@
- SlowedDown
- Stutter
- Electrocution
- ForcedSleep
- type: Body
template: AnimalTemplate
preset: AnimalPreset
@@ -177,6 +178,7 @@
- SlowedDown
- Stutter
- Electrocution
- ForcedSleep
- type: ThermalRegulator
metabolismHeat: 800
radiatedHeat: 100

View File

@@ -81,6 +81,7 @@
- SlurredSpeech
- PressureImmunity
- Muted
- ForcedSleep
- type: DiseaseCarrier
- type: Blindable
# Other

View File

@@ -161,6 +161,25 @@
- Back
- suitStorage
- type: entity
parent: GasTankBase
id: NitrousOxideTank
name: nitrous oxide tank
description: Contains a mixture of air and nitrous oxide. Make sure you don't refill it with pure N2O.
components:
- type: Sprite
sprite: Objects/Tanks/anesthetic.rsi
- type: GasTank
outputPressure: 101.325
air:
volume: 70
temperature: 293.15
- type: Clothing
sprite: Objects/Tanks/anesthetic.rsi
Slots:
- Back
- suitStorage
- type: entity
parent: GasTankBase
id: PlasmaTank

View File

@@ -90,3 +90,23 @@
components:
- type: GasMiner
spawnGas: WaterVapor
- type: entity
name: Miasma gas miner
parent: GasMinerBase
id: GasMinerMiasma
placement:
mode: SnapgridCenter
components:
- type: GasMiner
spawnGas: Miasma
- type: entity
name: Nitrous Oxide gas miner
parent: GasMinerBase
id: GasMinerNitrousOxide
placement:
mode: SnapgridCenter
components:
- type: GasMiner
spawnGas: NitrousOxide

View File

@@ -360,7 +360,7 @@
components:
- type: Sprite
layers:
- state: redws
- state: greenys
- type: GasCanister
gasMixture:
volume: 1000
@@ -390,6 +390,44 @@
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: entity
parent: GasCanister
id: NitrousOxideCanister
name: nitrous oxide canister
components:
- type: Sprite
layers:
- state: redws
- type: GasCanister
gasMixture:
volume: 1000
moles:
- 0 # oxygen
- 0 # nitrogen
- 0 # CO2
- 0 # Plasma
- 0 # Tritium
- 0 # Water vapor
- 0 # Miasma
- 1871.71051 # N2O
temperature: 293.15
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 300
behaviors:
- !type:PlaySoundBehavior
sound:
path: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
NitrousOxideCanisterBroken:
min: 1
max: 1
- !type:DoActsBehavior
acts: [ "Destruction" ]
# Broke Entities
@@ -512,6 +550,15 @@
id: MiasmaCanisterBroken
name: broken miasma canister
noSpawn: true
components:
- type: Sprite
state: greenys-1
- type: entity
parent: GasCanisterBrokenBase
id: NitrousOxideCanisterBroken
name: broken nitrous oxide canister
noSpawn: true
components:
- type: Sprite
state: redws-1

View File

@@ -27,6 +27,7 @@
Tritium: danger
WaterVapor: danger
Miasma: danger
NitrousOxide: danger
- type: AtmosAlarmable
alarmedBy: ["AirAlarm"]
- type: AtmosDevice

View File

@@ -151,6 +151,13 @@
ratios:
CarbonDioxide: 1.0
Nitrogen: -1.0
- !type:ModifyLungGas
conditions:
- !type:OrganType
type: Slime
ratios:
NitrousOxide: 1.0
Nitrogen: -1.0
- type: reagent
id: Miasma
@@ -215,3 +222,61 @@
Blunt: -4
Slash: -3
Piercing: -3
- type: reagent
id: NitrousOxide
name: reagent-name-nitrous-oxide
desc: reagent-desc-nitrous-oxide
physicalDesc: reagent-physical-desc-gaseous
color: "#808080"
boilingPoint: -88
meltingPoint: -90
metabolisms:
Gas:
effects:
- !type:PopupMessage
conditions:
- !type:ReagentThreshold
reagent: NitrousOxide
min: 0.5
- !type:OrganType
type: Slime
shouldHave: false
type: Local
visualType: Medium
messages: [ "effect-sleepy" ]
probability: 0.1
- !type:MovespeedModifier
conditions:
- !type:ReagentThreshold
reagent: NitrousOxide
min: 1
- !type:OrganType
type: Slime
shouldHave: false
walkSpeedModifier: 0.65
sprintSpeedModifier: 0.65
- !type:GenericStatusEffect
conditions:
- !type:ReagentThreshold
reagent: NitrousOxide
min: 1.8
- !type:OrganType
type: Slime
shouldHave: false
key: ForcedSleep
component: ForcedSleeping
time: 3
type: Add
- !type:HealthChange
conditions:
- !type:ReagentThreshold
reagent: NitrousOxide
min: 3.5
- !type:OrganType
type: Slime
shouldHave: false
ignoreResistances: true
damage:
types:
Poison: 0.25

View File

@@ -44,6 +44,37 @@
probability: 0.33
- type: reagent
id: ChloralHydrate
name: reagent-name-chloral-hydrate
group: Toxins
desc: reagent-desc-chloral-hydrate
color: "#000067"
physicalDesc: reagent-physical-desc-nondescript
metabolisms:
Poison:
effects:
- !type:MovespeedModifier
walkSpeedModifier: 0.65
sprintSpeedModifier: 0.65
- !type:GenericStatusEffect
conditions:
- !type:ReagentThreshold
reagent: ChloralHydrate
min: 15
key: ForcedSleep
component: ForcedSleeping
refresh: false
type: Add
- !type:HealthChange
conditions:
- !type:ReagentThreshold
reagent: ChloralHydrate
min: 20
damage:
types:
Poison: 1.5
- type: reagent
id: Mold
name: reagent-name-mold
@@ -69,6 +100,7 @@
- SpaceFlu
- BirdFlew
- Plague
- MemeticAmirmir
- type: reagent
id: PolytrinicAcid

View File

@@ -312,4 +312,17 @@
Carbon:
amount: 1
products:
MuteToxin: 2 #Lower yield is intentional
MuteToxin: 2
- type: reaction
id: ChloralHydrate
impact: Medium
reactants:
Chlorine:
amount: 3
Ethanol:
amount: 1
Water:
amount: 1
products:
ChloralHydrate: 1

View File

@@ -30,3 +30,16 @@
id: RobotBeeps
files:
- /Audio/Effects/Diseases/beepboop.ogg
- type: soundCollection
id: Yawns
files:
- /Audio/Effects/Diseases/yawn1.ogg
- /Audio/Effects/Diseases/yawn2.ogg
- type: soundCollection
id: Snores
files:
- /Audio/Effects/Diseases/snore1.ogg
- /Audio/Effects/Diseases/snore2.ogg
- /Audio/Effects/Diseases/snore3.ogg

View File

@@ -33,10 +33,13 @@
- type: statusEffect
id: SlurredSpeech
- type: statusEffect
id: PressureImmunity
- type: statusEffect
id: Muted
alert: Muted
- type: statusEffect
id: ForcedSleep #I.e., they will not wake on damage or similar

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -82,6 +82,12 @@
{
"name": "green-1"
},
{
"name": "greenys"
},
{
"name": "greenys-1"
},
{
"name": "darkblue"
},