diff --git a/baystation12.dme b/baystation12.dme
index 5263097db58..c887273366d 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -357,6 +357,7 @@
#include "code\datums\organs\organ.dm"
#include "code\datums\organs\organ_external.dm"
#include "code\datums\organs\organ_internal.dm"
+#include "code\datums\organs\pain.dm"
#include "code\datums\organs\wound.dm"
#include "code\datums\spells\area_teleport.dm"
#include "code\datums\spells\conjure.dm"
@@ -637,6 +638,7 @@
#include "code\game\objects\structures.dm"
#include "code\game\objects\weapons.dm"
#include "code\game\objects\effects\aliens.dm"
+#include "code\game\objects\effects\barsign.dm"
#include "code\game\objects\effects\biomass_rift.dm"
#include "code\game\objects\effects\bump_teleporter.dm"
#include "code\game\objects\effects\effect_system.dm"
@@ -1027,6 +1029,7 @@
#include "code\modules\mob\living\carbon\carbon.dm"
#include "code\modules\mob\living\carbon\carbon_defines.dm"
#include "code\modules\mob\living\carbon\give.dm"
+#include "code\modules\mob\living\carbon\shock.dm"
#include "code\modules\mob\living\carbon\alien\alien.dm"
#include "code\modules\mob\living\carbon\alien\death.dm"
#include "code\modules\mob\living\carbon\alien\login.dm"
@@ -1340,6 +1343,7 @@
#include "code\WorkInProgress\Cael_Aislinn\Rust\gyrotron_controller.dm"
#include "code\WorkInProgress\Cael_Aislinn\Rust\radiation.dm"
#include "code\WorkInProgress\Cael_Aislinn\Rust\virtual_particle_catcher.dm"
+#include "code\WorkInProgress\Ported\policetape.dm"
#include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm"
#include "code\ZAS\Airflow.dm"
#include "code\ZAS\Connection.dm"
diff --git a/code/WorkInProgress/Ported/policetape.dm b/code/WorkInProgress/Ported/policetape.dm
index 3fa0a4a8511..2c2e41025aa 100644
--- a/code/WorkInProgress/Ported/policetape.dm
+++ b/code/WorkInProgress/Ported/policetape.dm
@@ -74,7 +74,7 @@
can_place = 0
else
for(var/obj/O in cur)
- if(O.density)
+ if(!istype(O, /obj/item/tape) && O.density)
can_place = 0
break
cur = get_step_towards(cur,end)
diff --git a/code/datums/organs/pain.dm b/code/datums/organs/pain.dm
index 456a94086f7..d1e3ef9a081 100644
--- a/code/datums/organs/pain.dm
+++ b/code/datums/organs/pain.dm
@@ -53,8 +53,7 @@ mob/living/carbon/human/proc/handle_pain()
return
var/maxdam = 0
var/datum/organ/external/damaged_organ = null
- for(var/name in organs)
- var/datum/organ/external/E = organs[name]
+ for(var/datum/organ/external/E in organs)
// amputated limbs don't cause pain
if(E.amputated) continue
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 1094be44c48..f6780570bcb 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -27,6 +27,18 @@
/*
* ID CARDS
*/
+/obj/item/weapon/card/id/examine()
+ ..()
+ read()
+
+/obj/item/weapon/card/id/New()
+ ..()
+ spawn(30)
+ if(istype(loc, /mob/living/carbon/human))
+ blood_type = loc:dna:b_type
+ dna_hash = loc:dna:unique_enzymes
+ fingerprint_hash = md5(loc:dna:uni_identity)
+
/obj/item/weapon/card/id/attack_self(mob/user as mob)
for(var/mob/O in viewers(user, null))
O.show_message(text("[] shows you: \icon[] []: assignment: []", user, src, src.name, src.assignment), 1)
@@ -48,6 +60,9 @@
set src in usr
usr << text("\icon[] []: The current assignment on the card is [].", src, src.name, src.assignment)
+ usr << "The blood type on the card is [blood_type]."
+ usr << "The DNA hash on the card is [dna_hash]."
+ usr << "The fingerprint hash on the card is [fingerprint_hash]."
return
/obj/item/weapon/card/id/syndicate/attack_self(mob/user as mob)
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index de4773218f0..6348e294e61 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -18,25 +18,12 @@
return 1
proc/get_data()
- return
-
-
-
- trigger(emote, source as mob)
- return
-
-
- activate()
- return
-
-
- implanted(mob/source)
- return 1
-
-
- get_data()
return "No information available"
+ proc/hear(message, source as mob)
+ return
+
+
/obj/item/weapon/implant/tracking
@@ -64,7 +51,7 @@ Implant Specifics:
"}
-/obj/item/weapon/implant/explosive
+/obj/item/weapon/implant/dexplosive
name = "explosive"
desc = "And boom goes the weasel."
@@ -95,6 +82,53 @@ Implant Specifics:
"}
if(src.imp_in)
src.imp_in.gib()
+//BS12 Explosive
+/obj/item/weapon/implant/explosive
+ name = "explosive implant"
+ desc = "A military grade micro bio-explosive. Highly dangerous."
+ var/phrase = "supercalifragilisticexpialidocious"
+
+
+ get_data()
+ var/dat = {"
+Implant Specifications:
+Name: Robust Corp RX-78 Intimidation Class Implant
+Life: Activates upon codephrase.
+Important Notes: Explodes
+
+Implant Details:
+Function: Contains a compact, electrically detonated explosive that detonates upon receiving a specially encoded signal or upon host death.
+Special Features: Explodes
+Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."}
+ return dat
+
+ hear_talk(mob/M as mob, msg)
+ hear(msg)
+ return
+
+ hear(var/msg)
+ world << "Implant heard: [msg]"
+ var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "")
+ msg = sanitize_simple(msg, replacechars)
+ world << "Implant understood: [msg]"
+ world << "Implant's phrase: [phrase]"
+ if(findtext(msg,phrase))
+ if(istype(imp_in, /mob/))
+ var/mob/T = imp_in
+ T.gib()
+ explosion(get_turf(imp_in), 1, 3, 4, 6, 3)
+ var/turf/t = get_turf(imp_in)
+ if(t)
+ t.hotspot_expose(3500,125)
+ del(src)
+
+ implanted(mob/source as mob)
+ phrase = input("Choose activation phrase:") as text
+ var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "")
+ phrase = sanitize_simple(phrase, replacechars)
+ usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.", 0, 0)
+ usr << "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate."
+ return 1
/obj/item/weapon/implant/chem
@@ -212,3 +246,86 @@ the implant may become unstable and either pre-maturely inject the subject or si
source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0)
source << "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate."
return 1
+
+
+/obj/item/weapon/implant/death_alarm
+ name = "death alarm implant"
+ desc = "An alarm which monitors host vital signs and transmits a radio message upon death."
+ var/mobname = "Will Robinson"
+
+ get_data()
+ var/dat = {"
+Implant Specifications:
+Name: NanoTrasen \"Profit Margin\" Class Employee Lifesign Sensor
+Life: Activates upon death.
+Important Notes: Alerts crew to crewmember death.
+
+Implant Details:
+Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
+Special Features: Alerts crew to crewmember death.
+Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."}
+ return dat
+
+ process()
+ if (!implanted) return
+ var/mob/M = imp_in
+ if (M == null)
+ world << "Are?.."
+ var/area/t = get_area(M)
+
+ if(isnull(M)) // If the mob got gibbed
+ var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null)
+ a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm")
+ del(a)
+ processing_objects.Remove(src)
+ else if(M.stat == 2)
+ var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null)
+ if(istype(t, /area/syndicate_station) || istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite) )
+ //give the syndies a bit of stealth
+ a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm")
+ else
+ a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm")
+ del(a)
+ processing_objects.Remove(src)
+
+
+ implanted(mob/source as mob)
+ mobname = source.real_name
+ processing_objects.Add(src)
+ return 1
+
+/obj/item/weapon/implant/compressed
+ name = "compressed matter implant"
+ desc = "Based on compressed matter technology, can store a single item."
+ var/activation_emote = "sigh"
+ var/obj/item/scanned = null
+
+ get_data()
+ var/dat = {"
+Implant Specifications:
+Name: NanoTrasen \"Profit Margin\" Class Employee Lifesign Sensor
+Life: Activates upon death.
+Important Notes: Alerts crew to crewmember death.
+
+Implant Details:
+Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
+Special Features: Alerts crew to crewmember death.
+Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."}
+ return dat
+
+ trigger(emote, mob/source as mob)
+ if (src.scanned == null)
+ return 0
+
+ if (emote == src.activation_emote)
+ source << "The air glows as \the [src.scanned.name] uncompresses."
+ var/turf/t = get_turf(source)
+ src.scanned.loc = t
+ del src
+
+ implanted(mob/source as mob)
+ src.activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
+ source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0)
+ source << "The implanted freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate."
+ return 1
+
diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm
index 4f6d81f5fb7..2197909b1ad 100644
--- a/code/game/objects/items/weapons/implants/implantcase.dm
+++ b/code/game/objects/items/weapons/implants/implantcase.dm
@@ -116,3 +116,15 @@
src.imp = new /obj/item/weapon/implant/loyalty( src )
..()
return
+
+
+/obj/item/weapon/implantcase/death_alarm
+ name = "Glass Case- 'Death Alarm'"
+ desc = "A case containing a death alarm implant."
+ icon = 'items.dmi'
+ icon_state = "implantcase-b"
+
+ New()
+ src.imp = new /obj/item/weapon/implant/death_alarm( src )
+ ..()
+ return
diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm
index 217fd563319..a775f3a065a 100644
--- a/code/game/objects/items/weapons/implants/implanter.dm
+++ b/code/game/objects/items/weapons/implants/implanter.dm
@@ -62,7 +62,7 @@
/obj/item/weapon/implanter/explosive
- name = "implanter-explosive"
+ name = "implanter (E)"
/obj/item/weapon/implanter/explosive/New()
src.imp = new /obj/item/weapon/implant/explosive( src )
@@ -77,4 +77,39 @@
src.imp = new /obj/item/weapon/implant/adrenalin(src)
..()
update()
- return
\ No newline at end of file
+ return
+
+/obj/item/weapon/implanter/compressed
+ name = "implanter (C)"
+ icon_state = "cimplanter0"
+
+/obj/item/weapon/implanter/compressed/New()
+ imp = new /obj/item/weapon/implant/compressed( src )
+ ..()
+ update()
+ return
+
+/obj/item/weapon/implanter/compressed/update()
+ if (imp)
+ var/obj/item/weapon/implant/compressed/c = imp
+ if(!c.scanned)
+ icon_state = "cimplanter0"
+ else
+ icon_state = "cimplanter1"
+ else
+ icon_state = "cimplanter2"
+ return
+
+/obj/item/weapon/implanter/compressed/attack(mob/M as mob, mob/user as mob)
+ var/obj/item/weapon/implant/compressed/c = imp
+ if (!c) return
+ if (c.scanned == null)
+ user << "Please scan an object with the implanter first."
+ return
+ ..()
+
+/obj/item/weapon/implanter/compressed/afterattack(atom/A, mob/user as mob)
+ if(istype(A,/obj/item) && imp)
+ imp:scanned = A
+ A.loc.contents.Remove(A)
+ update()
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index da0115b0949..e5b94e78021 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -112,4 +112,6 @@
new /obj/item/clothing/suit/hazardvest(src)
new /obj/item/clothing/mask/gas(src)
new /obj/item/clothing/glasses/meson(src)
+ new /obj/item/taperoll/engineering(src)
+ new /obj/item/taperoll/engineering(src)
return
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 4518a721534..8514f6a6a9a 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -156,6 +156,7 @@
new /obj/item/weapon/melee/baton(src)
new /obj/item/weapon/gun/energy/taser(src)
new /obj/item/clothing/glasses/sunglasses/sechud(src)
+ new /obj/item/taperoll/police(src)
return
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 954204db2be..863a52770a1 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -118,7 +118,8 @@
if (holder.level >= -1)
seeprayers = 1
- verbs += /client/proc/cmd_admin_say
+ verbs += /client/proc/cmd_admin_say //Allows anyone rank -1 or higher to use asay -- removed when it hits 0 (mods), added again at 1 (Temp Admin)
+ verbs += /client/proc/cmd_mod_say //Allows anyone rank -1 or higher to use msay
verbs += /client/proc/deadmin_self
verbs += /client/proc/toggleadminhelpsound
else
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index fae1e43474b..ccf0e794871 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -12,6 +12,7 @@
var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
-
+ var/analgesic = 0 // when this is set, the mob isn't affected by shock or pain
+ // life should decrease this by 1 every tick
// total amount of wounds on mob, used to spread out healing and the like over all wounds
var/number_wounds = 0
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index a7e58ec5c82..4d79d304a8c 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -26,6 +26,8 @@
else if(E.status & ORGAN_BROKEN)
tally += 1.5
+ if(shock_stage >= 10) tally += 3
+
if(FAT in src.mutations)
tally += 1.5
if (bodytemperature < 283.222)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 49deadde423..1975716f0ea 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -92,6 +92,10 @@
//stuff in the stomach
handle_stomach()
+ handle_shock()
+
+ handle_pain()
+
//Status updates, death etc.
handle_regular_status_updates() //TODO: optimise ~Carn
update_canmove()
@@ -968,6 +972,8 @@
silent = 0
return 1
+ // the analgesic effect wears off slowly
+ analgesic = max(0, analgesic - 1)
//UNCONSCIOUS. NO-ONE IS HOME
if( (getOxyLoss() > 50) || (config.health_threshold_crit > health) )
@@ -1384,5 +1390,43 @@
if(mind && mind.changeling)
mind.changeling.regenerate()
+ handle_shock()
+ ..()
+
+ if(analgesic) return // analgesic avoids all traumatic shock temporarily
+
+ if(health < 0)// health 0 makes you immediately collapse
+ shock_stage = max(shock_stage, 61)
+
+ if(traumatic_shock >= 80)
+ shock_stage += 1
+ else
+ shock_stage = min(shock_stage, 100)
+ shock_stage = max(shock_stage-1, 0)
+ return
+
+ if(shock_stage == 10)
+ src << ""+pick("It hurts so much!", "You really need some painkillers..", "Dear god, the pain!")
+
+ if(shock_stage >= 30)
+ if(shock_stage == 30) emote("me",1,"is having trouble keeping their eyes open.")
+ eye_blurry = max(2, eye_blurry)
+ stuttering = max(stuttering, 5)
+
+ if(shock_stage == 40)
+ src << ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")
+
+ if (shock_stage >= 60)
+ if(shock_stage == 60) emote("me",1,"'s body becomes limp.")
+ if (prob(5))
+ Stun(20)
+ lying = 1
+
+ if(shock_stage == 80)
+ src << ""+pick("You see a light at the end of the tunnel!", "You feel like you could die any moment now.", "You're about to lose consciousness.")
+
+ if (shock_stage > 80)
+ Paralyse(rand(15,28))
+
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/shock.dm b/code/modules/mob/living/carbon/shock.dm
index 1df452c8e44..f6cc59cd15c 100644
--- a/code/modules/mob/living/carbon/shock.dm
+++ b/code/modules/mob/living/carbon/shock.dm
@@ -20,8 +20,9 @@
// broken or ripped off organs will add quite a bit of pain
if(istype(src,/mob/living/carbon/human))
var/mob/living/carbon/human/M = src
- for(var/name in M.organs)
- var/datum/organ/external/organ = M.organs[name]
+ for(var/datum/organ/external/organ in M.organs)
+ if (!organ)
+ continue
if((organ.status & ORGAN_DESTROYED) && !organ.amputated)
src.traumatic_shock += 60
else if(organ.status & ORGAN_BROKEN || organ.open)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 5f4e37b25f2..2af9743d0ba 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -78,6 +78,7 @@ var/list/department_radio_keys = list(
/mob/living/say(var/message)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
+ message = capitalize(message)
if (!message)
return
diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm
index 2854975d497..7c2e01457be 100644
--- a/code/modules/reagents/Chemistry-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents.dm
@@ -881,6 +881,20 @@ datum
..()
return
+ tramadol
+ name = "Tramadol"
+ id = "tramadol"
+ description = "A simple, yet effective painkiller."
+ reagent_state = LIQUID
+ color = "#C8A5DC"
+
+ oxycodone
+ name = "Oxycodone"
+ id = "oxycodone"
+ description = "An effective and very addictive painkiller."
+ reagent_state = LIQUID
+ color = "#C805DC"
+
virus_food
name = "Virus Food"
id = "virusfood"
diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm
index 18bee9079b5..283bde88573 100644
--- a/code/modules/reagents/Chemistry-Recipes.dm
+++ b/code/modules/reagents/Chemistry-Recipes.dm
@@ -90,6 +90,20 @@ datum
required_reagents = list("radium" = 1, "phosphorus" = 1, "chlorine" = 1)
result_amount = 3
+ tramadol
+ name = "Tramadol"
+ id = "tramadol"
+ result = "tramadol"
+ required_reagents = list("inaprovaline" = 1, "ethanol" = 1, "oxygen" = 1)
+ result_amount = 3
+
+ oxycodone
+ name = "Oxycodone"
+ id = "oxycodone"
+ result = "oxycodone"
+ required_reagents = list("ethanol" = 1, "tramadol" = 1, "plasma" = 1)
+ result_amount = 1
+
//cyanide
// name = "Cyanide"
// id = "cyanide"
diff --git a/code/world.dm b/code/world.dm
index 27bac98ccda..54de5797842 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -148,8 +148,8 @@ Starting up. [time2text(world.timeofday, "hh:mm.ss")]
/world/Reboot(var/reason)
- spawn(0)
- world << sound(pick('sound/AI/newroundsexy.ogg','sound/misc/apcdestroyed.ogg','sound/misc/bangindonk.ogg')) // random end sounds!! - LastyBatsy
+// spawn(0) // Yeah there we go end round sounds removed, mission accomplished
+// world << sound(pick('sound/AI/newroundsexy.ogg','sound/misc/apcdestroyed.ogg','sound/misc/bangindonk.ogg')) // random end sounds!! - LastyBatsy
for(var/client/C)
if (config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 5737221252a..3637d1eb4c2 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ