Skip to content

Commit

Permalink
a
Browse files Browse the repository at this point in the history
  • Loading branch information
nmajask committed May 21, 2022
1 parent 8ec2fca commit da83fdc
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 127 deletions.
6 changes: 3 additions & 3 deletions code/_onclick/hud/alert.dm
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ If you're feeling frisky, examine yourself and click the underlined item to pull
icon_state = "embeddedobject"

/obj/screen/alert/embeddedobject/Click()
if(isliving(usr))
var/mob/living/carbon/human/M = usr
return M.help_shake_act(M)
if(iscarbon(usr))
var/mob/living/carbon/C = usr
return C.remove_embedded_object(C)

/obj/screen/alert/weightless
name = "Weightless"
Expand Down
17 changes: 15 additions & 2 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,20 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(ismob(loc))
var/mob/mob_loc = loc
mob_loc.regenerate_icons()
/**
* Called when this object is first embedded into a carbon
*/
/obj/item/proc/on_embed(mob/living/carbon/human/embedde, obj/item/bodypart/part)
return TRUE

/**
* Called when this object is no longer embedded into a carbon
*/
/obj/item/proc/on_embed_removal(mob/living/carbon/human/embedde)
return TRUE

// Called every life tick when the object is embedded in a human
/obj/item/proc/embed_tick(/mob/living/carbon/human/embedde, /obj/item/bodypart/part)
/**
* Called every life tick when the object is embedded in a carbon
*/
/obj/item/proc/embed_tick(mob/living/carbon/human/embedde, obj/item/bodypart/part)
return
20 changes: 20 additions & 0 deletions code/modules/mob/living/carbon/carbon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,26 @@
visible_message(span_danger("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name]."), \
span_userdanger("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name]."))

// Embed Stuff
if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
var/obj/item/bodypart/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.embedding.embedded_unsafe_removal_time*I.w_class
usr.visible_message(span_warning("[usr] attempts to remove [I] from [usr.p_their()] [L.name]."),span_notice("You attempt to remove [I] from your [L.name]... (It will take [DisplayTimeText(time_taken)].)"))
if(do_after(usr, time_taken, needhand = 1, target = src))
if(!I || !L || I.loc != src)
return
var/damage_amount = I.embedding.embedded_unsafe_removal_pain_multiplier * I.w_class
L.receive_damage(damage_amount, sharpness = SHARP_EDGED)//It hurts to rip it out, get surgery you dingus.
if(remove_embedded_object(I, get_turf(src), damage_amount))
usr.put_in_hands(I)
usr.visible_message("[usr] successfully rips [I] out of [usr.p_their()] [L.name]!", span_notice("You successfully remove [I] from your [L.name]."))
return

/mob/living/carbon/fall(forced)
if(loc)
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing
Expand Down
87 changes: 83 additions & 4 deletions code/modules/mob/living/carbon/carbon_defense.dm
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,15 @@
return TRUE

/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
if(!skipcatch) //ugly, but easy
if(can_catch_item())
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/obj/item/I = AM
if(istype(I, /obj/item))
if(((throwingdatum ? throwingdatum.speed : I.throw_speed) >= EMBED_THROWSPEED_THRESHOLD) || I.embedding.embedded_ignore_throwspeed_threshold)
var/obj/item/bodypart/body_part = pick(bodyparts)
if(prob(clamp(I.embedding.embed_chance - run_armor_check(body_part, MELEE), 0, 100)) && embed_object(I, deal_damage = TRUE))
hitpush = FALSE
skipcatch = TRUE //can't catch the now embedded item
if(!skipcatch) //ugly, but easy
if(can_catch_item())
if(I.item_flags & UNCATCHABLE)
return FALSE
if(isturf(I.loc))
Expand All @@ -68,6 +73,80 @@
return TRUE
..()

/**
* Embeds an object into this carbon
*/
/mob/living/carbon/proc/embed_object(obj/item/embedding, part, deal_damage, silent, forced)
if(!(forced || (can_embed(embedding) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE))))
return FALSE
var/obj/item/bodypart/body_part = part
// In case its a zone
if(!istype(body_part) && body_part)
body_part = get_bodypart(body_part)
// Otherwise pick one
if(!istype(body_part))
body_part = pick(bodyparts)
// Thats probably not good
if(!istype(body_part))
return FALSE
if(!embedding.on_embed(src, body_part))
return
body_part.embedded_objects |= embedding
embedding.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
embedding.forceMove(src)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
if(deal_damage)
body_part.receive_damage(embedding.w_class*embedding.embedding.embedded_impact_pain_multiplier, wound_bonus=-30, sharpness = TRUE)
if(!silent)
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
visible_message(span_danger("[embedding] embeds itself in [src]'s [body_part.name]!"), span_userdanger("[embedding] embeds itself in your [body_part.name]!"))
return TRUE

/**
* Removes the given embedded object from this carbon
*/
/mob/living/carbon/proc/remove_embedded_object(obj/item/embedded, new_loc, silent, forced)
var/obj/item/bodypart/body_part
for(var/obj/item/bodypart/part in bodyparts)
if(embedded in part.embedded_objects)
body_part = part
if(!body_part)
return
if(!embedded.on_embed_removal(src))
return
body_part.embedded_objects -= embedded
if(!silent)
emote("scream")
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(usr, COMSIG_CLEAR_MOOD_EVENT, "embedded")
if(new_loc)
embedded.forceMove(new_loc)
return TRUE

/**
* Called when a mob tries to remove an embedded object from this carbon
*/
/mob/living/carbon/proc/try_remove_embedded_object(mob/user)
var/list/choice_list = list()
var/obj/item/bodypart/body_part
for(var/obj/item/bodypart/part in bodyparts)
for(var/obj/item/embedded in part.embedded_objects)
choice_list[embedded] = image(embedded)
var/obj/item/choice = show_radial_menu(user, src, choice_list, tooltips = TRUE)
if(!istype(choice) || !(choice in choice_list))
return
var/time_taken = choice.embedding.embedded_unsafe_removal_time * choice.w_class
user.visible_message(span_warning("[user] attempts to remove [choice] from [usr.p_their()] [body_part.name]."),span_notice("You attempt to remove [choice] from your [body_part.name]... (It will take [DisplayTimeText(time_taken)].)"))
if(!do_after(user, time_taken, needhand = 1, target = src) && !(choice in body_part.embedded_objects))
return
var/damage_amount = choice.embedding.embedded_unsafe_removal_pain_multiplier * choice.w_class
body_part.receive_damage(damage_amount > 0, sharpness = SHARP_EDGED)//It hurts to rip it out, get surgery you dingus.
if(remove_embedded_object(choice, get_turf(src), damage_amount))
user.put_in_hands(choice)
user.visible_message("[user] successfully rips [choice] out of [user == src? p_their() : "[src]'s"] [body_part.name]!", span_notice("You successfully remove [choice] from your [body_part.name]."))
return TRUE

/mob/living/carbon/proc/get_interaction_efficiency(zone)
var/obj/item/bodypart/limb = get_bodypart(zone)
if(!limb)
Expand Down
17 changes: 11 additions & 6 deletions code/modules/mob/living/carbon/examine.dm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@
else if(get_bodypart(BODY_ZONE_HEAD))
. += span_deadsay("It appears that [t_his] brain is missing...")

var/list/disabled = list()
for(var/X in bodyparts)
var/obj/item/bodypart/body_part = X
if(body_part.bodypart_disabled)
disabled += body_part
for(var/obj/item/I in body_part.embedded_objects)
. += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [body_part.name]!</B>\n"
for(var/i in body_part.wounds)
var/datum/wound/iter_wound = i
. += "[iter_wound.get_examine_description(user)]\n"

var/list/missing = get_missing_limbs()
for(var/t in missing)
if(t==BODY_ZONE_HEAD)
Expand Down Expand Up @@ -68,12 +79,6 @@
else
msg += "<b>[t_He] [t_is] severely deformed!</b>\n"

for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
for(var/i in BP.wounds)
var/datum/wound/W = i
msg += "[W.get_examine_description(user)]\n"

if(HAS_TRAIT(src, TRAIT_DUMB))
msg += "[t_He] seem[p_s()] to be clumsy and unable to think.\n"

Expand Down
23 changes: 0 additions & 23 deletions code/modules/mob/living/carbon/human/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -231,29 +231,6 @@
spreadFire(AM)

/mob/living/carbon/human/Topic(href, href_list)
if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
var/obj/item/bodypart/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.embedding.embedded_unsafe_removal_time*I.w_class
usr.visible_message(span_warning("[usr] attempts to remove [I] from [usr.p_their()] [L.name]."),span_notice("You attempt to remove [I] from your [L.name]... (It will take [DisplayTimeText(time_taken)].)"))
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.receive_damage(I.embedding.embedded_unsafe_removal_pain_multiplier*I.w_class, sharpness=SHARP_EDGED)//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 [usr.p_their()] [L.name]!",span_notice("You successfully remove [I] from your [L.name]."))
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(usr, COMSIG_CLEAR_MOOD_EVENT, "embedded")
return

if(href_list["item"]) //canUseTopic check for this is handled by mob/Topic()
var/slot = text2num(href_list["item"])
if(slot in check_obscured_slots(TRUE))
Expand Down
31 changes: 0 additions & 31 deletions code/modules/mob/living/carbon/human/human_defense.dm
Original file line number Diff line number Diff line change
Expand Up @@ -169,38 +169,7 @@
hitpush = FALSE
skipcatch = TRUE
blocked = TRUE
else if(I)
if(((throwingdatum ? throwingdatum.speed : I.throw_speed) >= EMBED_THROWSPEED_THRESHOLD) || I.embedding.embedded_ignore_throwspeed_threshold)
if(prob(I.embedding.embed_chance) && embed_object(I, deal_damage = TRUE))
hitpush = FALSE
skipcatch = TRUE //can't catch the now embedded item

return ..()

/mob/living/carbon/human/proc/embed_object(obj/item/embedding, part, deal_damage, silent, forced)
if(!(forced || (can_embed(embedding) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE))))
return FALSE
var/obj/item/bodypart/body_part = part
// In case its a zone
if(!istype(body_part) && body_part)
body_part = get_bodypart(body_part)
// Otherwise pick one
if(!istype(body_part))
body_part = pick(bodyparts)
// Thats probably not good
if(!istype(body_part))
return FALSE

body_part.embedded_objects |= embedding
embedding.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
embedding.forceMove(src)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
if(deal_damage)
body_part.receive_damage(embedding.w_class*embedding.embedding.embedded_impact_pain_multiplier, wound_bonus=-30, sharpness = TRUE)
if(!silent)
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
visible_message(span_danger("[embedding] embeds itself in [src]'s [body_part.name]!"), span_userdanger("[embedding] embeds itself in your [body_part.name]!"))
return TRUE

/mob/living/carbon/human/grippedby(mob/living/user, instant = FALSE)
if(w_uniform)
Expand Down
30 changes: 0 additions & 30 deletions code/modules/mob/living/carbon/human/life.dm
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@
//heart attack stuff
handle_heart()

if(stat != DEAD)
//Stuff jammed in your limbs hurts
handle_embedded_objects()

dna.species.spec_life(src) // for mutantraces
else
for(var/i in all_wounds)
Expand Down Expand Up @@ -307,32 +303,6 @@
return TRUE
return ..()


/mob/living/carbon/human/proc/handle_embedded_objects()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
for(var/obj/item/I in BP.embedded_objects)
I.embed_tick(src, BP)
var/pain_chance_current = I.embedding.embedded_pain_chance
if(!(mobility_flags & MOBILITY_STAND))
pain_chance_current *= 0.2
if(prob(pain_chance_current))
BP.receive_damage(I.w_class*I.embedding.embedded_pain_multiplier, wound_bonus = CANT_WOUND)
to_chat(src, span_userdanger("[I] embedded in your [BP.name] hurts!"))

var/fall_chance_current = I.embedding.embedded_fall_chance
if(!(mobility_flags & MOBILITY_STAND))
fall_chance_current *= 0.2

if(prob(fall_chance_current))
BP.receive_damage(I.w_class*I.embedding.embedded_fall_pain_multiplier, wound_bonus = CANT_WOUND) // can wound
BP.embedded_objects -= I
I.forceMove(drop_location())
visible_message(span_danger("[I] falls out of [name]'s [BP.name]!"),span_userdanger("[I] falls out of your [BP.name]!"))
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded")

/mob/living/carbon/human/proc/handle_heart()
var/we_breath = !HAS_TRAIT_FROM(src, TRAIT_NOBREATH, SPECIES_TRAIT)

Expand Down
33 changes: 33 additions & 0 deletions code/modules/mob/living/carbon/life.dm
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
if(stat != DEAD)
handle_liver()

if(stat != DEAD)
//Stuff jammed in your limbs hurts
handle_embedded_objects()

else
. = ..()

Expand Down Expand Up @@ -650,6 +654,35 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
var/datum/brain_trauma/BT = T
BT.on_life()


////////////
// EMBEDS //
////////////

/mob/living/carbon/proc/handle_embedded_objects()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
for(var/obj/item/I in BP.embedded_objects)
I.embed_tick(src, BP)
var/pain_chance_current = I.embedding.embedded_pain_chance
if(!(mobility_flags & MOBILITY_STAND))
pain_chance_current *= 0.2
if(prob(pain_chance_current))
BP.receive_damage(I.w_class*I.embedding.embedded_pain_multiplier, wound_bonus = CANT_WOUND)
to_chat(src, span_userdanger("[I] embedded in your [BP.name] hurts!"))

var/fall_chance_current = I.embedding.embedded_fall_chance
if(!(mobility_flags & MOBILITY_STAND))
fall_chance_current *= 0.2

if(prob(fall_chance_current))
BP.receive_damage(I.w_class*I.embedding.embedded_fall_pain_multiplier, wound_bonus = CANT_WOUND) // can wound
remove_embedded_object(I, drop_location(), FALSE)
visible_message(span_danger("[I] falls out of [name]'s [BP.name]!"), span_userdanger("[I] falls out of your [BP.name]!"))
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded")

/////////////////////////////////////
//MONKEYS WITH TOO MUCH CHOLOESTROL//
/////////////////////////////////////
Expand Down
5 changes: 1 addition & 4 deletions code/modules/spells/spell_types/summonitem.dm
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,8 @@
for(var/X in C.bodyparts)
var/obj/item/bodypart/part = X
if(item_to_retrieve in part.embedded_objects)
part.embedded_objects -= item_to_retrieve
C.remove_embedded_object(item_to_retrieve, silent = TRUE, forced = TRUE)
to_chat(C, span_warning("The [item_to_retrieve] that was embedded in your [L] has mysteriously vanished. How fortunate!"))
if(!C.has_embedded_objects())
C.clear_alert("embeddedobject")
SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "embedded")
break

else
Expand Down
3 changes: 1 addition & 2 deletions code/modules/surgery/bodyparts/dismemberment.dm
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@
break

for(var/obj/item/I in embedded_objects)
embedded_objects -= I
I.forceMove(src)
phantom_owner.remove_embedded_object(I, src, TRUE, TRUE)
if(!phantom_owner.has_embedded_objects())
phantom_owner.clear_alert("embeddedobject")
SEND_SIGNAL(phantom_owner, COMSIG_CLEAR_MOOD_EVENT, "embedded")
Expand Down
5 changes: 3 additions & 2 deletions code/modules/surgery/bodyparts/helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -161,18 +161,19 @@
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
for(var/obj/item/I in L.embedded_objects)
remove_embedded_object(I, T, TRUE, TRUE)
L.embedded_objects -= I
I.forceMove(T)

clear_alert("embeddedobject")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded")

/mob/living/carbon/proc/has_embedded_objects()
. = 0
. = FALSE
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
for(var/obj/item/I in L.embedded_objects)
return 1
return TRUE


//Helper for quickly creating a new limb - used by augment code in species.dm spec_attacked_by
Expand Down
Loading

0 comments on commit da83fdc

Please sign in to comment.