Skip to content

Commit

Permalink
Merge pull request #122 from SS14-Classic/Update-12/28/2024
Browse files Browse the repository at this point in the history
Update 12/28/2024
  • Loading branch information
VMSolidus authored Dec 29, 2024
2 parents 4e5a40e + c2df5f1 commit 7f0452e
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Content.Client/Jittering/JitteringSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private void OnShutdown(EntityUid uid, JitteringComponent jittering, ComponentSh

private void OnAnimationCompleted(EntityUid uid, JitteringComponent jittering, AnimationCompletedEvent args)
{
if(args.Key != _jitterAnimationKey)
if (args.Key != _jitterAnimationKey || jittering.LifeStage >= ComponentLifeStage.Stopping)
return;

if (TryComp(uid, out AnimationPlayerComponent? animationPlayer)
Expand Down
61 changes: 61 additions & 0 deletions Content.Server/Traits/TraitSystem.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Administration.Systems;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking;
using Content.Server.Players.PlayTimeTracking;
using Content.Shared.CCVar;
using Content.Shared.Chat;
using Content.Shared.Customization.Systems;
using Content.Shared.Database;
using Content.Shared.Players;
using Content.Shared.Roles;
using Content.Shared.Traits;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Utility;
using Timer = Robust.Shared.Timing.Timer;

namespace Content.Server.Traits;

Expand All @@ -20,6 +29,11 @@ public sealed class TraitSystem : EntitySystem
[Dependency] private readonly PlayTimeTrackingManager _playTimeTracking = default!;
[Dependency] private readonly IConfigurationManager _configuration = default!;
[Dependency] private readonly IComponentFactory _componentFactory = default!;
[Dependency] private readonly IAdminLogManager _adminLog = default!;
[Dependency] private readonly AdminSystem _adminSystem = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IChatManager _chatManager = default!;

public override void Initialize()
{
Expand All @@ -31,6 +45,9 @@ public override void Initialize()
// When the player is spawned in, add all trait components selected during character creation
private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args)
{
var pointsTotal = _configuration.GetCVar(CCVars.GameTraitsDefaultPoints);
var traitSelections = _configuration.GetCVar(CCVars.GameTraitsMax);

foreach (var traitId in args.Profile.TraitPreferences)
{
if (!_prototype.TryIndex<TraitPrototype>(traitId, out var traitPrototype))
Expand All @@ -47,8 +64,15 @@ private void OnPlayerSpawnComplete(PlayerSpawnCompleteEvent args)
out _))
continue;

// To check for cheaters. :FaridaBirb.png:
pointsTotal += traitPrototype.Points;
--traitSelections;

AddTrait(args.Mob, traitPrototype);
}

if (pointsTotal < 0 || traitSelections < 0)
PunishCheater(args.Mob);
}

/// <summary>
Expand All @@ -59,4 +83,41 @@ public void AddTrait(EntityUid uid, TraitPrototype traitPrototype)
foreach (var function in traitPrototype.Functions)
function.OnPlayerSpawn(uid, _componentFactory, EntityManager, _serialization);
}

/// <summary>
/// On a non-cheating client, it's not possible to save a character with a negative number of traits. This can however
/// trigger incorrectly if a character was saved, and then at a later point in time an admin changes the traits Cvars to reduce the points.
/// Or if the points costs of traits is increased.
/// </summary>
private void PunishCheater(EntityUid uid)
{
_adminLog.Add(LogType.AdminMessage, LogImpact.High,
$"{ToPrettyString(uid):entity} attempted to spawn with an invalid trait list. This might be a mistake, or they might be cheating");

if (!_configuration.GetCVar(CCVars.TraitsPunishCheaters)
|| !_playerManager.TryGetSessionByEntity(uid, out var targetPlayer))
return;

// For maximum comedic effect, this is plenty of time for the cheater to get on station and start interacting with people.
var timeToDestroy = _random.NextFloat(120, 360);

Timer.Spawn(TimeSpan.FromSeconds(timeToDestroy), () => VaporizeCheater(targetPlayer));
}

/// <summary>
/// https://www.youtube.com/watch?v=X2QMN0a_TrA
/// </summary>
private void VaporizeCheater (Robust.Shared.Player.ICommonSession targetPlayer)
{
_adminSystem.Erase(targetPlayer);

var feedbackMessage = $"[font size=24][color=#ff0000]{"You have spawned in with an illegal trait point total. If this was a result of cheats, then your nonexistence is a skill issue. Otherwise, feel free to click 'Return To Lobby', and fix your trait selections."}[/color][/font]";
_chatManager.ChatMessageToOne(
ChatChannel.Emotes,
feedbackMessage,
feedbackMessage,
EntityUid.Invalid,
false,
targetPlayer.Channel);
}
}
30 changes: 30 additions & 0 deletions Content.Shared/CCVar/CCVars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,13 @@ public static readonly CVarDef<bool>
public static readonly CVarDef<int> GameTraitsDefaultPoints =
CVarDef.Create("game.traits_default_points", 10, CVar.REPLICATED);

/// <summary>
/// Whether the game will SMITE people who used cheat engine to spawn with all of the traits.
/// Illegal trait totals will still be logged even if this is disabled.
/// If you are intending to decrease the trait points availability, or modify the costs of traits, consider temporarily disabling this.
/// </summary>
public static readonly CVarDef<bool> TraitsPunishCheaters =
CVarDef.Create("game.traits_punish_cheaters", true, CVar.REPLICATED);

/// <summary>
/// Whether to allow characters to select loadout items.
Expand Down Expand Up @@ -2813,5 +2820,28 @@ public static readonly CVarDef<float>
/// </summary>
public static readonly CVarDef<bool> UseDynamicHostname =
CVarDef.Create("game.use_dynamic_hostname", false, CVar.SERVERONLY);

#region SoftCrit

/// <summary>
/// Used for basic Soft-Crit implementation. Entities are allowed to crawl when in crit, as this CVar intercepts the mover controller check for incapacitation,
/// and prevents it from stopping movement if this CVar is set to true and the user is Crit but Not Dead. This is only for movement,
/// you still can't stand up while crit, and you're still more or less helpless.
/// </summary>
public static readonly CVarDef<bool> AllowMovementWhileCrit =
CVarDef.Create("mobstate.allow_movement_while_crit", true, CVar.REPLICATED);

public static readonly CVarDef<bool> AllowTalkingWhileCrit =
CVarDef.Create("mobstate.allow_talking_while_crit", true, CVar.REPLICATED);

/// <summary>
/// Currently does nothing because I would have to figure out WHERE I would even put this check, and the mover controller is fairly complicated.
/// The goal is to make it so that attempting to move while in 'soft crit' can potentially cause further injury, causing you to die faster. Ideally there would be special
/// actions that can be performed in soft crit, such as applying pressure to your own injuries to slow down the bleedout, or other varieties of "Will To Live".
/// </summary>
public static readonly CVarDef<bool> DamageWhileCritMove =
CVarDef.Create("mobstate.damage_while_crit_move", false, CVar.REPLICATED);

#endregion
}
}
28 changes: 26 additions & 2 deletions Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Content.Shared.Bed.Sleep;
using Content.Shared.Buckle.Components;
using Content.Shared.CCVar;
using Content.Shared.CombatMode.Pacification;
using Content.Shared.Damage.ForceSay;
using Content.Shared.Emoting;
Expand All @@ -16,17 +17,20 @@
using Content.Shared.Standing;
using Content.Shared.Strip.Components;
using Content.Shared.Throwing;
using Robust.Shared.Configuration;
using Robust.Shared.Physics.Components;

namespace Content.Shared.Mobs.Systems;

public partial class MobStateSystem
{
[Dependency] private readonly IConfigurationManager _configurationManager = default!;

//General purpose event subscriptions. If you can avoid it register these events inside their own systems
private void SubscribeEvents()
{
SubscribeLocalEvent<MobStateComponent, BeforeGettingStrippedEvent>(OnGettingStripped);
SubscribeLocalEvent<MobStateComponent, ChangeDirectionAttemptEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, ChangeDirectionAttemptEvent>(OnDirectionAttempt);
SubscribeLocalEvent<MobStateComponent, UseAttemptEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, AttackAttemptEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, ConsciousAttemptEvent>(CheckAct);
Expand All @@ -38,7 +42,7 @@ private void SubscribeEvents()
SubscribeLocalEvent<MobStateComponent, DropAttemptEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, PickupAttemptEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, StartPullAttemptEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, UpdateCanMoveEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, UpdateCanMoveEvent>(OnMoveAttempt);
SubscribeLocalEvent<MobStateComponent, StandAttemptEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, PointAttemptEvent>(CheckAct);
SubscribeLocalEvent<MobStateComponent, TryingToSleepEvent>(OnSleepAttempt);
Expand All @@ -48,6 +52,23 @@ private void SubscribeEvents()
SubscribeLocalEvent<MobStateComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
}

private void OnDirectionAttempt(Entity<MobStateComponent> ent, ref ChangeDirectionAttemptEvent args)
{
if (ent.Comp.CurrentState is MobState.Critical && _configurationManager.GetCVar(CCVars.AllowMovementWhileCrit))
return;

CheckAct(ent.Owner, ent.Comp, args);
}

private void OnMoveAttempt(Entity<MobStateComponent> ent, ref UpdateCanMoveEvent args)
{
if (ent.Comp.CurrentState is MobState.Critical && _configurationManager.GetCVar(CCVars.AllowMovementWhileCrit))
return;

CheckAct(ent.Owner, ent.Comp, args);
}


private void OnUnbuckleAttempt(Entity<MobStateComponent> ent, ref UnbuckleAttemptEvent args)
{
// TODO is this necessary?
Expand Down Expand Up @@ -145,6 +166,9 @@ private void OnSpeakAttempt(EntityUid uid, MobStateComponent component, SpeakAtt
return;
}

if (component.CurrentState is MobState.Critical && _configurationManager.GetCVar(CCVars.AllowTalkingWhileCrit))
return;

CheckAct(uid, component, args);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,11 @@ private void HandleDirChange(EntityUid entity, Direction dir, ushort subTick, bo
if (MoverQuery.TryGetComponent(entity, out var mover))
SetMoveInput(mover, MoveButtons.None);

if (!_mobState.IsIncapacitated(entity))
HandleDirChange(relayMover.RelayEntity, dir, subTick, state);
if (_mobState.IsDead(entity)
|| _mobState.IsCritical(entity) && !_configManager.GetCVar(CCVars.AllowMovementWhileCrit))
return;

HandleDirChange(relayMover.RelayEntity, dir, subTick, state);

return;
}
Expand Down
7 changes: 4 additions & 3 deletions Content.Shared/Movement/Systems/SharedMoverController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,10 @@ protected void HandleMobMovement(
var canMove = mover.CanMove;
if (RelayTargetQuery.TryGetComponent(uid, out var relayTarget))
{
if (_mobState.IsIncapacitated(relayTarget.Source) ||
TryComp<SleepingComponent>(relayTarget.Source, out _) ||
!MoverQuery.TryGetComponent(relayTarget.Source, out var relayedMover))
if (_mobState.IsDead(relayTarget.Source)
|| TryComp<SleepingComponent>(relayTarget.Source, out _)
|| !MoverQuery.TryGetComponent(relayTarget.Source, out var relayedMover)
|| _mobState.IsCritical(relayTarget.Source) && !_configManager.GetCVar(CCVars.AllowMovementWhileCrit))
{
canMove = false;
}
Expand Down
40 changes: 40 additions & 0 deletions Resources/Changelog/Changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8757,3 +8757,43 @@ Entries:
id: 6587
time: '2024-12-22T10:26:41.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/1366
- author: juniwoofs
changes:
- type: Add
message: two new cuddly friends to the station! (harpy and morty plush)
id: 6588
time: '2024-12-22T19:24:58.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/1369
- author: VMSolidus
changes:
- type: Add
message: >-
Implemented Anti-cheat for Traits. Attempting to join a round with an
illegal traits list will result in hilarious consequences.
id: 6589
time: '2024-12-22T19:55:22.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/1358
- author: VMSolidus
changes:
- type: Add
message: Prisoners now spawn with a Pacifier Implant.
id: 6590
time: '2024-12-22T19:56:21.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/1341
- author: sleepyyapril
changes:
- type: Fix
message: Fixed jittering displacing your character when shaken.
id: 6591
time: '2024-12-22T19:57:10.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/1334
- author: VMSolidus
changes:
- type: Add
message: >-
Added server config options for basic "Soft-Crit". When enabled,
characters who are critically injured can still slowly crawl, but are
otherwise still helpless and dying.
id: 6592
time: '2024-12-26T03:50:10.0000000+00:00'
url: https://github.com/Simple-Station/Einstein-Engines/pull/1370
2 changes: 2 additions & 0 deletions Resources/Prototypes/Entities/Markers/Spawners/Random/toy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
- PlushieTrystan
- PlushieSlips
- PlushieJester
- PlushieHarpy
- PlushieMort
chance: 0.5
offset: 0.2

Expand Down
60 changes: 60 additions & 0 deletions Resources/Prototypes/Entities/Objects/Fun/toys.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1966,3 +1966,63 @@
- type: Sprite
sprite: Objects/Fun/toys.rsi
state: shadowkin

- type: entity
parent: BasePlushie
id: PlushieMort
name: morty plushie
description: A plushie of the lovely Morty. It's a resilient, yet sensitive type of plush.
components:
- type: Sprite
sprite: Objects/Fun/toys.rsi
state: mortplush

- type: entity
parent: BasePlushie
id: PlushieHarpy
name: harpy plushie
description: A soft plushie of a harpy! A small tag on it guarantees that all feathers are ethically sourced.
components:
- type: Sprite
sprite: Objects/Fun/toys.rsi
state: harpyplushie
- type: StaminaDamageOnHit
damage: 0.8
- type: EmitSoundOnActivate
sound:
path: /Audio/DeltaV/Voice/Harpy/caw1.ogg
params:
variation: 0.05
- type: EmitSoundOnUse
sound:
path: /Audio/DeltaV/Voice/Harpy/caw1.ogg
- type: EmitSoundOnCollide
sound:
path: /Audio/DeltaV/Voice/Harpy/caw1.ogg
params:
variation: 0.05
- type: EmitSoundOnLand
sound:
path: /Audio/DeltaV/Voice/Harpy/caw1.ogg
params:
variation: 0.05
- type: UseDelay
delay: 0.8
- type: MeleeWeapon
wideAnimationRotation: -135
attackRate: 0.5
damage:
types:
Blunt: 0
soundHit:
path: /Audio/DeltaV/Voice/Harpy/caw1.ogg
params:
variation: 0.05
soundSwing:
path: /Audio/DeltaV/Voice/Harpy/caw1.ogg
params:
variation: 0.05
soundNoDamage:
path: /Audio/DeltaV/Voice/Harpy/caw1.ogg
params:
variation: 0.05
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
- !type:CharacterTraitRequirement
traits:
- ShadowkinBlackeye
special:
- !type:AddComponentSpecial
components:
- type: Pacified

- type: startingGear
id: PrisonerGear
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions Resources/Textures/Objects/Fun/toys.rsi/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,12 @@
},
{
"name": "shadowkin"
},
{
"name": "mortplush"
},
{
"name": "harpyplushie"
}
]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 7f0452e

Please sign in to comment.