diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index 124be53452..3c0e190427 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -35,9 +35,8 @@ #define ORGAN_BLEEDING (1<<1) #define ORGAN_BROKEN (1<<2) #define ORGAN_DESTROYED (1<<3) -#define ORGAN_SPLINTED (1<<4) -#define ORGAN_DEAD (1<<5) -#define ORGAN_MUTATED (1<<6) +#define ORGAN_DEAD (1<<4) +#define ORGAN_MUTATED (1<<5) #define DROPLIMB_EDGE 0 #define DROPLIMB_BLUNT 1 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 33f0635015..474b2d3b25 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -463,11 +463,11 @@ its easier to just keep the beam vertical. //spawn(0) //if(I) //It's possible that it could be deleted in the meantime. var/obj/O = I - O.show_message( message, 1, blind_message, 2) + O.show_message(message, 1, blind_message, 2) else if(ismob(I)) var/mob/M = I if(M.see_invisible >= invisibility) // Cannot view the invisible - M.show_message( message, 1, blind_message, 2) + M.show_message(message, 1, blind_message, 2) else if (blind_message) M.show_message(blind_message, 2) @@ -488,7 +488,24 @@ its easier to just keep the beam vertical. 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) + O.show_message(message, 2, deaf_message, 1) else if(ismob(I)) var/mob/M = I - M.show_message( message, 2, deaf_message, 1) + M.show_message(message, 2, deaf_message, 1) + +/atom/movable/proc/dropInto(var/atom/destination) + while(istype(destination)) + var/atom/drop_destination = destination.onDropInto(src) + if(!istype(drop_destination) || drop_destination == destination) + return forceMove(destination) + destination = drop_destination + return forceMove(null) + +/atom/proc/onDropInto(var/atom/movable/AM) + return // If onDropInto returns null, then dropInto will forceMove AM into us. + +/atom/movable/onDropInto(var/atom/movable/AM) + return loc // If onDropInto returns something, then dropInto will attempt to drop AM there. + +/atom/proc/InsertedContents() + return contents diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index e45be4bb6a..d164485f38 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -63,13 +63,35 @@ return /atom/movable/proc/forceMove(atom/destination) + if(loc == destination) + return 0 + var/is_origin_turf = isturf(loc) + var/is_destination_turf = isturf(destination) + // It is a new area if: + // Both the origin and destination are turfs with different areas. + // When either origin or destination is a turf and the other is not. + var/is_new_area = (is_origin_turf ^ is_destination_turf) || (is_origin_turf && is_destination_turf && loc.loc != destination.loc) + + var/atom/origin = loc + loc = destination + + if(origin) + origin.Exited(src, destination) + if(is_origin_turf) + for(var/atom/movable/AM in origin) + AM.Uncrossed(src) + if(is_new_area && is_origin_turf) + origin.loc.Exited(src, destination) + if(destination) - if(loc) - loc.Exited(src) - loc = destination - loc.Entered(src) - return 1 - return 0 + destination.Entered(src, origin) + if(is_destination_turf) // If we're entering a turf, cross all movable atoms + for(var/atom/movable/AM in loc) + if(AM != src) + AM.Crossed(src) + if(is_new_area && is_destination_turf) + destination.loc.Entered(src, origin) + return 1 //called when src is thrown into hit_atom /atom/movable/proc/throw_impact(atom/hit_atom, var/speed) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 9d90f018ef..022ce367f0 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -329,7 +329,7 @@ organStatus["broken"] = E.broken_description if(E.status & ORGAN_ROBOT) organStatus["robotic"] = 1 - if(E.status & ORGAN_SPLINTED) + if(E.splinted) organStatus["splinted"] = 1 if(E.status & ORGAN_BLEEDING) organStatus["bleeding"] = 1 @@ -483,7 +483,7 @@ break if(istype(e, /obj/item/organ/external/chest) && occupant.is_lung_ruptured()) lung_ruptured = "Lung ruptured:" - if(e.status & ORGAN_SPLINTED) + if(e.splinted) splint = "Splinted:" if(e.status & ORGAN_BLEEDING) bled = "Bleeding:" diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 9f0843e134..bc05306282 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -161,7 +161,7 @@ REAGENT SCANNER continue var/limb = e.name if(e.status & ORGAN_BROKEN) - if(((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) && (!(e.status & ORGAN_SPLINTED))) + if(((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) && (!e.splinted)) user << "Unsecured fracture in subject [limb]. Splinting recommended for transport." if(e.has_infected_wound()) user << "Infected wound detected in subject [limb]. Disinfection recommended." diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 3e9c9a7524..41ae7ac7c3 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -264,7 +264,7 @@ if(!(affecting.organ_tag in splintable_organs)) user << "You can't use \the [src] to apply a splint there!" return - if(affecting.status & ORGAN_SPLINTED) + if(affecting.splinted) user << "[M]'s [limb] is already splinted!" return if (M != user) @@ -275,17 +275,21 @@ user << "You can't apply a splint to the arm you're using!" return user.visible_message("[user] starts to apply \the [src] to their [limb].", "You start to apply \the [src] to your [limb].", "You hear something being wrapped.") - if(do_after(user, 50)) - if (M != user) - user.visible_message("[user] finishes applying \the [src] to [M]'s [limb].", "You finish applying \the [src] to [M]'s [limb].", "You hear something being wrapped.") - else - if(prob(25)) - user.visible_message("[user] successfully applies \the [src] to their [limb].", "You successfully apply \the [src] to your [limb].", "You hear something being wrapped.") - else - user.visible_message("[user] fumbles \the [src].", "You fumble \the [src].", "You hear something being wrapped.") + if(do_after(user, 50, M)) + if(M == user && prob(75)) + user.visible_message("\The [user] fumbles [src].", "You fumble [src].", "You hear something being wrapped.") + return + var/obj/item/stack/medical/splint/S = split(1) + if(S) + if(affecting.apply_splint(S)) + S.forceMove(affecting) + if (M != user) + user.visible_message("\The [user] finishes applying [src] to [M]'s [limb].", "You finish applying \the [src] to [M]'s [limb].", "You hear something being wrapped.") + else + user.visible_message("\The [user] successfully applies [src] to their [limb].", "You successfully apply \the [src] to your [limb].", "You hear something being wrapped.") return - affecting.status |= ORGAN_SPLINTED - use(1) + S.dropInto(src.loc) //didn't get applied, so just drop it + user.visible_message("\The [user] fails to apply [src].", "You fail to apply [src].", "You hear something being wrapped.") return diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index d88e8c5372..107ea11520 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -394,3 +394,6 @@ var/shake_dir = pick(-1, 1) animate(src, transform=turn(matrix(), 8*shake_dir), pixel_x=init_px + 2*shake_dir, time=1) animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING) + +/obj/structure/closet/onDropInto(var/atom/movable/AM) + return diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm index f06e839ae3..942921b0e9 100644 --- a/code/modules/clothing/spacesuits/spacesuits.dm +++ b/code/modules/clothing/spacesuits/spacesuits.dm @@ -63,7 +63,7 @@ var/list/supporting_limbs //If not-null, automatically splints breaks. Checked when removing the suit. /obj/item/clothing/suit/space/equipped(mob/M) - check_limb_support() + check_limb_support(M) ..() /obj/item/clothing/suit/space/dropped(var/mob/user) @@ -77,14 +77,24 @@ /obj/item/clothing/suit/space/proc/check_limb_support(var/mob/living/carbon/human/user) // If this isn't set, then we don't need to care. - if(!supporting_limbs || !supporting_limbs.len) + if(!istype(user) || isnull(supporting_limbs)) return - if(!istype(user) || user.wear_suit == src) - return + if(user.wear_suit == src) + for(var/obj/item/organ/external/E in user.bad_external_organs) + if(E.is_broken() && E.apply_splint(src)) + user << "You feel [src] constrict about your [E.name], supporting it." + supporting_limbs |= E + else + // Otherwise, remove the splints. + for(var/obj/item/organ/external/E in supporting_limbs) + if(E.splinted == src && E.remove_splint(src)) + user << "\The [src] stops supporting your [E.name]." + supporting_limbs.Cut() - // Otherwise, remove the splints. - for(var/obj/item/organ/external/E in supporting_limbs) - E.status &= ~ ORGAN_SPLINTED - user << "The suit stops supporting your [E.name]." - supporting_limbs = list() +/obj/item/clothing/suit/space/proc/handle_fracture(var/mob/living/carbon/human/user, var/obj/item/organ/external/E) + if(!istype(user) || isnull(supporting_limbs)) + return + if(E.is_broken() && E.apply_splint(src)) + user << "You feel [src] constrict about your [E.name], supporting it." + supporting_limbs |= E diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm index 3fcf07713b..42bd4b709b 100644 --- a/code/modules/games/cards.dm +++ b/code/modules/games/cards.dm @@ -146,7 +146,7 @@ for(var/datum/playingcard/P in cards) H.cards += P H.concealed = src.concealed - user.drop_from_inventory(src,user.loc) + user.drop_from_inventory(src) qdel(src) H.update_icon() return diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index d608bb0988..5e4bfeb24a 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -50,6 +50,11 @@ var/list/holder_mob_icon_cache = list() continue M.forceMove(get_turf(src)) +/obj/item/weapon/holder/onDropInto(var/atom/movable/AM) + if(ismob(loc)) // Bypass our holding mob and drop directly to its loc + return loc.loc + return ..() + /obj/item/weapon/holder/GetID() for(var/mob/M in contents) var/obj/item/I = M.GetIdCard() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index ad71cebe1f..1c6e2436d4 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -126,16 +126,12 @@ var/list/slot_equipment_priority = list( \ // Removes an item from inventory and places it in the target atom. // If canremove or other conditions need to be checked then use unEquip instead. -/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/Target = null) +/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/target = null) if(W) - if(!Target) - Target = loc - - remove_from_mob(W) - if(!(W && W.loc)) return 1 // self destroying objects (tk, grabs) - - W.forceMove(Target) + remove_from_mob(W, target) + if(!(W && W.loc)) + return 1 // self destroying objects (tk, grabs) update_icons() return 1 return 0 @@ -194,7 +190,9 @@ var/list/slot_equipment_priority = list( \ //Attemps to remove an object on a mob. -/mob/proc/remove_from_mob(var/obj/O) +/mob/proc/remove_from_mob(var/obj/O, var/atom/target) + if(!O) // Nothing to remove, so we succeed. + return 1 src.u_equip(O) if (src.client) src.client.screen -= O @@ -202,7 +200,10 @@ var/list/slot_equipment_priority = list( \ O.screen_loc = null if(istype(O, /obj/item)) var/obj/item/I = O - I.forceMove(src.loc) + if(target) + I.forceMove(target) + else + I.dropInto(loc) I.dropped(src) return 1 diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 7d9712277c..1394b86b4a 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -251,8 +251,8 @@ //splints for(var/organ in list(BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM)) var/obj/item/organ/external/o = get_organ(organ) - if(o && o.status & ORGAN_SPLINTED) - msg += "[T.He] [T.has] a splint on [T.his] [o.name]!\n" + if(o && o.splinted && o.splinted.loc == o) + msg += "[T.He] [T.has] \a [o.splinted] on [T.his] [o.name]!\n" if(suiciding) msg += "[T.He] appears to have commited suicide... there is no hope of recovery.\n" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index d7c7de37ee..f459052a43 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1013,7 +1013,7 @@ /mob/living/carbon/human/proc/handle_embedded_objects() for(var/obj/item/organ/external/organ in src.organs) - if(organ.status & ORGAN_SPLINTED) //Splints prevent movement. + if(organ.splinted) //Splints prevent movement. continue for(var/obj/item/O in organ.implants) if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad. diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index ae9dd9a506..de4b36dceb 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -45,7 +45,7 @@ var/obj/item/organ/external/E = get_organ(organ_name) if(!E || E.is_stump()) tally += 4 - if(E.status & ORGAN_SPLINTED) + if(E.splinted) tally += 0.5 else if(E.status & ORGAN_BROKEN) tally += 1.5 @@ -57,7 +57,7 @@ var/obj/item/organ/external/E = get_organ(organ_name) if(!E || E.is_stump()) tally += 4 - else if(E.status & ORGAN_SPLINTED) + else if(E.splinted) tally += 0.5 else if(E.status & ORGAN_BROKEN) tally += 1.5 diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 8db85ef5fe..873a9e1220 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -142,10 +142,10 @@ return for (var/obj/item/organ/external/E in organs) - if(!E || !E.can_grasp || (E.status & ORGAN_SPLINTED)) + if(!E || !E.can_grasp) continue - if(E.is_broken() || E.is_dislocated()) + if((E.is_broken() || E.is_dislocated()) && !E.splinted) switch(E.body_part) if(HAND_LEFT, ARM_LEFT) if(!l_hand) diff --git a/code/modules/mob/living/carbon/human/stripping.dm b/code/modules/mob/living/carbon/human/stripping.dm index 700a0a5308..d67eaf76a9 100644 --- a/code/modules/mob/living/carbon/human/stripping.dm +++ b/code/modules/mob/living/carbon/human/stripping.dm @@ -125,9 +125,13 @@ if(can_reach_splints) var/removed_splint for(var/obj/item/organ/external/o in organs) - if (o && o.status & ORGAN_SPLINTED) - o.status &= ~ORGAN_SPLINTED - removed_splint = 1 + if (o && o.splinted) + var/obj/item/S = o.splinted + if(istype(S) && S.loc == o) //can only remove splints that are actually worn on the organ (deals with hardsuit splints) + S.add_fingerprint(user) + if(o.remove_splint()) + user.put_in_active_hand(S) + removed_splint = 1 if(removed_splint) visible_message("\The [user] removes \the [src]'s splints!") else diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 9d7ba1bc63..04058f2fe2 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -519,7 +519,7 @@ for(var/name in H.organs_by_name) var/obj/item/organ/external/e = H.organs_by_name[name] if(e && H.lying) - if(((e.status & ORGAN_BROKEN && !(e.status & ORGAN_SPLINTED)) || e.status & ORGAN_BLEEDING) && (H.getBruteLoss() + H.getFireLoss() >= 100)) + if(((e.status & ORGAN_BROKEN && !(e.splinted)) || e.status & ORGAN_BLEEDING) && (H.getBruteLoss() + H.getFireLoss() >= 100)) return 1 break return 0 diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index fad60cc0d7..c3a349df17 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -254,7 +254,6 @@ var/list/organ_cache = list() robotic = ORGAN_ROBOT src.status &= ~ORGAN_BROKEN src.status &= ~ORGAN_BLEEDING - src.status &= ~ORGAN_SPLINTED src.status &= ~ORGAN_CUT_AWAY /obj/item/organ/proc/mechassist() //Used to add things like pacemakers, etc diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 612cda4a98..89f3e17ff3 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -50,6 +50,7 @@ var/list/implants = list() // Currently implanted objects. var/organ_rel_size = 25 // Relative size of the organ. var/base_miss_chance = 20 // Chance of missing. + var/atom/movable/splinted // Joint/state stuff. var/can_grasp // It would be more appropriate if these two were named "affects_grasp" and "affects_stand" at this point @@ -84,6 +85,10 @@ for(var/obj/item/organ/O in internal_organs) qdel(O) + if(splinted && splinted.loc == src) + qdel(splinted) + splinted = null + if(owner) owner.organs -= src owner.organs_by_name[organ_tag] = null @@ -524,11 +529,11 @@ This function completely restores a damaged organ to perfect condition. //external organs handle brokenness a bit differently when it comes to damage. Instead brute_dam is checked inside process() //this also ensures that an external organ cannot be "broken" without broken_description being set. /obj/item/organ/external/is_broken() - return ((status & ORGAN_CUT_AWAY) || ((status & ORGAN_BROKEN) && !(status & ORGAN_SPLINTED))) + return ((status & ORGAN_CUT_AWAY) || ((status & ORGAN_BROKEN) && !(splinted))) //Determines if we even need to process this organ. /obj/item/organ/external/proc/need_process() - if(status & (ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED)) + if(status & (ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_DEAD|ORGAN_MUTATED)) return 1 if((brute_dam || burn_dam) && (robotic < ORGAN_ROBOT)) //Robot limbs don't autoheal and thus don't need to process when damaged return 1 @@ -1006,21 +1011,10 @@ Note that amputating the affected organ does in fact remove the infection from t // This is mostly for the ninja suit to stop ninja being so crippled by breaks. // TODO: consider moving this to a suit proc or process() or something during // hardsuit rewrite. - if(owner && !(status & ORGAN_SPLINTED) && istype(owner,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = owner - - if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space)) - - var/obj/item/clothing/suit/space/suit = H.wear_suit - - if(isnull(suit.supporting_limbs)) - return - - owner << "You feel \the [suit] constrict about your [name], supporting it." - status |= ORGAN_SPLINTED - suit.supporting_limbs |= src - return + if(!(splinted) && owner && istype(owner.wear_suit, /obj/item/clothing/suit/space)) + var/obj/item/clothing/suit/space/suit = owner.wear_suit + suit.handle_fracture(owner, src) /obj/item/organ/external/proc/mend_fracture() if(robotic >= ORGAN_ROBOT) @@ -1031,6 +1025,20 @@ Note that amputating the affected organ does in fact remove the infection from t status &= ~ORGAN_BROKEN return 1 +/obj/item/organ/external/proc/apply_splint(var/atom/movable/splint) + if(!splinted) + splinted = splint + return 1 + return 0 + +/obj/item/organ/external/proc/remove_splint() + if(splinted) + if(splinted.loc == src) + splinted.dropInto(owner? owner.loc : src.loc) + splinted = null + return 1 + return 0 + /obj/item/organ/external/robotize(var/company, var/skip_prosthetics = 0, var/keep_organs = 0) if(robotic >= ORGAN_ROBOT) @@ -1054,6 +1062,7 @@ Note that amputating the affected organ does in fact remove the infection from t dislocated = -1 cannot_break = 1 + remove_splint() get_icon() unmutate() diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index cc4428fcb6..818e208ff4 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -140,7 +140,6 @@ user.visible_message("\blue [user] has mended the damaged bones in [target]'s [affected.name] with \the [tool]." , \ "\blue You have mended the damaged bones in [target]'s [affected.name] with \the [tool]." ) affected.status &= ~ORGAN_BROKEN - affected.status &= ~ORGAN_SPLINTED affected.stage = 0 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) diff --git a/html/changelogs/Yoshax - Splint.yml b/html/changelogs/Yoshax - Splint.yml new file mode 100644 index 0000000000..32841c06e1 --- /dev/null +++ b/html/changelogs/Yoshax - Splint.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Yoshax + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Splints are once again reusable and have been improved behind the scenes." + - bugfix: "Removing splints will now correctly give you the splint used to splint the organ."