From 1d4011322ef8d1935e3aa79332048608b269cfec Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Wed, 25 Oct 2023 18:16:21 +1100 Subject: [PATCH] Readding FBP. --- code/__defines/aspects.dm | 15 +++++++ .../aspects/aspects_prosthetic_limbs.dm | 38 ++++++++++++++++- .../designs/robotics/designs_prosthetics.dm | 11 +++-- .../mob/living/carbon/human/human_movement.dm | 2 +- code/modules/organs/external/_external.dm | 14 +++++-- code/modules/organs/external/head.dm | 4 +- code/modules/organs/organ.dm | 12 ++++-- .../prosthetics/prosthetics_manufacturer.dm | 9 ++++ code/modules/species/species_bodytype.dm | 41 ++++++++++++++++--- .../species/species_bodytype_helpers.dm | 2 +- code/modules/species/station/human.dm | 4 +- 11 files changed, 130 insertions(+), 22 deletions(-) diff --git a/code/__defines/aspects.dm b/code/__defines/aspects.dm index e1498bae6d7..6e7619db774 100644 --- a/code/__defines/aspects.dm +++ b/code/__defines/aspects.dm @@ -51,4 +51,19 @@ model = MODEL_PATH; \ parent = /decl/aspect/prosthetic_limb/right_leg; \ aspect_cost = COST; \ +} \ +/decl/aspect/prosthetic_limb/head/##MODEL_ID { \ + model = MODEL_PATH; \ + parent = /decl/aspect/prosthetic_limb/head; \ + aspect_cost = COST * 0.5; \ +} \ +/decl/aspect/prosthetic_limb/chest/##MODEL_ID { \ + model = MODEL_PATH; \ + parent = /decl/aspect/prosthetic_limb/chest; \ + aspect_cost = COST * 0.5; \ +} \ +/decl/aspect/prosthetic_limb/groin/##MODEL_ID { \ + model = MODEL_PATH; \ + parent = /decl/aspect/prosthetic_limb/groin; \ + aspect_cost = COST * 0.5; \ } diff --git a/code/modules/aspects/aspects_prosthetic_limbs.dm b/code/modules/aspects/aspects_prosthetic_limbs.dm index 2595ba96094..40c97f9b2c4 100644 --- a/code/modules/aspects/aspects_prosthetic_limbs.dm +++ b/code/modules/aspects/aspects_prosthetic_limbs.dm @@ -5,6 +5,8 @@ sort_value = 2 aspect_flags = ASPECTS_PHYSICAL abstract_type = /decl/aspect/prosthetic_limb + var/fullbody_synthetic_only = FALSE + var/replace_children = TRUE var/check_bodytype var/bodypart_name var/apply_to_limb = BP_L_HAND @@ -63,6 +65,10 @@ /decl/aspect/prosthetic_limb/is_available_to(datum/preferences/pref) . = ..() if(.) + if(fullbody_synthetic_only) + var/decl/bodytype/bodytype = pref.get_bodytype_decl() + if(!bodytype?.is_robotic) + return FALSE if(model) var/decl/bodytype/prosthetic/R = GET_DECL(model) if(!istype(R)) @@ -89,15 +95,19 @@ // Robotize the selected limb. if(. && apply_to_limb) + var/use_model = model || get_base_model(holder.get_species_name()) var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(holder, apply_to_limb) if(!istype(E)) var/list/organ_data = holder.should_have_limb(apply_to_limb) var/limb_path = organ_data["path"] if("path" in organ_data) - E = new limb_path(holder, null, model || get_base_model(holder.get_species_name())) + E = new limb_path(holder, null, use_model) if(istype(E) && E.bodytype != model) // sometimes in the last line we save ourselves some work here // this should be pre-validated by is_available_to() - E.set_bodytype_with_children(model || get_base_model(holder.get_species_name())) + if(replace_children) + E.set_bodytype_with_children(use_model) + else + E.set_bodytype(use_model) /decl/aspect/prosthetic_limb/left_hand bodypart_name = "Left Hand" @@ -142,3 +152,27 @@ aspect_cost = 2 apply_to_limb = BP_R_LEG incompatible_with_limbs = list(BP_R_FOOT, BP_R_LEG) + +/decl/aspect/prosthetic_limb/head + bodypart_name = "Head" + aspect_cost = 1 + apply_to_limb = BP_HEAD + incompatible_with_limbs = list(BP_HEAD) + fullbody_synthetic_only = TRUE + replace_children = FALSE + +/decl/aspect/prosthetic_limb/chest + bodypart_name = "Upper Body" + aspect_cost = 1 + apply_to_limb = BP_CHEST + incompatible_with_limbs = list(BP_CHEST) + fullbody_synthetic_only = TRUE + replace_children = FALSE + +/decl/aspect/prosthetic_limb/groin + bodypart_name = "Lower Body" + aspect_cost = 1 + apply_to_limb = BP_GROIN + incompatible_with_limbs = list(BP_GROIN) + fullbody_synthetic_only = TRUE + replace_children = FALSE diff --git a/code/modules/fabrication/designs/robotics/designs_prosthetics.dm b/code/modules/fabrication/designs/robotics/designs_prosthetics.dm index 663198ca351..c6dd464a844 100644 --- a/code/modules/fabrication/designs/robotics/designs_prosthetics.dm +++ b/code/modules/fabrication/designs/robotics/designs_prosthetics.dm @@ -31,12 +31,17 @@ } \ /datum/fabricator_recipe/robotics/prosthetic/model_##MODEL_ID/groin { \ path = /obj/item/organ/external/groin; \ -} -/* Readd if FBP construction is desirable +} \ /datum/fabricator_recipe/robotics/prosthetic/model_##MODEL_ID/chest { \ path = /obj/item/organ/external/chest; \ } \ -*/ +/datum/fabricator_recipe/robotics/prosthetic/model_##MODEL_ID/head { \ + path = /obj/item/organ/external/head; \ +} \ +/datum/fabricator_recipe/robotics/prosthetic/model_##MODEL_ID/groin { \ + path = /obj/item/organ/external/groin; \ +} + /datum/fabricator_recipe/robotics/prosthetic var/model diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 77ed36f7740..4d660df5951 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -149,6 +149,6 @@ var/mob/M = buckled M.unbuckle_mob() var/decl/bodytype/B = get_bodytype() - playsound(loc, isSynthetic() ? pick(B.synthetic_bodyfall_sounds) : pick(B.bodyfall_sounds), 50, TRUE, -1) + playsound(loc, B.bodyfall_sounds, 50, TRUE, -1) else if(!lying && !old_buckled_lying) handle_stance() // Force an immediate stance update. diff --git a/code/modules/organs/external/_external.dm b/code/modules/organs/external/_external.dm index 47569ca121f..71c8d9cc1ee 100644 --- a/code/modules/organs/external/_external.dm +++ b/code/modules/organs/external/_external.dm @@ -132,10 +132,14 @@ LAZYADD(unarmed_attacks, attack_type) get_icon() -/obj/item/organ/external/set_bodytype(decl/bodytype/new_bodytype, override_material = null) - . = ..() +/obj/item/organ/external/set_bodytype(decl/bodytype/new_bodytype, override_material = null, apply_to_internal_organs = TRUE) + var/decl/bodytype/old_bodytype = bodytype + . = ..(new_bodytype, override_material) + if(bodytype != old_bodytype && apply_to_internal_organs) + bodytype.rebuild_internal_organs(src, override_material) slowdown = bodytype.movement_slowdown - update_icon(TRUE) + if(.) + update_icon(TRUE) /obj/item/organ/external/proc/set_bodytype_with_children(decl/bodytype/new_bodytype, override_material = null) set_bodytype(new_bodytype, override_material) @@ -428,6 +432,8 @@ //If attached to an owner mob if(istype(owner)) + owner.full_prosthetic = null + // Initialize fingerprints if we don't already have some (TODO: we're assuming this is our first owner, maybe check for this elsewhere?). if((limb_flags & ORGAN_FLAG_FINGERPRINT) && !fingerprint && !BP_IS_PROSTHETIC(src)) fingerprint = owner.get_full_print(ignore_blockers = TRUE) @@ -1388,6 +1394,8 @@ Note that amputating the affected organ does in fact remove the infection from t continue organ.do_install(null, src, FALSE, update_icon, FALSE) //Forcemove the organ and properly set it up in our internal data + victim.full_prosthetic = null + //Note that we don't need to change our own hierarchy when not removing from a mob // Remove parent references diff --git a/code/modules/organs/external/head.dm b/code/modules/organs/external/head.dm index 75783bdc40a..14ebb37894a 100644 --- a/code/modules/organs/external/head.dm +++ b/code/modules/organs/external/head.dm @@ -75,9 +75,9 @@ /obj/item/organ/external/head/get_agony_multiplier() return (owner && owner.headcheck(organ_tag)) ? 1.50 : 1 -/obj/item/organ/external/head/set_bodytype(decl/bodytype/new_bodytype, override_material = null) +/obj/item/organ/external/head/set_bodytype(decl/bodytype/new_bodytype, override_material = null, apply_to_internal_organs = TRUE) . = ..() - has_lips = bodytype.appearance_flags & HAS_LIPS + has_lips = (bodytype.appearance_flags & HAS_LIPS) can_intake_reagents = !(bodytype.body_flags & BODY_FLAG_NO_EAT) draw_eyes = bodytype.has_eyes diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index e620be9b5bc..a2a723fd1b3 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -125,13 +125,16 @@ blood_DNA = list(dna.unique_enzymes = dna.b_type) set_species(dna.species) -/obj/item/organ/proc/set_bodytype(decl/bodytype/new_bodytype, override_material = null) +/obj/item/organ/proc/set_bodytype(decl/bodytype/new_bodytype, override_material = null, apply_to_internal_organs = TRUE) + SHOULD_CALL_PARENT(TRUE) if(isnull(new_bodytype)) - CRASH("Null bodytype passed to set_bodytype!") + PRINT_STACK_TRACE("Null bodytype passed to set_bodytype!") + return FALSE if(ispath(new_bodytype, /decl/bodytype)) new_bodytype = GET_DECL(new_bodytype) if(!istype(new_bodytype)) - CRASH("Invalid bodytype [new_bodytype]") + PRINT_STACK_TRACE("Invalid bodytype [new_bodytype]") + return FALSE bodytype = new_bodytype if(bodytype.modifier_string) name = "[bodytype.modifier_string] [initial(name)]" @@ -141,7 +144,7 @@ min_broken_damage *= bodytype.hardiness bodytype.resize_organ(src) set_material(override_material || bodytype.material) - matter = bodytype.matter + matter = bodytype.matter?.Copy() create_matter() // maybe this should be a generalized repopulate_reagents helper?? if(reagents) @@ -150,6 +153,7 @@ if(bodytype.body_flags & BODY_FLAG_NO_DNA) QDEL_NULL(dna) reset_status() + return TRUE /obj/item/organ/proc/set_species(specie_name) vital_to_owner = null // This generally indicates the owner mob is having species set, and this value may be invalidated. diff --git a/code/modules/organs/prosthetics/prosthetics_manufacturer.dm b/code/modules/organs/prosthetics/prosthetics_manufacturer.dm index b91d7da5b10..126d600e12a 100644 --- a/code/modules/organs/prosthetics/prosthetics_manufacturer.dm +++ b/code/modules/organs/prosthetics/prosthetics_manufacturer.dm @@ -9,6 +9,15 @@ material = /decl/material/solid/metal/steel eye_flash_mod = 1 eye_darksight_range = 2 + associated_gender = PLURAL + bodyfall_sounds = list( + 'sound/foley/metal1.ogg' + ) + has_organ = list( + BP_BRAIN = /obj/item/organ/internal/mmi_holder, + BP_EYES = /obj/item/organ/internal/eyes, + BP_CELL = /obj/item/organ/internal/cell + ) /// Determines which bodyparts can use this limb. var/list/applies_to_part diff --git a/code/modules/species/species_bodytype.dm b/code/modules/species/species_bodytype.dm index 9bafc3b6237..8c6b99ecd2e 100644 --- a/code/modules/species/species_bodytype.dm +++ b/code/modules/species/species_bodytype.dm @@ -79,10 +79,6 @@ var/global/list/bodytypes_by_category = list() 'sound/foley/meat2.ogg' ) - var/list/synthetic_bodyfall_sounds = list( - 'sound/foley/metal1.ogg' - ) - // Used for initializing prefs/preview var/base_color = COLOR_BLACK var/base_eye_color = COLOR_BLACK @@ -91,7 +87,7 @@ var/global/list/bodytypes_by_category = list() /// Used to initialize organ material var/material = /decl/material/solid/meat /// Used to initialize organ matter - var/matter = null + var/list/matter = null /// The reagent organs are filled with, which currently affects what mobs that eat the organ will receive. /// TODO: Remove this in a later matter edibility refactor. var/edible_reagent = /decl/material/liquid/nutriment/protein @@ -390,3 +386,38 @@ var/global/list/bodytypes_by_category = list() var/decl/hierarchy/outfit/outfit = outfit_by_type(preview_outfit) outfit.equip_outfit(mannequin, equip_adjustments = (OUTFIT_ADJUSTMENT_SKIP_SURVIVAL_GEAR|OUTFIT_ADJUSTMENT_SKIP_BACKPACK)) mannequin.update_transform() + +/decl/bodytype/proc/rebuild_internal_organs(var/obj/item/organ/external/limb, var/override_material) + + if(!limb.owner) + return + + // Work out what we want to have in this organ. + var/list/replacing_organs = list() + for(var/organ_tag in has_organ) + var/obj/item/organ/internal/organ_prototype = has_organ[organ_tag] + if(initial(organ_prototype.parent_organ) == limb.organ_tag) + replacing_organs[organ_tag] = organ_prototype + + // No organs, just delete everything. + if(!length(replacing_organs)) + for(var/obj/item/organ/internal/innard in limb.internal_organs) + limb.owner.remove_organ(innard, FALSE, FALSE, TRUE, TRUE, FALSE) + qdel(innard) + return + + // Check what we already have that matches. + for(var/obj/item/organ/internal/innard in limb.internal_organs) + var/obj/item/organ/internal/organ_prototype = replacing_organs[innard.organ_tag] + if(organ_prototype && istype(innard, organ_prototype)) + innard.set_bodytype(type, override_material || material) + replacing_organs -= innard.organ_tag + else + limb.owner.remove_organ(innard, FALSE, FALSE, TRUE, TRUE, FALSE) + qdel(innard) + + // Install any necessary new organs. + for(var/organ_tag in replacing_organs) + var/organ_type = replacing_organs[organ_tag] + var/obj/item/organ/internal/new_innard = new organ_type(limb.owner, null, limb.owner.dna, src) + limb.owner.add_organ(new_innard, GET_EXTERNAL_ORGAN(limb.owner, new_innard.parent_organ), FALSE, FALSE) diff --git a/code/modules/species/species_bodytype_helpers.dm b/code/modules/species/species_bodytype_helpers.dm index 815c6b3938c..d2efe0d3bca 100644 --- a/code/modules/species/species_bodytype_helpers.dm +++ b/code/modules/species/species_bodytype_helpers.dm @@ -38,4 +38,4 @@ pref.body_markings = base_markings?.Copy() /decl/bodytype/proc/apply_appearance(var/mob/living/carbon/human/H) - H.skin_colour = base_color \ No newline at end of file + H.skin_colour = base_color diff --git a/code/modules/species/station/human.dm b/code/modules/species/station/human.dm index d2e602c39b7..11962d6f9b0 100644 --- a/code/modules/species/station/human.dm +++ b/code/modules/species/station/human.dm @@ -8,9 +8,11 @@ spawn_flags = SPECIES_CAN_JOIN inherent_verbs = list(/mob/living/carbon/human/proc/tie_hair) + // Add /decl/bodytype/prosthetic/basic_human to this list to allow full-body prosthetics. available_bodytypes = list( /decl/bodytype/human, - /decl/bodytype/human/masculine + /decl/bodytype/human/masculine, + /decl/bodytype/prosthetic/basic_human ) exertion_effect_chance = 10