diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 407c5912fe8..62bb4c8be68 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -82,6 +82,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_DISFIGURED "disfigured"
#define TRAIT_XENO_HOST "xeno_host" //Tracks whether we're gonna be a baby alien's mummy.
#define TRAIT_STUNIMMUNE "stun_immunity"
+#define TRAIT_STUNRESISTANCE "stun_resistance"
#define TRAIT_SLEEPIMMUNE "sleep_immunity"
#define TRAIT_PUSHIMMUNE "push_immunity"
#define TRAIT_SHOCKIMMUNE "shock_immunity"
diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm
index 17773473b4d..e68d44c2959 100644
--- a/code/_globalvars/lists/maintenance_loot.dm
+++ b/code/_globalvars/lists/maintenance_loot.dm
@@ -69,6 +69,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/extinguisher = 11,
/obj/item/hand_labeler = 1,
/obj/item/paper/crumpled = 1,
+ /obj/item/reagent_containers/hypospray/medipen/pumpup = 6,
/obj/item/pen = 1,
/obj/item/reagent_containers/spray/pestspray = 1,
/obj/item/reagent_containers/glass/rag = 3,
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index fedf8be5894..f4b976da962 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -174,13 +174,14 @@
var/cooldown_check = 0 // Used interally, you don't want to modify
var/cooldown = 40 // Default wait time until can stun again.
- var/stun_time_carbon = 60 // How long we stun for - 6 seconds.
- var/stun_time_silicon = 0.60 // Multiplier for stunning silicons; if enabled, is 60% of human stun time.
+ var/knockdown_time_carbon = (1.5 SECONDS) // Knockdown length for carbons.
+ var/stun_time_silicon = (5 SECONDS) // If enabled, how long do we stun silicons.
+ var/stamina_damage = 55 // Do we deal stamina damage.
var/affect_silicon = FALSE // Does it stun silicons.
var/on_sound // "On" sound, played when switching between able to stun or not.
var/on_stun_sound = "sound/effects/woodhit.ogg" // Default path to sound for when we stun.
var/stun_animation = TRUE // Do we animate the "hit" when stunning.
- var/on = TRUE // Are we on or off
+ var/on = TRUE // Are we on or off.
var/on_icon_state // What is our sprite when turned on
var/off_icon_state // What is our sprite when turned off
@@ -189,12 +190,6 @@
var/force_off // Damage when off - not stunning
var/weight_class_on // What is the new size class when turned on
-/obj/item/melee/classic_baton/Initialize()
- . = ..()
-
- // Derive stun time from multiplier.
- stun_time_silicon = stun_time_carbon * stun_time_silicon
-
// Description for trying to stun when still on cooldown.
/obj/item/melee/classic_baton/proc/get_wait_description()
return
@@ -241,7 +236,10 @@
add_fingerprint(user)
if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
to_chat(user, "You hit yourself over the head.")
- user.Paralyze(stun_time_carbon * force)
+
+ user.Paralyze(knockdown_time_carbon * force)
+ user.adjustStaminaLoss(stamina_damage)
+
additional_effects_carbon(user) // user is the target here
if(ishuman(user))
var/mob/living/carbon/human/H = user
@@ -291,7 +289,8 @@
user.do_attack_animation(target)
playsound(get_turf(src), on_stun_sound, 75, 1, -1)
- target.Paralyze(stun_time_carbon)
+ target.Knockdown(knockdown_time_carbon)
+ target.adjustStaminaLoss(stamina_damage)
additional_effects_carbon(target, user)
log_combat(user, target, "stunned", src)
@@ -385,9 +384,9 @@
item_flags = NONE
force = 5
- cooldown = 20
- stun_time_carbon = 85
- affect_silicon = TRUE
+ cooldown = 25
+ stamina_damage = 85
+ affect_silicon = TRUE
on_sound = 'sound/weapons/contractorbatonextend.ogg'
on_stun_sound = 'sound/effects/contractorbatonhit.ogg'
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index efe2d999f72..283de3fc31d 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -12,7 +12,10 @@
attack_verb = list("beaten")
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
- var/stunforce = 140
+ var/cooldown_check = 0
+
+ var/cooldown = (2 SECONDS)
+ var/stunforce = 100
var/status = 0
var/obj/item/stock_parts/cell/cell
var/hitcost = 1000
@@ -131,15 +134,19 @@
if(user.a_intent != INTENT_HARM)
if(status)
- if(baton_stun(M, user))
- user.do_attack_animation(M)
- return
+ if(cooldown_check <= world.time)
+ if(baton_stun(M, user))
+ user.do_attack_animation(M)
+ return
+ else
+ to_chat(user, "The baton is still charging!")
else
M.visible_message("[user] has prodded [M] with [src]. Luckily it was off.", \
"[user] has prodded you with [src]. Luckily it was off")
else
if(status)
- baton_stun(M, user)
+ if(cooldown_check <= world.time)
+ baton_stun(M, user)
..()
@@ -157,9 +164,16 @@
if(!deductcharge(hitcost))
return 0
- L.Paralyze(stunforce)
+ /// After a target is hit, we do a chunk of stamina damage, along with other effects.
+ /// After a period of time, we then check to see what stun duration we give.
+ L.Jitter(20)
+ L.confused = max(8, L.confused)
L.apply_effect(EFFECT_STUTTER, stunforce)
+ L.adjustStaminaLoss(60)
+
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
+ addtimer(CALLBACK(src, .proc/apply_stun_effect_end, L), 2.5 SECONDS)
+
if(user)
L.lastattacker = user.real_name
L.lastattackerckey = user.ckey
@@ -173,9 +187,20 @@
var/mob/living/carbon/human/H = L
H.forcesay(GLOB.hit_appends)
+ cooldown_check = world.time + cooldown
return 1
+/// After the initial stun period, we check to see if the target needs to have the stun applied.
+/obj/item/melee/baton/proc/apply_stun_effect_end(mob/living/target)
+ var/trait_check = HAS_TRAIT(target, TRAIT_STUNRESISTANCE) //var since we check it in out to_chat as well as determine stun duration
+ if(trait_check)
+ target.Paralyze(stunforce * 0.1)
+ else
+ target.Paralyze(stunforce)
+ if(!target.IsParalyzed())
+ to_chat(target, "You muscles seize, making you collapse[trait_check ? ", but your body quickly recovers..." : "!"]")
+
/obj/item/melee/baton/emp_act(severity)
. = ..()
if (!(. & EMP_PROTECT_SELF))
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 1c80a5358bf..8b91e30cb64 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -440,3 +440,46 @@
M.emote(pick("twitch","laugh","frown"))
..()
. = 1
+
+/datum/reagent/drug/pumpup
+ name = "Pump-Up"
+ description = "Take on the world! A fast acting, hard hitting drug that pushes the limit on what you can handle."
+ reagent_state = LIQUID
+ color = "#e38e44"
+ metabolization_rate = 2 * REAGENTS_METABOLISM
+ overdose_threshold = 30
+
+/datum/reagent/drug/pumpup/on_mob_metabolize(mob/living/L)
+ ..()
+ ADD_TRAIT(L, TRAIT_STUNRESISTANCE, type)
+
+/datum/reagent/drug/pumpup/on_mob_end_metabolize(mob/living/L)
+ REMOVE_TRAIT(L, TRAIT_STUNRESISTANCE, type)
+ ..()
+
+/datum/reagent/drug/pumpup/on_mob_life(mob/living/carbon/M)
+ M.Jitter(5)
+
+ if(prob(5))
+ to_chat(M, "[pick("Go! Go! GO!", "You feel ready...", "You feel invincible...")]")
+ if(prob(15))
+ M.losebreath++
+ M.adjustToxLoss(2, 0)
+ ..()
+ . = 1
+
+/datum/reagent/drug/pumpup/overdose_start(mob/living/M)
+ to_chat(M, "You can't stop shaking, your heart beats faster and faster...")
+
+/datum/reagent/drug/pumpup/overdose_process(mob/living/M)
+ M.Jitter(5)
+ if(prob(5))
+ M.drop_all_held_items()
+ if(prob(15))
+ M.emote(pick("twitch","drool"))
+ if(prob(20))
+ M.losebreath++
+ M.adjustStaminaLoss(4, 0)
+ if(prob(15))
+ M.adjustToxLoss(2, 0)
+ ..()
diff --git a/code/modules/reagents/chemistry/recipes/drugs.dm b/code/modules/reagents/chemistry/recipes/drugs.dm
index 7049c3da0ea..0b66c232c85 100644
--- a/code/modules/reagents/chemistry/recipes/drugs.dm
+++ b/code/modules/reagents/chemistry/recipes/drugs.dm
@@ -47,3 +47,9 @@
results = list(/datum/reagent/drug/happiness = 4)
required_reagents = list(/datum/reagent/nitrous_oxide = 2, /datum/reagent/medicine/epinephrine = 1, /datum/reagent/consumable/ethanol = 1)
required_catalysts = list(/datum/reagent/toxin/plasma = 5)
+
+/datum/chemical_reaction/pumpup
+ name = "Pump-Up"
+ id = /datum/reagent/drug/pumpup
+ results = list(/datum/reagent/drug/pumpup = 5)
+ required_reagents = list(/datum/reagent/medicine/epinephrine = 2, /datum/reagent/consumable/coffee = 5)
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index d792cae884f..c1100bfdcc3 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -235,3 +235,11 @@
ignore_flags = 0
reagent_flags = NONE
list_reagents = list(/datum/reagent/magillitis = 5)
+
+/obj/item/reagent_containers/hypospray/medipen/pumpup
+ name = "maintanance pump-up"
+ desc = "A ghetto looking autoinjector filled with a cheap adrenaline shot... Great for shrugging off the effects of stunbatons."
+ volume = 15
+ amount_per_transfer_from_this = 15
+ list_reagents = list(/datum/reagent/drug/pumpup = 15)
+ icon_state = "maintenance"
diff --git a/icons/obj/syringe.dmi b/icons/obj/syringe.dmi
index dda0dcbc244..0b763dded78 100644
Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ