diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 7a51eb5defb..695ab933aeb 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -113,6 +113,10 @@
#define COMPANY_ALIGNMENTS list(COMPANY_LOYAL,COMPANY_SUPPORTATIVE,COMPANY_NEUTRAL,COMPANY_SKEPTICAL,COMPANY_OPPOSED)
+// Defines the argument used for get_mobs_and_objs_in_view_fast
+#define GHOSTS_ALL_HEAR 1
+#define ONLY_GHOSTS_IN_VIEW 0
+
// Defines mob sizes, used by lockers and to determine what is considered a small sized mob, etc.
#define MOB_LARGE 16
diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm
index 1210ba9f3e8..85548fe6352 100644
--- a/code/_helpers/game.dm
+++ b/code/_helpers/game.dm
@@ -245,6 +245,41 @@
. += M
return .
+/proc/get_mobs_and_objs_in_view_fast(var/turf/T, var/range, var/list/mobs, var/list/objs, var/checkghosts = GHOSTS_ALL_HEAR)
+
+ var/list/hear = list()
+ DVIEW(hear, range, T, INVISIBILITY_MAXIMUM)
+ var/list/hearturfs = list()
+
+ for(var/am in hear)
+ var/atom/movable/AM = am
+ if(ismob(AM))
+ mobs += AM
+ hearturfs += AM.locs[1]
+ else if(isobj(AM))
+ objs += AM
+ hearturfs += AM.locs[1]
+
+
+ for(var/m in player_list)
+ var/mob/M = m
+ if(checkghosts == GHOSTS_ALL_HEAR && M.stat == DEAD && (M.client && M.client.prefs.toggles & CHAT_GHOSTEARS))
+ mobs |= M
+ continue
+ if(M.loc && M.locs[1] in hearturfs)
+ mobs |= M
+
+
+
+ for(var/o in listening_objects)
+ var/obj/O = o
+ if(O && O.loc && O.locs[1] in hearturfs)
+ objs |= O
+
+
+
+
+
#define SIGN(X) ((X<0)?-1:1)
proc
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 132587422cb..44751295b56 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -458,22 +458,22 @@ its easier to just keep the beam vertical.
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
-/atom/proc/visible_message(var/message, var/blind_message)
- var/list/messageturfs = list()//List of turfs we broadcast to.
- var/list/messagemobs = list()//List of living mobs nearby who can hear it, and distant ghosts who've chosen to hear it
- for (var/turf in view(world.view, get_turf(src)))
- messageturfs += turf
+/atom/proc/visible_message(var/message, var/blind_message, var/range = world.view)
+ var/turf/T = get_turf(src)
+ var/list/mobs = list()
+ var/list/objs = list()
+ get_mobs_and_objs_in_view_fast(T,range, mobs, objs, ONLY_GHOSTS_IN_VIEW)
- for(var/A in player_list)
- var/mob/M = A
- if (!M.client || istype(M, /mob/new_player))
- continue
- if(get_turf(M) in messageturfs)
- messagemobs += M
+ for(var/o in objs)
+ var/obj/O = o
+ O.show_message(message,1,blind_message,2)
- for(var/A in messagemobs)
- var/mob/M = A
- M.show_message(message, 1, blind_message, 2)
+ for(var/m in mobs)
+ var/mob/M = m
+ if(M.see_invisible >= invisibility)
+ M.show_message(message,1,blind_message,2)
+ else if(blind_message)
+ M.show_message(blind_message, 2)
// Show a message to all mobs and objects in earshot of this atom
// Use for objects performing audible actions
@@ -485,18 +485,18 @@ its easier to just keep the beam vertical.
var/range = world.view
if(hearing_distance)
range = hearing_distance
- var/list/hear = get_mobs_or_objects_in_view(range,src)
+ var/turf/T = get_turf(src)
+ var/list/mobs = list()
+ var/list/objs = list()
+ get_mobs_and_objs_in_view_fast(T,range, mobs, objs, ONLY_GHOSTS_IN_VIEW)
+
+ for(var/m in mobs)
+ var/mob/M = m
+ M.show_message(message,2,deaf_message,1)
+ for(var/o in objs)
+ var/obj/O = o
+ O.show_message(message,2,deaf_message,1)
- for(var/I in hear)
- if(isobj(I))
- spawn(0)
- if(I) //It's possible that it could be deleted in the meantime.
- var/obj/O = I
- O.show_message( message, 2, deaf_message, 1)
- else if(ismob(I))
- var/mob/M = I
- M.show_message( message, 2, deaf_message, 1)
-
/atom/proc/change_area(var/area/oldarea, var/area/newarea)
change_area_name(oldarea.name, newarea.name)
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 24faa63f439..008e9baef29 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -63,9 +63,11 @@ var/global/list/default_medbay_channels = list(
..()
wires = new(src)
internal_channels = default_internal_channels.Copy()
+ listening_objects += src
/obj/item/device/radio/Destroy()
qdel(wires)
+ listening_objects -= src
wires = null
if(radio_controller)
radio_controller.remove_object(src, frequency)
diff --git a/code/game/objects/items/devices/spy_bug.dm b/code/game/objects/items/devices/spy_bug.dm
index 063e7a85cea..7e591b4a679 100644
--- a/code/game/objects/items/devices/spy_bug.dm
+++ b/code/game/objects/items/devices/spy_bug.dm
@@ -23,6 +23,11 @@
..()
radio = new(src)
camera = new(src)
+ listening_objects += src
+
+/obj/item/device/spy_bug/Destroy()
+ listening_objects -= src
+ return ..()
/obj/item/device/spy_bug/examine(mob/user)
. = ..(user, 0)
@@ -62,6 +67,11 @@
/obj/item/device/spy_monitor/New()
radio = new(src)
+ listening_objects += src
+
+/obj/item/device/spy_monitor/Destroy()
+ listening_objects -= src
+ return ..()
/obj/item/device/spy_monitor/examine(mob/user)
. = ..(user, 1)
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index e59d3e993b5..3ed02fe7d3a 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -20,6 +20,14 @@
throw_speed = 4
throw_range = 20
+/obj/item/device/taperecorder/New()
+ ..()
+ listening_objects += src
+
+/obj/item/device/taperecorder/Destroy()
+ listening_objects -= src
+ return ..()
+
/obj/item/device/taperecorder/hear_talk(mob/living/M as mob, msg, var/verb="says", datum/language/speaking=null)
if(recording)
timestamp += timerecorded
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 3f262f84e17..ecd9a8a610f 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -50,7 +50,7 @@
Destroy()
if(part)
part.implants.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/implant/tracking
name = "tracking implant"
@@ -162,6 +162,7 @@ Implant Specifics:
"}
if (malfunction == MALFUNCTION_PERMANENT)
return
+
var/need_gib = null
if(istype(imp_in, /mob/))
var/mob/T = imp_in
@@ -252,6 +253,15 @@ Implant Specifics:
"}
explosion(get_turf(imp_in), -1, -1, 2, 3)
qdel(src)
+/obj/item/weapon/implant/explosive/New()
+ ..()
+ listening_objects += src
+
+/obj/item/weapon/implant/explosive/Destroy()
+ listening_objects -= src
+ return ..()
+
+
/obj/item/weapon/implant/chem
name = "chemical implant"
desc = "Injects things."
diff --git a/code/global.dm b/code/global.dm
index 1ef56d9bf1b..0be6248f484 100644
--- a/code/global.dm
+++ b/code/global.dm
@@ -17,6 +17,8 @@ var/global/list/sec_hud_users = list() // List of all entities using
var/global/list/hud_icon_reference = list()
var/global/list/janitorial_supplies = list() // List of all the janitorial supplies on the map that the PDA cart may be tracking.
+var/global/list/listening_objects = list() // List of objects that need to be able to hear, used to avoid recursive searching through contents.
+
var/global/list/global_mutations = list() // List of hidden mutation things.
diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm
index 021216f2181..c29731c677f 100644
--- a/code/modules/assembly/holder.dm
+++ b/code/modules/assembly/holder.dm
@@ -211,6 +211,15 @@
return 1
+/obj/item/device/assembly_holder/New()
+ ..()
+ listening_objects += src
+
+/obj/item/device/assembly_holder/Destroy()
+ listening_objects -= src
+ return ..()
+
+
/obj/item/device/assembly_holder/hear_talk(mob/living/M as mob, msg, verb, datum/language/speaking)
if(a_right)
a_right.hear_talk(M,msg,verb,speaking)
diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm
index 7e8c89cc796..eac18f4afd1 100644
--- a/code/modules/assembly/voice.dm
+++ b/code/modules/assembly/voice.dm
@@ -7,6 +7,14 @@
var/listening = 0
var/recorded //the activation message
+/obj/item/device/assembly/voice/New()
+ ..()
+ listening_objects += src
+
+/obj/item/device/assembly/voice/Destroy()
+ listening_objects -= src
+ return ..()
+
/obj/item/device/assembly/voice/hear_talk(mob/living/M as mob, msg)
if(listening)
recorded = msg
@@ -33,4 +41,4 @@
/obj/item/device/assembly/voice/toggle_secure()
. = ..()
- listening = 0
\ No newline at end of file
+ listening = 0
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index 438b14abe0d..e8967791905 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -34,21 +34,24 @@
var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm.
attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(istype(O,/obj/item/organ/brain) && !(istype(O,/obj/item/organ/brain/golem)) && !brainmob) //Time to stick a brain in it --NEO /MMI'ing a scroll of paper makes 0 sense
-
+ if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO
var/obj/item/organ/brain/B = O
if(B.health <= 0)
- user << "\red That brain is well and truly dead."
+ user << "That brain is well and truly dead."
return
+ else if(!B.lobotomized && B.can_lobotomize)
+ user << "The brain won't fit until you perform a lobotomy!"
+ return
+ else if(!B.can_lobotomize)
+ user << "The [B] is incompatible with [src]!"
else if(!B.brainmob)
- user << "\red You aren't sure where this brain came from, but you're pretty sure it's a useless brain."
+ user << "You aren't sure where this brain came from, but you're pretty sure it's a useless brain."
return
- for(var/mob/V in viewers(src, null))
- V.show_message(text("\blue [user] sticks \a [O] into \the [src]."))
+ user.visible_message("[user] sticks \a [B] into \the [src].")
- brainmob = O:brainmob
- O:brainmob = null
+ brainmob = B.brainmob
+ B.brainmob = null
brainmob.loc = src
brainmob.container = src
brainmob.stat = 0
@@ -56,7 +59,7 @@
living_mob_list += brainmob
user.drop_item()
- brainobj = O
+ brainobj = B
brainobj.loc = src
name = "Man-Machine Interface: [brainmob.real_name]"
diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm
index 6cbe65c1805..6bf79bc5734 100644
--- a/code/modules/mob/living/carbon/brain/brain_item.dm
+++ b/code/modules/mob/living/carbon/brain/brain_item.dm
@@ -14,6 +14,8 @@
origin_tech = list(TECH_BIO = 3)
attack_verb = list("attacked", "slapped", "whacked")
var/mob/living/carbon/brain/brainmob = null
+ var/lobotomized = 0
+ var/can_lobotomize = 1
/obj/item/organ/pariah_brain
name = "brain remnants"
@@ -90,12 +92,44 @@
target.key = brainmob.key
..()
+/obj/item/organ/brain/proc/lobotomize(mob/user as mob)
+ lobotomized = 1
+
+ if(owner)
+ owner << "As part of your brain is drilled out, you feel your past self, your memories, your very being slip away..."
+ owner << "You have been lobotomized. Your memories and your former life have been surgically removed from your brain, and while you are lobotomized you remember nothing that ever came before this moment."
+
+ else if(brainmob)
+ brainmob << "As part of your brain is drilled out, you feel your past self, your memories, your very being slip away..."
+ brainmob << "You have been lobotomized. Your memories and your former life have been surgically removed from your brain, and while you are lobotomized you remember nothing that ever came before this moment."
+
+ return
+
+/obj/item/organ/brain/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/weapon/surgicaldrill))
+ if(!lobotomized)
+ user.visible_message("[user] drills [src] deftly with [W], severing part of the brain!")
+ lobotomize(user)
+ else
+ user << "The brain has already been operated on!"
+ ..()
+
+/obj/item/organ/brain/process()
+ ..()
+
+ if(!owner)
+ return
+
+ if(lobotomized && (owner.getBrainLoss() < 50)) //lobotomized brains cannot be healed with chemistry. Part of the brain is irrevocably missing. Can be fixed magically with cloning, ofc.
+ owner.setBrainLoss(50)
+
/obj/item/organ/brain/slime
name = "slime core"
desc = "A complex, organic knot of jelly and crystalline particles."
robotic = 2
icon = 'icons/mob/slimes.dmi'
icon_state = "green slime extract"
+ can_lobotomize = 0
/obj/item/organ/brain/golem
name = "chelm"
@@ -103,3 +137,4 @@
robotic = 2
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll"
+ can_lobotomize = 0
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index e2883537c81..98858cef311 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -225,10 +225,9 @@ proc/get_radio_key_from_channel(var/channel)
if (speech_sound)
sound_vol *= 0.5
- var/turf/T = get_turf(src)
-
var/list/listening = list()
var/list/listening_obj = list()
+ var/turf/T = get_turf(src)
if(T)
//make sure the air can transmit speech - speaker's side
@@ -241,26 +240,8 @@ proc/get_radio_key_from_channel(var/channel)
italics = 1
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
- var/list/hear = hear(message_range,T)
- var/list/hearturfs = list()
+ get_mobs_and_objs_in_view_fast(T, message_range, listening, listening_obj)
- for(var/I in hear)
- if(ismob(I))
- var/mob/M = I
- listening += M
- hearturfs += M.locs[1]
- else if(isobj(I))
- var/obj/O = I
- hearturfs += O.locs[1]
- listening_obj |= O
-
-
- for(var/mob/M in player_list)
- if(src.client && M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
- listening |= M
- continue
- if(M.loc && M.locs[1] in hearturfs)
- listening |= M
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index c026c5a63f3..ec38053e190 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -163,6 +163,8 @@ var/list/ai_verbs_default = list(
else
if (B.brainmob.mind)
B.brainmob.mind.transfer_to(src)
+ if(B.brainobj)
+ B.brainobj.lobotomized = 1
on_mob_init()
@@ -271,7 +273,7 @@ var/list/ai_verbs_default = list(
aiPDA.ownjob = "AI"
aiPDA.owner = pickedName
aiPDA.name = pickedName + " (" + aiPDA.ownjob + ")"
-
+
setup_icon() //this is because the ai custom name is related to the ai name, so, we just call the setup icon after someone named their ai
/*
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index bb01772a235..aafdaa59a49 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -128,6 +128,8 @@
icontype = "Basic"
updatename(modtype)
updateicon()
+ if(mmi && mmi.brainobj)
+ mmi.brainobj.lobotomized = 1
radio = new /obj/item/device/radio/borg(src)
common_radio = radio
diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm
index 79bf2f5b4a3..476caea5f89 100644
--- a/code/modules/mob/living/simple_animal/friendly/corgi.dm
+++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm
@@ -1,12 +1,12 @@
//Corgi
/mob/living/simple_animal/corgi
- name = "\improper corgi"
+ name = "corgi"
real_name = "corgi"
desc = "It's a corgi."
icon_state = "corgi"
icon_living = "corgi"
icon_dead = "corgi_dead"
- speak = list("YAP", "Woof!", "Bark!", "AUUUUUU")
+ speak = list("YAP!", "Woof!", "Bark!", "AUUUUUU!")
speak_emote = list("barks", "woofs")
emote_hear = list("barks", "woofs", "yaps","pants")
emote_see = list("shakes its head", "shivers")
@@ -19,7 +19,7 @@
response_harm = "kicks"
see_in_dark = 5
mob_size = 5
- max_nutrition = 250//Dogs are insatiable eating monsters. This scales with their mob size too
+ max_nutrition = 250 //Dogs are insatiable eating monsters. This scales with their mob size too
stomach_size_mult = 30
seek_speed = 6
possession_candidate = 1
@@ -29,7 +29,7 @@
/mob/living/simple_animal/corgi/New()
..()
- nutrition = max_nutrition * 0.3//Ian doesn't start with a full belly so will be hungry at roundstart
+ nutrition = max_nutrition * 0.3 //Ian doesn't start with a full belly so will be hungry at roundstart
nutrition_step = mob_size * 0.12
//IAN! SQUEEEEEEEEE~
@@ -55,12 +55,10 @@
sleep(1)
-
/mob/living/simple_animal/corgi/beg(var/atom/thing, var/atom/holder)
visible_emote("stares at the [thing] that [holder] has with sad puppy eyes.",0)
-
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
name = "Corgi meat"
desc = "Tastes like... well you know..."
diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm
index 1870454e935..ed6d9b578b2 100644
--- a/code/modules/mob/living/simple_animal/friendly/fox.dm
+++ b/code/modules/mob/living/simple_animal/friendly/fox.dm
@@ -1,11 +1,12 @@
//Foxxy
/mob/living/simple_animal/corgi/fox
name = "fox"
+ real_name = "fox"
desc = "It's a fox. I wonder what it says?"
icon_state = "fox"
icon_living = "fox"
icon_dead = "fox_dead"
- speak = list("Ack-Ack","Ack-Ack-Ack-Ackawoooo","Geckers","Awoo","Tchoff")
+ speak = list("Ack-Ack.", "Ack-Ack-Ack-Ackawoooo!", "Awoo!", "Tchoff.")
speak_emote = list("geckers", "barks")
emote_hear = list("howls","barks")
emote_see = list("shakes its head", "shivers")
@@ -18,8 +19,9 @@
response_disarm = "gently pushes aside"
response_harm = "kicks"
mob_size = 4
+
//Captain fox
/mob/living/simple_animal/corgi/fox/Chauncey
name = "Chauncey"
+ real_name = "Chauncey"
desc = "Chauncey, the Captain's trustworthy fox. I wonder what it says?"
-
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 179fc231f79..ff44620e461 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -158,21 +158,26 @@
var/range = world.view
if(hearing_distance)
range = hearing_distance
- var/list/hear = get_mobs_or_objects_in_view(range,src)
- for(var/I in hear)
- if(isobj(I))
- spawn(0)
- if(I) //It's possible that it could be deleted in the meantime.
- var/obj/O = I
- O.show_message( message, 2, deaf_message, 1)
- else if(ismob(I))
- var/mob/M = I
- var/msg = message
- if(self_message && M==src)
- msg = self_message
- M.show_message( msg, 2, deaf_message, 1)
+ var/turf/T = get_turf(src)
+ var/list/mobs = list()
+ var/list/objs = list()
+ get_mobs_and_objs_in_view_fast(T, range, mobs, objs)
+
+
+ for(var/m in mobs)
+ var/mob/M = m
+ if(self_message && M==src)
+ M.show_message(self_message,2,deaf_message,1)
+ continue
+
+ M.show_message(message,2,deaf_message,1)
+
+
+ for(var/o in objs)
+ var/obj/O = o
+ O.show_message(message,2,deaf_message,1)
/mob/proc/findname(msg)
for(var/mob/M in mob_list)
diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm
index ec3c5b8756e..c2cd06e0d70 100644
--- a/code/modules/organs/organ_internal.dm
+++ b/code/modules/organs/organ_internal.dm
@@ -189,9 +189,6 @@
parent_organ = "chest"
dead_icon = "heart-off"
-/obj/item/organ/internal/vaurca/process()
- return
-
/obj/item/organ/vaurca/neuralsocket
name = "neural socket"
organ_tag = "neural socket"
diff --git a/code/modules/projectiles/guns/energy/lawgiver.dm b/code/modules/projectiles/guns/energy/lawgiver.dm
index d8d3d91e797..a4c578e8de3 100644
--- a/code/modules/projectiles/guns/energy/lawgiver.dm
+++ b/code/modules/projectiles/guns/energy/lawgiver.dm
@@ -65,12 +65,20 @@
)
)
+/obj/item/weapon/gun/energy/lawgiver/New()
+ ..()
+ listening_objects += src
+
+/obj/item/weapon/gun/energy/lawgiver/Destroy()
+ listening_objects -= src
+ return ..()
+
/obj/item/weapon/gun/energy/lawgiver/proc/play_message()
while (message_enabled && !message_disable) //Shut down command issued. Inform user that boardcasting has been stopped
usr.audible_message("[usr]'s [src.name] broadcasts: [message]","")
playsound(get_turf(src), 'sound/voice/halt.ogg', 100, 1, vary = 0)
sleep(message_delay)
- usr << "\red Broadcasting Message disabled"
+ usr << "Broadcasting Message disabled"
message_enabled = 0
message_disable = 0
@@ -80,7 +88,7 @@
else
src.dna = user.dna.unique_enzymes
src.owner_name = user.real_name
- user << "\blue You feel your palm heat up as the gun reads your DNA profile."
+ user << "You feel your palm heat up as the gun reads your DNA profile."
desc += "
Linked to: [user.real_name]"
return
@@ -93,7 +101,7 @@
var/obj/item/organ/external/RA = H.get_organ("r_arm")
var/active_hand = H.hand
playsound(user, 'sound/weapons/lawgiver_idfail.ogg', 40, 1)
- user << "\red You hear a soft beep from the gun and 'ID FAIL' flashes across the screen."
+ user << "You hear a soft beep from the gun and 'ID FAIL' flashes across the screen."
user << "You feel a tiny prick in your hand!"
user.drop_item()
//Blow up Unauthorized Users Hand
@@ -132,50 +140,50 @@
sel_mode = 1
projectile_type=/obj/item/projectile/bullet/pistol
fire_sound='sound/weapons/Gunshot_smg.ogg'
- usr << "\red [src.name] is now set to single shot mode."
+ usr << "[src.name] is now set to single shot mode."
else if(findtext(msg,"rapidfire"))
sel_mode = 2
projectile_type=/obj/item/projectile/bullet/pistol
fire_sound='sound/weapons/Gunshot_smg.ogg'
- usr << "\red [src.name] is now set to rapid fire mode."
+ usr << "[src.name] is now set to rapid fire mode."
else if(findtext(msg,"highex") || findtext(msg,"grenade"))
sel_mode = 3
projectile_type=/obj/item/projectile/bullet/gyro/law
fire_sound='sound/effects/Explosion1.ogg'
- usr << "\red [src.name] is now set to high explosive mode."
+ usr << "[src.name] is now set to high explosive mode."
else if(findtext(msg,"stun"))
sel_mode = 4
projectile_type=/obj/item/projectile/beam/stun
fire_sound='sound/weapons/Taser.ogg'
- usr << "\red [src.name] is now set to stun mode."
+ usr << "[src.name] is now set to stun mode."
else if(findtext(msg,"hotshot") || findtext(msg,"incendiary"))
sel_mode = 5
projectile_type=/obj/item/projectile/bullet/shotgun/incendiary
fire_sound='sound/weapons/Gunshot.ogg'
- usr << "\red [src.name] is now set to incendiary mode."
+ usr << "[src.name] is now set to incendiary mode."
else if(findtext(msg,"armorpiercing") || findtext(msg,"execution"))
sel_mode = 6
projectile_type=/obj/item/projectile/bullet/rifle/a556
fire_sound='sound/weapons/Gunshot.ogg'
- usr << "\red [src.name] is now set to armorpiercing mode."
+ usr << "[src.name] is now set to armorpiercing mode."
else if(findtext(msg,"pellets"))
sel_mode = 7
projectile_type=/obj/item/projectile/bullet/pellet/shotgun
fire_sound='sound/weapons/Gunshot.ogg'
- usr << "\red [src.name] is now set to pellet mode."
+ usr << "[src.name] is now set to pellet mode."
/* Other Stuff */
else if(findtext(msg,"reset") && (findtext(msg,"user") || findtext(msg,"dna")))
dna = null
desc = default_desc
- usr << "\red [src.name]´s owner has been reset. Do not attempt to fire [src.name] without rebinding a new owner"
+ usr << "[src.name]´s owner has been reset. Do not attempt to fire [src.name] without rebinding a new owner."
else if((findtext(msg,"disable") || findtext(msg,"deactivate")) && findtext(msg,"crowdcontrol"))
message_disable = 1
- usr << "\red [src.name]´s crowdcontrol deactivation sequence started"
+ usr << "[src.name]´s crowdcontrol deactivation sequence started."
else if((findtext(msg,"enable") || findtext(msg,"activate")) && findtext(msg,"crowdcontrol"))
if(message_enabled) //Check if a message is already broadcasting -> abort
- usr << "\red [src.name] is already broadcasting a message."
+ usr << "[src.name] is already broadcasting a message."
return
- usr << "\red [src.name]´s crowdcontrol activation sequence started"
+ usr << "[src.name]´s crowdcontrol activation sequence started."
message = "Citizens stay calm. Stand back from the crime scene. Interference with the crime scene carries an automatic brig sentence."
message_enabled = 1
message_disable = 0
diff --git a/code/modules/research/xenoarchaeology/finds/finds_special.dm b/code/modules/research/xenoarchaeology/finds/finds_special.dm
index af73f541d60..359ba673603 100644
--- a/code/modules/research/xenoarchaeology/finds/finds_special.dm
+++ b/code/modules/research/xenoarchaeology/finds/finds_special.dm
@@ -10,6 +10,7 @@
processing_objects.Add(src)
spawning_id = pick("blood","holywater","lube","stoxin","ethanol","ice","glycerol","fuel","cleaner")
+
/obj/item/weapon/reagent_containers/glass/replenishing/process()
reagents.add_reagent(spawning_id, 0.3)
@@ -23,6 +24,12 @@
/obj/item/clothing/mask/gas/poltergeist/New()
processing_objects.Add(src)
+ listening_objects += src
+
+/obj/item/clothing/mask/gas/poltergeist/Destroy()
+ processing_objects.Remove(src)
+ listening_objects -= src
+ return ..()
/obj/item/clothing/mask/gas/poltergeist/process()
if(heard_talk.len && istype(src.loc, /mob/living) && prob(10))
@@ -57,6 +64,12 @@
/obj/item/weapon/vampiric/New()
..()
processing_objects.Add(src)
+ listening_objects += src
+
+/obj/item/weapon/vampiric/Destroy()
+ processing_objects.Remove(src)
+ listening_objects -= src
+ return ..()
/obj/item/weapon/vampiric/process()
//see if we've identified anyone nearby
@@ -146,6 +159,10 @@
processing_objects.Add(src)
loc_last_process = src.loc
+/obj/effect/decal/cleanable/blood/splatter/animated/Destroy()
+ processing_objects.Remove(src)
+ return ..()
+
/obj/effect/decal/cleanable/blood/splatter/animated/process()
if(target_turf && src.loc != target_turf)
step_towards(src,target_turf)
@@ -175,6 +192,10 @@
/obj/effect/shadow_wight/New()
processing_objects.Add(src)
+/obj/effect/shadow_wight/Destroy()
+ processing_objects.Remove(src)
+ return ..()
+
/obj/effect/shadow_wight/process()
if(src.loc)
src.loc = get_turf(pick(orange(1,src)))
@@ -200,4 +221,4 @@
processing_objects.Remove(src)
/obj/effect/shadow_wight/Bump(var/atom/obstacle)
- obstacle << "\red You feel a chill run down your spine!"
+ obstacle << "You feel a chill run down your spine!"
diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm
index 121850dac55..70fde119120 100644
--- a/code/modules/surgery/organs_internal.dm
+++ b/code/modules/surgery/organs_internal.dm
@@ -101,7 +101,7 @@
/datum/surgery_step/internal/detatch_organ
allowed_tools = list(
- /obj/item/weapon/scalpel = 100,
+ /obj/item/weapon/scalpel = 100,
/obj/item/weapon/material/knife = 75,
/obj/item/weapon/material/shard = 50
)
@@ -342,6 +342,49 @@
"Your hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!")
affected.createwound(BRUISE, 20)
+/datum/surgery_step/internal/lobotomize
+ allowed_tools = list(
+ /obj/item/weapon/scalpel/manager = 95,
+ /obj/item/weapon/surgicaldrill = 75,
+ /obj/item/weapon/pickaxe/ = 5
+ )
+
+ min_duration = 100
+ max_duration = 120
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+
+ if (!..())
+ return 0
+
+ target.op_stage.current_organ = null
+
+ var/obj/item/organ/brain/sponge = target.internal_organs_by_name["brain"]
+ if(sponge && sponge.can_lobotomize && !sponge.lobotomized)
+ target.op_stage.current_organ = sponge
+ return ..()
+ else
+ return 0
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/brain/B = target.op_stage.current_organ
+ user.visible_message("[user] begins lobotomizing [target]'s [B.name] with \the [tool].", \
+ "You start lobotomizing [target]'s [B.name] with \the [tool].")
+ target.custom_pain("Someone's scraping away at your [B.name]!",1)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/brain/B = target.op_stage.current_organ
+ user.visible_message("[user] has lobotomized [target]'s \the [B.name] with \the [tool]." , \
+ "You have lobotomized [target]'s [B.name] with \the [tool].")
+ B.lobotomize(user)
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user]'s hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!", \
+ "Your hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!")
+ affected.createwound(BRUISE, 20)
+
//////////////////////////////////////////////////////////////////
// HEART SURGERY //
//////////////////////////////////////////////////////////////////
diff --git a/html/changelog.html b/html/changelog.html
index d8c5873886f..f5ef44ab3a1 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -56,6 +56,24 @@
-->