Merge remote-tracking branch 'upstream/master' into so-edgey

This commit is contained in:
Fox-McCloud
2017-07-01 20:17:16 -04:00
71 changed files with 648 additions and 572 deletions
@@ -2154,7 +2154,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
else if(status == "cyborg")
if(rlimb_data[name])
O.robotize(rlimb_data[name])
O.robotize(rlimb_data[name], convert_all = 0)
else
O.robotize()
else
@@ -978,10 +978,6 @@
else
M.stop_pulling()
if(wearer.pinned.len)
to_chat(src, "<span class='notice'>Your host is pinned to a wall by [wearer.pinned[1]]</span>!")
return 0
// AIs are a bit slower than regular and ignore move intent.
wearer_move_delay = world.time + ai_controlled_move_delay
+3 -3
View File
@@ -952,17 +952,17 @@
/obj/item/clothing/suit/tailcoat
name = "victorian tailcoat"
desc = "a fancy victorian tailcoat."
desc = "A fancy victorian tailcoat."
icon_state = "tailcoat"
item_state = "tailcoat"
/obj/item/clothing/suit/victcoat
name = "ladies victorian coat"
desc = "a fancy victorian coat."
desc = "A fancy victorian coat."
icon_state = "ladiesvictoriancoat"
item_state = "ladiesvictoriancoat"
/obj/item/clothing/suit/victcoat/red
name = "ladies red victorian coat"
icon_state = "ladiesredvictoriancoat"
item_state = "ladiesredvictoriancoat"
item_state = "ladiesredvictoriancoat"
+4 -4
View File
@@ -791,10 +791,10 @@
/obj/item/clothing/under/victdress
name = "black victorian dress"
desc = "a victorian style dress, fancy!."
desc = "A victorian style dress, fancy!"
icon_state = "victorianblackdress"
item_state = "Victorianblackdress"
item_color = "Victorianblackdress"
item_state = "victorianblackdress"
item_color = "victorianblackdress"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
/obj/item/clothing/under/victdress/red
@@ -805,7 +805,7 @@
/obj/item/clothing/under/victsuit
name = "victorian suit"
desc = "a victorian style suit, fancy!."
desc = "A victorian style suit, fancy!"
icon_state = "victorianvest"
item_state = "victorianvest"
item_color = "victorianvest"
+1
View File
@@ -137,6 +137,7 @@ var/list/event_last_fired = list()
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Sentience", /datum/event/sentience, 50),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50))
)
+47
View File
@@ -0,0 +1,47 @@
/datum/event/sentience
/datum/event/sentience/start()
var/ghostmsg = "Do you want to awaken as a sentient being?"
var/list/candidates = pollCandidates(ghostmsg, ROLE_SENTIENT, 1)
var/list/potential = list()
var/sentience_type = SENTIENCE_ORGANIC
for(var/mob/living/simple_animal/L in living_mob_list)
var/turf/T = get_turf(L)
if (T.z != 1)
continue
if(!(L in player_list) && !L.mind && (L.sentience_type == sentience_type))
potential += L
var/mob/living/simple_animal/SA = pick(potential)
var/mob/SG = pick(candidates)
if(!SA || !SG) //if you can't find either a simple animal or a player, end
return FALSE
var/sentience_report = "<font size=3><b>[command_name()] Medium-Priority Update</b></font>"
var/data = pick("scans from our long-range sensors", "our sophisticated probabilistic models", "our omnipotence", "the communications traffic on your station", "energy emissions we detected", "\[REDACTED\]", "Steve")
var/pets = pick("animals", "pets", "simple animals", "lesser lifeforms", "\[REDACTED\]")
var/strength = pick("human", "skrell", "vox", "grey", "diona", "IPC", "tajaran", "vulpakanin", "kidan", "plasmaman", "drask",
"slime", "monkey", "moderate", "lizard", "security", "command", "clown", "mime", "low", "very low", "greytide", "catgirl", "\[REDACTED\]")
sentience_report += "<br><br>Based on [data], we believe that one of the station's [pets] has developed [strength] level intelligence, and the ability to communicate."
SA.key = SG.key
SA.universal_speak = 1
SA.sentience_act()
SA.maxHealth = max(SA.maxHealth, 200)
SA.health = SA.maxHealth
SA.del_on_death = FALSE
greet_sentient(SA)
print_command_report(sentience_report, "[command_name()] Update")
/datum/event/sentience/proc/greet_sentient(var/mob/living/carbon/human/M)
to_chat(M, "<span class='userdanger'>Hello world!</span>")
to_chat(M, "<span class='warning'>Due to freak radiation, you have gained \
human level intelligence and the ability to speak and understand \
human language!</span>")
+27 -1
View File
@@ -96,6 +96,9 @@
return (copytext(message, length(message)) == "!") ? 2 : 1
/datum/language/proc/broadcast(mob/living/speaker, message, speaker_mask)
if(!check_can_speak(speaker))
return FALSE
log_say("[key_name(speaker)]: ([name]) [message]")
if(!speaker_mask)
@@ -114,6 +117,9 @@
/datum/language/proc/check_special_condition(mob/other, mob/living/speaker)
return TRUE
/datum/language/proc/check_can_speak(mob/living/speaker)
return TRUE
/datum/language/proc/get_spoken_verb(msg_end)
switch(msg_end)
if("!")
@@ -290,10 +296,30 @@
flags = RESTRICTED | HIVEMIND
/datum/language/grey/broadcast(mob/living/speaker, message, speaker_mask)
var/their = "their"
if(speaker.gender == "female")
their = "her"
if(speaker.gender == "male")
their = "his"
speaker.visible_message("<span class='notice'>[speaker] touches [their] fingers to [their] temple.</span>")
..(speaker,message,speaker.real_name)
/datum/language/grey/check_can_speak(mob/living/speaker)
if(ishuman(speaker))
var/mob/living/carbon/human/S = speaker
var/obj/item/organ/external/rhand = S.get_organ("r_hand")
var/obj/item/organ/external/lhand = S.get_organ("l_hand")
if((!rhand || !rhand.is_usable()) && (!lhand || !lhand.is_usable()))
to_chat(speaker,"<span class='warning'>You can't communicate without the ability to use your hands!</span>")
return FALSE
if(speaker.incapacitated(ignore_lying = 1))
to_chat(speaker,"<span class='warning'>You can't communicate while unable to move your hands to your head!</span>")
return FALSE
return TRUE
/datum/language/grey/check_special_condition(mob/living/carbon/human/other, mob/living/carbon/human/speaker)
if(other in range(7, speaker))
if(atoms_share_level(other, speaker))
return TRUE
return FALSE
@@ -71,9 +71,9 @@
var/obj/item/organ/internal/brain/B = src
if(!special)
var/mob/living/simple_animal/borer/borer = owner.has_brain_worms()
if(borer)
borer.detach() //Should remove borer if the brain is removed - RR
borer.leave_host() //Should remove borer if the brain is removed - RR
if(owner.mind && !non_primary)//don't transfer if the owner does not have a mind.
B.transfer_identity(user)
+4
View File
@@ -244,6 +244,10 @@
if(status == "")
status = "OK"
src.show_message(text("\t []My [] is [].",status=="OK"?"<span class='notice'></span>":"<span class='warning'></span>",org.name,status),1)
for(var/obj/item/I in org.embedded_objects)
to_chat(src, "\t <a href='byond://?src=[UID()];embedded_object=[I.UID()];embedded_limb=[org.UID()]' class='warning'>There is \a [I] embedded in your [org.name]!</a>")
if(staminaloss)
if(staminaloss > 30)
to_chat(src, "<span class='info'>You're completely exhausted.</span>")
+6 -17
View File
@@ -90,8 +90,10 @@
if(src) qdel(src)
/mob/living/carbon/human/death(gibbed)
if(stat == DEAD) return
if(healths) healths.icon_state = "health5"
if(stat == DEAD)
return
if(healths)
healths.icon_state = "health5"
if(!gibbed)
emote("deathgasp") //let the world KNOW WE ARE DEAD
@@ -102,21 +104,8 @@
set_heartattack(FALSE)
//Handle species-specific deaths.
if(species) species.handle_death(src)
//Handle brain slugs.
var/obj/item/organ/external/head = get_organ("head")
var/mob/living/simple_animal/borer/B
if(istype(head))
for(var/I in head.implants)
if(istype(I,/mob/living/simple_animal/borer))
B = I
if(B)
if(B.controlling && B.host == src)
B.detach()
verbs -= /mob/living/carbon/proc/release_control
if(species)
species.handle_death(src)
callHook("death", list(src, gibbed))
@@ -382,6 +382,9 @@
else
wound_flavor_text["[temp.limb_name]"] = ""
for(var/obj/item/I in temp.embedded_objects)
msg += "<B>[t_He] [t_has] \a [bicon(I)] [I] embedded in [t_his] [temp.name]!</B>\n"
//Handles the text strings being added to the actual description.
//If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext.
var/display_chest = 0
@@ -438,9 +441,6 @@
if(display_gloves)
msg += "<span class='warning'><b>[src] has blood running from under [t_his] gloves!</b></span>\n"
for(var/implant in get_visible_implants(0))
msg += "<span class='warning'><b>[src] has \a [implant] sticking out of [t_his] flesh!</b></span>\n"
if(digitalcamo)
msg += "[t_He] [t_is] repulsively uncanny!\n"
if(!(skipface || ( wear_mask && ( wear_mask.flags_inv & HIDEFACE || wear_mask.flags_cover & MASKCOVERSMOUTH) ) ) && is_thrall(src) && in_range(user,src))
+22 -34
View File
@@ -8,7 +8,6 @@
//why are these here and not in human_defines.dm
//var/list/hud_list[10]
var/datum/species/species //Contains icon generation and language information, set during New().
var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us.
var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call.
/mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna = 0)
@@ -700,6 +699,28 @@
if(G && G.pickpocket)
thief_mode = 1
if(href_list["embedded_object"])
var/obj/item/organ/external/L = locate(href_list["embedded_limb"]) in bodyparts
if(!L)
return
var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
return
var/time_taken = I.embedded_unsafe_removal_time*I.w_class
usr.visible_message("<span class='warning'>[usr] attempts to remove [I] from their [L.name].</span>","<span class='notice'>You attempt to remove [I] from your [L.name]... (It will take [time_taken/10] seconds.)</span>")
if(do_after(usr, time_taken, needhand = 1, target = src))
if(!I || !L || I.loc != src || !(I in L.embedded_objects))
return
L.embedded_objects -= I
L.take_damage(I.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus.
I.forceMove(get_turf(src))
usr.put_in_hands(I)
usr.emote("scream")
usr.visible_message("[usr] successfully rips [I] out of their [L.name]!","<span class='notice'>You successfully remove [I] from your [L.name].</span>")
if(!has_embedded_objects())
clear_alert("embeddedobject")
return
if(href_list["item"])
var/slot = text2num(href_list["item"])
if(slot in check_obscured_slots())
@@ -1348,16 +1369,6 @@
else
..()
/mob/living/carbon/human/get_visible_implants(var/class = 0)
var/list/visible_implants = list()
for(var/obj/item/organ/external/organ in bodyparts)
for(var/obj/item/weapon/O in organ.implants)
if(!istype(O,/obj/item/weapon/implant) && (O.w_class > class) && !istype(O,/obj/item/weapon/shard/shrapnel))
visible_implants += O
return(visible_implants)
/mob/living/carbon/human/generate_name()
name = species.makeName(gender,src)
real_name = name
@@ -1365,29 +1376,6 @@
dna.real_name = name
return name
/mob/living/carbon/human/proc/handle_embedded_objects()
for(var/obj/item/organ/external/organ in bodyparts)
if(organ.status & ORGAN_SPLINTED) //Splints prevent movement.
continue
for(var/obj/item/weapon/O in organ.implants)
if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad.
// All kinds of embedded objects cause bleeding.
var/msg = null
switch(rand(1,3))
if(1)
msg ="<span class='warning'>A spike of pain jolts your [organ.name] as you bump [O] inside.</span>"
if(2)
msg ="<span class='warning'>Your movement jostles [O] in your [organ.name] painfully.</span>"
if(3)
msg ="<span class='warning'>[O] in your [organ.name] twists painfully as you move.</span>"
to_chat(src, msg)
organ.take_damage(rand(1,3), 0, 0)
if(!(organ.status & ORGAN_ROBOT)) //There is no blood in protheses.
organ.status |= ORGAN_BLEEDING
src.adjustToxLoss(rand(1,3))
/mob/living/carbon/human/verb/check_pulse()
set category = null
set name = "Check pulse"
@@ -8,7 +8,7 @@ emp_act
*/
/mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone)
/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone)
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
@@ -41,19 +41,6 @@ emp_act
. = bullet_act(P, "chest") //act on chest instead
return
//Shrapnel
if(P.damage_type == BRUTE)
var/armor = getarmor_organ(organ, "bullet")
if((P.embed && prob(20 + max(P.damage - armor, -10))))
var/obj/item/weapon/shard/shrapnel/SP = new()
(SP.name) = "[P.name] shrapnel"
if(P.ammo_casing && P.ammo_casing.caliber)
(SP.desc) = "[SP.desc] It looks like it is a [P.ammo_casing.caliber] caliber round."
else
(SP.desc) = "[SP.desc] The round's caliber is unidentifiable."
(SP.loc) = organ
organ.embed(SP)
organ.add_autopsy_data(P.name, P.damage) // Add the bullet's name to the autopsy data
return (..(P , def_zone))
@@ -295,21 +282,6 @@ emp_act
if(Iforce > 10 || Iforce >= 5 && prob(33))
forcesay(hit_appends) //forcesay checks stat already
/* //Melee weapon embedded object code. Commented out, as most people on the forums seem to find this annoying and think it does not contribute to general gameplay. - Dave
if(I.damtype == BRUTE && !I.is_robot_module())
var/damage = I.force
if(armor)
damage /= armor+1
//blunt objects should really not be embedding in things unless a huge amount of force is involved
var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
//Sharp objects will always embed if they do enough damage.
if(((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance))) && (I.no_embed == 0) )
affecting.embed(I)
return 1*/
//this proc handles being hit by a thrown atom
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
var/obj/item/I
@@ -323,24 +295,19 @@ emp_act
hitpush = 0
skipcatch = 1
blocked = 1
/*else if(I)
else if(I)
if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD)
if(!I.is_robot_module())
var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].", I.armour_penetration) //I guess "melee" is the best fit here
var/sharp = is_sharp(I)
var/damage = throwpower * (I.throw_speed / 5)
if(armor)
damage /= armor + 1
//blunt objects should really not be embedding in things unless a huge amount of force is involved
var/embed_chance = sharp? damage / I.w_class : damage/(I.w_class * 3)
var/embed_threshold = sharp? 5 * I.w_class : 15 * I.w_class
//Sharp objects will always embed if they do enough damage.
//Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold
if(((sharp && prob(damage / (10 * I.w_class) * 100)) || (damage > embed_threshold && prob(embed_chance))) && (I.no_embed == 0))
affecting.embed(I)*/
if(can_embed(I))
if(prob(I.embed_chance))
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
var/obj/item/organ/external/L = pick(bodyparts)
L.embedded_objects |= I
// I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
I.forceMove(src)
L.take_damage(I.w_class*I.embedded_impact_pain_multiplier)
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
hitpush = 0
skipcatch = 1 //can't catch the now embedded item
return ..()
/mob/living/carbon/human/proc/bloody_hands(var/mob/living/source, var/amount = 2)
@@ -419,5 +386,5 @@ emp_act
/mob/living/carbon/human/water_act(volume, temperature, source)
..()
if(temperature >= 330) bodytemperature = bodytemperature + (temperature - bodytemperature)
if(temperature <= 280) bodytemperature = bodytemperature - (bodytemperature - temperature)
species.water_act(src,volume,temperature,source)
+20 -7
View File
@@ -40,6 +40,10 @@
if(!client)
species.handle_npc(src)
if(stat != DEAD)
//Stuff jammed in your limbs hurts
handle_embedded_objects()
if(stat == DEAD)
handle_decay()
@@ -813,13 +817,6 @@
blinded = 1
stat = UNCONSCIOUS
if(embedded_flag && !(mob_master.current_cycle % 10))
var/list/E
E = get_visible_implants(0)
if(!E.len)
embedded_flag = 0
//Vision //god knows why this is here
var/obj/item/organ/vision
if(species.vision_organ)
@@ -932,6 +929,22 @@
adjustToxLoss(-3)
lastpuke = 0
/mob/living/carbon/human/proc/handle_embedded_objects()
for(var/X in bodyparts)
var/obj/item/organ/external/BP = X
for(var/obj/item/I in BP.embedded_objects)
if(prob(I.embedded_pain_chance))
BP.take_damage(I.w_class*I.embedded_pain_multiplier)
to_chat(src, "<span class='userdanger'>[I] embedded in your [BP.name] hurts!</span>")
if(prob(I.embedded_fall_chance))
BP.take_damage(I.w_class*I.embedded_fall_pain_multiplier)
BP.embedded_objects -= I
I.forceMove(get_turf(src))
visible_message("<span class='danger'>[I] falls out of [name]'s [BP.name]!</span>","<span class='userdanger'>[I] falls out of your [BP.name]!</span>")
if(!has_embedded_objects())
clear_alert("embeddedobject")
/mob/living/carbon/human/handle_changeling()
if(mind)
if(mind.changeling)
@@ -399,9 +399,6 @@
if(has_gravity(H))
gravity = 1
if(H.embedded_flag)
H.handle_embedded_objects() //Moving with objects stuck in you can cause bad times.
if(!ignoreslow && gravity)
if(slowdown)
. = slowdown
@@ -741,3 +738,9 @@ It'll return null if the organ doesn't correspond, so include null checks when u
if(H.see_override) //Override all
H.see_invisible = H.see_override
/datum/species/proc/water_act(mob/living/carbon/human/M, volume, temperature, source)
if(temperature >= 330)
M.bodytemperature = M.bodytemperature + (temperature - M.bodytemperature)
if(temperature <= 280)
M.bodytemperature = M.bodytemperature - (M.bodytemperature - temperature)
@@ -753,6 +753,11 @@
genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED)
..()
/datum/species/grey/water_act(var/mob/living/carbon/C, volume, temperature, source)
..()
C.take_organ_damage(5,min(volume,20))
C.emote("scream")
/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H)
var/speech_pref = H.client.prefs.speciesprefs
if(speech_pref)
+1
View File
@@ -512,6 +512,7 @@
human_mob.restore_blood()
human_mob.shock_stage = 0
human_mob.decaylevel = 0
human_mob.remove_all_embedded_objects()
restore_all_organs()
surgeries.Cut() //End all surgeries.
@@ -260,10 +260,6 @@
stored_comms["glass"]++
else if(istype(W,/obj/item/ammo_casing))
stored_comms["metal"]++
else if(istype(W,/obj/item/weapon/shard/shrapnel))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["metal"]++
else if(istype(W,/obj/item/weapon/shard))
stored_comms["glass"]++
stored_comms["glass"]++
-98
View File
@@ -1052,104 +1052,6 @@ var/list/slot_equipment_priority = list( \
/mob/proc/get_species()
return ""
/mob/proc/get_visible_implants(var/class = 0)
var/list/visible_implants = list()
for(var/obj/item/O in embedded)
if(O.w_class > class)
visible_implants += O
return visible_implants
/mob/proc/yank_out_object()
set category = "Object"
set name = "Yank out object"
set desc = "Remove an embedded item at the cost of bleeding and pain."
set src in view(1)
if(!isliving(usr) || usr.next_move > world.time)
return
usr.changeNext_move(CLICK_CD_RESIST)
if(usr.stat == 1)
to_chat(usr, "You are unconcious and cannot do that!")
return
if(usr.restrained())
to_chat(usr, "You are restrained and cannot do that!")
return
var/mob/S = src
var/mob/U = usr
var/list/valid_objects = list()
var/self = null
if(S == U)
self = 1 // Removing object from yourself.
valid_objects = get_visible_implants(0)
if(!valid_objects.len)
if(self)
to_chat(src, "You have nothing stuck in your body that is large enough to remove.")
else
to_chat(U, "[src] has nothing stuck in their wounds that is large enough to remove.")
return
var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects
if(self)
visible_message("<span class='warning'>[usr] appears to be trying to extract an object from their body.</span>")
to_chat(src, "<span class='warning'>You attempt to get a good grip on [selection] in your body.</span>")
else
visible_message("<span class='warning'>[usr] attempts to get a good grip on [selection] in [S]'s body.</span>")
to_chat(U, "<span class='warning'>You attempt to get a good grip on [selection] in [S]'s body.</span>")
if(!do_after(U, 80, target = S))
return
if(!selection || !S || !U)
return
if(self)
visible_message("<span class='warning'><b>[src] rips [selection] out of their body.</b></span>","<span class='warning'><b>You rip [selection] out of your body.</b></span>")
else
visible_message("<span class='warning'><b>[usr] rips [selection] out of [src]'s body.</b></span>","<span class='warning'><b>[usr] rips [selection] out of your body.</b></span>")
valid_objects = get_visible_implants(0)
if(valid_objects.len == 1) //Yanking out last object - removing verb.
src.verbs -= /mob/proc/yank_out_object
if(ishuman(src))
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/affected
for(var/obj/item/organ/external/organ in H.bodyparts) //Grab the organ holding the implant.
for(var/obj/item/weapon/O in organ.implants)
if(O == selection)
affected = organ
affected.implants -= selection
H.shock_stage+=10
if(prob(10)) //I'M SO ANEMIC I COULD JUST -DIE-.
var/datum/wound/internal_bleeding/I = new ()
affected.wounds += I
H.custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 1)
if(ishuman(U))
var/mob/living/carbon/human/human_user = U
human_user.bloody_hands(H)
selection.forceMove(get_turf(src))
if(!(U.l_hand && U.r_hand))
U.put_in_hands(selection)
for(var/obj/item/weapon/O in pinned)
if(O == selection)
pinned -= O
if(!pinned.len)
anchored = 0
return 1
/mob/dead/observer/verb/respawn()
set name = "Respawn as NPC"
set category = "Ghost"
-2
View File
@@ -53,8 +53,6 @@
var/lastpuke = 0
var/unacidable = 0
var/can_strip = 1
var/list/pinned = list() //List of things pinning this creature to walls (see living_defense.dm)
var/list/embedded = list() //Embedded items, since simple mobs don't have organs.
var/list/languages = list() // For speaking/listening.
var/list/abilities = list() // For species-derived or admin-given powers.
var/list/speak_emote = list("says") // Verbs used when speaking. Defaults to 'say' if speak_emote is null.
@@ -43,7 +43,7 @@
if(!istype(file))
data["error"] = "I/O ERROR: Unable to open file."
else
data["filedata"] = pencode_to_html(file.stored_data, sign = 0, fields = 0)
data["filedata"] = pencode_to_html(file.stored_data, format = 1, sign = 0, fields = 0)
data["filename"] = "[file.filename].[file.filetype]"
else
if(!computer || !HDD)
+1 -1
View File
@@ -203,7 +203,7 @@
/obj/item/weapon/paper/proc/parsepencode(var/t, var/obj/item/weapon/pen/P, mob/user as mob)
t = pencode_to_html(t, usr, P, TRUE, TRUE, deffont, signfont, crayonfont)
t = pencode_to_html(t, usr, P, TRUE, TRUE, TRUE, deffont, signfont, crayonfont)
//Count the fields
var/laststart = 1
+2
View File
@@ -158,6 +158,7 @@
w_class = initial(w_class)
name = initial(name)
hitsound = initial(hitsound)
embed_chance = initial(embed_chance)
throwforce = initial(throwforce)
playsound(user, 'sound/weapons/saberoff.ogg', 5, 1)
to_chat(user, "<span class='warning'>[src] can now be concealed.</span>")
@@ -168,6 +169,7 @@
w_class = WEIGHT_CLASS_NORMAL
name = "energy dagger"
hitsound = 'sound/weapons/blade1.ogg'
embed_chance = 100 //rule of cool
throwforce = 35
playsound(user, 'sound/weapons/saberon.ogg', 5, 1)
to_chat(user, "<span class='warning'>[src] is now active.</span>")
-1
View File
@@ -99,6 +99,5 @@
flag = "bullet"
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
embed = 0
weaken = 5
stun = 5
@@ -169,8 +169,6 @@
/obj/item/weapon/arrow/rod/removed()
if(superheated) // The rod has been superheated - we don't want it to be useable when removed from the bow.
visible_message("[src] shatters into a scattering of overstressed metal shards as it leaves the crossbow.")
var/obj/item/weapon/shard/shrapnel/S = new /obj/item/weapon/shard/shrapnel
S.loc = get_turf(src)
qdel(src)
#undef XBOW_TENSION_20
-1
View File
@@ -48,7 +48,6 @@
var/drowsy = 0
var/stamina = 0
var/jitter = 0
var/embed = 0 // whether or not the projectile can embed itself in the mob
var/forcedodge = 0 //to pass through everything
var/dismemberment = 0 //The higher the number, the greater the bonus to dismembering. 0 will not dismember at all.
@@ -4,7 +4,6 @@
damage = 60
damage_type = BRUTE
flag = "bullet"
embed = 1
hitsound_wall = "ricochet"
/obj/item/projectile/bullet/weakbullet //beanbag, heavy stamina damage
@@ -13,10 +12,8 @@
stamina = 80
/obj/item/projectile/bullet/weakbullet/rubber //beanbag that shells that don't embed
embed = 0
/obj/item/projectile/bullet/weakbullet/booze
embed = 0
/obj/item/projectile/bullet/weakbullet/booze/on_hit(atom/target, blocked = 0)
if(..(target, blocked))
@@ -43,7 +40,6 @@
icon_state = "bullet-r"
/obj/item/projectile/bullet/weakbullet2/rubber //detective's bullets that don't embed
embed = 0
/obj/item/projectile/bullet/weakbullet3
damage = 20
@@ -53,7 +49,6 @@
damage = 5
stamina = 30
icon_state = "bullet-r"
embed = 0
/obj/item/projectile/bullet/toxinbullet
damage = 15
@@ -141,7 +136,6 @@
name = "rubber pellet"
damage = 3
stamina = 25
embed = 0
icon_state = "bullet-r"
/obj/item/projectile/bullet/stunshot//taser slugs for shotguns, nothing special
@@ -152,7 +146,6 @@
stutter = 5
jitter = 20
range = 7
embed = 0
icon_state = "spark"
color = "#FFFF00"
@@ -203,7 +196,6 @@
stun = 5
forcedodge = 1
nodamage = 1
embed = 0
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
hitsound = 'sound/items/bikehorn.ogg'
icon = 'icons/obj/hydroponics/harvest.dmi'
@@ -237,7 +229,6 @@
name = "dart"
icon_state = "cbbolt"
damage = 6
embed = 0
var/piercing = 0
/obj/item/projectile/bullet/dart/New()
@@ -299,7 +290,6 @@
name = "cap"
damage = 0
nodamage = 1
embed = 0
/obj/item/projectile/bullet/cap/fire()
loc = null
@@ -4,7 +4,6 @@
icon_state = "ice_1"
damage = 20
flag = "energy"
embed = 1
/obj/item/projectile/forcebolt/strong
name = "force bolt"
@@ -35,7 +35,6 @@
ammo_type = /obj/item/ammo_casing/caseless/foam_dart
range = 10
var/obj/item/weapon/pen/pen = null
embed = 0
log_override = TRUE//it won't log even when there's a pen inside, but since the damage will be so low, I don't think there's any point in making it any more complex
/obj/item/projectile/bullet/reusable/foam_dart/handle_drop()
@@ -20,10 +20,65 @@
drink_desc = "The father of all refreshments."
/datum/reagent/water/reaction_mob(mob/living/M, method=TOUCH, volume)
// Put out fire
if(method == TOUCH)
// Put out fire
M.adjust_fire_stacks(-(volume / 10))
M.ExtinguishMob()
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.get_species() != "Grey") //God this is so gross I hate it.
return
if(volume > 25)
if(H.wear_mask)
to_chat(H, "<span class='danger'>Your mask protects you from the water!</span>")
return
if(H.head)
to_chat(H, "<span class='danger'>Your helmet protects you from the water!</span>")
return
if(!M.unacidable)
if(prob(75))
var/obj/item/organ/external/affecting = H.get_organ("head")
if(affecting)
affecting.take_damage(5, 10)
H.UpdateDamageIcon()
H.emote("scream")
else
M.take_organ_damage(5,10)
else
M.take_organ_damage(5,10)
if(method == INGEST)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.get_species() != "Grey")
return
if(volume < 10)
to_chat(M, "<span class='danger'>The watery solvent substance stings you, but isn't concentrated enough to harm you!</span>")
if(volume >=10 && volume <=25)
if(!H.unacidable)
M.take_organ_damage(0,min(max(volume-10,2)*2,20))
M.emote("scream")
if(volume > 25)
if(!M.unacidable)
if(prob(75))
var/obj/item/organ/external/affecting = H.get_organ("head")
if(affecting)
affecting.take_damage(0, 20)
H.UpdateDamageIcon()
H.emote("scream")
else
M.take_organ_damage(0,20)
/datum/reagent/water/reaction_turf(turf/simulated/T, volume)
if(!istype(T))
@@ -1,10 +1,3 @@
//Procedures in this file: Putting items in body cavity. Implant removal. Items removal.
//////////////////////////////////////////////////////////////////
// ITEM PLACEMENT SURGERY //
//////////////////////////////////////////////////////////////////
/datum/surgery/cavity_implant
name = "Cavity Implant/Removal"
steps = list(/datum/surgery_step/generic/cut_open,/datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/open_encased/saw,
@@ -199,198 +192,15 @@
affected.wounds += I
affected.owner.custom_pain("You feel something rip in your [affected.name]!", 1)
user.drop_item()
target.internal_organs += tool
affected.hidden = tool
tool.forceMove(affected)
return 1
else
if(IC)
user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "<span class='notice'>You pull [IC] out of [target]'s [target_zone].</span>")
user.put_in_hands(IC)
target.internal_organs -= IC
affected.hidden = null
return 1
else
to_chat(user, "<span class='warning'>You don't find anything in [target]'s [target_zone].</span>")
return 0
//////////////////////////////////////////////////////////////////
// IMPLANT/ITEM REMOVAL SURGERY //
//////////////////////////////////////////////////////////////////
/datum/surgery/cavity_implant_rem
name = "Implant Removal"
steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin,/datum/surgery_step/cavity/implant_removal,/datum/surgery_step/cavity/close_space,/datum/surgery_step/generic/cauterize/)
possible_locs = list("chest")//head is for borers..i can put it elsewhere
/datum/surgery/cavity_implant_rem/synth
name = "Implant Removal"
steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/cavity/implant_removal,/datum/surgery_step/robotics/external/close_hatch)
possible_locs = list("chest")//head is for borers..i can put it elsewhere
/datum/surgery/cavity_implant_rem/can_start(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
if(!affected)
return 0
if(affected.status & ORGAN_ROBOT)
return 0
return 1
/datum/surgery/cavity_implant_rem/synth/can_start(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
if(!affected)
return 0
if(!(affected.status & ORGAN_ROBOT))
return 0
return 1
/datum/surgery_step/cavity/implant_removal
name = "extract implant"
allowed_tools = list(
/obj/item/weapon/hemostat = 100, \
/obj/item/weapon/wirecutters = 75, \
/obj/item/weapon/kitchen/utensil/fork = 20
)
var/obj/item/weapon/implant/I = null
time = 64
/datum/surgery_step/cavity/implant_removal/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
I = locate(/obj/item/weapon/implant) in target
user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \
"You start poking around inside [target]'s [affected.name] with \the [tool]." )
target.custom_pain("The pain in your [affected.name] is living hell!",1)
..()
/datum/surgery_step/cavity/implant_removal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
I = locate(/obj/item/weapon/implant) in target
if(I && (target_zone == "chest")) //implant removal only works on the chest.
user.visible_message("<span class='notice'>[user] takes something out of [target]'s [affected.name] with \the [tool].</span>", \
"<span class='notice'>You take [I] out of [target]'s [affected.name]s with \the [tool].</span>" )
I.removed(target)
var/obj/item/weapon/implantcase/case
if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase))
case = user.get_item_by_slot(slot_l_hand)
else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase))
case = user.get_item_by_slot(slot_r_hand)
else
case = locate(/obj/item/weapon/implantcase) in get_turf(target)
if(case && !case.imp)
case.imp = I
I.loc = case
case.update_icon()
user.visible_message("[user] places [I] into [case]!", "<span class='notice'>You place [I] into [case].</span>")
else
qdel(I)
return 1
else
user.visible_message("<span class='notice'> [user] could not find anything inside [target]'s [affected.name], and pulls \the [tool] out.</span>", \
"<span class='notice'>You could not find anything inside [target]'s [affected.name].</span>")
return 1
/datum/surgery_step/cavity/implant_removal/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
..()
var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
if(affected.implants.len)
var/fail_prob = 10
fail_prob += 100 - tool_quality(tool)
if(prob(fail_prob))
var/obj/item/weapon/implant/imp = affected.implants[1]
user.visible_message("<span class='warning'> Something beeps inside [target]'s [affected.name]!</span>")
playsound(imp.loc, 'sound/items/countdown.ogg', 75, 1, -3)
spawn(25)
imp.activate()
return 0
//////////////////////////////////////////////////////////////////
// EMBEDDED ITEM REOMOVAL //
//////////////////////////////////////////////////////////////////
/datum/surgery/embedded_removal
name = "Removal of Embedded Objects"
steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/remove_object, /datum/surgery_step/generic/cauterize)
possible_locs = list("r_arm","l_arm","r_leg","l_leg","r_hand","r_foot","l_hand","l_foot","groin","chest","head")
/datum/surgery/embedded_removal/synth
steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch, /datum/surgery_step/remove_object, /datum/surgery_step/robotics/external/close_hatch)
possible_locs = list("r_arm","l_arm","r_leg","l_leg","r_hand","r_foot","l_hand","l_foot","groin","chest","head")
/datum/surgery/embedded_removal/can_start(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
if(!affected)
return 0
if(affected.status & ORGAN_ROBOT)
return 0
return 1
/datum/surgery/embedded_removal/synth/can_start(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
if(!affected)
return 0
if(!(affected.status & ORGAN_ROBOT))
return 0
return 1
/datum/surgery_step/remove_object
name = "remove embedded objects"
time = 32
allowed_tools = list(
/obj/item/weapon/scalpel/laser/manager = 100, \
/obj/item/weapon/hemostat = 100, \
/obj/item/stack/cable_coil = 75, \
/obj/item/device/assembly/mousetrap = 20
)
var/obj/item/organ/external/L = null
/datum/surgery_step/remove_object/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery)
L = target.get_organ(target_zone)
if(L)
user.visible_message("[user] looks for objects embedded in [target]'s [target_zone].", "<span class='notice'>You look for objects embedded in [target]'s [target_zone]...</span>")
else
user.visible_message("[user] looks for [target]'s [target_zone].", "<span class='notice'>You look for [target]'s [target_zone]...</span>")
/datum/surgery_step/remove_object/end_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(L)
if(ishuman(target))
var/mob/living/carbon/human/H = target
var/objects = 0
for(var/obj/item/I in L.implants)
if(!istype(I,/obj/item/weapon/implant))
objects++
I.forceMove(get_turf(H))
L.implants -= I
//Handle possessive brain borers.
if(H.has_brain_worms() && target_zone == "head")//remove worms outside the loop
var/mob/living/simple_animal/borer/worm = H.has_brain_worms()
if(worm.controlling)
target.release_control()
worm.detach()
worm.leave_host()
user.visible_message("a slug like creature wiggles out of [H]'s [target_zone]!")
if(objects > 0)
user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L.limb_name]!", "<span class='notice'>You sucessfully remove [objects] objects from [H]'s [L.limb_name].</span>")
else
to_chat(user, "<span class='warning'>You find no objects embedded in [H]'s [L.limb_name]!</span>")
else
to_chat(user, "<span class='warning'>You can't find [target]'s [target_zone], let alone any objects embedded in it!</span>")
return 1
return 0
+78
View File
@@ -0,0 +1,78 @@
//////////////////////////////////////////////////////////////////
// IMPLANT REMOVAL SURGERY //
//////////////////////////////////////////////////////////////////
/datum/surgery/implant_removal
name = "Implant Removal"
steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin,/datum/surgery_step/extract_implant,/datum/surgery_step/generic/cauterize)
possible_locs = list("chest")
/datum/surgery/implant_removal/synth
name = "Implant Removal"
steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/extract_implant,/datum/surgery_step/robotics/external/close_hatch)
possible_locs = list("chest")
/datum/surgery/implant_removal/can_start(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
if(!affected)
return 0
if(affected.status & ORGAN_ROBOT)
return 0
return 1
/datum/surgery/implant_removal/synth/can_start(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
if(!affected)
return 0
if(!(affected.status & ORGAN_ROBOT))
return 0
return 1
/datum/surgery_step/extract_implant
name = "extract implant"
allowed_tools = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 65)
time = 64
var/obj/item/weapon/implant/I = null
/datum/surgery_step/extract_implant/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
I = locate(/obj/item/weapon/implant) in target
user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \
"You start poking around inside [target]'s [affected.name] with \the [tool]." )
target.custom_pain("The pain in your [affected.name] is living hell!",1)
..()
/datum/surgery_step/extract_implant/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
I = locate(/obj/item/weapon/implant) in target
if(I && (target_zone == "chest")) //implant removal only works on the chest.
user.visible_message("<span class='notice'>[user] takes something out of [target]'s [affected.name] with \the [tool].</span>", \
"<span class='notice'>You take [I] out of [target]'s [affected.name]s with \the [tool].</span>" )
I.removed(target)
var/obj/item/weapon/implantcase/case
if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase))
case = user.get_item_by_slot(slot_l_hand)
else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase))
case = user.get_item_by_slot(slot_r_hand)
else
case = locate(/obj/item/weapon/implantcase) in get_turf(target)
if(case && !case.imp)
case.imp = I
I.forceMove(case)
case.update_icon()
user.visible_message("[user] places [I] into [case]!", "<span class='notice'>You place [I] into [case].</span>")
else
qdel(I)
else
user.visible_message("<span class='notice'> [user] could not find anything inside [target]'s [affected.name], and pulls \the [tool] out.</span>", \
"<span class='notice'>You could not find anything inside [target]'s [affected.name].</span>")
return 1
@@ -52,4 +52,7 @@
qdel(tool)
affected.open = 0
affected.germ_level = 0
affected.status &= ~ORGAN_BLEEDING
return 1
+27 -25
View File
@@ -59,7 +59,7 @@
var/encased // Needs to be opened with a saw to access the organs.
var/obj/item/hidden = null
var/list/implants = list()
var/list/embedded_objects = list()
// how often wounds should be updated, a higher number means less often
var/wound_update_accuracy = 1
@@ -105,7 +105,7 @@
QDEL_LIST(wounds)
QDEL_LIST(implants)
QDEL_LIST(embedded_objects)
QDEL_NULL(hidden)
@@ -363,12 +363,6 @@ This function completely restores a damaged organ to perfect condition.
for(var/obj/item/organ/external/EO in contents)
EO.rejuvenate()
// remove embedded objects and drop them on the floor
for(var/obj/implanted_object in implants)
if(!istype(implanted_object,/obj/item/weapon/implant)) // We don't want to remove REAL implants. Just shrapnel etc.
implanted_object.loc = owner.loc
implants -= implanted_object
owner.updatehealth()
update_icon()
if(!owner)
@@ -911,20 +905,6 @@ Note that amputating the affected organ does in fact remove the infection from t
/obj/item/organ/external/proc/is_malfunctioning()
return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam) && !tough)
/obj/item/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0)
if(!owner || loc != owner)
return
if(!silent)
owner.visible_message("<span class='danger'>\The [W] sticks in the wound!</span>")
implants += W
owner.embedded_flag = 1
owner.verbs += /mob/proc/yank_out_object
W.add_blood(owner)
if(ismob(W.loc))
var/mob/living/H = W.loc
H.drop_item()
W.loc = owner
/obj/item/organ/external/proc/open_enough_for_surgery()
return (encased ? (open == 3) : (open == 2))
@@ -935,14 +915,17 @@ Note that amputating the affected organ does in fact remove the infection from t
var/is_robotic = status & ORGAN_ROBOT
var/mob/living/carbon/human/victim = owner
for(var/obj/item/I in embedded_objects)
embedded_objects -= I
I.forceMove(src)
if(!owner.has_embedded_objects())
owner.clear_alert("embeddedobject")
. = ..()
status |= ORGAN_DESTROYED
victim.bad_external_organs -= src
for(var/implant in implants) //todo: check if this can be left alone
qdel(implant)
// Attached organs also fly off.
if(!ignore_children)
for(var/obj/item/organ/external/O in children)
@@ -1022,3 +1005,22 @@ Note that amputating the affected organ does in fact remove the infection from t
..() // Parent call loads in the DNA
if(data["dna"])
sync_colour_to_dna()
//Remove all embedded objects from all limbs on the carbon mob
/mob/living/carbon/human/proc/remove_all_embedded_objects()
var/turf/T = get_turf(src)
for(var/X in bodyparts)
var/obj/item/organ/external/L = X
for(var/obj/item/I in L.embedded_objects)
L.embedded_objects -= I
I.forceMove(T)
clear_alert("embeddedobject")
/mob/living/carbon/human/proc/has_embedded_objects()
. = 0
for(var/X in bodyparts)
var/obj/item/organ/external/L = X
for(var/obj/item/I in L.embedded_objects)
return 1
+12
View File
@@ -159,6 +159,11 @@
else if(implement_type in implements_extract)
current_type = "extract"
var/list/organs = target.get_organs_zone(target_zone)
var/mob/living/simple_animal/borer/B = target.has_brain_worms()
if(target_zone == "head" && B)
user.visible_message("[user] begins to extract [B] from [target]'s [parse_zone(target_zone)].",
"<span class='notice'>You begin to extract [B] from [target]'s [parse_zone(target_zone)]...</span>")
return TRUE
if(!organs.len)
to_chat(user, "<span class='notice'>There are no removeable organs in [target]'s [parse_zone(target_zone)]!</span>")
return -1
@@ -262,6 +267,13 @@
I.status &= ~ORGAN_CUT_AWAY
else if(current_type == "extract")
var/mob/living/simple_animal/borer/B = target.has_brain_worms()
if(target_zone == "head" && B && B.host == target)
user.visible_message("[user] successfully extracts [B] from [target]'s [parse_zone(target_zone)]!",
"<span class='notice'>You successfully extract [B] from [target]'s [parse_zone(target_zone)].</span>")
add_logs(user, target, "surgically removed [B] from", addition="INTENT: [uppertext(user.a_intent)]")
B.leave_host()
return FALSE
if(I && I.owner == target)
user.visible_message("<span class='notice'> [user] has separated and extracts [target]'s [I] with [tool].</span>",
"<span class='notice'> You have separated and extracted [target]'s [I] with [tool].</span>")
@@ -0,0 +1,65 @@
/datum/surgery/embedded_removal
name = "Removal of Embedded Objects"
steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/remove_object,/datum/surgery_step/generic/cauterize)
possible_locs = list("head", "chest", "l_arm", "l_hand", "r_arm", "r_hand","r_leg", "r_foot", "l_leg", "l_foot", "groin")
/datum/surgery/embedded_removal/synth
steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/remove_object,/datum/surgery_step/robotics/external/close_hatch)
/datum/surgery/embedded_removal/can_start(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
if(!affected)
return 0
if(affected.status & ORGAN_ROBOT)
return 0
return 1
/datum/surgery/embedded_removal/synth/can_start(mob/user, mob/living/carbon/human/target)
if(!istype(target))
return 0
var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
if(!affected)
return 0
if(!(affected.status & ORGAN_ROBOT))
return 0
return 1
/datum/surgery_step/remove_object
name = "Remove Embedded Objects"
time = 32
accept_hand = 1
var/obj/item/organ/external/L = null
/datum/surgery_step/remove_object/begin_step(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
L = surgery.organ_ref
if(L)
user.visible_message("[user] looks for objects embedded in [target]'s [parse_zone(user.zone_sel.selecting)].", "<span class='notice'>You look for objects embedded in [target]'s [parse_zone(user.zone_sel.selecting)]...</span>")
else
user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_sel.selecting)].", "<span class='notice'>You look for [target]'s [parse_zone(user.zone_sel.selecting)]...</span>")
/datum/surgery_step/remove_object/end_step(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(L)
if(ishuman(target))
var/mob/living/carbon/human/H = target
var/objects = 0
for(var/obj/item/I in L.embedded_objects)
objects++
I.forceMove(get_turf(H))
L.embedded_objects -= I
if(!H.has_embedded_objects())
H.clear_alert("embeddedobject")
if(objects > 0)
user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L]!", "<span class='notice'>You successfully remove [objects] objects from [H]'s [L.name].</span>")
else
to_chat(user, "<span class='warning'>You find no objects embedded in [H]'s [L]!</span>")
else
to_chat(user, "<span class='warning'>You can't find [target]'s [parse_zone(user.zone_sel.selecting)], let alone any objects embedded in it!</span>")
return 1