diff --git a/Content.Server/Abilities/Boxer/Boxer/BoxerComponent.cs b/Content.Server/Abilities/Boxer/Boxer/BoxerComponent.cs
new file mode 100644
index 0000000000..cd3f5de0a7
--- /dev/null
+++ b/Content.Server/Abilities/Boxer/Boxer/BoxerComponent.cs
@@ -0,0 +1,23 @@
+using Content.Shared.Damage;
+
+namespace Content.Server.Abilities.Boxer
+{
+ ///
+ /// Added to the boxer on spawn.
+ ///
+ [RegisterComponent]
+ public sealed class BoxerComponent : Component
+ {
+ [DataField("modifiers", required: true)]
+ public DamageModifierSet UnarmedModifiers = default!;
+
+ [DataField("rangeBonus")]
+ public float RangeBonus = 1.5f;
+
+ ///
+ /// Damage modifier with boxing glove stam damage.
+ ///
+ [DataField("boxingGlovesModifier")]
+ public float BoxingGlovesModifier = 1.75f;
+ }
+}
diff --git a/Content.Server/Abilities/Boxer/Boxer/BoxingGlovesComponent.cs b/Content.Server/Abilities/Boxer/Boxer/BoxingGlovesComponent.cs
new file mode 100644
index 0000000000..92a9626013
--- /dev/null
+++ b/Content.Server/Abilities/Boxer/Boxer/BoxingGlovesComponent.cs
@@ -0,0 +1,11 @@
+using Content.Shared.Damage;
+
+namespace Content.Server.Abilities.Boxer
+{
+ ///
+ /// Boxer gets a bonus for these, and their fists, but not other unarmed weapons.
+ ///
+ [RegisterComponent]
+ public sealed class BoxingGlovesComponent : Component
+ {}
+}
diff --git a/Content.Server/Abilities/Boxer/BoxingSystem.cs b/Content.Server/Abilities/Boxer/BoxingSystem.cs
new file mode 100644
index 0000000000..a3a58a0619
--- /dev/null
+++ b/Content.Server/Abilities/Boxer/BoxingSystem.cs
@@ -0,0 +1,51 @@
+using Content.Server.Weapon.Melee;
+using Content.Server.Stunnable;
+using Content.Shared.Inventory.Events;
+using Content.Server.Weapon.Melee.Components;
+using Content.Server.Clothing.Components;
+using Content.Server.Damage.Components;
+using Content.Server.Damage.Events;
+using Robust.Shared.Audio;
+using Robust.Shared.Player;
+using Robust.Shared.Random;
+using Robust.Shared.Containers;
+
+namespace Content.Server.Abilities.Boxer
+{
+ public sealed class BoxingSystem : EntitySystem
+ {
+ [Dependency] private readonly StunSystem _stunSystem = default!;
+ [Dependency] private readonly IRobustRandom _robustRandom = default!;
+ [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent(OnInit);
+ SubscribeLocalEvent(ApplyBoxerModifiers);
+ SubscribeLocalEvent(OnStamHit);
+ }
+
+ private void OnInit(EntityUid uid, BoxerComponent boxer, ComponentInit args)
+ {
+ if (TryComp(uid, out var meleeComp))
+ meleeComp.Range *= boxer.RangeBonus;
+ }
+ private void ApplyBoxerModifiers(EntityUid uid, BoxerComponent component, MeleeHitEvent args)
+ {
+ if (component.UnarmedModifiers == default!)
+ {
+ Logger.Warning("BoxerComponent on " + uid + " couldn't get damage modifiers. Know that adding components with damage modifiers through VV or similar is unsupported.");
+ return;
+ }
+
+ args.ModifiersList.Add(component.UnarmedModifiers);
+ }
+ private void OnStamHit(EntityUid uid, BoxingGlovesComponent component, StaminaMeleeHitEvent args)
+ {
+ _containerSystem.TryGetContainingContainer(uid, out var equipee);
+ if (TryComp(equipee?.Owner, out var boxer))
+ args.Multiplier *= boxer.BoxingGlovesModifier;
+ }
+ }
+}
diff --git a/Content.Server/Damage/Components/StaminaDamageOnHitComponent.cs b/Content.Server/Damage/Components/StaminaDamageOnHitComponent.cs
index fafe2a366f..23b52197a4 100644
--- a/Content.Server/Damage/Components/StaminaDamageOnHitComponent.cs
+++ b/Content.Server/Damage/Components/StaminaDamageOnHitComponent.cs
@@ -1,3 +1,5 @@
+using Content.Shared.Sound;
+
namespace Content.Server.Damage.Components;
[RegisterComponent]
@@ -5,4 +7,10 @@ public sealed class StaminaDamageOnHitComponent : Component
{
[ViewVariables(VVAccess.ReadWrite), DataField("damage")]
public float Damage = 30f;
+
+ ///
+ /// Play a sound when this knocks down an entity.
+ ///
+ [DataField("knockdownSound")]
+ public SoundSpecifier? KnockdownSound;
}
diff --git a/Content.Server/Damage/Events/StaminaMeleeHitEvent.cs b/Content.Server/Damage/Events/StaminaMeleeHitEvent.cs
new file mode 100644
index 0000000000..e6a53d4466
--- /dev/null
+++ b/Content.Server/Damage/Events/StaminaMeleeHitEvent.cs
@@ -0,0 +1,30 @@
+using Robust.Shared.Collections;
+using Content.Server.Damage.Components;
+
+namespace Content.Server.Damage.Events;
+
+///
+/// The components in the list are going to be hit,
+/// give opportunities to change the damage or other stuff.
+///
+public sealed class StaminaMeleeHitEvent : HandledEntityEventArgs
+{
+ ///
+ /// List of hit stamina components.
+ public ValueList HitList;
+
+ ///
+ /// The multiplier. Generally, try to use *= or /= instead of overwriting.
+ ///
+ public float Multiplier = 1;
+
+ ///
+ /// The flat modifier. Generally, try to use += or -= instead of overwriting.
+ ///
+ public float FlatModifier = 0;
+
+ public StaminaMeleeHitEvent(ValueList hitList)
+ {
+ HitList = hitList;
+ }
+}
diff --git a/Content.Server/Damage/Systems/StaminaSystem.cs b/Content.Server/Damage/Systems/StaminaSystem.cs
index 5139945675..9098b4c526 100644
--- a/Content.Server/Damage/Systems/StaminaSystem.cs
+++ b/Content.Server/Damage/Systems/StaminaSystem.cs
@@ -5,10 +5,13 @@ using Content.Server.Weapon.Melee;
using Content.Shared.Alert;
using Content.Shared.Rounding;
using Content.Shared.Stunnable;
+using Content.Shared.Sound;
using Robust.Shared.Collections;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Player;
using Robust.Shared.Timing;
+using Robust.Shared.Audio;
+
namespace Content.Server.Damage.Systems;
@@ -70,10 +73,22 @@ public sealed class StaminaSystem : EntitySystem
toHit.Add(stam);
}
+ var hitEvent = new StaminaMeleeHitEvent(toHit);
+ RaiseLocalEvent(uid, hitEvent, false);
+
+ if (hitEvent.Handled)
+ return;
+
+ var damage = component.Damage;
+
+ damage *= hitEvent.Multiplier;
+
+ damage += hitEvent.FlatModifier;
+
foreach (var comp in toHit)
{
var oldDamage = comp.StaminaDamage;
- TakeStaminaDamage(comp.Owner, component.Damage / toHit.Count, comp);
+ TakeStaminaDamage(comp.Owner, damage / toHit.Count, comp, component.KnockdownSound);
if (comp.StaminaDamage.Equals(oldDamage))
{
_popup.PopupEntity(Loc.GetString("stamina-resist"), comp.Owner, Filter.Entities(args.User));
@@ -100,7 +115,7 @@ public sealed class StaminaSystem : EntitySystem
_alerts.ShowAlert(uid, AlertType.Stamina, (short) severity);
}
- public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null)
+ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null, SoundSpecifier? knockdownSound = null)
{
if (!Resolve(uid, ref component, false) || component.Critical) return;
@@ -131,6 +146,8 @@ public sealed class StaminaSystem : EntitySystem
{
if (component.StaminaDamage >= component.CritThreshold)
{
+ if (knockdownSound != null)
+ SoundSystem.Play(knockdownSound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid, knockdownSound.Params);
EnterStamCrit(uid, component);
}
}
diff --git a/Content.Server/Interaction/InteractionSystem.cs b/Content.Server/Interaction/InteractionSystem.cs
index 8a7fffaa61..ef839529d2 100644
--- a/Content.Server/Interaction/InteractionSystem.cs
+++ b/Content.Server/Interaction/InteractionSystem.cs
@@ -1,14 +1,15 @@
using Content.Server.Administration.Logs;
-using Content.Server.CombatMode;
using Content.Server.Hands.Components;
using Content.Server.Pulling;
using Content.Server.Storage.Components;
+using Content.Server.Weapon.Melee.Components;
using Content.Shared.ActionBlocker;
using Content.Shared.Database;
using Content.Shared.DragDrop;
using Content.Shared.Input;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
+using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Pulling.Components;
using Content.Shared.Weapons.Melee;
@@ -32,6 +33,8 @@ namespace Content.Server.Interaction
[Dependency] private readonly PullingSystem _pullSystem = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
+ [Dependency] private readonly InventorySystem _inventory = default!;
+
public override void Initialize()
{
@@ -259,17 +262,23 @@ namespace Content.Server.Interaction
// TODO: Make this saner?
// Attempt to do unarmed combat. We don't check for handled just because at this point it doesn't matter.
+
+ var used = user;
+
+ if (_inventory.TryGetSlotEntity(user, "gloves", out var gloves) && HasComp(gloves))
+ used = (EntityUid) gloves;
+
if (wideAttack)
{
- var ev = new WideAttackEvent(user, user, coordinates);
- RaiseLocalEvent(user, ev, false);
+ var ev = new WideAttackEvent(used, user, coordinates);
+ RaiseLocalEvent(used, ev, false);
if (ev.Handled)
_adminLogger.Add(LogType.AttackUnarmedWide, LogImpact.Low, $"{ToPrettyString(user):user} wide attacked at {coordinates}");
}
else
{
- var ev = new ClickAttackEvent(user, user, coordinates, target);
- RaiseLocalEvent(user, ev, false);
+ var ev = new ClickAttackEvent(used, user, coordinates, target);
+ RaiseLocalEvent(used, ev, false);
if (ev.Handled)
{
if (target != null)
diff --git a/Resources/Audio/Weapons/boxingbell.ogg b/Resources/Audio/Weapons/boxingbell.ogg
new file mode 100644
index 0000000000..a36382fc12
Binary files /dev/null and b/Resources/Audio/Weapons/boxingbell.ogg differ
diff --git a/Resources/Audio/Weapons/boxingpunch1.ogg b/Resources/Audio/Weapons/boxingpunch1.ogg
new file mode 100644
index 0000000000..a8f50bbb97
Binary files /dev/null and b/Resources/Audio/Weapons/boxingpunch1.ogg differ
diff --git a/Resources/Audio/Weapons/boxingpunch2.ogg b/Resources/Audio/Weapons/boxingpunch2.ogg
new file mode 100644
index 0000000000..31d5de6db8
Binary files /dev/null and b/Resources/Audio/Weapons/boxingpunch2.ogg differ
diff --git a/Resources/Audio/Weapons/boxingpunch3.ogg b/Resources/Audio/Weapons/boxingpunch3.ogg
new file mode 100644
index 0000000000..a72c43bd75
Binary files /dev/null and b/Resources/Audio/Weapons/boxingpunch3.ogg differ
diff --git a/Resources/Audio/Weapons/licenses.txt b/Resources/Audio/Weapons/licenses.txt
index 1dd99f9e2b..f5b81bbdc3 100644
--- a/Resources/Audio/Weapons/licenses.txt
+++ b/Resources/Audio/Weapons/licenses.txt
@@ -6,4 +6,8 @@ slash.ogg taken from https://github.com/tgstation/tgstation/blob/5d264fbea0124e5
tap.ogg taken from https://github.com/tgstation/tgstation/blob/803ca4537df35cf252b056d8460d510be8a4f353/sound/weapons/tap.ogg under CC BY-SA 3.0
-block_metal1.ogg taken from https://github.com/Citadel-Station-13/Citadel-Station-13/commit/31c5996a5db8cce0cb431cb1dc20d99cac83f268 under CC BY-SA 3.0
\ No newline at end of file
+BoxingPunch 1, 2, and 3 taken from Ryan Conway at https://freesound.org/people/ryanconway/sounds/260739/ under CC BY 3.0
+
+boxingbell.ogg taken from Herkules92 at https://freesound.org/people/Herkules92/sounds/520998/ under CC0 1.0
+
+block_metal1.ogg taken from https://github.com/Citadel-Station-13/Citadel-Station-13/commit/31c5996a5db8cce0cb431cb1dc20d99cac83f268 under CC BY-SA 3.0
diff --git a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml
index 50cbee6b3a..6c5d05ea6d 100644
--- a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml
+++ b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml
@@ -8,13 +8,23 @@
sprite: Clothing/Hands/Gloves/boxing.rsi
- type: Clothing
sprite: Clothing/Hands/Gloves/boxing.rsi
+ - type: BoxingGloves
+ - type: StaminaDamageOnHit
+ damage: 8 #Stam damage values seem a bit higher than regular damage because of the decay, etc
+ knockdownSound: /Audio/Weapons/boxingbell.ogg
+ - type: MeleeWeapon
+ damage:
+ types:
+ Blunt: 0.6
+ hitSound:
+ collection: BoxingHit
- type: Fiber
fiberMaterial: fibers-leather
fiberColor: fibers-red
- type: FingerprintMask
- type: entity
- parent: ClothingHandsBase
+ parent: ClothingHandsGlovesBoxingRed
id: ClothingHandsGlovesBoxingBlue
name: blue boxing gloves
description: Blue gloves for competitive boxing.
@@ -31,7 +41,7 @@
- type: FingerprintMask
- type: entity
- parent: ClothingHandsBase
+ parent: ClothingHandsGlovesBoxingRed
id: ClothingHandsGlovesBoxingGreen
name: green boxing gloves
description: Green gloves for competitive boxing.
@@ -48,7 +58,7 @@
- type: FingerprintMask
- type: entity
- parent: ClothingHandsBase
+ parent: ClothingHandsGlovesBoxingRed
id: ClothingHandsGlovesBoxingYellow
name: yellow boxing gloves
description: Yellow gloves for competitive boxing.
diff --git a/Resources/Prototypes/Entities/Clothing/Uniforms/misc_roles.yml b/Resources/Prototypes/Entities/Clothing/Uniforms/misc_roles.yml
new file mode 100644
index 0000000000..55ffe34b53
--- /dev/null
+++ b/Resources/Prototypes/Entities/Clothing/Uniforms/misc_roles.yml
@@ -0,0 +1,21 @@
+- type: entity
+ parent: ClothingUniformBase
+ id: UniformShortsRed
+ name: boxing shorts
+ description: These are shorts, not boxers.
+ components:
+ - type: Sprite
+ sprite: Clothing/Uniforms/Shorts/Color/red.rsi
+ - type: Clothing
+ sprite: Clothing/Uniforms/Shorts/Color/red.rsi
+
+- type: entity
+ parent: ClothingUniformBase
+ id: UniformShortsRedWithTop
+ name: boxing shorts with top
+ description: These are shorts, not boxers.
+ components:
+ - type: Sprite
+ sprite: Clothing/Uniforms/Shorts/Color/red_female.rsi
+ - type: Clothing
+ sprite: Clothing/Uniforms/Shorts/Color/red_female.rsi
diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml
index 84a3230a2c..2dbbc402ae 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml
@@ -178,7 +178,7 @@
- type: PDA
id: ClownIDCard
penSlot:
- startingItem: CrayonOrange # no pink crayon?!?
+ startingItem: CrayonOrange # no pink crayon?!?
# ^ Still unacceptable.
ejectSound: /Audio/Items/bikehorn.ogg
priority: -1
@@ -662,6 +662,21 @@
- type: Icon
state: pda-reporter
+- type: entity
+ parent: BasePDA
+ id: BoxerPDA
+ name: boxer PDA
+ description: Float like a butterfly, ringtone like a bee.
+ components:
+ - type: PDA
+ id: BoxerIDCard
+ - type: Appearance
+ visuals:
+ - type: PDAVisualizer
+ state: pda-boxer
+ - type: Icon
+ state: pda-boxer
+
- type: entity
parent: BasePDA
id: DetectivePDA
diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
index 4da2cedc2e..05de3ba21e 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
@@ -511,6 +511,18 @@
- type: PresetIdCard
job: Reporter
+- type: entity
+ parent: IDCardStandard
+ id: BoxerIDCard
+ name: boxer ID card
+ components:
+ - type: Sprite
+ layers:
+ - state: default
+ - state: idboxer
+ - type: PresetIdCard
+ job: Boxer
+
- type: entity
parent: IDCardStandard
id: DetectiveIDCard
diff --git a/Resources/Prototypes/Maps/lighthouse.yml b/Resources/Prototypes/Maps/lighthouse.yml
index aa22106cb8..5a7da3f981 100644
--- a/Resources/Prototypes/Maps/lighthouse.yml
+++ b/Resources/Prototypes/Maps/lighthouse.yml
@@ -17,6 +17,7 @@
Passenger: [ -1, -1 ]
Bartender: [ 1, 2 ]
Botanist: [ 2, 2 ]
+ Boxer: [ 2, 2 ] #Wildcard for this map
Chef: [ 2, 3 ]
Clown: [ 1, 1 ]
Janitor: [ 1, 2 ]
diff --git a/Resources/Prototypes/Roles/Jobs/Wildcards/boxer.yml b/Resources/Prototypes/Roles/Jobs/Wildcards/boxer.yml
new file mode 100644
index 0000000000..a13e928d5d
--- /dev/null
+++ b/Resources/Prototypes/Roles/Jobs/Wildcards/boxer.yml
@@ -0,0 +1,32 @@
+- type: job
+ id: Boxer
+ name: "boxer"
+ startingGear: BoxerGear
+ setPreference: false
+ departments:
+ - Civilian
+ icon: "Boxer"
+ supervisors: "the head of personnel"
+ access:
+ - Service
+ special:
+ - !type:AddComponentSpecial
+ components:
+ - type: Boxer
+ modifiers:
+ coefficients: #Remember these only apply to unarmed
+ Blunt: 1.5
+ Slash: 1.5
+ Piercing: 1.5
+
+- type: startingGear
+ id: BoxerGear
+ equipment:
+ jumpsuit: UniformShortsRed
+ back: ClothingBackpackFilled
+ id: BoxerPDA
+ ears: ClothingHeadsetService
+ gloves: ClothingHandsGlovesBoxingRed
+ innerclothingskirt: UniformShortsRedWithTop
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Medical/psychologist.yml b/Resources/Prototypes/Roles/Jobs/Wildcards/psychologist.yml
similarity index 96%
rename from Resources/Prototypes/Roles/Jobs/Medical/psychologist.yml
rename to Resources/Prototypes/Roles/Jobs/Wildcards/psychologist.yml
index 2e7b8da3bc..80344d8b2e 100644
--- a/Resources/Prototypes/Roles/Jobs/Medical/psychologist.yml
+++ b/Resources/Prototypes/Roles/Jobs/Wildcards/psychologist.yml
@@ -1,25 +1,25 @@
-- type: job
- id: Psychologist
- name: job-name-psychologist
- startingGear: PsychologistGear
- departments:
- - Medical
- icon: "Psychologist"
- supervisors: job-supervisors-cmo
- access:
- - Medical
- - Maintenance
- extendedAccess:
- - Chemistry
-
-- type: startingGear
- id: PsychologistGear
- equipment:
- jumpsuit: ClothingUniformJumpsuitPsychologist
- back: ClothingBackpackMedicalFilled
- shoes: ClothingShoesLeather
- id: PsychologistPDA
- ears: ClothingHeadsetMedical
- innerclothingskirt: ClothingUniformJumpsuitPsychologist
- satchel: ClothingBackpackSatchelMedicalFilled
- duffelbag: ClothingBackpackDuffelMedicalFilled
+- type: job
+ id: Psychologist
+ name: job-name-psychologist
+ startingGear: PsychologistGear
+ departments:
+ - Medical
+ icon: "Psychologist"
+ supervisors: job-supervisors-cmo
+ access:
+ - Medical
+ - Maintenance
+ extendedAccess:
+ - Chemistry
+
+- type: startingGear
+ id: PsychologistGear
+ equipment:
+ jumpsuit: ClothingUniformJumpsuitPsychologist
+ back: ClothingBackpackMedicalFilled
+ shoes: ClothingShoesLeather
+ id: PsychologistPDA
+ ears: ClothingHeadsetMedical
+ innerclothingskirt: ClothingUniformJumpsuitPsychologist
+ satchel: ClothingBackpackSatchelMedicalFilled
+ duffelbag: ClothingBackpackDuffelMedicalFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/reporter.yml b/Resources/Prototypes/Roles/Jobs/Wildcards/reporter.yml
similarity index 96%
rename from Resources/Prototypes/Roles/Jobs/Civilian/reporter.yml
rename to Resources/Prototypes/Roles/Jobs/Wildcards/reporter.yml
index d7fe4df96a..5333b04e2f 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/reporter.yml
+++ b/Resources/Prototypes/Roles/Jobs/Wildcards/reporter.yml
@@ -1,23 +1,23 @@
-- type: job
- id: Reporter
- name: job-name-reporter
- startingGear: ReporterGear
- departments:
- - Civilian
- icon: "Reporter"
- supervisors: job-supervisors-hop
- access:
- - Service
- - Maintenance
-
-- type: startingGear
- id: ReporterGear
- equipment:
- jumpsuit: ClothingUniformJumpsuitReporter
- back: ClothingBackpackFilled
- shoes: ClothingShoesColorWhite
- id: ReporterPDA
- ears: ClothingHeadsetService
- innerclothingskirt: ClothingUniformJumpsuitJournalist
- satchel: ClothingBackpackSatchelFilled
- duffelbag: ClothingBackpackDuffelFilled
+- type: job
+ id: Reporter
+ name: job-name-reporter
+ startingGear: ReporterGear
+ departments:
+ - Civilian
+ icon: "Reporter"
+ supervisors: job-supervisors-hop
+ access:
+ - Service
+ - Maintenance
+
+- type: startingGear
+ id: ReporterGear
+ equipment:
+ jumpsuit: ClothingUniformJumpsuitReporter
+ back: ClothingBackpackFilled
+ shoes: ClothingShoesColorWhite
+ id: ReporterPDA
+ ears: ClothingHeadsetService
+ innerclothingskirt: ClothingUniformJumpsuitJournalist
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/SoundCollections/generic_hit.yml b/Resources/Prototypes/SoundCollections/generic_hit.yml
index d03313be57..587a2a1d69 100644
--- a/Resources/Prototypes/SoundCollections/generic_hit.yml
+++ b/Resources/Prototypes/SoundCollections/generic_hit.yml
@@ -4,3 +4,10 @@
- /Audio/Weapons/genhit1.ogg
- /Audio/Weapons/genhit2.ogg
- /Audio/Weapons/genhit3.ogg
+
+- type: soundCollection
+ id: BoxingHit
+ files:
+ - /Audio/Weapons/boxingpunch1.ogg
+ - /Audio/Weapons/boxingpunch2.ogg
+ - /Audio/Weapons/boxingpunch3.ogg
diff --git a/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/equipped-INNERCLOTHING.png b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/equipped-INNERCLOTHING.png
new file mode 100644
index 0000000000..daed07cc39
Binary files /dev/null and b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/equipped-INNERCLOTHING.png differ
diff --git a/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/icon.png b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/icon.png
new file mode 100644
index 0000000000..47f5b4d940
Binary files /dev/null and b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/icon.png differ
diff --git a/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/meta.json b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/meta.json
new file mode 100644
index 0000000000..df00f2381b
--- /dev/null
+++ b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red.rsi/meta.json
@@ -0,0 +1,18 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "https://github.com/tgstation/tgstation/commit/beaea876ea426c0e215cee64619862dc19bd9cd8",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "equipped-INNERCLOTHING",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/equipped-INNERCLOTHING.png b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/equipped-INNERCLOTHING.png
new file mode 100644
index 0000000000..c6ab934201
Binary files /dev/null and b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/equipped-INNERCLOTHING.png differ
diff --git a/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/icon.png b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/icon.png
new file mode 100644
index 0000000000..0acddade4f
Binary files /dev/null and b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/icon.png differ
diff --git a/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/meta.json b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/meta.json
new file mode 100644
index 0000000000..df00f2381b
--- /dev/null
+++ b/Resources/Textures/Clothing/Uniforms/Shorts/Color/red_female.rsi/meta.json
@@ -0,0 +1,18 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "https://github.com/tgstation/tgstation/commit/beaea876ea426c0e215cee64619862dc19bd9cd8",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "equipped-INNERCLOTHING",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Interface/Misc/job_icons.rsi/Boxer.png b/Resources/Textures/Interface/Misc/job_icons.rsi/Boxer.png
new file mode 100644
index 0000000000..f260c921e4
Binary files /dev/null and b/Resources/Textures/Interface/Misc/job_icons.rsi/Boxer.png differ
diff --git a/Resources/Textures/Interface/Misc/job_icons.rsi/meta.json b/Resources/Textures/Interface/Misc/job_icons.rsi/meta.json
index 6cd0776d09..311a4231ba 100644
--- a/Resources/Textures/Interface/Misc/job_icons.rsi/meta.json
+++ b/Resources/Textures/Interface/Misc/job_icons.rsi/meta.json
@@ -16,6 +16,9 @@
{
"name": "Botanist"
},
+ {
+ "name": "Boxer"
+ },
{
"name": "AtmosphericTechnician"
},
diff --git a/Resources/Textures/Markers/jobs.rsi/boxer.png b/Resources/Textures/Markers/jobs.rsi/boxer.png
new file mode 100644
index 0000000000..60d10e2302
Binary files /dev/null and b/Resources/Textures/Markers/jobs.rsi/boxer.png differ
diff --git a/Resources/Textures/Markers/jobs.rsi/meta.json b/Resources/Textures/Markers/jobs.rsi/meta.json
index 50d5328c7d..f9da45e3d3 100644
--- a/Resources/Textures/Markers/jobs.rsi/meta.json
+++ b/Resources/Textures/Markers/jobs.rsi/meta.json
@@ -25,6 +25,9 @@
{
"name": "botanist"
},
+ {
+ "name": "boxer"
+ },
{
"name": "captain"
},
diff --git a/Resources/Textures/Objects/Devices/pda.rsi/meta.json b/Resources/Textures/Objects/Devices/pda.rsi/meta.json
index dc89c59d69..6837ed5f77 100644
--- a/Resources/Textures/Objects/Devices/pda.rsi/meta.json
+++ b/Resources/Textures/Objects/Devices/pda.rsi/meta.json
@@ -29,6 +29,9 @@
{
"name": "pda-bartender"
},
+ {
+ "name": "pda-boxer"
+ },
{
"name": "pda-captain"
},
diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-boxer.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-boxer.png
new file mode 100644
index 0000000000..d119636208
Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-boxer.png differ
diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idboxer.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idboxer.png
new file mode 100644
index 0000000000..0c2b5298e5
Binary files /dev/null and b/Resources/Textures/Objects/Misc/id_cards.rsi/idboxer.png differ
diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/meta.json b/Resources/Textures/Objects/Misc/id_cards.rsi/meta.json
index 185ea7fa83..b5bb20f02d 100644
--- a/Resources/Textures/Objects/Misc/id_cards.rsi/meta.json
+++ b/Resources/Textures/Objects/Misc/id_cards.rsi/meta.json
@@ -46,6 +46,9 @@
{
"name": "idbotanist"
},
+ {
+ "name": "idboxer"
+ },
{
"name": "idcaptain"
},