diff --git a/_maps/RandomRuins/BeachRuins/beach_float_resort.dmm b/_maps/RandomRuins/BeachRuins/beach_float_resort.dmm
index bbac1ae4e8d9..29ad64707d84 100644
--- a/_maps/RandomRuins/BeachRuins/beach_float_resort.dmm
+++ b/_maps/RandomRuins/BeachRuins/beach_float_resort.dmm
@@ -237,14 +237,6 @@
light_range = 2
},
/area/ruin/beach/float_resort/villa)
-"gr" = (
-/obj/structure/table/wood,
-/obj/structure/curtain/cloth,
-/obj/item/nullrod/tribal_knife,
-/turf/open/floor/wood{
- light_range = 2
- },
-/area/ruin/beach/float_resort/villa)
"gQ" = (
/obj/structure/flora/ausbushes/genericbush,
/turf/open/floor/plating/grass/beach,
@@ -2502,7 +2494,7 @@ kp
kp
kp
kp
-gr
+ar
OH
OH
OH
diff --git a/_maps/RandomRuins/WasteRuins/wasteplanet_pandora.dmm b/_maps/RandomRuins/WasteRuins/wasteplanet_pandora.dmm
index 8a63378ced3c..b6298e29f39d 100644
--- a/_maps/RandomRuins/WasteRuins/wasteplanet_pandora.dmm
+++ b/_maps/RandomRuins/WasteRuins/wasteplanet_pandora.dmm
@@ -35,7 +35,6 @@
/area/ruin/wasteplanet)
"bL" = (
/obj/structure/fluff/divine/convertaltar,
-/obj/item/nullrod/tribal_knife,
/obj/item/clothing/accessory/pandora_hope,
/turf/open/indestructible/hierophant/two/waste,
/area/ruin/wasteplanet)
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index d9edeb83202c..0ae530f47913 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -773,3 +773,6 @@
///called in /obj/item/gun/process_chamber (src)
#define COMSIG_GUN_CHAMBER_PROCESSED "gun_chamber_processed"
+
+///called when an elzu should unroot
+#define COMSIG_DIGOUT "dig_out"
diff --git a/code/datums/components/storage/concrete/pockets.dm b/code/datums/components/storage/concrete/pockets.dm
index bd0a59f85f42..ce224d44e4e5 100644
--- a/code/datums/components/storage/concrete/pockets.dm
+++ b/code/datums/components/storage/concrete/pockets.dm
@@ -83,10 +83,16 @@
/datum/component/storage/concrete/pockets/helmet/Initialize()
. = ..()
set_holdable(list(
- /obj/item/reagent_containers/food/drinks/bottle/vodka,
- /obj/item/reagent_containers/food/drinks/bottle/molotov,
- /obj/item/reagent_containers/food/drinks/drinkingglass,
- /obj/item/ammo_box/magazine/illestren_a850r
+ /obj/item/clothing/glasses/cold,
+ /obj/item/clothing/glasses/heat,
+ /obj/item/clothing/glasses/welding,
+ /obj/item/clothing/glasses/thermal,
+ /obj/item/clothing/glasses/night,
+ /obj/item/clothing/glasses/hud/health/night,
+ /obj/item/clothing/glasses/hud/security/night,
+ /obj/item/clothing/glasses/hud/security/sunglasses/inteq,
+ /obj/item/ammo_casing,
+ /obj/item/ammo_box/magazine/illestren_a850r,
))
/datum/component/storage/concrete/pockets/holster
diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm
index dbaac99c4296..d79847ea04c8 100644
--- a/code/datums/mood_events/generic_positive_events.dm
+++ b/code/datums/mood_events/generic_positive_events.dm
@@ -239,3 +239,8 @@
description = "Fishing is relaxing"
mood_change = 5
timeout = 3 MINUTES
+
+/datum/mood_event/root
+ description = span_nicegreen("I rooted recently, it feels good to charge naturally.\n")
+ mood_change = 5
+ timeout = 5 MINUTES
diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm
index 76a33319631f..c7765ff772ac 100644
--- a/code/datums/status_effects/neutral.dm
+++ b/code/datums/status_effects/neutral.dm
@@ -275,3 +275,29 @@
/atom/movable/screen/alert/status_effect/surrender/Click(location, control, params)
. = ..()
owner.emote("surrender")
+
+/datum/status_effect/rooted
+ id = "rooted"
+ alert_type = /atom/movable/screen/alert/status_effect/rooted
+
+/datum/status_effect/rooted/on_apply()
+ . = ..()
+ ADD_TRAIT(owner,TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
+ ADD_TRAIT(owner,TRAIT_PUSHIMMUNE, TRAIT_STATUS_EFFECT(id))
+ SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "root", /datum/mood_event/root)
+
+/datum/status_effect/rooted/on_remove()
+ . = ..()
+ REMOVE_TRAIT(owner,TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(id))
+ REMOVE_TRAIT(owner,TRAIT_PUSHIMMUNE, TRAIT_STATUS_EFFECT(id))
+
+/atom/movable/screen/alert/status_effect/rooted
+ name = "Rooted"
+ desc = "You're currently rooted into the ground and can't move. Click here to start digging yourself out."
+ icon_state = "dig_out"
+
+/atom/movable/screen/alert/status_effect/rooted/Click(location, control, params)
+ . = ..()
+ to_chat(owner, span_notice("You begin digging yourself free."))
+ SEND_SIGNAL(owner,COMSIG_DIGOUT)
+
diff --git a/code/game/objects/effects/anomalies/anomalies_static.dm b/code/game/objects/effects/anomalies/anomalies_static.dm
index a00babe5844a..ab574ee475dd 100644
--- a/code/game/objects/effects/anomalies/anomalies_static.dm
+++ b/code/game/objects/effects/anomalies/anomalies_static.dm
@@ -39,19 +39,19 @@
playsound(src, 'sound/effects/walkietalkie.ogg', 75)
if(stored_mob && looking.stat != DEAD && prob(25))
say_fucky_things()
- if (!HAS_TRAIT(looking, TRAIT_MINDSHIELD) && looking.stat != DEAD || !looking.research_scanner && looking.stat != DEAD || !HAS_TRAIT(looking, TRAIT_DEAF))
- looking.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 200)
- playsound(src, 'sound/effects/stall.ogg', 50)
- if(looking.getOrganLoss(ORGAN_SLOT_BRAIN) >= 150 && looking.stat != DEAD)
- if(prob(20))
- var/mob/living/carbon/victim = looking
- var/obj/effect/anomaly/tvstatic/planetary/expansion
- expansion = new(get_turf(victim))
- visible_message(span_warning("The static overtakes [victim], taking their place!"))
- victim.death()
- expansion.stored_mob = victim
- victim.forceMove(expansion)
- return
+ if(HAS_TRAIT(looking, TRAIT_MINDSHIELD) || looking.stat == DEAD || looking.research_scanner || HAS_TRAIT(looking, TRAIT_DEAF))
+ continue
+ looking.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 200)
+ playsound(src, 'sound/effects/stall.ogg', 50)
+ if(looking.getOrganLoss(ORGAN_SLOT_BRAIN) >= 150 && looking.stat != DEAD)
+ if(prob(20))
+ var/mob/living/carbon/victim = looking
+ var/obj/effect/anomaly/tvstatic/planetary/expansion
+ expansion = new(get_turf(victim))
+ visible_message(span_warning("The static overtakes [victim], [expansion] taking their place!"))
+ victim.death()
+ expansion.stored_mob = victim
+ victim.forceMove(expansion)
/obj/effect/anomaly/tvstatic/Bumped(atom/movable/AM)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 437aa7625d71..0cfa30f86a7c 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -699,6 +699,9 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
/obj/item/proc/get_belt_overlay() //Returns the icon used for overlaying the object on a belt
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state)
+/obj/item/proc/get_helmet_overlay() // returns the icon for overlaying on a helmet
+ return mutable_appearance('icons/mob/clothing/helmet_overlays.dmi', icon_state)
+
/obj/item/proc/update_slot_icon()
if(!ismob(loc))
return
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index cd01cef70503..872d81323cf3 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -671,33 +671,6 @@
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
-/obj/item/nullrod/tribal_knife
- icon_state = "crysknife"
- item_state = "crysknife"
- lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
- name = "arrhythmic knife"
- w_class = WEIGHT_CLASS_HUGE
- desc = "They say fear is the true mind killer, but stabbing them in the head works too. Honour compels you to not sheathe it once drawn."
- sharpness = IS_SHARP
- slot_flags = null
- hitsound = 'sound/weapons/bladeslice.ogg'
- attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
- item_flags = SLOWS_WHILE_IN_HAND
-
-/obj/item/nullrod/tribal_knife/Initialize(mapload)
- . = ..()
- START_PROCESSING(SSobj, src)
- AddComponent(/datum/component/butchering, 50, 100)
-
-/obj/item/nullrod/tribal_knife/Destroy()
- STOP_PROCESSING(SSobj, src)
- . = ..()
-
-/obj/item/nullrod/tribal_knife/process()
- slowdown = rand(-2, 2)
-
-
/obj/item/nullrod/pitchfork
icon_state = "pitchfork0"
lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi'
diff --git a/code/modules/cargo/packs/ammo.dm b/code/modules/cargo/packs/ammo.dm
index 53bfd35974e7..f1e46fe88cc8 100644
--- a/code/modules/cargo/packs/ammo.dm
+++ b/code/modules/cargo/packs/ammo.dm
@@ -143,6 +143,12 @@
contains = list(/obj/item/ammo_box/amagpellet_claris)
cost = 1000
+/datum/supply_pack/ammo/a300
+ name = ".300 Magnum Stripper Clip Crate"
+ desc = "Contains a five round .300 Magnum stripper clip for sniper rifles such as the HP Scout."
+ contains = list(/obj/item/ammo_box/a300)
+ cost = 750
+
/datum/supply_pack/ammo/ebr_ammo
name = "M514 EBR .308 Magazine Crate"
desc = "Contains a .308 magazine for the M514 EBR rifle, containing ten rounds."
@@ -173,6 +179,12 @@
contains = list(/obj/item/ammo_box/a762_40)
cost = 500
+/datum/supply_pack/ammo/a357_ammo_box
+ name = ".357 Ammo Box Crate"
+ desc = "Contains a fifty-round .357 box for revolvers such as the Scarborough Revolver and the HP Firebrand."
+ contains = list(/obj/item/ammo_box/a357_box)
+ cost = 250
+
/datum/supply_pack/ammo/c556mmHITP_ammo_box
name = "5.56 Caseless Ammo Box Crate"
desc = "Contains a fifty-round 5.56mm caseless box for SolGov sidearms like the Pistole C."
@@ -209,6 +221,12 @@
contains = list(/obj/item/ammo_box/c9mm/ap)
cost = 500
+/datum/supply_pack/ammo/a357match_ammo_box
+ name = ".357 Match Ammo Box Crate"
+ desc = "Contains a fifty-round .357 match box for better performance against armor."
+ contains = list(/obj/item/ammo_box/a357_box/match)
+ cost = 500
+
/datum/supply_pack/ammo/c556mmHITPap_ammo_box
name = "5.56 caseless AP Ammo Box Crate"
desc = "Contains a fifty-round 5.56mm caseless boxloaded with armor piercing ammo."
@@ -233,6 +251,12 @@
contains = list(/obj/item/ammo_box/c9mm/hp)
cost = 500
+/datum/supply_pack/ammo/a357hp_ammo_box
+ name = ".357 HP Ammo Box Crate"
+ desc = "Contains a fifty-round .357 box loaded with hollow point ammo, great against unarmored targets."
+ contains = list(/obj/item/ammo_box/a357_box/hp)
+ cost = 500
+
/datum/supply_pack/ammo/c10mmhp_ammo_box
name = "10mm HP Ammo Box Crate"
desc = "Contains a fifty-round 10mm box loaded with hollow point ammo, great against unarmored targets."
@@ -305,6 +329,18 @@
contains = list(/obj/item/ammo_box/c8x50mmhp_box)
cost = 500
+/datum/supply_pack/ammo/a300_box
+ name = ".300 Ammo Box Crate"
+ desc = "Contains a twenty-round .300 Magnum ammo box for sniper rifles such as the HP Scout."
+ contains = list(/obj/item/ammo_box/a300_box)
+ cost = 500
+
+/datum/supply_pack/ammo/a4570_box
+ name = ".45-70 Ammo Box Crate"
+ desc = "Contains a twelve-round box containing devastatingly powerful .45-70 caliber ammunition."
+ contains = list(/obj/item/ammo_box/a4570)
+ cost = 500
+
/datum/supply_pack/ammo/ferropelletboxcrate
name = "Ferromagnetic Pellet Box Crate"
desc = "Contains a fifty-round ferromagnetic pellet ammo box for gauss guns such as the Claris."
diff --git a/code/modules/cargo/packs/gun.dm b/code/modules/cargo/packs/gun.dm
index 3b3a6f225870..4025db76d300 100644
--- a/code/modules/cargo/packs/gun.dm
+++ b/code/modules/cargo/packs/gun.dm
@@ -7,16 +7,19 @@
*/
/datum/supply_pack/gun/disposable
- name = "Disposable Guns Crate"
- desc = "In some sectors, these disposable pistols are the only firearms that can be legally sold for less than 400cr. That price is still far too high; this pack contains five."
- cost = 750
- contains = list(/obj/item/gun/ballistic/automatic/pistol/disposable,
- /obj/item/gun/ballistic/automatic/pistol/disposable,
- /obj/item/gun/ballistic/automatic/pistol/disposable,
- /obj/item/gun/ballistic/automatic/pistol/disposable,
- /obj/item/gun/ballistic/automatic/pistol/disposable)
+ name = "Disposable Gun Crate"
+ desc = "In some sectors, these disposable pistols are the only firearms that can be legally sold for less than 200cr. That price is still far too high."
+ cost = 150
+ contains = list(/obj/item/gun/ballistic/automatic/pistol/disposable)
crate_name = "disposable gun crate"
+/datum/supply_pack/gun/derringer
+ name = ".38 Derringer Crate"
+ desc = "A cheap, concealable pistol manufactured by the reputable Hunter's Pride. At least it's better than a disposable pistol. Chambered in .38 rounds."
+ cost = 350
+ contains = list(/obj/item/gun/ballistic/derringer)
+ crate_name = "derringer crate"
+
/datum/supply_pack/gun/commanders
name = "Commander Pistol Crate"
desc = "Contains a modified Candor 'Commander' pistol, produced by Nanotrasen and chambered in 9mm."
@@ -36,15 +39,15 @@
cost = 1000
contains = list(/obj/item/gun/ballistic/automatic/pistol/candor)
-/datum/supply_pack/gun/revolver
- name = "Scarborough Revolver Crate"
- desc = "Contains a concealable Scarborough revolver, chambered in .357."
+/datum/supply_pack/gun/pepperbox
+ name = "HP Firebrand Pepperbox Revolver Crate"
+ desc = "Contains a concealable pepperbox revolver manufactured by the Saint Roumain Militia, chambered in .357."
cost = 1250
- contains = list(/obj/item/gun/ballistic/revolver)
+ contains = list(/obj/item/gun/ballistic/revolver/firebrand)
/datum/supply_pack/gun/detrevolver
name = "Hunter's Pride Detective Revolver Crate"
- desc = "Contains a concealable Solarian revolver, chambered in .38."
+ desc = "Contains a concealable revolver favored by police departments around the sector, chambered in .38."
cost = 600
contains = list(/obj/item/gun/ballistic/revolver/detective)
@@ -107,6 +110,13 @@
Shotguns
*/
+/datum/supply_pack/gun/doublebarrel_shotgun
+ name = "Double Barrel Shotgun Crate"
+ desc = "For when you need to deal with 2 drunkards the old-fashioned way. Contains a double-barreled shotgun, favored by Bartenders. Warranty voided if sawed off."
+ cost = 1000
+ contains = list(/obj/item/gun/ballistic/shotgun/doublebarrel)
+ crate_name = "shotguns crate"
+
/datum/supply_pack/gun/hellfire_shotgun
name = "Hellfire Shotgun Crate"
desc = "For when you need to deal with 7 hooligans. Contains a pump shotgun, with a 8-round capacity."
@@ -132,13 +142,6 @@
contains = list(/obj/item/gun/ballistic/shotgun/flamingarrow)
crate_name = "rifle crate"
-/datum/supply_pack/gun/cobra20
- name = "Cobra-20 SMG Crate"
- desc = "Contains a .45 submachine gun, manufactured by Scarborough Arms and chambered in .45"
- cost = 3000
- contains = list(/obj/item/gun/ballistic/automatic/smg/c20r/cobra)
- crate_name = "SMG crate"
-
/datum/supply_pack/gun/illestren
name = "Illestren Rifle Crate"
desc = "Contains a expertly made bolt action rifle intended for hunting wildlife. Chambered in 8x50mmR rounds."
@@ -146,6 +149,27 @@
contains = list(/obj/item/gun/ballistic/rifle/illestren)
crate_name = "rifle crate"
+/datum/supply_pack/gun/beacon
+ name = "Contender Break Action Rifle Crate"
+ desc = "Contains a single shot break action rifle to hunt wildlife that annoys you in particular. Chambered in devastating .45-70 rounds. Warranty voided if sawed off."
+ cost = 2250
+ contains = list(/obj/item/gun/ballistic/shotgun/doublebarrel/beacon)
+ crate_name = "rifle crate"
+
+/datum/supply_pack/gun/scout
+ name = "Scout Sniper Rifle Crate"
+ desc = "Contains a traditional scoped rifle to hunt wildlife and big game from a respectful distance. Chambered in powerful .300 Magnum."
+ cost = 5500
+ contains = list(/obj/item/gun/ballistic/rifle/scout)
+ crate_name = "rifle crate"
+
+/datum/supply_pack/gun/cobra20
+ name = "Cobra-20 SMG Crate"
+ desc = "Contains a .45 submachine gun, manufactured by Scarborough Arms and chambered in .45"
+ cost = 3000
+ contains = list(/obj/item/gun/ballistic/automatic/smg/c20r/cobra)
+ crate_name = "SMG crate"
+
/datum/supply_pack/gun/wt550
name = "WT-550 Auto Rifle Crate"
desc = "Contains a high-powered, automatic personal defense weapon chambered in 4.6x30mm."
diff --git a/code/modules/cargo/packs/sec_supply.dm b/code/modules/cargo/packs/sec_supply.dm
index 023ab5ee853f..8ff09a5dc38a 100644
--- a/code/modules/cargo/packs/sec_supply.dm
+++ b/code/modules/cargo/packs/sec_supply.dm
@@ -56,11 +56,9 @@
/datum/supply_pack/sec_supply/riotshields
name = "Riot Shields Crate"
- desc = "For when the greytide gets really uppity. Contains three riot shields."
- cost = 2000
- contains = list(/obj/item/shield/riot,
- /obj/item/shield/riot,
- /obj/item/shield/riot)
+ desc = "Contains a riot shield, effective at holding back hostile fauna, xenofauna, or large crowds."
+ cost = 600
+ contains = list(/obj/item/shield/riot)
crate_name = "riot shields crate"
/datum/supply_pack/sec_supply/survknives
diff --git a/code/modules/client/loadout/loadout_suit.dm b/code/modules/client/loadout/loadout_suit.dm
index ec9fc916723e..8c758145f71e 100644
--- a/code/modules/client/loadout/loadout_suit.dm
+++ b/code/modules/client/loadout/loadout_suit.dm
@@ -111,3 +111,7 @@
display_name = "worn shirt"
path = /obj/item/clothing/suit/ianshirt
+/datum/gear/suit/hawaiian
+ display_name = "floral shirt"
+ description = "From grills to guns, this shirt's seen it all."
+ path = /obj/item/clothing/suit/hawaiian
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 22baf7d2ae86..651ebe8b0745 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -16,10 +16,15 @@
dog_fashion = /datum/dog_fashion/head/helmet
- var/can_flashlight = FALSE //if a flashlight can be mounted. if it has a flashlight and this is false, it is permanently attached.
+ //if a flashlight can be mounted. if it has a flashlight and this is false, it is permanently attached.
+ var/can_flashlight = FALSE
var/obj/item/flashlight/seclite/attached_light
var/datum/action/item_action/toggle_helmet_flashlight/action_light
+ pocket_storage_component_path = /datum/component/storage/concrete/pockets/helmet
+ // should we overlay the items inside our helmet
+ var/content_overlays = FALSE
+
/obj/item/clothing/head/helmet/Initialize()
. = ..()
if(attached_light)
@@ -171,16 +176,21 @@
var/mutable_appearance/flashlightlight_overlay
if(isinhands)
return
- if(!attached_light)
- return
- if(attached_light.on)
- flashlightlight_overlay = mutable_appearance('icons/mob/clothing/head.dmi', "[flashlight_state]_on")
+ if(attached_light)
+ if(attached_light.on)
+ flashlightlight_overlay = mutable_appearance('icons/mob/clothing/head.dmi', "[flashlight_state]_on")
+ else
+ flashlightlight_overlay = mutable_appearance('icons/mob/clothing/head.dmi', flashlight_state)
+ . += flashlightlight_overlay
+ if(content_overlays)
+ for(var/obj/item/I in contents)
+ . += I.get_helmet_overlay()
else
- flashlightlight_overlay = mutable_appearance('icons/mob/clothing/head.dmi', flashlight_state)
- . += flashlightlight_overlay
+ return
/obj/item/clothing/head/helmet/sec
can_flashlight = TRUE
+ content_overlays = TRUE
/obj/item/clothing/head/helmet/sec/attackby(obj/item/I, mob/user, params)
if(issignaler(I))
@@ -214,6 +224,7 @@
"Snow" = "helmetalt_snow",
"Urban" = "helmetalt_urban",
)
+ content_overlays = TRUE
/obj/item/clothing/head/helmet/marine
name = "tactical combat helmet"
@@ -497,6 +508,7 @@
icon_state = "inteq_swat"
item_state = "inteq_swat"
flags_inv = HIDEHAIR
+ content_overlays = TRUE
/obj/item/clothing/head/helmet/inteq
name = "inteq helmet"
@@ -504,6 +516,7 @@
icon_state = "inteq_helmet"
icon_state = "inteq_helmet"
can_flashlight = TRUE
+ content_overlays = TRUE
/obj/item/clothing/head/solgov
name = "\improper SolGov officer's cap"
@@ -545,6 +558,7 @@
desc = "A robust combat helmet commonly employed by Syndicate forces, regardless of alignment."
icon_state = "operator"
item_state = "operator"
+ content_overlays = TRUE
/obj/item/clothing/head/helmet/medical
name = "\improper trauma team helmet"
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index 4b19735b5f62..fe89fab6b21d 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -19,6 +19,8 @@
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF
resistance_flags = NONE
dog_fashion = null
+ content_overlays = FALSE
+ pocket_storage_component_path = null
/obj/item/clothing/suit/space
name = "space suit"
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 64b4c656bb1f..a1680fcaba0c 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -661,8 +661,8 @@
flags_inv = HIDEHAIR|HIDEEARS|HIDEFACIALHAIR|HIDEFACE|HIDEMASK
/obj/item/clothing/suit/hawaiian
- name = "hawaiian overshirt"
- desc = "A cool shirt for chilling on the beach."
+ name = "floral shirt"
+ desc = "From grills to guns, this shirt's seen it all."
icon_state = "hawaiian_blue"
item_state = "hawaiian_blue"
diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
index 248e9f413795..6aa59e824169 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -1,4 +1,8 @@
#define ELZUOSE_EMAG_COLORS list("#00ffff", "#ffc0cb", "#9400D3", "#4B0082", "#0000FF", "#00FF00", "#FFFF00", "#FF7F00", "#FF0000")
+#define GOOD_SOIL list(/turf/open/floor/plating/grass, /turf/open/floor/plating/dirt, /turf/open/floor/ship/dirt, /turf/open/floor/grass/ship, /turf/open/floor/plating/asteroid/whitesands/grass, /turf/open/floor/grass/fairy/beach)
+#define DIG_TIME (7.5 SECONDS)
+#define ROOT_TIME (3 SECONDS)
+#define ROOT_CHARGE_GAIN (5 * ELZUOSE_CHARGE_SCALING_MULTIPLIER)
/datum/species/elzuose
name = "\improper Elzuose"
@@ -14,6 +18,7 @@
attack_type = BURN //burn bish
exotic_bloodtype = "E"
damage_overlay_type = "" //We are too cool for regular damage overlays
+ species_age_max = 300
species_traits = list(DYNCOLORS, EYECOLOR, HAIR, FACEHAIR)
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
species_language_holder = /datum/language_holder/ethereal
@@ -46,35 +51,118 @@
loreblurb = "Elzuosa are an uncommon and unusual species best described as crystalline, electrically-powered plantpeople. They hail from the warm planet Kalixcis, where they evolved alongside the Sarathi. Kalixcian culture places no importance on blood-bonds, and those from it tend to consider their family anyone they are sufficiently close to, and choose their own names."
var/drain_time = 0 //used to keep ethereals from spam draining power sources
var/obj/effect/dummy/lighting_obj/ethereal_light
+ var/datum/action/innate/root/rooting
/datum/species/elzuose/Destroy(force)
if(ethereal_light)
QDEL_NULL(ethereal_light)
return ..()
-/datum/species/elzuose/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
+/datum/species/elzuose/on_species_gain(mob/living/carbon/_carbon, datum/species/old_species, pref_load)
. = ..()
- if(!ishuman(C))
+ if(!ishuman(_carbon))
return
- var/mob/living/carbon/human/ethereal = C
+ var/mob/living/carbon/human/ethereal = _carbon
default_color = "#[ethereal.dna.features["ethcolor"]]"
RegisterSignal(ethereal, COMSIG_ATOM_EMAG_ACT, PROC_REF(on_emag_act))
RegisterSignal(ethereal, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act))
ethereal_light = ethereal.mob_light()
spec_updatehealth(ethereal)
+ rooting = new
+ rooting.Grant(_carbon)
+ RegisterSignal(ethereal, COMSIG_DIGOUT, PROC_REF(digout))
+ RegisterSignal(ethereal, COMSIG_MOVABLE_MOVED, PROC_REF(uproot))
//The following code is literally only to make admin-spawned ethereals not be black.
- C.dna.features["mcolor"] = C.dna.features["ethcolor"] //Ethcolor and Mut color are both dogshit and will be replaced
- for(var/obj/item/bodypart/BP as anything in C.bodyparts)
+ _carbon.dna.features["mcolor"] = _carbon.dna.features["ethcolor"] //Ethcolor and Mut color are both dogshit and will be replaced
+ for(var/obj/item/bodypart/BP as anything in _carbon.bodyparts)
if(BP.limb_id == SPECIES_ELZUOSE)
BP.update_limb(is_creating = TRUE)
-/datum/species/elzuose/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load)
- UnregisterSignal(C, COMSIG_ATOM_EMAG_ACT)
- UnregisterSignal(C, COMSIG_ATOM_EMP_ACT)
+/datum/species/elzuose/on_species_loss(mob/living/carbon/human/_carbon, datum/species/new_species, pref_load)
+ UnregisterSignal(_carbon, COMSIG_ATOM_EMAG_ACT)
+ UnregisterSignal(_carbon, COMSIG_ATOM_EMP_ACT)
+ UnregisterSignal(_carbon, COMSIG_DIGOUT)
+ UnregisterSignal(_carbon, COMSIG_MOVABLE_MOVED)
QDEL_NULL(ethereal_light)
+ if(rooting)
+ rooting.Remove(_carbon)
return ..()
+/datum/action/innate/root
+ name = "Root"
+ desc = "Root into good soil to gain charge."
+ check_flags = AB_CHECK_CONSCIOUS
+ button_icon_state = "plant-22"
+ icon_icon = 'icons/obj/flora/plants.dmi'
+ background_icon_state = "bg_alien"
+
+/datum/action/innate/root/Activate()
+ var/mob/living/carbon/human/_human = owner
+ var/datum/species/elzuose/_elzu = _human.dna.species
+ // this is healthy for elzu, they shouldnt be able to overcharge and get heart attacks from this
+ var/obj/item/organ/stomach/ethereal/stomach = _human.getorganslot(ORGAN_SLOT_STOMACH)
+
+ if(_human.wear_suit && istype(_human.wear_suit, /obj/item/clothing))
+ var/obj/item/clothing/CS = _human.wear_suit
+ if (CS.clothing_flags & THICKMATERIAL)
+ to_chat(_human, span_warning("Your [CS.name] is too thick to root in!"))
+ return
+
+ if(stomach.crystal_charge > ELZUOSE_CHARGE_FULL)
+ to_chat(_human,span_warning("Your charge is full!"))
+ return
+ _elzu.drain_time = world.time + ROOT_TIME
+ _human.visible_message(span_notice("[_human] is digging into the ground"),span_warning("You start to dig yourself into the ground to root. You won't won't be able to move once you start the process."),span_notice("You hear digging."))
+ if(!do_after(_human,DIG_TIME, target = _human))
+ to_chat(_human,span_warning("You were interupted!"))
+ return
+ _human.apply_status_effect(/datum/status_effect/rooted)
+ to_chat(_human, span_notice("You root into the ground and begin to feed."))
+
+ while(do_after(_human, ROOT_TIME, target = _human))
+ if(istype(stomach))
+ to_chat(_human, span_notice("You receive some charge from rooting."))
+ stomach.adjust_charge(ROOT_CHARGE_GAIN)
+ _human.adjustBruteLoss(-3)
+ _human.adjustFireLoss(-3)
+
+ if(stomach.crystal_charge > ELZUOSE_CHARGE_FULL)
+ stomach.crystal_charge = ELZUOSE_CHARGE_FULL
+ to_chat(_human, span_notice("You're full on charge!"))
+ break
+
+ else
+ to_chat(_human,span_warning("You're missing your biological battery and can't recieve charge from rooting!"))
+ break
+
+/datum/species/elzuose/proc/digout(mob/living/carbon/human/_human)
+ if(do_after(_human, DIG_TIME,target = _human))
+ to_chat(_human,span_notice("You finish digging yourself out."))
+ _human.remove_status_effect(/datum/status_effect/rooted)
+ return
+
+/datum/species/elzuose/proc/uproot(mob/living/carbon/human/_human)
+ //You got moved and uprooted, time to suffer the consequences.
+ if(_human.has_status_effect(/datum/status_effect/rooted))
+ _human.visible_message(span_warning("[_human] is forcefully uprooted. That looked like it hurt."),span_warning("You're forcefully unrooted! Ouch!"),span_warning("You hear someone scream in pain."))
+ _human.apply_damage(8,BRUTE,BODY_ZONE_CHEST)
+ _human.apply_damage(8,BRUTE,BODY_ZONE_L_LEG)
+ _human.apply_damage(8,BRUTE,BODY_ZONE_R_LEG)
+ _human.emote("scream")
+ _human.remove_status_effect(/datum/status_effect/rooted)
+ return
+
+/datum/action/innate/root/IsAvailable()
+ if(..())
+ var/mob/living/carbon/human/_human = owner
+ var/turf/terrain = get_turf(_human)
+ if(_human.has_status_effect(/datum/status_effect/rooted))
+ return FALSE
+ if(is_type_in_list(terrain,GOOD_SOIL))
+ return TRUE
+ return FALSE
+
/datum/species/elzuose/random_name(gender,unique,lastname)
if(unique)
return random_unique_lizard_name(gender)
@@ -86,30 +174,30 @@
return randname
-/datum/species/elzuose/spec_updatehealth(mob/living/carbon/human/H)
+/datum/species/elzuose/spec_updatehealth(mob/living/carbon/human/_human)
. = ..()
if(!ethereal_light)
return
- if(H.stat != DEAD && !EMPeffect)
+ if(_human.stat != DEAD && !EMPeffect)
if(!emag_effect)
- current_color = health_adjusted_color(H, default_color)
- set_ethereal_light(H, current_color)
+ current_color = health_adjusted_color(_human, default_color)
+ set_ethereal_light(_human, current_color)
ethereal_light.set_light_on(TRUE)
fixed_mut_color = copytext_char(current_color, 2)
else
ethereal_light.set_light_on(FALSE)
fixed_mut_color = rgb(128,128,128)
- for(var/obj/item/bodypart/parts_to_update as anything in H.bodyparts)
+ for(var/obj/item/bodypart/parts_to_update as anything in _human.bodyparts)
parts_to_update.species_color = fixed_mut_color
parts_to_update.update_limb()
- H.update_body()
- H.update_hair()
+ _human.update_body()
+ _human.update_hair()
-/datum/species/elzuose/proc/health_adjusted_color(mob/living/carbon/human/H, default_color)
- var/health_percent = max(H.health, 0) / 100
+/datum/species/elzuose/proc/health_adjusted_color(mob/living/carbon/human/_human, default_color)
+ var/health_percent = max(_human.health, 0) / 100
var/static/unhealthy_color_red_part = GETREDPART(unhealthy_color)
var/static/unhealthy_color_green_part = GETGREENPART(unhealthy_color)
@@ -126,130 +214,129 @@
)
return result
-/datum/species/elzuose/proc/set_ethereal_light(mob/living/carbon/human/H, current_color)
+/datum/species/elzuose/proc/set_ethereal_light(mob/living/carbon/human/_human, current_color)
if(!ethereal_light)
return
- var/health_percent = max(H.health, 0) / 100
+ var/health_percent = max(_human.health, 0) / 100
var/light_range = 1 + (1 * health_percent)
var/light_power = 1 + round(0.5 * health_percent)
ethereal_light.set_light_range_power_color(light_range, light_power, current_color)
-/datum/species/elzuose/proc/on_emp_act(mob/living/carbon/human/H, severity)
+/datum/species/elzuose/proc/on_emp_act(mob/living/carbon/human/_human, severity)
EMPeffect = TRUE
- spec_updatehealth(H)
- to_chat(H, "You feel the light of your body leave you.")
+ spec_updatehealth(_human)
+ to_chat(_human, span_notice("You feel the light of your body leave you."))
switch(severity)
if(EMP_LIGHT)
- addtimer(CALLBACK(src, PROC_REF(stop_emp), H), 10 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 10 seconds
+ addtimer(CALLBACK(src, PROC_REF(stop_emp), _human), 10 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 10 seconds
if(EMP_HEAVY)
- addtimer(CALLBACK(src, PROC_REF(stop_emp), H), 20 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 20 seconds
+ addtimer(CALLBACK(src, PROC_REF(stop_emp), _human), 20 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 20 seconds
-/datum/species/elzuose/proc/on_emag_act(mob/living/carbon/human/H, mob/user)
+/datum/species/elzuose/proc/on_emag_act(mob/living/carbon/human/_human, mob/user)
if(emag_effect)
return
emag_effect = TRUE
if(user)
- to_chat(user, "You tap [H] on the back with your card.")
- H.visible_message("[H] starts flickering in an array of colors!")
- handle_emag(H)
- addtimer(CALLBACK(src, PROC_REF(stop_emag), H), 30 SECONDS) //Disco mode for 30 seconds! This doesn't affect the ethereal at all besides either annoying some players, or making someone look badass.
+ to_chat(user, span_notice("You tap [_human] on the back with your card."))
+ _human.visible_message(span_danger("[_human] starts flickering in an array of colors!"))
+ handle_emag(_human)
+ addtimer(CALLBACK(src, PROC_REF(stop_emag), _human), 30 SECONDS) //Disco mode for 30 seconds! This doesn't affect the ethereal at all besides either annoying some players, or making someone look badass.
-/datum/species/elzuose/spec_life(mob/living/carbon/human/H)
+/datum/species/elzuose/spec_life(mob/living/carbon/human/_human)
.=..()
- handle_charge(H)
+ handle_charge(_human)
-/datum/species/elzuose/proc/stop_emp(mob/living/carbon/human/H)
+/datum/species/elzuose/proc/stop_emp(mob/living/carbon/human/_human)
EMPeffect = FALSE
- spec_updatehealth(H)
- to_chat(H, "You feel more energized as your shine comes back.")
+ spec_updatehealth(_human)
+ to_chat(_human, span_notice("You feel more energized as your shine comes back."))
-/datum/species/elzuose/proc/handle_emag(mob/living/carbon/human/H)
+/datum/species/elzuose/proc/handle_emag(mob/living/carbon/human/_human)
if(!emag_effect)
return
current_color = pick(ELZUOSE_EMAG_COLORS)
- spec_updatehealth(H)
- addtimer(CALLBACK(src, PROC_REF(handle_emag), H), 5) //Call ourselves every 0.5 seconds to change color
+ spec_updatehealth(_human)
+ addtimer(CALLBACK(src, PROC_REF(handle_emag), _human), 5) //Call ourselves every 0.5 seconds to change color
-/datum/species/elzuose/proc/stop_emag(mob/living/carbon/human/H)
+/datum/species/elzuose/proc/stop_emag(mob/living/carbon/human/_human)
emag_effect = FALSE
- spec_updatehealth(H)
- H.visible_message("[H] stops flickering and goes back to their normal state!")
+ spec_updatehealth(_human)
+ _human.visible_message(span_danger("[_human] stops flickering and goes back to their normal state!"))
-/datum/species/elzuose/proc/handle_charge(mob/living/carbon/human/H)
+/datum/species/elzuose/proc/handle_charge(mob/living/carbon/human/_human)
brutemod = 1.25
- switch(get_charge(H))
+ switch(get_charge(_human))
if(ELZUOSE_CHARGE_NONE to ELZUOSE_CHARGE_LOWPOWER)
- if(get_charge(H) == ELZUOSE_CHARGE_NONE)
- H.throw_alert("ELZUOSE_CHARGE", /atom/movable/screen/alert/etherealcharge, 3)
+ if(get_charge(_human) == ELZUOSE_CHARGE_NONE)
+ _human.throw_alert("ELZUOSE_CHARGE", /atom/movable/screen/alert/etherealcharge, 3)
else
- H.throw_alert("ELZUOSE_CHARGE", /atom/movable/screen/alert/etherealcharge, 2)
- if(H.health > 10.5)
- apply_damage(0.2, TOX, null, null, H)
+ _human.throw_alert("ELZUOSE_CHARGE", /atom/movable/screen/alert/etherealcharge, 2)
+ if(_human.health > 10.5)
+ apply_damage(0.2, TOX, null, null, _human)
brutemod = 1.75
if(ELZUOSE_CHARGE_LOWPOWER to ELZUOSE_CHARGE_NORMAL)
- H.throw_alert("ELZUOSE_CHARGE", /atom/movable/screen/alert/etherealcharge, 1)
+ _human.throw_alert("ELZUOSE_CHARGE", /atom/movable/screen/alert/etherealcharge, 1)
brutemod = 1.5
if(ELZUOSE_CHARGE_FULL to ELZUOSE_CHARGE_OVERLOAD)
- H.throw_alert("ethereal_overcharge", /atom/movable/screen/alert/ethereal_overcharge, 1)
+ _human.throw_alert("ethereal_overcharge", /atom/movable/screen/alert/ethereal_overcharge, 1)
brutemod = 1.5
if(ELZUOSE_CHARGE_OVERLOAD to ELZUOSE_CHARGE_DANGEROUS)
- H.throw_alert("ethereal_overcharge", /atom/movable/screen/alert/ethereal_overcharge, 2)
+ _human.throw_alert("ethereal_overcharge", /atom/movable/screen/alert/ethereal_overcharge, 2)
brutemod = 1.75
if(prob(10)) //10% each tick for ethereals to explosively release excess energy if it reaches dangerous levels
- discharge_process(H)
+ discharge_process(_human)
else
- H.clear_alert("ELZUOSE_CHARGE")
- H.clear_alert("ethereal_overcharge")
+ _human.clear_alert("ELZUOSE_CHARGE")
+ _human.clear_alert("ethereal_overcharge")
-/datum/species/elzuose/proc/discharge_process(mob/living/carbon/human/H)
- to_chat(H, "You begin to lose control over your charge!")
- H.visible_message("[H] begins to spark violently!")
+/datum/species/elzuose/proc/discharge_process(mob/living/carbon/human/_human)
+ _human.visible_message(span_danger("[_human] begins to spark violently!"),_human,span_warning("You begin to lose control over your charge!"))
var/static/mutable_appearance/overcharge //shameless copycode from lightning spell
overcharge = overcharge || mutable_appearance('icons/effects/effects.dmi', "electricity", EFFECTS_LAYER)
- H.add_overlay(overcharge)
- if(do_mob(H, H, 50, 1))
- H.flash_lighting_fx(5, 7, current_color)
- var/obj/item/organ/stomach/ethereal/stomach = H.getorganslot(ORGAN_SLOT_STOMACH)
- playsound(H, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5)
- H.cut_overlay(overcharge)
- tesla_zap(H, 2, (stomach.crystal_charge / ELZUOSE_CHARGE_SCALING_MULTIPLIER) * 50, ZAP_OBJ_DAMAGE | ZAP_ALLOW_DUPLICATES)
+ _human.add_overlay(overcharge)
+ if(do_mob(_human, _human, 50, 1))
+ _human.flash_lighting_fx(5, 7, current_color)
+ var/obj/item/organ/stomach/ethereal/stomach = _human.getorganslot(ORGAN_SLOT_STOMACH)
+ playsound(_human, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5)
+ _human.cut_overlay(overcharge)
+ tesla_zap(_human, 2, (stomach.crystal_charge / ELZUOSE_CHARGE_SCALING_MULTIPLIER) * 50, ZAP_OBJ_DAMAGE | ZAP_ALLOW_DUPLICATES)
if(istype(stomach))
stomach.adjust_charge(ELZUOSE_CHARGE_FULL - stomach.crystal_charge)
- to_chat(H, "You violently discharge energy!")
- H.visible_message("[H] violently discharges energy!")
+ to_chat(_human,span_warning("You violently discharge energy!"))
+ _human.visible_message(span_danger("[_human] violently discharges energy!"))
if(prob(10)) //chance of developing heart disease to dissuade overcharging oneself
var/datum/disease/D = new /datum/disease/heart_failure
- H.ForceContractDisease(D)
- to_chat(H, "You're pretty sure you just felt your heart stop for a second there..")
- H.playsound_local(H, 'sound/effects/singlebeat.ogg', 100, 0)
- H.Paralyze(100)
+ _human.ForceContractDisease(D)
+ to_chat(_human, span_userdanger("You're pretty sure you just felt your heart stop for a second there."))
+ _human.playsound_local(_human, 'sound/effects/singlebeat.ogg', 100, 0)
+ _human.Paralyze(100)
return
-/datum/species/elzuose/proc/get_charge(mob/living/carbon/H) //this feels like it should be somewhere else. Eh?
- var/obj/item/organ/stomach/ethereal/stomach = H.getorganslot(ORGAN_SLOT_STOMACH)
+/datum/species/elzuose/proc/get_charge(mob/living/carbon/_human) //this feels like it should be somewhere else. Eh?
+ var/obj/item/organ/stomach/ethereal/stomach = _human.getorganslot(ORGAN_SLOT_STOMACH)
if(istype(stomach))
return stomach.crystal_charge
return ELZUOSE_CHARGE_NONE
-/datum/species/elzuose/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
+/datum/species/elzuose/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/_human)
if(istype(I, /obj/item/multitool))
if(user.a_intent == INTENT_HARM)
. = ..() // multitool beatdown
return
if (emag_effect == TRUE)
- to_chat(user, "The multitool can't get a lock on [H]'s EM frequency")
+ to_chat(user, span_warning("The multitool can't get a lock on [_human]'s EM frequency!"))
return
- if(user != H)
+ if(user != _human)
// random color change
default_color = "#" + GLOB.color_list_ethereal[pick(GLOB.color_list_ethereal)]
- current_color = health_adjusted_color(H, default_color)
- spec_updatehealth(H)
- H.visible_message("[H]'s EM frequency is scrambled to a random color.")
+ current_color = health_adjusted_color(_human, default_color)
+ spec_updatehealth(_human)
+ _human.visible_message(span_danger("[_human]'s EM frequency is scrambled to a random color."))
else
// select new color
var/new_etherealcolor = input(user, "Choose your Elzuose color:", "Character Preference",default_color) as color|null
@@ -257,10 +344,10 @@
var/temp_hsv = RGBtoHSV(new_etherealcolor)
if(ReadHSV(temp_hsv)[3] >= ReadHSV("#505050")[3]) // elzu colors should be bright ok??
default_color = sanitize_hexcolor(new_etherealcolor, 6, TRUE)
- current_color = health_adjusted_color(H, default_color)
- spec_updatehealth(H)
- H.visible_message("[H] modulates \his EM frequency to [new_etherealcolor].")
+ current_color = health_adjusted_color(_human, default_color)
+ spec_updatehealth(_human)
+ _human.visible_message(span_notice("[_human] modulates [_human.p_their()] EM frequency to [new_etherealcolor]"))
else
- to_chat(user, "Invalid color. Your color is not bright enough.")
+ to_chat(user, span_danger("Invalid color. Your color is not bright enough."))
else
. = ..()
diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
index fa7b0a133bae..0b5a7f80a837 100644
--- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
+++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
@@ -23,6 +23,28 @@
desc = "A 7-round speed loader for quickly reloading .357 revolvers. These hollow point rounds do incredible damage against soft targets, but are nearly ineffective against armored ones."
ammo_type = /obj/item/ammo_casing/a357/hp
+/obj/item/ammo_box/a357_box
+ name = "ammo box (.357)"
+ desc = "A box of standard .357 ammo."
+ icon_state = "357box"
+ ammo_type = /obj/item/ammo_casing/a357
+ max_ammo = 50
+
+/obj/item/ammo_box/a357_box/match
+ name = "ammo box (.357)"
+ desc = "A box of match .357 ammo."
+ icon_state = "357box-match"
+ ammo_type = /obj/item/ammo_casing/a357/match
+ max_ammo = 50
+
+/obj/item/ammo_box/a357_box/hp
+ name = "ammo box (.357)"
+ desc = "A box of hollow point .357 ammo."
+ icon_state = "357box-hp"
+ ammo_type = /obj/item/ammo_casing/a357/hp
+ max_ammo = 50
+
+
// .45-70 Ammo Holders (Hunting Revolver)
/obj/item/ammo_box/a4570
@@ -443,3 +465,10 @@
icon_state = "8x50mmbox-hp"
ammo_type = /obj/item/ammo_casing/a8_50rhp
max_ammo = 20
+
+/obj/item/ammo_box/a300_box
+ name = "ammo box (.300 Magnum)"
+ desc = "A box of standard .300 Magnum ammo."
+ icon_state = "300box"
+ ammo_type = /obj/item/ammo_casing/a300
+ max_ammo = 20
diff --git a/code/modules/projectiles/boxes_magazines/internal/revolver.dm b/code/modules/projectiles/boxes_magazines/internal/revolver.dm
index 43748f7afe7b..d757ddf03047 100644
--- a/code/modules/projectiles/boxes_magazines/internal/revolver.dm
+++ b/code/modules/projectiles/boxes_magazines/internal/revolver.dm
@@ -28,7 +28,10 @@
/obj/item/ammo_box/magazine/internal/cylinder/pepperbox
name = "pepperbox revolver cylinder"
+ ammo_type = /obj/item/ammo_casing/a357
+ caliber = ".357"
max_ammo = 5
+ instant_load = FALSE
/obj/item/ammo_box/magazine/internal/cylinder/rev45
name = "cattleman revolver cylinder"
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index 34c2e0cb3094..1b1fe28a7c8a 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -668,6 +668,7 @@
manufacturer = MANUFACTURER_HUNTERSPRIDE
spread_unwielded = 50
fire_delay = 0
+ gate_offset = 4
semi_auto = TRUE
safety_wording = "safety"
diff --git a/html/changelogs/AutoChangeLog-pr-2922.yml b/html/changelogs/AutoChangeLog-pr-2922.yml
deleted file mode 100644
index 05d682b3229d..000000000000
--- a/html/changelogs/AutoChangeLog-pr-2922.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: SuhEugene
-changes:
- - {admin: made invisimin admins invisible for HUDs and ghosts}
-delete-after: true
diff --git a/html/changelogs/AutoChangeLog-pr-2924.yml b/html/changelogs/AutoChangeLog-pr-2924.yml
deleted file mode 100644
index e70ce74597c7..000000000000
--- a/html/changelogs/AutoChangeLog-pr-2924.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: Anticept
-changes:
- - {tweak: 'intercomms, widebands, and headsets default speaker on again. Handhelds
- remain off by default.'}
-delete-after: true
diff --git a/html/changelogs/AutoChangeLog-pr-2935.yml b/html/changelogs/AutoChangeLog-pr-2935.yml
deleted file mode 100644
index 019adfc18ce4..000000000000
--- a/html/changelogs/AutoChangeLog-pr-2935.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: Anticept
-changes:
- - {balance: 'pure soulus dust now makes 20u per reaction, and system cleaner is
- not required.'}
-delete-after: true
diff --git a/html/changelogs/AutoChangeLog-pr-2938.yml b/html/changelogs/AutoChangeLog-pr-2938.yml
deleted file mode 100644
index 3561c2ae1fce..000000000000
--- a/html/changelogs/AutoChangeLog-pr-2938.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: Sun-Soaked
-changes:
- - {bugfix: weird uncertainty around the name of EXOCOM. EXOCON is not real.}
-delete-after: true
diff --git a/html/changelogs/AutoChangeLog-pr-2944.yml b/html/changelogs/AutoChangeLog-pr-2944.yml
deleted file mode 100644
index 94224903c076..000000000000
--- a/html/changelogs/AutoChangeLog-pr-2944.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: SomeguyManperson
-changes:
- - {tweak: match rounds will no longer consider the person firing them as a viable
- target when ricocheting}
-delete-after: true
diff --git a/html/changelogs/AutoChangeLog-pr-2946.yml b/html/changelogs/AutoChangeLog-pr-2946.yml
deleted file mode 100644
index eb54df0147db..000000000000
--- a/html/changelogs/AutoChangeLog-pr-2946.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: Martinpachu
-changes:
- - {rscadd: The Candor may now be bought from the outpost.}
-delete-after: true
diff --git a/html/changelogs/AutoChangeLog-pr-2947.yml b/html/changelogs/AutoChangeLog-pr-2947.yml
deleted file mode 100644
index 980e6d143543..000000000000
--- a/html/changelogs/AutoChangeLog-pr-2947.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: Martinpachu
-changes:
- - {balance: The detective's revolver is now priced at 600 credits instead of 1000.}
- - {balance: The detective's revolver size is now Small.}
-delete-after: true
diff --git a/html/changelogs/archive/2024-05.yml b/html/changelogs/archive/2024-05.yml
index be9fdeed89f0..52fa8a5dc4ca 100644
--- a/html/changelogs/archive/2024-05.yml
+++ b/html/changelogs/archive/2024-05.yml
@@ -4,3 +4,45 @@
2024-05-04:
Apogee-dev:
- bugfix: fixed missing object descriptions on nanotrasen uniforms
+2024-05-06:
+ Anticept:
+ - tweak: intercomms, widebands, and headsets default speaker on again. Handhelds
+ remain off by default.
+ - balance: pure soulus dust now makes 20u per reaction, and system cleaner is not
+ required.
+ Martinpachu:
+ - balance: The detective's revolver is now priced at 600 credits instead of 1000.
+ - balance: The detective's revolver size is now Small.
+ - rscadd: The Candor may now be bought from the outpost.
+ PositiveEntropy:
+ - rscdel: Removes the Arrhythmic Knife.
+ SomeguyManperson:
+ - tweak: match rounds will no longer consider the person firing them as a viable
+ target when ricocheting
+ SuhEugene:
+ - admin: made invisimin admins invisible for HUDs and ghosts
+ Sun-Soaked:
+ - bugfix: weird uncertainty around the name of EXOCOM. EXOCON is not real.
+2024-05-09:
+ PositiveEntropy:
+ - rscadd: The HP Firebrand, HP Scout, HP Contender, .38 Derringer and Double Barrel
+ Shotgun are now purchasable in the outpost store.
+ - bugfix: The Disposable Gun crate is now granularized.
+ - rscdel: The Scarborough Revolver is no longer purchasable in the outpost store.
+2024-05-10:
+ meemofcourse:
+ - rscadd: Helmets now have a small, two-item storage. You can put goggles in there,
+ and it might overlay them.
+2024-05-14:
+ Gristlebee:
+ - rscadd: Elzu rooting
+ - tweak: Max age for elzu characters can be 300.
+ Martinpachu:
+ - tweak: Riot shield crates now contain only one shield but are priced at 600 credits.
+ MassiveMen:
+ - rscadd: Hawaiian Shirt is now in loadout
+ - tweak: Hawaiian Shirt is now Floral Shirt
+ - tweak: New item description teehee
+ SomeguyManperson:
+ - bugfix: static anomalies can now be safely approached if mindshielded, wearing
+ a research scanner, or deaf, not all three at the same time
diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi
index 1e03d316c2e3..60ada01078d7 100644
Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ
diff --git a/icons/mob/clothing/helmet_overlays.dmi b/icons/mob/clothing/helmet_overlays.dmi
new file mode 100644
index 000000000000..1c41c357a42a
Binary files /dev/null and b/icons/mob/clothing/helmet_overlays.dmi differ
diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi
index 3e0a5b2bdc2b..4f2f029a96b7 100644
Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ
diff --git a/icons/turf/decals.dmi b/icons/turf/decals.dmi
index 9fb84aa888c2..a62024cc8e0e 100644
Binary files a/icons/turf/decals.dmi and b/icons/turf/decals.dmi differ
diff --git a/shiptest.dme b/shiptest.dme
index 84e8a83efd8c..d640159e2ee9 100644
--- a/shiptest.dme
+++ b/shiptest.dme
@@ -1853,8 +1853,8 @@
#include "code\modules\buildmode\submodes\map_export.dm"
#include "code\modules\buildmode\submodes\outfit.dm"
#include "code\modules\buildmode\submodes\proccall.dm"
-#include "code\modules\buildmode\submodes\throwing.dm"
#include "code\modules\buildmode\submodes\relocate_to.dm"
+#include "code\modules\buildmode\submodes\throwing.dm"
#include "code\modules\buildmode\submodes\tweakcomps.dm"
#include "code\modules\buildmode\submodes\variable_edit.dm"
#include "code\modules\cargo\bounty.dm"