Merge remote-tracking branch 'upstream/stable' into ed-20-11-2024-upstream-sync

# Conflicts:
#	Resources/Maps/cog.yml
This commit is contained in:
Ed
2024-11-20 00:34:51 +03:00
69 changed files with 1480 additions and 1791 deletions

View File

@@ -124,6 +124,10 @@ public sealed class ColorFlashEffectSystem : SharedColorFlashEffectSystem
continue;
}
var targetEv = new GetFlashEffectTargetEvent(ent);
RaiseLocalEvent(ent, ref targetEv);
ent = targetEv.Target;
EnsureComp<ColorFlashEffectComponent>(ent, out comp);
comp.NetSyncEnabled = false;
comp.Color = sprite.Color;
@@ -132,3 +136,9 @@ public sealed class ColorFlashEffectSystem : SharedColorFlashEffectSystem
}
}
}
/// <summary>
/// Raised on an entity to change the target for a color flash effect.
/// </summary>
[ByRefEvent]
public record struct GetFlashEffectTargetEvent(EntityUid Target);

View File

@@ -1,7 +1,10 @@
using Content.Client.Effects;
using Content.Client.Smoking;
using Content.Shared.Chemistry.Components;
using Content.Shared.Polymorph.Components;
using Content.Shared.Polymorph.Systems;
using Robust.Client.GameObjects;
using Robust.Shared.Player;
namespace Content.Client.Polymorph.Systems;
@@ -10,14 +13,20 @@ public sealed class ChameleonProjectorSystem : SharedChameleonProjectorSystem
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
private EntityQuery<AppearanceComponent> _appearanceQuery;
private EntityQuery<SpriteComponent> _spriteQuery;
public override void Initialize()
{
base.Initialize();
_appearanceQuery = GetEntityQuery<AppearanceComponent>();
_spriteQuery = GetEntityQuery<SpriteComponent>();
SubscribeLocalEvent<ChameleonDisguiseComponent, AfterAutoHandleStateEvent>(OnHandleState);
SubscribeLocalEvent<ChameleonDisguisedComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<ChameleonDisguisedComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<ChameleonDisguisedComponent, GetFlashEffectTargetEvent>(OnGetFlashEffectTargetEvent);
}
private void OnHandleState(Entity<ChameleonDisguiseComponent> ent, ref AfterAutoHandleStateEvent args)
@@ -25,9 +34,30 @@ public sealed class ChameleonProjectorSystem : SharedChameleonProjectorSystem
CopyComp<SpriteComponent>(ent);
CopyComp<GenericVisualizerComponent>(ent);
CopyComp<SolutionContainerVisualsComponent>(ent);
CopyComp<BurnStateVisualsComponent>(ent);
// reload appearance to hopefully prevent any invisible layers
if (_appearanceQuery.TryComp(ent, out var appearance))
_appearance.QueueUpdate(ent, appearance);
}
private void OnStartup(Entity<ChameleonDisguisedComponent> ent, ref ComponentStartup args)
{
if (!_spriteQuery.TryComp(ent, out var sprite))
return;
ent.Comp.WasVisible = sprite.Visible;
sprite.Visible = false;
}
private void OnShutdown(Entity<ChameleonDisguisedComponent> ent, ref ComponentShutdown args)
{
if (_spriteQuery.TryComp(ent, out var sprite))
sprite.Visible = ent.Comp.WasVisible;
}
private void OnGetFlashEffectTargetEvent(Entity<ChameleonDisguisedComponent> ent, ref GetFlashEffectTargetEvent args)
{
args.Target = ent.Comp.Disguise;
}
}

View File

@@ -157,7 +157,7 @@ public sealed partial class GunSystem : SharedGunSystem
var useKey = gun.UseKey ? EngineKeyFunctions.Use : EngineKeyFunctions.UseSecondary;
if (_inputSystem.CmdStates.GetState(useKey) != BoundKeyState.Down)
if (_inputSystem.CmdStates.GetState(useKey) != BoundKeyState.Down && !gun.BurstActivated)
{
if (gun.ShotCounter != 0)
EntityManager.RaisePredictiveEvent(new RequestStopShootEvent { Gun = GetNetEntity(gunUid) });

View File

@@ -55,6 +55,8 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
{
base.Initialize();
Log.Level = LogLevel.Debug;
SubscribeLocalEvent<GhostRoleAntagSpawnerComponent, TakeGhostRoleEvent>(OnTakeGhostRole);
SubscribeLocalEvent<AntagSelectionComponent, ObjectivesTextGetInfoEvent>(OnObjectivesTextGetInfo);
@@ -360,6 +362,8 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
_role.MindAddRoles(curMind.Value, def.MindRoles, null, true);
ent.Comp.SelectedMinds.Add((curMind.Value, Name(player)));
SendBriefing(session, def.Briefing);
Log.Debug($"Selected {ToPrettyString(curMind)} as antagonist: {ToPrettyString(ent)}");
}
var afterEv = new AfterAntagEntitySelectedEvent(session, player, ent, def);

View File

@@ -428,6 +428,7 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
{
var cartridgeEvent = args.MessageEvent;
cartridgeEvent.LoaderUid = GetNetEntity(uid);
cartridgeEvent.Actor = args.Actor;
RelayEvent(component, cartridgeEvent, true);
}

View File

@@ -51,7 +51,8 @@ public sealed class CursedMaskSystem : SharedCursedMaskSystem
}
var npcFaction = EnsureComp<NpcFactionMemberComponent>(wearer);
ent.Comp.OldFactions = npcFaction.Factions;
ent.Comp.OldFactions.Clear();
ent.Comp.OldFactions.UnionWith(npcFaction.Factions);
_npcFaction.ClearFactions((wearer, npcFaction), false);
_npcFaction.AddFaction((wearer, npcFaction), ent.Comp.CursedMaskFaction);

View File

@@ -41,6 +41,8 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
{
base.Initialize();
Log.Level = LogLevel.Debug;
SubscribeLocalEvent<TraitorRuleComponent, AfterAntagEntitySelectedEvent>(AfterEntitySelected);
SubscribeLocalEvent<TraitorRuleComponent, ObjectivesTextPrependEvent>(OnObjectivesTextPrepend);
}
@@ -53,6 +55,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
private void AfterEntitySelected(Entity<TraitorRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
{
Log.Debug($"AfterAntagEntitySelected {ToPrettyString(ent)}");
MakeTraitor(args.EntityUid, ent);
}
@@ -78,14 +81,22 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component)
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - start");
//Grab the mind if it wasn't provided
if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind))
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - failed, no Mind found");
return false;
}
var briefing = "";
if (component.GiveCodewords)
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - added codewords flufftext to briefing");
briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", component.Codewords)));
}
var issuer = _random.Pick(_prototypeManager.Index(component.ObjectiveIssuers).Values);
@@ -94,6 +105,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
if (component.GiveUplink)
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink start");
// Calculate the amount of currency on the uplink.
var startingBalance = component.StartingBalance;
if (_jobs.MindTryGetJob(mindId, out var prototype))
@@ -105,18 +117,27 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
}
// Choose and generate an Uplink, and return the uplink code if applicable
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink request start");
var uplinkParams = RequestUplink(traitor, startingBalance, briefing);
code = uplinkParams.Item1;
briefing = uplinkParams.Item2;
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink request completed");
}
string[]? codewords = null;
if (component.GiveCodewords)
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - set codewords from component");
codewords = component.Codewords;
}
if (component.GiveBriefing)
{
_antag.SendBriefing(traitor, GenerateBriefing(codewords, code, issuer), null, component.GreetSoundNotification);
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Sent the Briefing");
}
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Adding TraitorMind");
component.TraitorMinds.Add(mindId);
// Assign briefing
@@ -126,9 +147,14 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
_roleSystem.MindHasRole<TraitorRoleComponent>(mindId, out var traitorRole);
if (traitorRole is not null)
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Add traitor briefing components");
AddComp<RoleBriefingComponent>(traitorRole.Value.Owner);
Comp<RoleBriefingComponent>(traitorRole.Value.Owner).Briefing = briefing;
}
else
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - did not get traitor briefing");
}
// Send codewords to only the traitor client
var color = TraitorCodewordColor; // Fall back to a dark red Syndicate color if a prototype is not found
@@ -137,9 +163,11 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
_roleCodewordSystem.SetRoleCodewords(codewordComp, "traitor", component.Codewords.ToList(), color);
// Change the faction
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Change faction");
_npcFaction.RemoveFaction(traitor, component.NanoTrasenFaction, false);
_npcFaction.AddFaction(traitor, component.SyndicateFaction);
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Finished");
return true;
}
@@ -148,10 +176,12 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
var pda = _uplink.FindUplinkTarget(traitor);
Note[]? code = null;
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink add");
var uplinked = _uplink.AddUplink(traitor, startingBalance, pda, true);
if (pda is not null && uplinked)
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink is PDA");
// Codes are only generated if the uplink is a PDA
code = EnsureComp<RingerUplinkComponent>(pda.Value).Code;
@@ -163,6 +193,7 @@ public sealed class TraitorRuleSystem : GameRuleSystem<TraitorRuleComponent>
}
else if (pda is null && uplinked)
{
Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink is implant");
briefing += "\n" + Loc.GetString("traitor-role-uplink-implant-short");
}

View File

@@ -1,99 +1,5 @@
using Content.Server.Polymorph.Components;
using Content.Shared.Actions;
using Content.Shared.Construction.Components;
using Content.Shared.Hands;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Polymorph;
using Content.Shared.Polymorph.Components;
using Content.Shared.Polymorph.Systems;
using Content.Shared.StatusIcon.Components;
using Robust.Shared.Physics.Components;
namespace Content.Server.Polymorph.Systems;
public sealed class ChameleonProjectorSystem : SharedChameleonProjectorSystem
{
[Dependency] private readonly MetaDataSystem _meta = default!;
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
[Dependency] private readonly PolymorphSystem _polymorph = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedTransformSystem _xform = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ChameleonDisguiseComponent, GotEquippedHandEvent>(OnEquippedHand);
SubscribeLocalEvent<ChameleonDisguiseComponent, DisguiseToggleNoRotEvent>(OnToggleNoRot);
SubscribeLocalEvent<ChameleonDisguiseComponent, DisguiseToggleAnchoredEvent>(OnToggleAnchored);
}
private void OnEquippedHand(Entity<ChameleonDisguiseComponent> ent, ref GotEquippedHandEvent args)
{
if (!TryComp<PolymorphedEntityComponent>(ent, out var poly))
return;
_polymorph.Revert((ent, poly));
args.Handled = true;
}
public override void Disguise(ChameleonProjectorComponent proj, EntityUid user, EntityUid entity)
{
if (_polymorph.PolymorphEntity(user, proj.Polymorph) is not {} disguise)
return;
// make disguise look real (for simple things at least)
var meta = MetaData(entity);
_meta.SetEntityName(disguise, meta.EntityName);
_meta.SetEntityDescription(disguise, meta.EntityDescription);
var comp = EnsureComp<ChameleonDisguiseComponent>(disguise);
comp.SourceEntity = entity;
comp.SourceProto = Prototype(entity)?.ID;
Dirty(disguise, comp);
// no sechud trolling
RemComp<StatusIconComponent>(disguise);
_appearance.CopyData(entity, disguise);
var mass = CompOrNull<PhysicsComponent>(entity)?.Mass ?? 0f;
// let the disguise die when its taken enough damage, which then transfers to the player
// health is proportional to mass, and capped to not be insane
if (TryComp<MobThresholdsComponent>(disguise, out var thresholds))
{
// if the player is of flesh and blood, cap max health to theirs
// so that when reverting damage scales 1:1 and not round removing
var playerMax = _mobThreshold.GetThresholdForState(user, MobState.Dead).Float();
var max = playerMax == 0f ? proj.MaxHealth : Math.Max(proj.MaxHealth, playerMax);
var health = Math.Clamp(mass, proj.MinHealth, proj.MaxHealth);
_mobThreshold.SetMobStateThreshold(disguise, health, MobState.Critical, thresholds);
_mobThreshold.SetMobStateThreshold(disguise, max, MobState.Dead, thresholds);
}
// add actions for controlling transform aspects
_actions.AddAction(disguise, proj.NoRotAction);
_actions.AddAction(disguise, proj.AnchorAction);
}
private void OnToggleNoRot(Entity<ChameleonDisguiseComponent> ent, ref DisguiseToggleNoRotEvent args)
{
var xform = Transform(ent);
xform.NoLocalRotation = !xform.NoLocalRotation;
}
private void OnToggleAnchored(Entity<ChameleonDisguiseComponent> ent, ref DisguiseToggleAnchoredEvent args)
{
var uid = ent.Owner;
var xform = Transform(uid);
if (xform.Anchored)
_xform.Unanchor(uid, xform);
else
_xform.AnchorEntity((uid, xform));
}
}
public sealed class ChameleonProjectorSystem : SharedChameleonProjectorSystem;

View File

@@ -31,6 +31,7 @@ namespace Content.Server.Research.Disk
_research.ModifyServerPoints(args.Target.Value, component.Points, server);
_popupSystem.PopupEntity(Loc.GetString("research-disk-inserted", ("points", component.Points)), args.Target.Value, args.User);
EntityManager.QueueDeleteEntity(uid);
args.Handled = true;
}
private void OnMapInit(EntityUid uid, ResearchDiskComponent component, MapInitEvent args)

View File

@@ -1,4 +1,6 @@
using Content.Shared.Damage;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Map;
namespace Content.Server.Weapons.Ranged.Systems;
@@ -13,17 +15,28 @@ public sealed partial class GunSystem
*/
// Automatic firing without stopping if the AutoShootGunComponent component is exist and enabled
var query = EntityQueryEnumerator<AutoShootGunComponent, GunComponent>();
var query = EntityQueryEnumerator<GunComponent>();
while (query.MoveNext(out var uid, out var autoShoot, out var gun))
while (query.MoveNext(out var uid, out var gun))
{
if (!autoShoot.Enabled)
continue;
if (gun.NextFire > Timing.CurTime)
continue;
AttemptShoot(uid, gun);
if (TryComp(uid, out AutoShootGunComponent? autoShoot))
{
if (!autoShoot.Enabled)
continue;
AttemptShoot(uid, gun);
}
else if (gun.BurstActivated)
{
var parent = _transform.GetParentUid(uid);
if (HasComp<DamageableComponent>(parent))
AttemptShoot(parent, uid, gun, gun.ShootCoordinates ?? new EntityCoordinates(uid, gun.DefaultDirection));
else
AttemptShoot(uid, gun);
}
}
}
}

View File

@@ -17,4 +17,7 @@ public sealed class CartridgeUiMessage : BoundUserInterfaceMessage
public abstract class CartridgeMessageEvent : EntityEventArgs
{
public NetEntity LoaderUid;
[NonSerialized]
public EntityUid Actor;
}

View File

@@ -1,3 +1,4 @@
using Content.Shared.Polymorph.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
@@ -7,9 +8,22 @@ namespace Content.Shared.Polymorph.Components;
/// Component added to disguise entities.
/// Used by client to copy over appearance from the disguise's source entity.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
[RegisterComponent, NetworkedComponent, Access(typeof(SharedChameleonProjectorSystem))]
[AutoGenerateComponentState(true)]
public sealed partial class ChameleonDisguiseComponent : Component
{
/// <summary>
/// The user of this disguise.
/// </summary>
[DataField]
public EntityUid User;
/// <summary>
/// The projector that created this disguise.
/// </summary>
[DataField]
public EntityUid Projector;
/// <summary>
/// The disguise source entity for copying the sprite.
/// </summary>

View File

@@ -0,0 +1,25 @@
using Content.Shared.Polymorph.Systems;
using Robust.Shared.GameStates;
namespace Content.Shared.Polymorph.Components;
/// <summary>
/// Added to a player when they use a chameleon projector.
/// Handles making them invisible and revealing when damaged enough or switching hands.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedChameleonProjectorSystem))]
[AutoGenerateComponentState]
public sealed partial class ChameleonDisguisedComponent : Component
{
/// <summary>
/// The disguise entity parented to the player.
/// </summary>
[DataField, AutoNetworkedField]
public EntityUid Disguise;
/// <summary>
/// For client, whether the user's sprite was previously visible or not.
/// </summary>
[DataField]
public bool WasVisible;
}

View File

@@ -1,4 +1,3 @@
using Content.Shared.Polymorph;
using Content.Shared.Polymorph.Systems;
using Content.Shared.Whitelist;
using Robust.Shared.Prototypes;
@@ -25,22 +24,26 @@ public sealed partial class ChameleonProjectorComponent : Component
public EntityWhitelist? Blacklist;
/// <summary>
/// Polymorph configuration for the disguise entity.
/// Disguise entity to spawn and use.
/// </summary>
[DataField(required: true)]
public PolymorphConfiguration Polymorph = new();
public EntProtoId DisguiseProto = string.Empty;
/// <summary>
/// Action for disabling your disguise's rotation.
/// </summary>
[DataField]
public EntProtoId NoRotAction = "ActionDisguiseNoRot";
[DataField]
public EntityUid? NoRotActionEntity;
/// <summary>
/// Action for anchoring your disguise in place.
/// </summary>
[DataField]
public EntProtoId AnchorAction = "ActionDisguiseAnchor";
[DataField]
public EntityUid? AnchorActionEntity;
/// <summary>
/// Minimum health to give the disguise.
@@ -55,14 +58,8 @@ public sealed partial class ChameleonProjectorComponent : Component
public float MaxHealth = 100f;
/// <summary>
/// Popup shown to the user when they try to disguise as an invalid entity.
/// User currently disguised by this projector, if any
/// </summary>
[DataField]
public LocId InvalidPopup = "chameleon-projector-invalid";
/// <summary>
/// Popup shown to the user when they disguise as a valid entity.
/// </summary>
[DataField]
public LocId SuccessPopup = "chameleon-projector-success";
public EntityUid? Disguised;
}

View File

@@ -1,67 +1,264 @@
using Content.Shared.Actions;
using Content.Shared.Coordinates;
using Content.Shared.Damage;
using Content.Shared.Hands;
using Content.Shared.Interaction;
using Content.Shared.Polymorph;
using Content.Shared.Item;
using Content.Shared.Polymorph.Components;
using Content.Shared.Popups;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Prototypes;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Storage.Components;
using Content.Shared.Verbs;
using Content.Shared.Whitelist;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager;
using System.Diagnostics.CodeAnalysis;
namespace Content.Shared.Polymorph.Systems;
/// <summary>
/// Handles whitelist/blacklist checking.
/// Actual polymorphing and deactivation is done serverside.
/// Handles disguise validation, disguising and revealing.
/// Most appearance copying is done clientside.
/// </summary>
public abstract class SharedChameleonProjectorSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly ISerializationManager _serMan = default!;
[Dependency] private readonly MetaDataSystem _meta = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly SharedTransformSystem _xform = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ChameleonDisguiseComponent, InteractHandEvent>(OnDisguiseInteractHand, before: [typeof(SharedItemSystem)]);
SubscribeLocalEvent<ChameleonDisguiseComponent, DamageChangedEvent>(OnDisguiseDamaged);
SubscribeLocalEvent<ChameleonDisguiseComponent, InsertIntoEntityStorageAttemptEvent>(OnDisguiseInsertAttempt);
SubscribeLocalEvent<ChameleonDisguiseComponent, ComponentShutdown>(OnDisguiseShutdown);
SubscribeLocalEvent<ChameleonProjectorComponent, AfterInteractEvent>(OnInteract);
SubscribeLocalEvent<ChameleonProjectorComponent, GetVerbsEvent<UtilityVerb>>(OnGetVerbs);
SubscribeLocalEvent<ChameleonProjectorComponent, DisguiseToggleNoRotEvent>(OnToggleNoRot);
SubscribeLocalEvent<ChameleonProjectorComponent, DisguiseToggleAnchoredEvent>(OnToggleAnchored);
SubscribeLocalEvent<ChameleonProjectorComponent, HandDeselectedEvent>(OnDeselected);
SubscribeLocalEvent<ChameleonProjectorComponent, GotUnequippedHandEvent>(OnUnequipped);
SubscribeLocalEvent<ChameleonProjectorComponent, ComponentShutdown>(OnProjectorShutdown);
}
#region Disguise entity
private void OnDisguiseInteractHand(Entity<ChameleonDisguiseComponent> ent, ref InteractHandEvent args)
{
TryReveal(ent.Comp.User);
args.Handled = true;
}
private void OnDisguiseDamaged(Entity<ChameleonDisguiseComponent> ent, ref DamageChangedEvent args)
{
// this mirrors damage 1:1
if (args.DamageDelta is {} damage)
_damageable.TryChangeDamage(ent.Comp.User, damage);
}
private void OnDisguiseInsertAttempt(Entity<ChameleonDisguiseComponent> ent, ref InsertIntoEntityStorageAttemptEvent args)
{
// stay parented to the user, not the storage
args.Cancelled = true;
}
private void OnDisguiseShutdown(Entity<ChameleonDisguiseComponent> ent, ref ComponentShutdown args)
{
_actions.RemoveProvidedActions(ent.Comp.User, ent.Comp.Projector);
}
#endregion
#region Projector
private void OnInteract(Entity<ChameleonProjectorComponent> ent, ref AfterInteractEvent args)
{
if (!args.CanReach || args.Target is not {} target)
if (args.Handled || !args.CanReach || args.Target is not {} target)
return;
args.Handled = true;
TryDisguise(ent, args.User, target);
}
private void OnGetVerbs(Entity<ChameleonProjectorComponent> ent, ref GetVerbsEvent<UtilityVerb> args)
{
if (!args.CanAccess)
return;
var user = args.User;
args.Handled = true;
var target = args.Target;
args.Verbs.Add(new UtilityVerb()
{
Act = () =>
{
TryDisguise(ent, user, target);
},
Text = Loc.GetString("chameleon-projector-set-disguise")
});
}
public bool TryDisguise(Entity<ChameleonProjectorComponent> ent, EntityUid user, EntityUid target)
{
if (_container.IsEntityInContainer(target))
{
_popup.PopupClient(Loc.GetString("chameleon-projector-inside-container"), target, user);
return false;
}
if (IsInvalid(ent.Comp, target))
{
_popup.PopupClient(Loc.GetString(ent.Comp.InvalidPopup), target, user);
return;
_popup.PopupClient(Loc.GetString("chameleon-projector-invalid"), target, user);
return false;
}
_popup.PopupClient(Loc.GetString(ent.Comp.SuccessPopup), target, user);
Disguise(ent.Comp, user, target);
_popup.PopupClient(Loc.GetString("chameleon-projector-success"), target, user);
Disguise(ent, user, target);
return true;
}
private void OnToggleNoRot(Entity<ChameleonProjectorComponent> ent, ref DisguiseToggleNoRotEvent args)
{
if (ent.Comp.Disguised is not {} uid)
return;
var xform = Transform(uid);
_xform.SetLocalRotationNoLerp(uid, 0, xform);
xform.NoLocalRotation = !xform.NoLocalRotation;
args.Handled = true;
}
private void OnToggleAnchored(Entity<ChameleonProjectorComponent> ent, ref DisguiseToggleAnchoredEvent args)
{
if (ent.Comp.Disguised is not {} uid)
return;
var xform = Transform(uid);
if (xform.Anchored)
_xform.Unanchor(uid, xform);
else
_xform.AnchorEntity((uid, xform));
args.Handled = true;
}
private void OnDeselected(Entity<ChameleonProjectorComponent> ent, ref HandDeselectedEvent args)
{
RevealProjector(ent);
}
private void OnUnequipped(Entity<ChameleonProjectorComponent> ent, ref GotUnequippedHandEvent args)
{
RevealProjector(ent);
}
private void OnProjectorShutdown(Entity<ChameleonProjectorComponent> ent, ref ComponentShutdown args)
{
RevealProjector(ent);
}
#endregion
#region API
/// <summary>
/// Returns true if an entity cannot be used as a disguise.
/// </summary>
public bool IsInvalid(ChameleonProjectorComponent comp, EntityUid target)
{
return _whitelistSystem.IsWhitelistFail(comp.Whitelist, target)
|| _whitelistSystem.IsBlacklistPass(comp.Blacklist, target);
return _whitelist.IsWhitelistFail(comp.Whitelist, target)
|| _whitelist.IsBlacklistPass(comp.Blacklist, target);
}
/// <summary>
/// On server, polymorphs the user into an entity and sets up the disguise.
/// </summary>
public virtual void Disguise(ChameleonProjectorComponent comp, EntityUid user, EntityUid entity)
public void Disguise(Entity<ChameleonProjectorComponent> ent, EntityUid user, EntityUid entity)
{
var proj = ent.Comp;
// no spawning prediction sorry
if (_net.IsClient)
return;
// reveal first to allow quick switching
TryReveal(user);
// add actions for controlling transform aspects
_actions.AddAction(user, ref proj.NoRotActionEntity, proj.NoRotAction, container: ent);
_actions.AddAction(user, ref proj.AnchorActionEntity, proj.AnchorAction, container: ent);
proj.Disguised = user;
var disguise = SpawnAttachedTo(proj.DisguiseProto, user.ToCoordinates());
var disguised = AddComp<ChameleonDisguisedComponent>(user);
disguised.Disguise = disguise;
Dirty(user, disguised);
// make disguise look real (for simple things at least)
var meta = MetaData(entity);
_meta.SetEntityName(disguise, meta.EntityName);
_meta.SetEntityDescription(disguise, meta.EntityDescription);
var comp = EnsureComp<ChameleonDisguiseComponent>(disguise);
comp.User = user;
comp.Projector = ent;
comp.SourceEntity = entity;
comp.SourceProto = Prototype(entity)?.ID;
Dirty(disguise, comp);
// item disguises can be picked up to be revealed, also makes sure their examine size is correct
CopyComp<ItemComponent>((disguise, comp));
_appearance.CopyData(entity, disguise);
}
/// <summary>
/// Removes the disguise, if the user is disguised.
/// </summary>
public bool TryReveal(Entity<ChameleonDisguisedComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp, false))
return false;
if (TryComp<ChameleonDisguiseComponent>(ent.Comp.Disguise, out var disguise)
&& TryComp<ChameleonProjectorComponent>(disguise.Projector, out var proj))
{
proj.Disguised = null;
}
var xform = Transform(ent);
xform.NoLocalRotation = false;
_xform.Unanchor(ent, xform);
Del(ent.Comp.Disguise);
RemComp<ChameleonDisguisedComponent>(ent);
return true;
}
/// <summary>
/// Reveal a projector's user, if any.
/// </summary>
public void RevealProjector(Entity<ChameleonProjectorComponent> ent)
{
if (ent.Comp.Disguised is {} user)
TryReveal(user);
}
#endregion
/// <summary>
/// Copy a component from the source entity/prototype to the disguise entity.
/// </summary>

View File

@@ -22,6 +22,12 @@ public sealed partial class ChamberMagazineAmmoProviderComponent : MagazineAmmoP
[ViewVariables(VVAccess.ReadWrite), DataField("autoCycle"), AutoNetworkedField]
public bool AutoCycle = true;
/// <summary>
/// Can the gun be racked, which opens and then instantly closes the bolt to cycle a round.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("canRack"), AutoNetworkedField]
public bool CanRack = true;
[ViewVariables(VVAccess.ReadWrite), DataField("soundBoltClosed"), AutoNetworkedField]
public SoundSpecifier? BoltClosedSound = new SoundPathSpecifier("/Audio/Weapons/Guns/Bolt/rifle_bolt_closed.ogg");

View File

@@ -1,3 +1,4 @@
using System.Numerics;
using Content.Shared.Weapons.Ranged.Events;
using Content.Shared.Weapons.Ranged.Systems;
using Robust.Shared.Audio;
@@ -156,6 +157,30 @@ public sealed partial class GunComponent : Component
[AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
public int ShotsPerBurstModified = 3;
/// <summary>
/// How long time must pass between burstfire shots.
/// </summary>
[DataField, AutoNetworkedField]
public float BurstCooldown = 0.25f;
/// <summary>
/// The fire rate of the weapon in burst fire mode.
/// </summary>
[DataField, AutoNetworkedField]
public float BurstFireRate = 8f;
/// <summary>
/// Whether the burst fire mode has been activated.
/// </summary>
[AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
public bool BurstActivated = false;
/// <summary>
/// The burst fire bullet count.
/// </summary>
[AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
public int BurstShotsCount = 0;
/// <summary>
/// Used for tracking semi-auto / burst
/// </summary>
@@ -232,6 +257,12 @@ public sealed partial class GunComponent : Component
/// </summary>
[DataField]
public bool ClumsyProof = false;
/// <summary>
/// Firing direction for an item not being held (e.g. shuttle cannons, thrown guns still firing).
/// </summary>
[DataField]
public Vector2 DefaultDirection = new Vector2(0, -1);
}
[Flags]

View File

@@ -67,7 +67,10 @@ public abstract partial class SharedGunSystem
return;
args.Handled = true;
UseChambered(uid, component, args.User);
if (component.CanRack)
UseChambered(uid, component, args.User);
else
ToggleBolt(uid, component, args.User);
}
/// <summary>
@@ -75,7 +78,7 @@ public abstract partial class SharedGunSystem
/// </summary>
private void OnChamberActivationVerb(EntityUid uid, ChamberMagazineAmmoProviderComponent component, GetVerbsEvent<ActivationVerb> args)
{
if (!args.CanAccess || !args.CanInteract || component.BoltClosed == null)
if (!args.CanAccess || !args.CanInteract || component.BoltClosed == null || !component.CanRack)
return;
args.Verbs.Add(new ActivationVerb()

View File

@@ -218,7 +218,7 @@ public abstract partial class SharedGunSystem : EntitySystem
/// </summary>
public void AttemptShoot(EntityUid gunUid, GunComponent gun)
{
var coordinates = new EntityCoordinates(gunUid, new Vector2(0, -1));
var coordinates = new EntityCoordinates(gunUid, gun.DefaultDirection);
gun.ShootCoordinates = coordinates;
AttemptShoot(gunUid, gunUid, gun);
gun.ShotCounter = 0;
@@ -258,6 +258,9 @@ public abstract partial class SharedGunSystem : EntitySystem
var fireRate = TimeSpan.FromSeconds(1f / gun.FireRateModified);
if (gun.SelectedMode == SelectiveFire.Burst || gun.BurstActivated)
fireRate = TimeSpan.FromSeconds(1f / gun.BurstFireRate);
// First shot
// Previously we checked shotcounter but in some cases all the bullets got dumped at once
// curTime - fireRate is insufficient because if you time it just right you can get a 3rd shot out slightly quicker.
@@ -278,18 +281,24 @@ public abstract partial class SharedGunSystem : EntitySystem
// Get how many shots we're actually allowed to make, due to clip size or otherwise.
// Don't do this in the loop so we still reset NextFire.
switch (gun.SelectedMode)
if (!gun.BurstActivated)
{
case SelectiveFire.SemiAuto:
shots = Math.Min(shots, 1 - gun.ShotCounter);
break;
case SelectiveFire.Burst:
shots = Math.Min(shots, gun.ShotsPerBurstModified - gun.ShotCounter);
break;
case SelectiveFire.FullAuto:
break;
default:
throw new ArgumentOutOfRangeException($"No implemented shooting behavior for {gun.SelectedMode}!");
switch (gun.SelectedMode)
{
case SelectiveFire.SemiAuto:
shots = Math.Min(shots, 1 - gun.ShotCounter);
break;
case SelectiveFire.Burst:
shots = Math.Min(shots, gun.ShotsPerBurstModified - gun.ShotCounter);
break;
case SelectiveFire.FullAuto:
break;
default:
throw new ArgumentOutOfRangeException($"No implemented shooting behavior for {gun.SelectedMode}!");
}
} else
{
shots = Math.Min(shots, gun.ShotsPerBurstModified - gun.ShotCounter);
}
var attemptEv = new AttemptShootEvent(user, null);
@@ -301,7 +310,8 @@ public abstract partial class SharedGunSystem : EntitySystem
{
PopupSystem.PopupClient(attemptEv.Message, gunUid, user);
}
gun.BurstActivated = false;
gun.BurstShotsCount = 0;
gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
return;
}
@@ -328,6 +338,10 @@ public abstract partial class SharedGunSystem : EntitySystem
var emptyGunShotEvent = new OnEmptyGunShotEvent();
RaiseLocalEvent(gunUid, ref emptyGunShotEvent);
gun.BurstActivated = false;
gun.BurstShotsCount = 0;
gun.NextFire += TimeSpan.FromSeconds(gun.BurstCooldown);
// Play empty gun sounds if relevant
// If they're firing an existing clip then don't play anything.
if (shots > 0)
@@ -347,6 +361,22 @@ public abstract partial class SharedGunSystem : EntitySystem
return;
}
// Handle burstfire
if (gun.SelectedMode == SelectiveFire.Burst)
{
gun.BurstActivated = true;
}
if (gun.BurstActivated)
{
gun.BurstShotsCount += shots;
if (gun.BurstShotsCount >= gun.ShotsPerBurstModified)
{
gun.NextFire += TimeSpan.FromSeconds(gun.BurstCooldown);
gun.BurstActivated = false;
gun.BurstShotsCount = 0;
}
}
// Shoot confirmed - sounds also played here in case it's invalid (e.g. cartridge already spent).
Shoot(gunUid, gun, ev.Ammo, fromCoordinates, toCoordinates.Value, out var userImpulse, user, throwItems: attemptEv.ThrowItems);
var shotEv = new GunShotEvent(user, ev.Ammo);

View File

@@ -1,31 +1,4 @@
Entries:
- author: mirrorcult
changes:
- message: With space law being overhauled, you can now examine items to see their
contraband status, and whether with your current access you'd be accosted by
Security for owning it. This will also clearly show non-stealth syndicate items.
type: Add
id: 7096
time: '2024-08-12T03:57:50.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/28688
- author: DieselMohawk
changes:
- message: Resprited Security vest and helmet
type: Tweak
id: 7097
time: '2024-08-12T06:20:56.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30291
- author: Ubaser
changes:
- message: Mantles are now available in loadouts, requiring 20 hours of that head
of department's time.
type: Add
- message: Mantles are no longer spawned in dressers or able to be printed at uniform
lathes.
type: Remove
id: 7098
time: '2024-08-12T07:14:46.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/30929
- author: LeoSantich
changes:
- message: Updated 'narsie' and 'ratvar' to 'Nar'Sie' and 'Ratvar' in randomly generated
@@ -3944,3 +3917,35 @@
id: 7595
time: '2024-11-06T13:20:05.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33084
- author: BramvanZijp
changes:
- message: Flare guns have been reworked to no longer automatically eject shells
after firing, and must now be opened manually to insert or eject shells. A safety
feature has also been added to prevent loading lethal shells into them.
type: Tweak
- message: Flare guns are twice as likely to appear in emergency closets, with the
same rarity as MRE's.
type: Tweak
- message: Added the security shell gun, a modified flare gun which is capable of
handling both nonlethal and lethal shotgun shells. It is able to be crafted
in the security techfab without needing any research.
type: Add
id: 7596
time: '2024-11-06T14:27:11.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/32829
- author: SlamBamActionman
changes:
- message: WT550 and C20-r's "burst" firemodes are now actual bursts.
type: Tweak
- message: Drozd is now a burst-only weapon (DPS remains unchanged!).
type: Tweak
id: 7597
time: '2024-11-06T14:39:16.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/31292
- author: PopGamer46
changes:
- message: Fixed Lambordeere (botany shuttle) bolt buttons not being connected
type: Fix
id: 7598
time: '2024-11-07T22:02:25.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33065

View File

@@ -4,7 +4,7 @@
[game]
desc = "Official English Space Station 14 servers. Vanilla, roleplay ruleset."
lobbyenabled = true
soft_max_players = 70
soft_max_players = 80
panic_bunker.enabled = true
panic_bunker.disable_with_admins = true
panic_bunker.enable_without_admins = true

View File

@@ -1,2 +1,4 @@
chameleon-projector-inside-container = There's no room to scan that!
chameleon-projector-invalid = You can't disguise as that!
chameleon-projector-success = Projected new disguise.
chameleon-projector-set-disguise = Set Disguise

View File

@@ -1206,6 +1206,10 @@ entities:
rot: 1.5707963267948966 rad
pos: 0.5,5.5
parent: 1
- type: DeviceLinkSource
linkedPorts:
50:
- Pressed: DoorBolt
- uid: 199
components:
- type: MetaData
@@ -1214,6 +1218,10 @@ entities:
rot: 1.5707963267948966 rad
pos: 0.5,2.5
parent: 1
- type: DeviceLinkSource
linkedPorts:
82:
- Pressed: DoorBolt
- proto: SMESBasic
entities:
- uid: 65

File diff suppressed because it is too large Load Diff

View File

@@ -12942,6 +12942,10 @@ entities:
rot: -1.5707963267948966 rad
pos: 30.5,-42.5
parent: 2
- type: DeviceList
devices:
- 20006
- 20005
- uid: 8436
components:
- type: Transform
@@ -95454,6 +95458,9 @@ entities:
rot: 1.5707963267948966 rad
pos: 26.5,-42.5
parent: 2
- type: DeviceNetwork
deviceLists:
- 8434
- type: AtmosPipeColor
color: '#0335FCFF'
- uid: 20037
@@ -96655,6 +96662,9 @@ entities:
rot: 1.5707963267948966 rad
pos: 26.5,-45.5
parent: 2
- type: DeviceNetwork
deviceLists:
- 8434
- type: AtmosPipeColor
color: '#FF1212FF'
- uid: 20038

View File

@@ -10880,7 +10880,7 @@ entities:
pos: -42.5,29.5
parent: 5350
- type: Door
secondsUntilStateChange: -5745.716
secondsUntilStateChange: -5834.8745
state: Opening
- type: DeviceLinkSink
invokeCounter: 2
@@ -56106,11 +56106,6 @@ entities:
rot: -1.5707963267948966 rad
pos: -73.5,7.5
parent: 5350
- uid: 6164
components:
- type: Transform
pos: -71.5,-8.5
parent: 5350
- uid: 6165
components:
- type: Transform

View File

@@ -30,7 +30,7 @@
- id: MedkitOxygenFilled
prob: 0.2
- id: WeaponFlareGun
prob: 0.05
prob: 0.1
- id: BoxMRE
prob: 0.1

View File

@@ -1784,6 +1784,11 @@
# intended for swarms that eat pills so only temporary
- type: TimedDespawn
lifetime: 60
- type: Hunger
baseDecayRate: 10 # always hungry
starvingSlowdownModifier: 1
- type: Thirst
baseDecayRate: 10 # always thirsty
- type: entity
parent: MobMouse
@@ -3381,7 +3386,7 @@
- type: HTN
rootTask:
task: RuminantCompound
- type: entity
name: diona nymph
parent: [SimpleMobBase, StripableInventoryBase]

View File

@@ -69,8 +69,6 @@
canShuttle: false
title: comms-console-announcement-title-station-ai
color: "#2ed2fd"
- type: Speech
speechVerb: Robotic
- type: ShowJobIcons
- type: entity
@@ -395,6 +393,9 @@
drawFov: false
- type: Examiner
- type: InputMover
- type: Speech
speechVerb: Robotic
speechSounds: Borg
- type: Tag
tags:
- HideContextMenu

View File

@@ -17,15 +17,12 @@
blacklist:
components:
- ChameleonDisguise # no becoming kleiner
- InsideEntityStorage # no clark kent going in phone booth and becoming superman
- MindContainer # no
- Pda # PDAs currently make you invisible /!\
polymorph:
entity: ChameleonDisguise
disguiseProto: ChameleonDisguise
- type: entity
categories: [ HideSpawnMenu ]
parent: BaseMob
id: ChameleonDisguise
name: Urist McKleiner
components:
@@ -33,20 +30,11 @@
- type: Sprite
sprite: /Textures/Mobs/Species/Human/parts.rsi
state: full
# so people can attempt to pick it up
- type: Item
# so it can take damage
# projector system sets health to be proportional to mass
- type: Transform
noRot: true # players rotation and anchor is used instead
- type: InteractionOutline
- type: Clickable
- type: Damageable
- type: MobState
- type: MobThresholds
thresholds:
0: Alive
1: Critical
200: Dead
- type: MovementSpeedModifier
baseWalkSpeed: 1 # precise movement for the perfect spot
baseSprintSpeed: 5 # the jig is up
- type: ChameleonDisguise
# actions
@@ -57,6 +45,7 @@
components:
- type: InstantAction
icon: Interface/VerbIcons/refresh.svg.192dpi.png
itemIconStyle: BigAction
event: !type:DisguiseToggleNoRotEvent
- type: entity
@@ -68,4 +57,5 @@
icon:
sprite: Objects/Tools/wrench.rsi
state: icon
itemIconStyle: BigAction
event: !type:DisguiseToggleAnchoredEvent

View File

@@ -24,6 +24,11 @@
name: shell (.50 beanbag)
parent: BaseShellShotgun
components:
- type: Tag
tags:
- Cartridge
- ShellShotgun
- ShellShotgunLight
- type: Sprite
layers:
- state: beanbag
@@ -52,6 +57,11 @@
name: shell (.50 flare)
parent: BaseShellShotgun
components:
- type: Tag
tags:
- Cartridge
- ShellShotgun
- ShellShotgunLight
- type: Sprite
layers:
- state: flare
@@ -106,6 +116,11 @@
name: shell (.50 tranquilizer)
parent: BaseShellShotgun
components:
- type: Tag
tags:
- Cartridge
- ShellShotgun
- ShellShotgunLight
- type: Sprite
layers:
- state: tranquilizer
@@ -130,6 +145,11 @@
description: A homemade shotgun shell that shoots painful glass shrapnel. The spread is so wide that it couldn't hit the broad side of a barn.
parent: BaseShellShotgun
components:
- type: Tag
tags:
- Cartridge
- ShellShotgun
- ShellShotgunLight
- type: Sprite
layers:
- state: improvised

View File

@@ -19,6 +19,7 @@
minAngle: 2
maxAngle: 16
fireRate: 8
burstFireRate: 8
angleIncrease: 3
angleDecay: 16
selectedMode: FullAuto
@@ -27,6 +28,7 @@
- FullAuto
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/smg.ogg
defaultDirection: 1, 0
- type: ChamberMagazineAmmoProvider
soundRack:
path: /Audio/Weapons/Guns/Cock/smg_cock.ogg
@@ -140,12 +142,15 @@
- type: Gun
minAngle: 21
maxAngle: 32
fireRate: 6
selectedMode: FullAuto
fireRate: 12
burstFireRate: 12
selectedMode: Burst
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/atreides.ogg
availableModes:
- FullAuto
- Burst
shotsPerBurst: 3
burstCooldown: 0.25
- type: ItemSlots
slots:
gun_magazine:
@@ -250,6 +255,8 @@
angleDecay: 6
selectedMode: FullAuto
shotsPerBurst: 5
burstCooldown: 0.2
burstFireRate: 7
availableModes:
- SemiAuto
- Burst

View File

@@ -1,17 +1,44 @@
- type: entity
name: flare gun
parent: BaseWeaponLauncher
parent: BaseItem
id: WeaponFlareGun
description: A compact, single-shot pistol that fires shotgun shells.
description: A compact, single-shot pistol that fires shotgun shells. Comes with a safety feature that prevents the user from fitting lethal shells inside.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Shotguns/flaregun.rsi
layers:
- state: icon
- state: base
map: ["enum.GunVisualLayers.Base"]
- type: Item
size: Small
sprite: Objects/Weapons/Guns/Shotguns/flaregun.rsi
- type: ItemSlots
slots:
gun_chamber:
name: Chamber
startingItem: ShellShotgunFlare
priority: 1
whitelist:
tags: ## TODO: Add a risk of the gun blowing up if using non-light shotgun shells, and then re-enable them.
## - ShellShotgun
- ShellShotgunLight
- type: ContainerContainer
containers:
gun_chamber: !type:ContainerSlot
- type: ChamberMagazineAmmoProvider
autoCycle: false
boltClosed: true
canRack: false
soundBoltClosed: /Audio/Weapons/Guns/Cock/revolver_cock.ogg
soundBoltOpened: /Audio/Weapons/Guns/Cock/revolver_cock.ogg
soundRack: /Audio/Weapons/Guns/Cock/revolver_cock.ogg
- type: Clothing
sprite: Objects/Weapons/Guns/Shotguns/flaregun.rsi
quickEquip: false
slots:
- Belt
- suitStorage
- type: Appearance
- type: Gun
fireRate: 8
selectedMode: SemiAuto
@@ -19,21 +46,30 @@
- SemiAuto
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/flaregun.ogg
- type: BallisticAmmoProvider
whitelist:
tags:
- ShellShotgun
proto: ShellShotgunFlare
capacity: 1
soundInsert:
path: /Audio/Weapons/Guns/MagIn/shotgun_insert.ogg
- type: ContainerContainer
containers:
ballistic-ammo: !type:Container
ents: []
- type: Clothing
sprite: Objects/Weapons/Guns/Shotguns/flaregun.rsi
quickEquip: false
- type: entity
name: security shell gun
parent: [WeaponFlareGun, BaseSecurityContraband]
id: WeaponFlareGunSecurity
description: A modified flare gun originally designed to be used by security to launch non-lethal shotgun shells, however it can also fire lethal shells without risk.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Shotguns/flaregun_security.rsi
layers:
- state: base
map: ["enum.GunVisualLayers.Base"]
- type: Item
size: Small
sprite: Objects/Weapons/Guns/Shotguns/flaregun_security.rsi
- type: ItemSlots
slots:
- Belt
- suitStorage
gun_chamber:
name: Chamber
priority: 1
whitelist:
tags:
- ShellShotgun
- type: Tag
tags:
- Sidearm

View File

@@ -768,6 +768,7 @@
- TargetHuman
- TargetSyndicate
- WeaponDisablerPractice
- WeaponFlareGunSecurity
- WeaponLaserCarbinePractice
- Zipties
dynamicRecipes:

View File

@@ -152,4 +152,4 @@
sprite: Structures/Windows/cracks_diagonal.rsi
- type: Construction
graph: WindowDiagonal
node: clockworkWindowDiagonal
node: clockworkWindowDiagonal

View File

@@ -91,4 +91,4 @@
- East
- type: DamageVisuals
damageOverlay:
sprite: Structures/Windows/cracks_diagonal.rsi
sprite: Structures/Windows/cracks_diagonal.rsi

View File

@@ -152,4 +152,4 @@
sprite: Structures/Windows/cracks_diagonal.rsi
- type: Construction
graph: WindowDiagonal
node: plasmaWindowDiagonal
node: plasmaWindowDiagonal

View File

@@ -195,4 +195,4 @@
doAfterDelay: 3
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: RGlass
damageModifierSet: RGlass

View File

@@ -159,4 +159,4 @@
sprite: Structures/Windows/cracks_diagonal.rsi
- type: Construction
graph: WindowDiagonal
node: reinforcedWindowDiagonal
node: reinforcedWindowDiagonal

View File

@@ -155,4 +155,4 @@
sprite: Structures/Windows/cracks_diagonal.rsi
- type: Construction
graph: WindowDiagonal
node: reinforcedPlasmaWindowDiagonal
node: reinforcedPlasmaWindowDiagonal

View File

@@ -152,4 +152,4 @@
sprite: Structures/Windows/cracks_diagonal.rsi
- type: Construction
graph: WindowDiagonal
node: reinforcedUraniumWindowDiagonal
node: reinforcedUraniumWindowDiagonal

View File

@@ -94,4 +94,4 @@
- East
- type: DamageVisuals
damageOverlay:
sprite: Structures/Windows/cracks_diagonal.rsi
sprite: Structures/Windows/cracks_diagonal.rsi

View File

@@ -147,4 +147,4 @@
sprite: Structures/Windows/cracks_diagonal.rsi
- type: Construction
graph: WindowDiagonal
node: uraniumWindowDiagonal
node: uraniumWindowDiagonal

View File

@@ -284,4 +284,4 @@
sprite: Structures/Windows/cracks_diagonal.rsi
- type: Construction
graph: WindowDiagonal
node: windowDiagonal
node: windowDiagonal

View File

@@ -191,12 +191,17 @@
- type: entity
id: TraitorReinforcement
parent: Traitor
parent: BaseTraitorRule
components:
- type: TraitorRule
giveUplink: false
giveCodewords: false # It would actually give them a different set of codewords than the regular traitors, anyway
giveBriefing: false
- type: AntagSelection
definitions:
- prefRoles: [ Traitor ]
mindRoles:
- MindRoleTraitor
- type: entity
id: Revolutionary
@@ -280,7 +285,6 @@
tableId: CalmPestEventsTable
- !type:NestedSelector
tableId: SpicyPestEventsTable
- type: entityTable
id: SpaceTrafficControlTable

View File

@@ -4,63 +4,61 @@
graph:
- node: start
edges:
- to: window # 50 hp
steps:
- material: Glass
amount: 2
doAfter: 2
- to: tintedWindow # 50 hp
steps:
- material: Glass
amount: 2
- material: Plastic
amount: 2
doAfter: 2
- to: plasmaWindow # 75 hp
- to: plasmaWindow
steps:
- material: PlasmaGlass
amount: 2
doAfter: 3
doAfter: 2
- to: uraniumWindow # 75 hp
steps:
- material: UraniumGlass
amount: 2
doAfter: 3
- to: clockworkWindow # 75 hp reinforced damage mod
steps:
- material: ClockworkGlass
amount: 2
doAfter: 3
- to: reinforcedWindow # 75 hp reinforced damage mod
- to: reinforcedWindow
steps:
- material: ReinforcedGlass
amount: 2
doAfter: 3
doAfter: 2
- to: reinforcedPlasmaWindow # 150 hp reinforced damage mod
- to: tintedWindow
steps:
- material: ReinforcedGlass
amount: 2
doAfter: 2
- to: reinforcedPlasmaWindow
steps:
- material: ReinforcedPlasmaGlass
amount: 2
doAfter: 4
doAfter: 3
- to: reinforcedUraniumWindow # 150 hp reinforced damage mod
- to: uraniumWindow
steps:
- material: UraniumGlass
amount: 2
doAfter: 2
- to: reinforcedUraniumWindow
steps:
- material: ReinforcedUraniumGlass
amount: 2
doAfter: 4
doAfter: 3
- to: shuttleWindow # 500 hp reinforced damage mod (wow)
- to: window
steps:
- material: Glass
amount: 2
doAfter: 3
- to: shuttleWindow
steps:
- material: Plasteel
amount: 2
- material: ReinforcedGlass
amount: 2
doAfter: 6
doAfter: 4
- to: clockworkWindow
steps:
- material: ClockworkGlass
amount: 2
doAfter: 3
- node: window
entity: Window
@@ -76,120 +74,6 @@
doAfter: 1
- tool: Anchoring
doAfter: 2
- to: tintedWindow
steps:
- material: Plastic
amount: 2
doAfter: 0.5
- to: plasmaWindow
steps:
- material: Plasma
amount: 2
doAfter: 1
- to: uraniumWindow
steps:
- material: Uranium
amount: 2
doAfter: 1
- to: clockworkWindow
steps:
- material: Brass
amount: 2
doAfter: 2
- to: reinforcedWindow
steps:
- material: MetalRod
amount: 2
doAfter: 2
- node: tintedWindow
entity: TintedWindow
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetGlass1
amount: 2
- !type:SpawnPrototype
prototype: SheetPlastic1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 1
- tool: Anchoring
doAfter: 2
- node: plasmaWindow
entity: PlasmaWindow
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetPGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- to: reinforcedPlasmaWindow
steps:
- material: MetalRod
amount: 2
doAfter: 1
- node: uraniumWindow
entity: UraniumWindow
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetUGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- to: reinforcedUraniumWindow
steps:
- material: MetalRod
amount: 2
doAfter: 1
- node: clockworkWindow
entity: ClockworkWindow
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetClockworkGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Welding
doAfter: 5
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Welding
doAfter: 5
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: reinforcedWindow
entity: ReinforcedWindow
@@ -213,20 +97,43 @@
doAfter: 1
- tool: Anchoring
doAfter: 2
- to: reinforcedPlasmaWindow
steps:
- material: Plasma
- node: tintedWindow
entity: TintedWindow
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetRGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 1
- to: reinforcedUraniumWindow
steps:
- material: Uranium
amount: 2
- tool: Prying
doAfter: 2
- tool: Screwing
doAfter: 1
- to: shuttleWindow
steps:
- material: Plasteel
- tool: Anchoring
doAfter: 2
- node: plasmaWindow
entity: PlasmaWindow
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetPGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: reinforcedPlasmaWindow
@@ -252,6 +159,25 @@
- tool: Anchoring
doAfter: 3
- node: uraniumWindow
entity: UraniumWindow
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetUGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: reinforcedUraniumWindow
entity: ReinforcedUraniumWindow
edges:
@@ -274,6 +200,29 @@
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: clockworkWindow
entity: ClockworkWindow
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetClockworkGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Welding
doAfter: 5
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Welding
doAfter: 5
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: shuttleWindow
entity: ShuttleWindow
@@ -304,4 +253,4 @@
- tool: Welding
doAfter: 4
- tool: Anchoring
doAfter: 1
doAfter: 1

View File

@@ -4,30 +4,12 @@
graph:
- node: start
edges:
- to: windowDiagonal
steps:
- material: Glass
amount: 2
doAfter: 2
- to: plasmaWindowDiagonal
steps:
- material: PlasmaGlass
amount: 2
doAfter: 2
- to: uraniumWindowDiagonal
steps:
- material: UraniumGlass
amount: 2
doAfter: 2
- to: clockworkWindowDiagonal
steps:
- material: ClockworkGlass
amount: 2
doAfter: 3
- to: reinforcedWindowDiagonal
steps:
- material: ReinforcedGlass
@@ -40,12 +22,30 @@
amount: 2
doAfter: 3
- to: uraniumWindowDiagonal
steps:
- material: UraniumGlass
amount: 2
doAfter: 2
- to: reinforcedUraniumWindowDiagonal
steps:
- material: ReinforcedUraniumGlass
amount: 2
doAfter: 3
- to: clockworkWindowDiagonal
steps:
- material: ClockworkGlass
amount: 2
doAfter: 3
- to: windowDiagonal
steps:
- material: Glass
amount: 2
doAfter: 3
- node: windowDiagonal
entity: WindowDiagonal
edges:
@@ -60,97 +60,6 @@
doAfter: 1
- tool: Anchoring
doAfter: 2
- to: plasmaWindowDiagonal
steps:
- material: Plasma
amount: 2
doAfter: 1
- to: uraniumWindowDiagonal
steps:
- material: Uranium
amount: 2
doAfter: 1
- to: clockworkWindowDiagonal
steps:
- material: Brass
amount: 2
doAfter: 2
- to: reinforcedWindowDiagonal
steps:
- material: MetalRod
amount: 2
doAfter: 2
- node: plasmaWindowDiagonal
entity: PlasmaWindowDiagonal
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetPGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- to: reinforcedPlasmaWindowDiagonal
steps:
- material: MetalRod
amount: 2
doAfter: 1
- node: uraniumWindowDiagonal
entity: UraniumWindowDiagonal
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetUGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- to: reinforcedUraniumWindowDiagonal
steps:
- material: MetalRod
amount: 2
doAfter: 1
- node: clockworkWindowDiagonal
entity: ClockworkWindowDiagonal
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetClockworkGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Welding
doAfter: 5
- tool: Screwing
doAfter: 1
- tool: Prying
doAfter: 2
- tool: Welding
doAfter: 5
- tool: Screwing
doAfter: 1
- tool: Anchoring
doAfter: 2
- node: reinforcedWindowDiagonal
entity: ReinforcedWindowDiagonal
@@ -174,16 +83,48 @@
doAfter: 1
- tool: Anchoring
doAfter: 2
- to: reinforcedPlasmaWindowDiagonal
steps:
- material: Plasma
- node: clockworkWindowDiagonal
entity: ClockworkWindowDiagonal
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetClockworkGlass1
amount: 2
doAfter: 1
- to: reinforcedUraniumWindowDiagonal
- !type:DeleteEntity {}
steps:
- material: Uranium
amount: 2
- tool: Welding
doAfter: 5
- tool: Screwing
doAfter: 1
- tool: Prying
doAfter: 2
- tool: Welding
doAfter: 5
- tool: Screwing
doAfter: 1
- tool: Anchoring
doAfter: 2
- node: plasmaWindowDiagonal
entity: PlasmaWindowDiagonal
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetPGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: reinforcedPlasmaWindowDiagonal
entity: ReinforcedPlasmaWindowDiagonal
@@ -208,6 +149,25 @@
- tool: Anchoring
doAfter: 3
- node: uraniumWindowDiagonal
entity: UraniumWindowDiagonal
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetUGlass1
amount: 2
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: reinforcedUraniumWindowDiagonal
entity: ReinforcedUraniumWindowDiagonal
edges:
@@ -229,4 +189,4 @@
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
doAfter: 3

View File

@@ -4,55 +4,47 @@
graph:
- node: start
edges:
- to: windowDirectional # 25 hp
- to: windowDirectional
steps:
- material: Glass
amount: 1
doAfter: 1
doAfter: 2
- to: windowFrostedDirectional # 25 hp
steps:
- material: Glass
amount: 1
- material: Plastic
amount: 1
doAfter: 1
- to: plasmaWindowDirectional # 37 hp
steps:
- material: PlasmaGlass
amount: 1
doAfter: 1.5
- to: uraniumWindowDirectional # 37 hp
steps:
- material: UraniumGlass
amount: 1
doAfter: 1.5
- to: windowClockworkDirectional # 37 hp reinforced damage mod
steps:
- material: ClockworkGlass
amount: 1
doAfter: 1.5
- to: windowReinforcedDirectional # 37 hp reinforced damage mod
- to: windowReinforcedDirectional
steps:
- material: ReinforcedGlass
amount: 1
doAfter: 1.5
doAfter: 3
- to: plasmaReinforcedWindowDirectional # 75 hp reinforced damage mod
- to: plasmaWindowDirectional
steps:
- material: PlasmaGlass
amount: 1
doAfter: 2
- to: plasmaReinforcedWindowDirectional
steps:
- material: ReinforcedPlasmaGlass
amount: 1
doAfter: 3
- to: uraniumWindowDirectional
steps:
- material: UraniumGlass
amount: 1
doAfter: 2
- to: uraniumReinforcedWindowDirectional # 75 hp reinforced damage mod
- to: uraniumReinforcedWindowDirectional
steps:
- material: ReinforcedUraniumGlass
amount: 1
doAfter: 2
doAfter: 3
- to: windowClockworkDirectional
steps:
- material: ClockworkGlass
amount: 1
doAfter: 3
- node: windowDirectional
entity: WindowDirectional
@@ -68,45 +60,21 @@
doAfter: 1
- tool: Anchoring
doAfter: 2
- to: windowFrostedDirectional
steps:
- material: Plastic
amount: 1
doAfter: 0.5
- to: plasmaWindowDirectional
steps:
- material: Plasma
amount: 1
doAfter: 0.5
- to: uraniumWindowDirectional
steps:
- material: Uranium
amount: 1
doAfter: 0.5
- to: windowClockworkDirectional
steps:
- material: Brass
amount: 1
doAfter: 1
- to: windowReinforcedDirectional
steps:
- material: MetalRod
amount: 1
doAfter: 1
- node: windowFrostedDirectional
entity: WindowFrostedDirectional
- node: windowReinforcedDirectional
entity: WindowReinforcedDirectional
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetGlass1
amount: 1
- !type:SpawnPrototype
prototype: SheetPlastic1
prototype: SheetRGlass1
amount: 1
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 1
- tool: Prying
doAfter: 2
- tool: Screwing
doAfter: 1
- tool: Anchoring
@@ -130,35 +98,6 @@
doAfter: 2
- tool: Anchoring
doAfter: 3
- to: plasmaReinforcedWindowDirectional
steps:
- material: MetalRod
amount: 1
doAfter: 0.5
- node: uraniumWindowDirectional
entity: UraniumWindowDirectional
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetUGlass1
amount: 1
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- to: uraniumReinforcedWindowDirectional
steps:
- material: MetalRod
amount: 1
doAfter: 0.5
- node: windowClockworkDirectional
entity: WindowClockworkDirectional
@@ -179,35 +118,6 @@
- tool: Anchoring
doAfter: 3
- node: windowReinforcedDirectional
entity: WindowReinforcedDirectional
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetRGlass1
amount: 1
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 1
- tool: Prying
doAfter: 2
- tool: Screwing
doAfter: 1
- tool: Anchoring
doAfter: 2
- to: plasmaReinforcedWindowDirectional
steps:
- material: Plasma
amount: 1
doAfter: 0.5
- to: uraniumReinforcedWindowDirectional
steps:
- material: Uranium
amount: 1
doAfter: 0.5
- node: plasmaReinforcedWindowDirectional
entity: PlasmaReinforcedWindowDirectional
edges:
@@ -226,6 +136,24 @@
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: uraniumWindowDirectional
entity: UraniumWindowDirectional
edges:
- to: start
completed:
- !type:SpawnPrototype
prototype: SheetUGlass1
amount: 1
- !type:DeleteEntity {}
steps:
- tool: Screwing
doAfter: 2
- tool: Prying
doAfter: 3
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
- node: uraniumReinforcedWindowDirectional
entity: UraniumReinforcedWindowDirectional
@@ -244,4 +172,4 @@
- tool: Screwing
doAfter: 2
- tool: Anchoring
doAfter: 3
doAfter: 3

View File

@@ -1746,4 +1746,4 @@
sprite: Structures/Doors/secret_door.rsi
state: closed
conditions:
- !type:TileNotBlocked
- !type:TileNotBlocked

View File

@@ -603,6 +603,15 @@
Plastic: 320
Uranium: 240
- type: latheRecipe
parent: BaseWeaponRecipe
id: WeaponFlareGunSecurity
result: WeaponFlareGunSecurity
completetime: 6
materials:
Plastic: 100
Steel: 400
- type: latheRecipe
parent: BaseWeaponRecipe
id: WeaponDisabler

View File

@@ -19,7 +19,6 @@
weight: 10
startingGear: QuartermasterGear
icon: "JobIconQuarterMaster"
requireAdminNotify: true
supervisors: job-supervisors-captain
canBeAntag: false
access:

View File

@@ -20,7 +20,6 @@
weight: 20
startingGear: CaptainGear
icon: "JobIconCaptain"
requireAdminNotify: true
joinNotifyCrew: true
supervisors: job-supervisors-centcom
canBeAntag: false

View File

@@ -20,7 +20,6 @@
weight: 20
startingGear: HoPGear
icon: "JobIconHeadOfPersonnel"
requireAdminNotify: true
supervisors: job-supervisors-captain
canBeAntag: false
access:

View File

@@ -19,7 +19,6 @@
weight: 10
startingGear: ChiefEngineerGear
icon: "JobIconChiefEngineer"
requireAdminNotify: true
supervisors: job-supervisors-captain
canBeAntag: false
access:

View File

@@ -21,7 +21,6 @@
weight: 10
startingGear: CMOGear
icon: "JobIconChiefMedicalOfficer"
requireAdminNotify: true
supervisors: job-supervisors-captain
canBeAntag: false
access:

View File

@@ -13,7 +13,6 @@
weight: 10
startingGear: ResearchDirectorGear
icon: "JobIconResearchDirector"
requireAdminNotify: true
supervisors: job-supervisors-captain
canBeAntag: false
access:

View File

@@ -19,7 +19,6 @@
weight: 10
startingGear: HoSGear
icon: "JobIconHeadOfSecurity"
requireAdminNotify: true
supervisors: job-supervisors-captain
canBeAntag: false
access:

View File

@@ -10,7 +10,6 @@
time: 36000 #10 hrs
startingGear: WardenGear
icon: "JobIconWarden"
requireAdminNotify: true
supervisors: job-supervisors-hos
canBeAntag: false
access:

View File

@@ -1198,6 +1198,9 @@
- type: Tag
id: ShellShotgun
- type: Tag
id: ShellShotgunLight # shotgun shells that are compatible with the flare gun.
- type: Tag
id: Shiv

View File

@@ -2,7 +2,7 @@
# Roleplay Rule 12 - Do not abandon your role
Do not join the round as a role that you don't intend to play. Do not enable antagonist roles that you don't intend to play. Abandoning a role includes not completing tasks that the role is expected to do, in addition to things like leaving the game. Members of command should almost all stay on the station until the emergency shuttle arrives. Enforcement of this rule is more strict for command and antagonist roles, and less strict for less important roles like passengers.
Violations of this rule typically result in temporary or indefinite role bans. We understand that you may need to leave round early or unexpectedly. If you are in an important role (which is relayed to you in chat upon receiving your role), you should notify command members or an admin via ahelp so that they know you are leaving. Space Station 14 is a game. Do not endanger the safety of yourself or others, and do not neglect important things to avoid leaving a round early, even if you have to leave immediately without notifying anyone. Role bans for disconnecting are typically only applied if there is a pattern, and are almost always temporary.
Violations of this rule typically result in temporary or indefinite role bans. We understand that you may need to leave round early or unexpectedly. If you are in an important role (which is relayed to you in chat upon receiving your role), you should notify command members so that they know you are leaving and attempt to cryosleep if possible. Space Station 14 is a game. Do not endanger the safety of yourself or others, and do not neglect important things to avoid leaving a round early, even if you have to leave immediately without notifying anyone. Role bans for disconnecting are typically only applied if there is a pattern, and are almost always temporary.
"Antag rolling" refers to a player abandoning their role if they do not get an antagonist role.

View File

@@ -8,7 +8,7 @@
},
"states": [
{
"name": "icon"
"name": "base"
},
{
"name": "bolt-open"

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -0,0 +1,33 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from cev-eris at https://github.com/discordia-space/CEV-Eris/raw/3f9ebb72931ff884427c3004a594ec61aaaa7041/icons/obj/guns/projectile/flaregun.dmi and edited",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "base"
},
{
"name": "bolt-open"
},
{
"name": "inhand-right",
"directions": 4
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "equipped-BELT",
"directions": 4
},
{
"name": "equipped-SUITSTORAGE",
"directions": 4
}
]
}