Merge branch 'master' into movespeed_modifiers_take_two

This commit is contained in:
kevinz000
2020-03-10 00:59:01 -07:00
committed by GitHub
509 changed files with 161127 additions and 66011 deletions
+1 -1
View File
@@ -9,7 +9,7 @@
/datum/surgery_step/sever_limb
name = "sever limb"
implements = list(/obj/item/shears = 300, TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/arm_blade = 80, /obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25)
implements = list(/obj/item/shears = 300, TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/arm_blade = 80, /obj/item/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25)
time = 64
experience_given = MEDICAL_SKILL_ORGAN_FIX
+4 -2
View File
@@ -87,14 +87,16 @@
var/mob/living/carbon/human/H = C
if(HAS_TRAIT(C, TRAIT_LIMBATTACHMENT))
if(!H.get_bodypart(body_zone) && !animal_origin)
user.temporarilyRemoveItemFromInventory(src, TRUE)
if(!attach_limb(C))
to_chat(user, "<span class='warning'>[H]'s body rejects [src]!</span>")
forceMove(H.loc)
if(H == user)
H.visible_message("<span class='warning'>[H] jams [src] into [H.p_their()] empty socket!</span>",\
"<span class='notice'>You force [src] into your empty socket, and it locks into place!</span>")
else
H.visible_message("<span class='warning'>[user] jams [src] into [H]'s empty socket!</span>",\
"<span class='notice'>[user] forces [src] into your empty socket, and it locks into place!</span>")
user.temporarilyRemoveItemFromInventory(src, TRUE)
attach_limb(C)
return
..()
+35 -22
View File
@@ -90,8 +90,11 @@
C.bodyparts -= src
if(held_index)
C.dropItemToGround(owner.get_item_for_held_index(held_index), 1)
C.hand_bodyparts[held_index] = null
if(C.hand_bodyparts[held_index] == src)
// We only want to do this if the limb being removed is the active hand part.
// This catches situations where limbs are "hot-swapped" such as augmentations and roundstart prosthetics.
C.dropItemToGround(owner.get_item_for_held_index(held_index), 1)
C.hand_bodyparts[held_index] = null
owner = null
@@ -259,23 +262,25 @@
/obj/item/bodypart/proc/replace_limb(mob/living/carbon/C, special)
if(!istype(C))
return
var/obj/item/bodypart/O = C.get_bodypart(body_zone)
var/obj/item/bodypart/O = C.get_bodypart(body_zone) //needs to happen before attach because multiple limbs in same zone breaks helpers
if(!attach_limb(C, special))//we can attach this limb and drop the old after because of our robust bodyparts system. you know, just for a sec.
return
if(O)
O.drop_limb(1)
attach_limb(C, special)
/obj/item/bodypart/head/replace_limb(mob/living/carbon/C, special)
if(!istype(C))
return
var/obj/item/bodypart/head/O = C.get_bodypart(body_zone)
if(!attach_limb(C, special))
return
if(O)
if(!special)
return
else
O.drop_limb(1)
attach_limb(C, special)
O.drop_limb(1)
/obj/item/bodypart/proc/attach_limb(mob/living/carbon/C, special)
if(SEND_SIGNAL(C, COMSIG_LIVING_ATTACH_LIMB, src, special) & COMPONENT_NO_ATTACH)
return FALSE
. = TRUE
moveToNullspace()
owner = C
C.bodyparts += src
@@ -312,7 +317,10 @@
C.update_mobility()
/obj/item/bodypart/head/attach_limb(mob/living/carbon/C, special)
/obj/item/bodypart/head/attach_limb(mob/living/carbon/C, special = FALSE, abort = FALSE)
. = ..()
if(!.)
return .
//Transfer some head appearance vars over
if(brain)
if(brainmob)
@@ -350,19 +358,22 @@
AP.Grant(C)
break
..()
C.updatehealth()
C.update_body()
C.update_hair()
C.update_damage_overlays()
C.update_mobility()
//Regenerates all limbs. Returns amount of limbs regenerated
/mob/living/proc/regenerate_limbs(noheal = FALSE, list/excluded_limbs = list())
SEND_SIGNAL(src, COMSIG_LIVING_REGENERATE_LIMBS, noheal, excluded_limbs)
/mob/living/proc/regenerate_limbs(noheal = FALSE, list/excluded_zones = list())
SEND_SIGNAL(src, COMSIG_LIVING_REGENERATE_LIMBS, noheal, excluded_zones)
/mob/living/carbon/regenerate_limbs(noheal = FALSE, list/excluded_limbs = list())
/mob/living/carbon/regenerate_limbs(noheal = FALSE, list/excluded_zones = list())
. = ..()
var/list/limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
if(length(excluded_limbs))
limb_list -= excluded_limbs
for(var/Z in limb_list)
var/list/zone_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
if(length(excluded_zones))
zone_list -= excluded_zones
for(var/Z in zone_list)
. += regenerate_limb(Z, noheal)
/mob/living/proc/regenerate_limb(limb_zone, noheal)
@@ -371,7 +382,7 @@
/mob/living/carbon/regenerate_limb(limb_zone, noheal)
var/obj/item/bodypart/L
if(get_bodypart(limb_zone))
return 0
return FALSE
L = newBodyPart(limb_zone, 0, 0)
if(L)
if(!noheal)
@@ -380,5 +391,7 @@
L.brutestate = 0
L.burnstate = 0
L.attach_limb(src, 1)
return 1
if(!L.attach_limb(src, 1))
qdel(L)
return FALSE
return TRUE
+1 -1
View File
@@ -290,7 +290,7 @@
body_plan_changed = TRUE
O.drop_limb(1)
qdel(O)
N.attach_limb(src)
N.attach_limb(src) //no sanity for if this fails here because we just dropped out a limb of the same zone, SHOULD be okay
if(body_plan_changed && ishuman(src))
var/mob/living/carbon/human/H = src
if(H.w_uniform)
+6 -7
View File
@@ -48,12 +48,11 @@
"<span class='notice'>[user] attempts to patch some of [target]'s [woundtype].</span>")
/datum/surgery_step/heal/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
if(..())
experience_given = min(experience_given+1,PER_ITERATION_XP_CAP)
while((brutehealing && target.getBruteLoss()) || (burnhealing && target.getFireLoss()))
if(!..())
break
experience_given = min(experience_given+1,PER_ITERATION_XP_CAP)
if(!..())
return
while((brutehealing && target.getBruteLoss()) || (burnhealing && target.getFireLoss()))
if(!..())
break
/datum/surgery_step/heal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/umsg = "You succeed in fixing some of [target]'s wounds" //no period, add initial space to "addons"
@@ -72,7 +71,7 @@
urhealedamt_burn *= 0.55
umsg += " as best as you can while they have clothing on"
tmsg += " as best as they can while [target] has clothing on"
target.heal_bodypart_damage(urhealedamt_brute,urhealedamt_burn)
experience_given = CEILING((target.heal_bodypart_damage(urhealedamt_brute,urhealedamt_burn)/5),1)
display_results(user, target, "<span class='notice'>[umsg].</span>",
"[tmsg].",
"[tmsg].")
+1 -1
View File
@@ -103,7 +103,7 @@
/datum/surgery_step/saw
name = "saw bone"
implements = list(TOOL_SAW = 100,/obj/item/melee/arm_blade = 75,
/obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 35, /obj/item/kitchen/knife/butcher = 25, /obj/item = 20) //20% success (sort of) with any sharp item with a force>=10
/obj/item/fireaxe = 50, /obj/item/hatchet = 35, /obj/item/kitchen/knife/butcher = 25, /obj/item = 20) //20% success (sort of) with any sharp item with a force>=10
time = 54
/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+3
View File
@@ -28,6 +28,9 @@
if(M)
M.adjustToxLoss(4, TRUE, TRUE) //forced to ensure people don't use it to gain tox as slime person
/obj/item/organ/appendix/get_availability(datum/species/S)
return !(TRAIT_NOHUNGER in S.species_traits)
/obj/item/organ/appendix/Remove(mob/living/carbon/M, special = 0)
for(var/datum/disease/appendicitis/A in M.diseases)
A.cure()
+32 -9
View File
@@ -132,6 +132,7 @@
. = ..()
if(!ion_trail)
ion_trail = new
ion_trail.auto_process = FALSE
ion_trail.set_up(M)
/obj/item/organ/cyberimp/chest/thrusters/Remove(mob/living/carbon/M, special = 0)
@@ -148,17 +149,19 @@
if(!silent)
to_chat(owner, "<span class='warning'>Your thrusters set seems to be broken!</span>")
return 0
on = TRUE
if(allow_thrust(0.01))
on = TRUE
ion_trail.start()
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/move_react)
owner.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/cybernetic)
RegisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE, .proc/pre_move_react)
if(!silent)
to_chat(owner, "<span class='notice'>You turn your thrusters set on.</span>")
else
ion_trail.stop()
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
owner.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/cybernetic)
UnregisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE)
if(!silent)
to_chat(owner, "<span class='notice'>You turn your thrusters set off.</span>")
on = FALSE
@@ -171,26 +174,44 @@
icon_state = "imp_jetpack"
/obj/item/organ/cyberimp/chest/thrusters/proc/move_react()
allow_thrust(0.01)
if(!on)//If jet dont work, it dont work
return
if(!owner)//Don't allow jet self using
return
if(!isturf(owner.loc))//You can't use jet in nowhere or in mecha/closet
return
if(!(owner.is_flying() || owner.is_floating()) || owner.buckled)//You don't want use jet in gravity or while buckled.
return
if(owner.pulledby)//You don't must use jet if someone pull you
return
if(owner.throwing)//You don't must use jet if you thrown
return
if(length(owner.client.keys_held & owner.client.movement_keys))//You use jet when press keys. yes.
allow_thrust(0.01)
/obj/item/organ/cyberimp/chest/thrusters/proc/pre_move_react()
ion_trail.oldposition = get_turf(owner)
/obj/item/organ/cyberimp/chest/thrusters/proc/allow_thrust(num)
if(!on || !owner)
return 0
if(!owner)
return FALSE
var/turf/T = get_turf(owner)
if(!T) // No more runtimes from being stuck in nullspace.
return 0
return FALSE
// Priority 1: use air from environment.
var/datum/gas_mixture/environment = T.return_air()
if(environment && environment.return_pressure() > 30)
return 1
ion_trail.generate_effect()
return TRUE
// Priority 2: use plasma from internal plasma storage.
// (just in case someone would ever use this implant system to make cyber-alien ops with jetpacks and taser arms)
if(owner.getPlasma() >= num*100)
owner.adjustPlasma(-num*100)
return 1
ion_trail.generate_effect()
return TRUE
// Priority 3: use internals tank.
var/obj/item/tank/I = owner.internal
@@ -198,9 +219,11 @@
var/datum/gas_mixture/removed = I.air_contents.remove(num)
if(removed.total_moles() > 0.005)
T.assume_air(removed)
return 1
ion_trail.generate_effect()
return TRUE
else
T.assume_air(removed)
ion_trail.generate_effect()
toggle(silent = TRUE)
return 0
return FALSE
-1
View File
@@ -83,7 +83,6 @@
C.clear_fullscreen("eye_damage")
return
/obj/item/organ/eyes/night_vision
name = "shadow eyes"
desc = "A spooky set of eyes that can see in the dark."
+3
View File
@@ -91,6 +91,9 @@
owner.set_heartattack(TRUE)
failed = TRUE
/obj/item/organ/heart/get_availability(datum/species/S)
return !(NOBLOOD in S.species_traits)
/obj/item/organ/heart/cursed
name = "cursed heart"
desc = "A heart that, when inserted, will force you to pump it manually."
+2 -2
View File
@@ -17,10 +17,10 @@
/mob/proc/getorganszone(zone)
return
/**
* Get an organ relating to a specific slot
* Returns a list of all organs in specified slot
*
* Arguments:
* * slot Slot to get the organ from
* * slot Slot to get the organs from
*/
/mob/proc/getorganslot(slot)
return
+3
View File
@@ -58,6 +58,9 @@
#undef HAS_NO_TOXIN
#undef HAS_PAINFUL_TOXIN
/obj/item/organ/liver/get_availability(datum/species/S)
return !(TRAIT_NOMETABOLISM in S.species_traits)
/obj/item/organ/liver/fly
name = "insectoid liver"
icon_state = "liver-x" //xenomorph liver? It's just a black liver so it fits.
+2
View File
@@ -409,6 +409,8 @@
owner.visible_message("<span class='danger'>[owner] grabs [owner.p_their()] throat, struggling for breath!</span>", "<span class='userdanger'>You suddenly feel like you can't breathe!</span>")
failed = TRUE
/obj/item/organ/lungs/get_availability(datum/species/S)
return !(TRAIT_NOBREATH in S.species_traits)
/obj/item/organ/lungs/plasmaman
name = "plasma filter"
@@ -203,3 +203,15 @@
if(!getorganslot(ORGAN_SLOT_EARS))
var/obj/item/organ/ears/ears = new()
ears.Insert(src)
/** get_availability
* returns whether the species should innately have this organ.
*
* regenerate organs works with generic organs, so we need to get whether it can accept certain organs just by what this returns.
* This is set to return true or false, depending on if a species has a specific organless trait. stomach for example checks if the species has NOSTOMACH and return based on that.
* Arguments:
* S - species, needed to return whether the species has an organ specific trait
*/
/obj/item/organ/proc/get_availability(datum/species/S)
return TRUE
+3
View File
@@ -42,6 +42,9 @@
H.vomit(damage)
to_chat(H, "<span class='warning'>Your stomach reels in pain as you're incapable of holding down all that food!</span>")
/obj/item/organ/stomach/get_availability(datum/species/S)
return !(NOSTOMACH in S.species_traits)
/obj/item/organ/stomach/proc/handle_disgust(mob/living/carbon/human/H)
if(H.disgust)
var/pukeprob = 5 + 0.05 * H.disgust
+13 -4
View File
@@ -17,7 +17,7 @@
/datum/surgery_step/add_prosthetic
name = "add prosthetic"
implements = list(/obj/item/bodypart = 100, /obj/item/organ_storage = 100, /obj/item/twohanded/required/chainsaw = 100, /obj/item/melee/synthetic_arm_blade = 100)
implements = list(/obj/item/bodypart = 100, /obj/item/organ_storage = 100, /obj/item/chainsaw = 100, /obj/item/melee/synthetic_arm_blade = 100)
time = 32
experience_given = MEDICAL_SKILL_ORGAN_FIX //won't get full XP if rejected
var/organ_rejection_dam = 0
@@ -72,7 +72,11 @@
tool = tool.contents[1]
if(istype(tool, /obj/item/bodypart) && user.temporarilyRemoveItemFromInventory(tool))
var/obj/item/bodypart/L = tool
L.attach_limb(target)
if(!L.attach_limb(target))
display_results(user, target, "<span class='warning'>You fail in replacing [target]'s [parse_zone(target_zone)]! Their body has rejected [L]!</span>",
"<span class='warning'>[user] fails to replace [target]'s [parse_zone(target_zone)]!</span>",
"<span class='warning'>[user] fails to replaces [target]'s [parse_zone(target_zone)]!</span>")
return
if(organ_rejection_dam)
target.adjustToxLoss(organ_rejection_dam)
experience_given -= (round(organ_rejection_dam/10))
@@ -83,13 +87,18 @@
else
var/obj/item/bodypart/L = target.newBodyPart(target_zone, FALSE, FALSE)
L.is_pseudopart = TRUE
L.attach_limb(target)
if(!L.attach_limb(target))
display_results(user, target, "<span class='warning'>You fail in attaching [target]'s [parse_zone(target_zone)]! Their body has rejected [L]!</span>",
"<span class='warning'>[user] fails to attach [target]'s [parse_zone(target_zone)]!</span>",
"<span class='warning'>[user] fails to attach [target]'s [parse_zone(target_zone)]!</span>")
L.forceMove(target.loc)
return
user.visible_message("<span class='notice'>[user] finishes attaching [tool]!</span>", "<span class='notice'>You attach [tool].</span>")
display_results(user, target, "<span class='notice'>You attach [tool].</span>",
"<span class='notice'>[user] finishes attaching [tool]!</span>",
"<span class='notice'>[user] finishes the attachment procedure!</span>")
qdel(tool)
if(istype(tool, /obj/item/twohanded/required/chainsaw))
if(istype(tool, /obj/item/chainsaw))
var/obj/item/mounted_chainsaw/new_arm = new(target)
target_zone == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm)
return
@@ -1,4 +1,4 @@
/datum/surgery/advanced/revival
/datum/surgery/revival
name = "Revival"
desc = "An experimental surgical procedure which involves reconstruction and reactivation of the patient's brain even long after death. The body must still be able to sustain life."
steps = list(/datum/surgery_step/incise,
@@ -13,7 +13,7 @@
possible_locs = list(BODY_ZONE_HEAD)
requires_bodypart_type = 0
/datum/surgery/advanced/revival/can_start(mob/user, mob/living/carbon/target)
/datum/surgery/revival/can_start(mob/user, mob/living/carbon/target)
if(!..())
return FALSE
if(target.stat != DEAD)
@@ -27,15 +27,15 @@
/datum/surgery_step/revive
name = "shock body"
implements = list(/obj/item/twohanded/shockpaddles = 100, /obj/item/melee/baton = 75, /obj/item/gun/energy = 60)
implements = list(/obj/item/shockpaddles = 100, /obj/item/melee/baton = 75, /obj/item/gun/energy = 60)
repeatable = TRUE
time = 120
experience_given = MEDICAL_SKILL_ADVANCED
/datum/surgery_step/revive/tool_check(mob/user, obj/item/tool)
. = TRUE
if(istype(tool, /obj/item/twohanded/shockpaddles))
var/obj/item/twohanded/shockpaddles/S = tool
if(istype(tool, /obj/item/shockpaddles))
var/obj/item/shockpaddles/S = tool
if((S.req_defib && !S.defib.powered) || !S.wielded || S.cooldown || S.busy)
to_chat(user, "<span class='warning'>You need to wield both paddles, and [S.defib] must be powered!</span>")
return FALSE