diff --git a/aurorastation.dme b/aurorastation.dme index 072763f8211..14116c43e28 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -2494,6 +2494,7 @@ #include "code\modules\organs\subtypes\diona.dm" #include "code\modules\organs\subtypes\industrial.dm" #include "code\modules\organs\subtypes\machine.dm" +#include "code\modules\organs\subtypes\nymph_limbs.dm" #include "code\modules\organs\subtypes\parasite.dm" #include "code\modules\organs\subtypes\skrell.dm" #include "code\modules\organs\subtypes\standard.dm" diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index 900ca3c240b..2f8107cf42f 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -47,6 +47,7 @@ #define ORGAN_PLANT (1<<10) #define ORGAN_ARTERY_CUT (1<<11) #define ORGAN_LIFELIKE (1<<12) // Robotic, made to appear organic. +#define ORGAN_NYMPH (1<<13) // the largest bitflag, in the WORLD #define ORGAN_DAMAGE_STATES ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED|ORGAN_ARTERY_CUT diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index c8c69fbce0f..5142a3e02e1 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -442,4 +442,6 @@ // Robot Overlay Defines #define ROBOT_PANEL_EXPOSED "exposed" #define ROBOT_PANEL_CELL "cell" -#define ROBOT_PANEL_NO_CELL "no cell" \ No newline at end of file +#define ROBOT_PANEL_NO_CELL "no cell" + +#define BLOOD_REGEN_RATE 0.1 \ No newline at end of file diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 3cb954fa930..3a010cdb540 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -254,6 +254,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(ind > 1) out += ", " out += "\tMechanical [organ_name]" + else if(status == "nymph") + ++ind + if(ind > 1) + out += ", " + out += "\tDiona Nymph [organ_name]" else if(status == "assisted") ++ind if(ind > 1) @@ -650,7 +655,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O to_chat(user, "Cancelled.") return TOPIC_NOACTION - var/list/available_states = list("Normal","Amputated","Prosthesis") + var/list/available_states = mob_species.possible_external_organs_modifications if(carries_organs) available_states = list("Normal","Prosthesis") var/new_state = input(user, "What state do you wish the limb to be in?") as null|anything in available_states @@ -664,6 +669,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(third_limb) pref.organ_data -= third_limb pref.rlimb_data -= third_limb + if("Amputated") pref.organ_data[limb] = "amputated" pref.rlimb_data[limb] = null @@ -691,6 +697,14 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.organ_data[second_limb] = "cyborg" if(third_limb && pref.organ_data[third_limb] == "amputated") pref.organ_data[third_limb] = null + + if("Diona Nymph") + pref.organ_data[limb] = "nymph" + pref.rlimb_data[limb] = null + if(second_limb) + pref.organ_data[second_limb] = "nymph" + pref.rlimb_data[second_limb] = null + return TOPIC_REFRESH_UPDATE_PREVIEW else if(href_list["organs"]) diff --git a/code/modules/mob/living/carbon/alien/diona/diona_nymph.dm b/code/modules/mob/living/carbon/alien/diona/diona_nymph.dm index 9daf5aadea1..879dd0d8ca7 100644 --- a/code/modules/mob/living/carbon/alien/diona/diona_nymph.dm +++ b/code/modules/mob/living/carbon/alien/diona/diona_nymph.dm @@ -47,6 +47,8 @@ var/datum/reagents/metabolism/ingested + var/can_attach = TRUE // Whether they can attach to a host + /mob/living/carbon/alien/diona/get_ingested_reagents() return ingested @@ -229,6 +231,7 @@ //This function makes sure the nymph has the correct split/merge verbs, depending on whether or not its part of a gestalt /mob/living/carbon/alien/diona/proc/update_verbs() if(gestalt && !detached) + verbs |= /mob/living/carbon/alien/diona/proc/split verbs -= /mob/living/proc/ventcrawl verbs -= /mob/living/proc/hide verbs -= /mob/living/carbon/alien/diona/proc/grow @@ -236,7 +239,8 @@ verbs -= /mob/living/carbon/proc/absorb_nymph verbs -= /mob/living/carbon/proc/sample verbs -= /mob/living/carbon/alien/diona/proc/remove_hat - verbs |= /mob/living/carbon/alien/diona/proc/split + verbs -= /mob/living/carbon/alien/diona/proc/attach_nymph_limb + verbs -= /mob/living/carbon/alien/diona/proc/detach_nymph_limb else verbs |= /mob/living/carbon/alien/diona/proc/merge verbs |= /mob/living/carbon/proc/absorb_nymph @@ -245,6 +249,8 @@ verbs |= /mob/living/proc/hide verbs |= /mob/living/carbon/proc/sample verbs |= /mob/living/carbon/alien/diona/proc/remove_hat + verbs |= /mob/living/carbon/alien/diona/proc/attach_nymph_limb + verbs |= /mob/living/carbon/alien/diona/proc/detach_nymph_limb verbs -= /mob/living/carbon/alien/diona/proc/split // we want to remove this one verbs -= /mob/living/carbon/alien/verb/evolve //We don't want the old alien evolve verb diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 961461b515b..5c9b641a0fd 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -498,4 +498,7 @@ . = contents - internal_organs /mob/living/carbon/proc/is_drowsy() - return (drowsiness >= 5) \ No newline at end of file + return (drowsiness >= 5) + +/mob/living/carbon/proc/should_have_limb(var/organ_check) + return FALSE \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index d262943ea7d..aa824d9b807 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1922,6 +1922,9 @@ /mob/living/carbon/human/should_have_organ(var/organ_check) return (species?.has_organ[organ_check]) +/mob/living/carbon/human/should_have_limb(var/limb_check) + return (species?.has_limbs[limb_check]) + /mob/living/proc/resuscitate() return FALSE diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 7c012da5051..9cf10aa96a2 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -90,6 +90,7 @@ if(O) O.status = 0 switch(status) + if ("amputated") organs_by_name[O.limb_name] = null organs -= O @@ -97,6 +98,14 @@ for(var/obj/item/organ/external/child in O.children) organs_by_name[child.limb_name] = null organs -= child + + if ("nymph") + if (organ_data[name]) + O.AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/D = O.GetComponent(/datum/component/nymph_limb) + if(D) + D.nymphize(src, O.limb_name, TRUE) + if ("cyborg") if (rlimb_data[name]) O.force_skintone = FALSE diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 7e631edf7e6..e95e7c35934 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -277,6 +277,7 @@ var/bodyfall_sound = /decl/sound_category/bodyfall_sound //default, can be used for species specific falling sounds var/list/alterable_internal_organs = list(BP_HEART, BP_EYES, BP_LUNGS, BP_LIVER, BP_KIDNEYS, BP_STOMACH, BP_APPENDIX) //what internal organs can be changed in character setup + var/list/possible_external_organs_modifications = list("Normal","Amputated","Prosthesis") /datum/species/proc/get_eyes(var/mob/living/carbon/human/H) return diff --git a/code/modules/mob/living/carbon/human/species/station/skrell/skrell.dm b/code/modules/mob/living/carbon/human/species/station/skrell/skrell.dm index 0a3746aa48f..e517f7c51e8 100644 --- a/code/modules/mob/living/carbon/human/species/station/skrell/skrell.dm +++ b/code/modules/mob/living/carbon/human/species/station/skrell/skrell.dm @@ -36,6 +36,8 @@ appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_SOCKS flags = NO_SLIP + possible_external_organs_modifications = list("Normal","Amputated","Prosthesis", "Diona Nymph") + has_limbs = list( BP_CHEST = list("path" = /obj/item/organ/external/chest), BP_GROIN = list("path" = /obj/item/organ/external/groin), diff --git a/code/modules/mob/living/carbon/human/species/station/unathi/unathi.dm b/code/modules/mob/living/carbon/human/species/station/unathi/unathi.dm index 9212ede86d1..01a89be3f0e 100644 --- a/code/modules/mob/living/carbon/human/species/station/unathi/unathi.dm +++ b/code/modules/mob/living/carbon/human/species/station/unathi/unathi.dm @@ -118,6 +118,8 @@ default_accent = ACCENT_HEGEMON_PEASANT allowed_accents = list(ACCENT_HEGEMON_NOBLE, ACCENT_HEGEMON_PEASANT, ACCENT_TRAD_NOBLE, ACCENT_TRAD_PEASANT, ACCENT_WASTELAND, ACCENT_DOMINIA_HIGH, ACCENT_DOMINIA_VULGAR) + possible_external_organs_modifications = list("Normal","Amputated","Prosthesis", "Diona Nymph") + /datum/species/unathi/after_equip(var/mob/living/carbon/human/H) . = ..() if(H.shoes) diff --git a/code/modules/organs/internal/heart.dm b/code/modules/organs/internal/heart.dm index f11bbf5fe47..8c531e65ca5 100644 --- a/code/modules/organs/internal/heart.dm +++ b/code/modules/organs/internal/heart.dm @@ -121,7 +121,7 @@ //Blood regeneration if there is some space if(blood_volume < species.blood_volume && blood_volume) if(REAGENT_DATA(owner.vessel, /decl/reagent/blood)) // Make sure there's blood at all - owner.vessel.add_reagent(/decl/reagent/blood, 0.1 + LAZYACCESS(owner.chem_effects, CE_BLOODRESTORE), temperature = species?.body_temperature) + owner.vessel.add_reagent(/decl/reagent/blood, BLOOD_REGEN_RATE + LAZYACCESS(owner.chem_effects, CE_BLOODRESTORE), temperature = species?.body_temperature) if(blood_volume <= BLOOD_VOLUME_SAFE) //We lose nutrition and hydration very slowly if our blood is too low owner.adjustNutritionLoss(2) owner.adjustHydrationLoss(1) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index d9a37a5f462..6756ca12587 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -102,6 +102,8 @@ var/obj/item/organ/infect_target_internal //make internal organs become infected one at a time instead of all at once var/obj/item/organ/infect_target_external //make child and parent organs become infected one at a time instead of all at once + var/mob/living/carbon/alien/diona/nymph //used by dionae limbs + /obj/item/organ/external/proc/invalidate_marking_cache() cached_markings = null @@ -597,6 +599,10 @@ This function completely restores a damaged organ to perfect condition. if(!(status & ORGAN_BROKEN)) perma_injury = 0 + if(status & ORGAN_NYMPH) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.handle_nymph(src) + if(surge_damage && (status & ORGAN_ASSISTED)) tick_surge_damage() //Yes, this being here is intentional since this proc does not call ..() unless the owner is null. @@ -655,7 +661,7 @@ Note that amputating the affected organ does in fact remove the infection from t return if(germ_level <= 0) //Catch any weirdness that might happen with negative values - germ_level = 0 + germ_level = 0 if(owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs //** Syncing germ levels with external wounds @@ -703,7 +709,7 @@ Note that amputating the affected organ does in fact remove the infection from t antibiotics = owner.chem_effects[CE_ANTIBIOTIC] if(germ_level < INFECTION_LEVEL_TWO) - //null out the infect targets since at this point we're not in danger of spreading our infection. + //null out the infect targets since at this point we're not in danger of spreading our infection. infect_target_internal = null infect_target_external = null return ..() diff --git a/code/modules/organs/subtypes/nymph_limbs.dm b/code/modules/organs/subtypes/nymph_limbs.dm new file mode 100644 index 00000000000..99c9adeb0ab --- /dev/null +++ b/code/modules/organs/subtypes/nymph_limbs.dm @@ -0,0 +1,346 @@ +// Left Leg +/obj/item/organ/external/leg/nymph + var/nymph_child = /obj/item/organ/external/foot/nymph + +/obj/item/organ/external/leg/nymph/Initialize() + . = ..() + AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.setup_limb(src) + +/obj/item/organ/external/leg/nymph/process() + ..() + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.handle_nymph(src) + +// Right Leg +/obj/item/organ/external/leg/right/nymph + var/nymph_child = /obj/item/organ/external/foot/right/nymph + +/obj/item/organ/external/leg/right/nymph/Initialize() + . = ..() + AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.setup_limb(src) + +/obj/item/organ/external/leg/right/nymph/process() + ..() + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.handle_nymph(src) + +// Left Arm +/obj/item/organ/external/arm/nymph + var/nymph_child = /obj/item/organ/external/hand/nymph + +/obj/item/organ/external/arm/nymph/Initialize() + . = ..() + AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.setup_limb(src) + +/obj/item/organ/external/arm/nymph/process() + ..() + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.handle_nymph(src) + +// Right Arm +/obj/item/organ/external/arm/right/nymph + var/nymph_child = /obj/item/organ/external/hand/right/nymph + +/obj/item/organ/external/arm/right/nymph/Initialize() + . = ..() + AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.setup_limb(src) + +/obj/item/organ/external/arm/right/nymph/process() + ..() + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.handle_nymph(src) + +// Left Hand +/obj/item/organ/external/hand/nymph + +/obj/item/organ/external/hand/nymph/Initialize() + . = ..() + AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.setup_limb(src) + +// Right Hand +/obj/item/organ/external/hand/right/nymph + +/obj/item/organ/external/hand/right/nymph/Initialize() + . = ..() + AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.setup_limb(src) + +// Left Foot +/obj/item/organ/external/foot/nymph + +/obj/item/organ/external/foot/nymph/Initialize() + . = ..() + AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.setup_limb(src) + +// Right Foot +/obj/item/organ/external/foot/right/nymph + +/obj/item/organ/external/foot/right/nymph/Initialize() + . = ..() + AddComponent(/datum/component/nymph_limb) + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + N.setup_limb(src) + +/datum/component/nymph_limb + var/list/valid_species = list(SPECIES_UNATHI, SPECIES_SKRELL) + var/list/valid_organs_to_replace = list(BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG) + // Main limb where the Nymph mob lives + var/list/nymph_limb_types = list( + /obj/item/organ/external/arm/nymph, + /obj/item/organ/external/arm/right/nymph, + /obj/item/organ/external/leg/nymph, + /obj/item/organ/external/leg/right/nymph + ) + // Child limbs + var/list/nymph_extremity_types = list( + /obj/item/organ/external/hand/nymph, + /obj/item/organ/external/hand/right/nymph, + /obj/item/organ/external/foot/nymph, + /obj/item/organ/external/foot/right/nymph + ) + var/list/nymph_limb_types_by_name = list( + BP_L_ARM = /obj/item/organ/external/arm/nymph, + BP_R_ARM = /obj/item/organ/external/arm/right/nymph, + BP_L_LEG = /obj/item/organ/external/leg/nymph, + BP_R_LEG = /obj/item/organ/external/leg/right/nymph, + BP_L_HAND = /obj/item/organ/external/hand/nymph, + BP_R_HAND = /obj/item/organ/external/hand/right/nymph, + BP_L_FOOT = /obj/item/organ/external/foot/nymph, + BP_R_FOOT = /obj/item/organ/external/foot/right/nymph + ) + +/datum/component/nymph_limb/proc/setup_limb(var/obj/item/organ/external/E) + if(is_type_in_list(E, nymph_limb_types)) + E.nymph = new /mob/living/carbon/alien/diona + else if(!is_type_in_list(E, nymph_extremity_types)) + return + + E.status |= (ORGAN_PLANT | ORGAN_NYMPH) + E.species = all_species["Nymph Limb"] + E.fingerprints = null + if(!E.dna) + E.blood_DNA = list() + E.set_dna(new /datum/dna) + + E.limb_flags &= ~(ORGAN_CAN_BREAK | ORGAN_CAN_MAIM | ORGAN_HAS_TENDON) + +// Called by process() +/datum/component/nymph_limb/proc/handle_nymph(var/obj/item/organ/external/E) + var/mob/living/carbon/alien/diona/limb_nymph = E.nymph + if(!istype(limb_nymph)) + return FALSE + if(!E || !is_type_in_list(E, nymph_limb_types)) + return FALSE + if((!E.owner || limb_nymph.stat == DEAD)) + nymph_out(E, limb_nymph) + return FALSE + + if(!E.is_usable()) + nymph_out(E, limb_nymph, forced = TRUE) + return FALSE + + var/blood_volume = round(REAGENT_VOLUME(E.owner.vessel, /decl/reagent/blood)) + if(blood_volume) + if(REAGENT_DATA(E.owner.vessel, /decl/reagent/blood)) + E.owner.vessel.remove_reagent(/decl/reagent/blood, BLOOD_REGEN_RATE / (2 * nymph_limb_types_by_name.len)) + if(blood_volume <= 0) + nymph_out(E, limb_nymph, forced = TRUE) + +// Host detach +/mob/living/carbon/human/proc/detach_nymph_limb() + set category = "Abilities" + set name = "Detach Nymph" + + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + + // Find our existing nymphlimbs + var/list/my_nymph_limbs = list() + for(var/obj/item/organ/external/O in organs) + if(is_type_in_list(O, N.nymph_limb_types)) + my_nymph_limbs += O + if(!my_nymph_limbs.len) + return FALSE + + // Player picks a nymphlimb and removes it + var/obj/item/organ/external/E = input(src, "Select a limb to detach:", "Nymph Limb Detach") as null|anything in my_nymph_limbs + if(!istype(E)) + return + if(!do_after(src, delay = 3 SECONDS, needhand = FALSE)) + return + if(E.detach_nymph_limb() && my_nymph_limbs.len == 1) + verbs -= /mob/living/carbon/human/proc/detach_nymph_limb + + regenerate_icons() + +// Nymph detach +/mob/living/carbon/alien/diona/proc/detach_nymph_limb() + set category = "Abilities" + set name = "Detach from Host" + + var/obj/item/organ/external/E = loc + if(istype(E)) + to_chat(src, "You start to detach from your host.") + to_chat(E.owner, "The nymph acting as your [E.name] starts to unattach itself.") + if(do_after(src, delay = 3 SECONDS, needhand = FALSE)) + E.detach_nymph_limb() + +// Organ detach +/obj/item/organ/external/proc/detach_nymph_limb() + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + var/mob/living/carbon/alien/diona/nymph = src:nymph + var/nymph_owner = owner + + if(nymph) + N.nymph_out(src, nymph) + to_chat(nymph_owner, span("warning", "The nymph attached to you as \a [name] unlatches its tendrils from your body and drops to \the [get_turf(src)].")) + to_chat(nymph, span("notice", "You tear your tendrils free of your host and drop to \the [get_turf(src)].")) + + return TRUE + +// Nymph attach +/mob/living/carbon/alien/diona/proc/attach_nymph_limb() + set category = "Abilities" + set name = "Attach to Nearby Host" + + if(incapacitated()) + return + if(!isturf(loc)) + return + if(!can_attach) + to_chat(src, span("warning", "You do not have the strength to attach to another host so soon.")) + + + var/datum/component/nymph_limb/N = GetComponent(/datum/component/nymph_limb) + var/list/mob/living/carbon/human/mob_list = list() + + // Find a new host + for(var/mob/living/carbon/human/H in view(1)) + if(ishuman(H) && (H.species?.name in N.valid_species) && \ + H.client && H.stat == CONSCIOUS) + mob_list += H + + if(!LAZYLEN(mob_list)) + to_chat(src, span("warning", "There are no valid hosts to bond to.")) + return FALSE + + var/choice = input(src, "Choose a host to bond to:", "Attach to Host") in mob_list + var/mob/living/carbon/human/target = choice + if(!Adjacent(target) || target.stat || !target.client) + return + + // Find a location to bond to, on the host + var/list/valid_locations = list() + for(var/O in target.organs_by_name) + if(!target.organs_by_name[O] && (O in N.valid_organs_to_replace)) + valid_locations += O + + var/limb_choice + if(!valid_locations.len) + to_chat(src, span("warning", "\The [target.name] has no suitable spots for you to attach to their body!")) + return + else + limb_choice = input(src,"Choose a location to attach onto \the [target.name]","Nymph Attachment Point") as null|anything in valid_locations + if(!limb_choice) + return + + if(!do_after(src, delay = 3 SECONDS, needhand = FALSE)) + return + + // Make new limb and put it on the host + limb_choice = N.nymph_limb_types_by_name[limb_choice] + var/obj/item/organ/external/new_nymph_limb = new limb_choice + if(!istype(new_nymph_limb)) + return + new_nymph_limb.replaced(target) + + if(new_nymph_limb:nymph_child) + var/obj/item/organ/external/new_nymph_child = new new_nymph_limb:nymph_child + new_nymph_child.replaced(target) + + target.regenerate_icons() + + N.nymph_in(new_nymph_limb, src) + +/datum/component/nymph_limb/proc/nymph_in(var/obj/item/organ/external/E, var/mob/living/carbon/alien/diona/nymph) + var/mob/living/carbon/alien/diona/limb_nymph = E.nymph + if(limb_nymph) + if(!limb_nymph.client) + QDEL_NULL(limb_nymph) + else + return + + if(nymph.client) + nymph.client.eye = E.owner + limb_nymph = nymph + limb_nymph.forceMove(E) + +/datum/component/nymph_limb/proc/nymph_out(var/obj/item/organ/external/E, var/mob/living/carbon/alien/diona/nymph, var/forced = FALSE) + if(nymph.client) + nymph.client.eye = nymph + nymph.forceMove(get_turf(E)) + E.nymph = null + + if(forced) + nymph.can_attach = FALSE + addtimer(CALLBACK(nymph, /datum/component/nymph_limb/.proc/can_attach, nymph), 5 MINUTES, TIMER_UNIQUE) + + E.removed(E.owner) + qdel(E) + +/datum/component/nymph_limb/proc/can_attach(var/mob/living/carbon/alien/diona/nymph) + if(nymph) + nymph.can_attach = TRUE + to_chat(nymph, span("notice", "Your body has regained enough strength to attach to a new host, if you can find one.")) + +// For limbs created by character setup +/datum/component/nymph_limb/proc/nymphize(var/mob/living/carbon/human/H, var/organ_name, var/forced = FALSE) + if(!H.should_have_limb(organ_name)) + return + if(H.organs_by_name[organ_name]) + if(forced) // Do we wish to remove any limbs currently occupying that spot? + var/obj/item/organ/external/O = H.get_organ(organ_name) + qdel(O) + H.organs_by_name[organ_name] = null + else + return + // Create and attach our new nymph limb + var/nymph_limb_type = nymph_limb_types_by_name[organ_name] + var/obj/item/organ/external/E = new nymph_limb_type + E.replaced(H) + for(var/obj/item/organ/external/child in E.children) + nymphize(H, child.organ_tag, TRUE) + H.verbs |= /mob/living/carbon/human/proc/detach_nymph_limb + +/datum/species/diona/nymph_limb // For use on nymph-limb organs only + name = "Nymph Limb" + short_name = "nym" + name_plural = "Nymph Limbs" + bodytype = "Nymph" + icobase = 'icons/mob/human_races/limbs_nymph.dmi' + deform = 'icons/mob/human_races/limbs_nymph.dmi' + + has_organ = list() + + has_limbs = list( + BP_L_ARM = list( "path" = /obj/item/organ/external/arm/nymph), + BP_R_ARM = list( "path" = /obj/item/organ/external/arm/right/nymph), + BP_L_LEG = list( "path" = /obj/item/organ/external/leg/nymph), + BP_R_LEG = list( "path" = /obj/item/organ/external/leg/right/nymph), + BP_L_HAND = list( "path" = /obj/item/organ/external/hand/nymph), + BP_R_HAND = list( "path" = /obj/item/organ/external/hand/right/nymph), + BP_L_FOOT = list( "path" = /obj/item/organ/external/foot/nymph), + BP_R_FOOT = list( "path" = /obj/item/organ/external/foot/right/nymph) + ) \ No newline at end of file diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index 06ddaded55a..cd4f7851015 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -8,7 +8,7 @@ var/list/allowed_tools = null // type paths referencing races that this step applies to. var/list/allowed_species = null - var/list/disallowed_species = null + var/list/disallowed_species = list("Nymph") // duration of the step var/min_duration = 0 diff --git a/html/changelogs/alberyk-dionalimb.yml b/html/changelogs/alberyk-dionalimb.yml new file mode 100644 index 00000000000..878059493bf --- /dev/null +++ b/html/changelogs/alberyk-dionalimb.yml @@ -0,0 +1,6 @@ +author: Albery, Aticus, Mikomyazaki + +delete-after: True + +changes: + - rscadd: "Added a diona nymph limbs to the limbs option in the character creation setup. Skrell and unathi can pick them." diff --git a/icons/mob/human_races/limbs_nymph.dmi b/icons/mob/human_races/limbs_nymph.dmi new file mode 100644 index 00000000000..d1c7460c8e7 Binary files /dev/null and b/icons/mob/human_races/limbs_nymph.dmi differ