diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index ee083f3468c..51186e53023 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -190,6 +190,17 @@ #define ORGAN_SLOT_VOICE "vocal_cords" #define ORGAN_SLOT_ZOMBIE "zombie_infection" +/// Organ slot external +#define ORGAN_SLOT_EXTERNAL_TAIL "tail" +#define ORGAN_SLOT_EXTERNAL_SPINES "spines" +#define ORGAN_SLOT_EXTERNAL_SNOUT "snout" +#define ORGAN_SLOT_EXTERNAL_FRILLS "frills" +#define ORGAN_SLOT_EXTERNAL_HORNS "horns" +#define ORGAN_SLOT_EXTERNAL_WINGS "wings" +#define ORGAN_SLOT_EXTERNAL_ANTENNAE "antennae" +#define ORGAN_SLOT_EXTERNAL_BODYMARKINGS "bodymarkings" + + /// Xenomorph organ slots #define ORGAN_SLOT_XENO_ACIDGLAND "acid_gland" #define ORGAN_SLOT_XENO_EGGSAC "eggsac" diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index c956ba673c7..6d5a5389e40 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -1062,6 +1062,10 @@ ///from /mob/living/carbon/human/proc/set_coretemperature(): (oldvalue, newvalue) #define COMSIG_HUMAN_CORETEMP_CHANGE "human_coretemp_change" +///from /datum/species/handle_fire. Called when the human is set on fire and burning clothes and stuff +#define COMSIG_HUMAN_BURNING "human_burning" + + // /datum/species signals ///from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index db74070cc87..e0fd3be5c1a 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -51,6 +51,17 @@ #define FIRE_LAYER 1 //If you're on fire #define TOTAL_LAYERS 34 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; //SKYRAT EDIT CHANGE - 30 from 29. Added BANDAGE_LAYER //SKYRAT EDIT ADDITION - ERP UPDATE - value changed to 34 from 30. Added layers for ERP items. +//Bitflags for the layers an external organ can draw on +#define EXTERNAL_FRONT (1 << 1) +#define EXTERNAL_ADJACENT (1 << 2) +#define EXTERNAL_BEHIND (1 << 3) +#define ALL_EXTERNAL_OVERLAYS EXTERNAL_FRONT | EXTERNAL_ADJACENT | EXTERNAL_BEHIND + +//The layer external organs draw. These are drawn on the limbs, so the layers are relative to the limb theyre being drawn on +#define EXTERNAL_FRONT_LAYER 2 +#define EXTERNAL_ADJACENT_LAYER 1 +#define EXTERNAL_BEHIND_LAYER -1 + //Human Overlay Index Shortcuts for alternate_worn_layer, layers //Because I *KNOW* somebody will think layer+1 means "above" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index aaba7d5741e..14364aab560 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -332,6 +332,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_NOBLEED "nobleed" //This carbon doesn't bleed /// This atom can ignore the "is on a turf" check for simple AI datum attacks, allowing them to attack from bags or lockers as long as any other conditions are met #define TRAIT_AI_BAGATTACK "bagattack" +///When people are floating from zero-grav or something, we can move around freely! +#define TRAIT_FREE_FLOAT_MOVEMENT "free_float_movement" /// This mobs bodyparts are invisible but still clickable. #define TRAIT_INVISIBLE_MAN "invisible_man" // You can stare into the abyss, but it does not stare back. diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 3ef54e7e9a1..48b58fef695 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -543,8 +543,7 @@ if(dna.features["moth_wings"]) var/genetic_value = GLOB.moth_wings_list[deconstruct_block(getblock(features, DNA_MOTH_WINGS_BLOCK), GLOB.moth_wings_list.len)] dna.features["original_moth_wings"] = genetic_value - if(dna.features["moth_wings"] != "Burnt Off") - dna.features["moth_wings"] = genetic_value + dna.features["moth_wings"] = genetic_value if(dna.features["moth_antennae"]) var/genetic_value = GLOB.moth_antennae_list[deconstruct_block(getblock(features, DNA_MOTH_ANTENNAE_BLOCK), GLOB.moth_antennae_list.len)] dna.features["original_moth_antennae"] = genetic_value diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 6444ae35449..16a6e9f5d76 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -155,10 +155,11 @@ . = ..() if(.) var/mob/living/carbon/human/H = user - if(findtext(select_message_type(user,intentional), "open")) - H.OpenWings() + var/obj/item/organ/external/wings/functional/wings = H.getorganslot(ORGAN_SLOT_EXTERNAL_WINGS) + if(wings && findtext(select_message_type(user,intentional), "open")) + wings.open_wings() else - H.CloseWings() + wings.close_wings() /datum/emote/living/carbon/human/wing/select_message_type(mob/user, intentional) . = ..() @@ -175,25 +176,6 @@ if(H.dna && H.dna.species && (H.dna.features["wings"] != "None")) return TRUE -/mob/living/carbon/human/proc/OpenWings() - if(!dna || !dna.species) - return - if(dna.species.mutant_bodyparts["wings"]) - dna.species.mutant_bodyparts["wingsopen"] = dna.species.mutant_bodyparts["wings"] - dna.species.mutant_bodyparts -= "wings" - update_body() - -/mob/living/carbon/human/proc/CloseWings() - if(!dna || !dna.species) - return - if(dna.species.mutant_bodyparts["wingsopen"]) - dna.species.mutant_bodyparts["wings"] = dna.species.mutant_bodyparts["wingsopen"] - dna.species.mutant_bodyparts -= "wingsopen" - update_body() - if(isturf(loc)) - var/turf/T = loc - T.Entered(src, null) - //Ayy lmao diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index ef518022e3c..257f5d6cb33 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -48,7 +48,7 @@ if(shoes && body_position == STANDING_UP && loc == NewLoc && has_gravity(loc)) SEND_SIGNAL(shoes, COMSIG_SHOES_STEP_ACTION) -/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee. - if(dna.species.space_move(src)) +/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) + if(movement_type & FLYING || HAS_TRAIT(src, TRAIT_FREE_FLOAT_MOVEMENT)) return TRUE return ..() diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index d61b7b02e37..fc4d4381579 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -616,6 +616,9 @@ generate/load female uniform sprites matching all previously decided variables for(var/X in bodyparts) var/obj/item/bodypart/BP = X . += "-[BP.body_zone]" + for(var/obj/item/organ/external/organ in BP.external_organs) + if(organ.can_draw_on_bodypart(src)) //make sure we're drawn before generating a key + . += "([organ.cache_key])" //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION /* if(BP.status == BODYPART_ORGANIC) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 3a471f0cb60..f9285923e19 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -79,6 +79,9 @@ GLOBAL_LIST_EMPTY(roundstart_races) BODY_ZONE_L_LEG = /obj/item/bodypart/l_leg,\ BODY_ZONE_R_LEG = /obj/item/bodypart/r_leg,\ BODY_ZONE_CHEST = /obj/item/bodypart/chest) + + ///List of external organs to generate like horns, frills, wings, etc. list(typepath of organ = "Round Beautiful BDSM Snout"). Still WIP + var/list/external_organs = list() ///Multiplier for the race's speed. Positive numbers make it move slower, negative numbers make it move faster. var/speedmod = 0 ///Percentage modifier for overall defense of the race, or less defense, if it's negative. @@ -124,8 +127,6 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/flying_species = FALSE ///The actual flying ability given to flying species var/datum/action/innate/flight/fly - ///Current wings icon - var/wings_icon = "Angel" //Dictates which wing icons are allowed for a given species. If count is >1 a radial menu is used to choose between all icons in list var/list/wings_icons = list("Angel") ///Used to determine what description to give when using a potion of flight, if false it will describe them as growing new wings @@ -461,6 +462,10 @@ GLOBAL_LIST_EMPTY(roundstart_races) C.Digitigrade_Leg_Swap(TRUE) for(var/X in inherent_traits) REMOVE_TRAIT(C, X, SPECIES_TRAIT) + for(var/obj/item/organ/external/organ in C.internal_organs) + if(organ.type in external_organs) + organ.Remove(C) + qdel(organ) //If their inert mutation is not the same, swap it out if((inert_mutation != new_species.inert_mutation) && LAZYLEN(C.dna.mutation_index) && (inert_mutation in C.dna.mutation_index)) @@ -476,15 +481,6 @@ GLOBAL_LIST_EMPTY(roundstart_races) for(var/i in inherent_factions) C.faction -= i - if(flying_species) - fly.Remove(C) - QDEL_NULL(fly) - if(C.movement_type & FLYING) - ToggleFlight(C) - if(C.dna && C.dna.species && (C.dna.features["wings"] == wings_icon)) - C.dna.species.mutant_bodyparts -= "wings" - C.dna.features["wings"] = "None" - C.update_body() clear_tail_moodlets(C) C.remove_movespeed_modifier(/datum/movespeed_modifier/species) @@ -877,18 +873,6 @@ GLOBAL_LIST_EMPTY(roundstart_races) else if (mutant_bodyparts["tail"]) bodyparts_to_add -= "waggingspines" - if(mutant_bodyparts["snout"]) //Take a closer look at that snout! - if((source.wear_mask && (source.wear_mask.flags_inv & HIDESNOUT)) || (source.head && (source.head.flags_inv & HIDESNOUT)) || !noggin || noggin.status == BODYPART_ROBOTIC) - bodyparts_to_add -= "snout" - - if(mutant_bodyparts["frills"]) - if(!source.dna.features["frills"] || source.dna.features["frills"] == "None" || source.head && (source.head.flags_inv & HIDEEARS) || !noggin || noggin.status == BODYPART_ROBOTIC) - bodyparts_to_add -= "frills" - - if(mutant_bodyparts["horns"]) - if(!source.dna.features["horns"] || source.dna.features["horns"] == "None" || source.head && (source.head.flags_inv & HIDEHAIR) || (source.wear_mask && (source.wear_mask.flags_inv & HIDEHAIR)) || !noggin || noggin.status == BODYPART_ROBOTIC) - bodyparts_to_add -= "horns" - if(mutant_bodyparts["ears"]) if(!source.dna.features["ears"] || source.dna.features["ears"] == "None" || source.head && (source.head.flags_inv & HIDEHAIR) || (source.wear_mask && (source.wear_mask.flags_inv & HIDEHAIR)) || !noggin || noggin.status == BODYPART_ROBOTIC) bodyparts_to_add -= "ears" @@ -1071,8 +1055,6 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/takes_crit_damage = (!HAS_TRAIT(H, TRAIT_NOCRITDAMAGE)) if((H.health < H.crit_threshold) && takes_crit_damage && H.stat != DEAD) H.adjustBruteLoss(0.5 * delta_time) - if(flying_species) - HandleFlight(H) /datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H) return @@ -1996,6 +1978,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(!CanIgniteMob(H)) return TRUE if(H.on_fire) + SEND_SIGNAL(H, COMSIG_HUMAN_BURNING) //the fire tries to damage the exposed clothes and items var/list/burning_items = list() var/obscured = H.check_obscured_slots(TRUE) @@ -2068,19 +2051,12 @@ GLOBAL_LIST_EMPTY(roundstart_races) //////////// /datum/species/proc/spec_stun(mob/living/carbon/human/H,amount) - if(flying_species && H.movement_type & FLYING) - ToggleFlight(H) - flyslip(H) - . = stunmod * H.physiology.stun_mod * amount - -////////////// -//Space Move// -////////////// - -/datum/species/proc/space_move(mob/living/carbon/human/H) if(H.movement_type & FLYING) - return TRUE - return FALSE + var/obj/item/organ/external/wings/functional/wings = H.getorganslot(ORGAN_SLOT_EXTERNAL_WINGS) + if(wings) + wings.toggle_flight(H) + wings.fly_slip(H) + . = stunmod * H.physiology.stun_mod * amount /datum/species/proc/negates_gravity(mob/living/carbon/human/H) if(H.movement_type & FLYING) @@ -2191,6 +2167,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(flying_species) //species that already have flying traits should not work with this proc return flying_species = TRUE + var/wings_icon if(wings_icons.len > 1) if(!H.client) wings_icon = pick(wings_icons) @@ -2211,96 +2188,9 @@ GLOBAL_LIST_EMPTY(roundstart_races) wings_icon = pick(wings_icons) else wings_icon = wings_icons[1] - if(isnull(fly)) - fly = new - fly.Grant(H) - if(H.dna.features["wings"] != wings_icon) - mutant_bodyparts["wings"] = wings_icon - H.dna.features["wings"] = wings_icon - H.update_body() - -/datum/species/proc/HandleFlight(mob/living/carbon/human/H) - if(H.movement_type & FLYING) - if(!CanFly(H)) - ToggleFlight(H) - return FALSE - return TRUE - else - return FALSE - -/datum/species/proc/CanFly(mob/living/carbon/human/H) - if(H.stat || H.body_position == LYING_DOWN) - return FALSE - if(H.wear_suit && ((H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) //Jumpsuits have tail holes, so it makes sense they have wing holes too - to_chat(H, span_warning("Your suit blocks your wings from extending!")) - return FALSE - var/turf/T = get_turf(H) - if(!T) - return FALSE - - var/datum/gas_mixture/environment = T.return_air() - if(environment && !(environment.return_pressure() > 30)) - to_chat(H, span_warning("The atmosphere is too thin for you to fly!")) - return FALSE - else - return TRUE - -/datum/species/proc/flyslip(mob/living/carbon/human/H) - var/obj/buckled_obj - if(H.buckled) - buckled_obj = H.buckled - - to_chat(H, span_notice("Your wings spazz out and launch you!")) - - playsound(H.loc, 'sound/misc/slip.ogg', 50, TRUE, -3) - - for(var/obj/item/I in H.held_items) - H.accident(I) - - var/olddir = H.dir - - H.stop_pulling() - if(buckled_obj) - buckled_obj.unbuckle_mob(H) - step(buckled_obj, olddir) - else - new /datum/forced_movement(H, get_ranged_target_turf(H, olddir, 4), 1, FALSE, CALLBACK(H, /mob/living/carbon/.proc/spin, 1, 1)) - return TRUE - -//UNSAFE PROC, should only be called through the Activate or other sources that check for CanFly -/datum/species/proc/ToggleFlight(mob/living/carbon/human/H) - if(!HAS_TRAIT_FROM(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)) - stunmod *= 2 - speedmod -= 0.35 - ADD_TRAIT(H, TRAIT_NO_FLOATING_ANIM, SPECIES_FLIGHT_TRAIT) - ADD_TRAIT(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT) - passtable_on(H, SPECIES_TRAIT) - H.OpenWings() - else - stunmod *= 0.5 - speedmod += 0.35 - REMOVE_TRAIT(H, TRAIT_NO_FLOATING_ANIM, SPECIES_FLIGHT_TRAIT) - REMOVE_TRAIT(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT) - passtable_off(H, SPECIES_TRAIT) - H.CloseWings() - -/datum/action/innate/flight - name = "Toggle Flight" - check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_IMMOBILE - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "flight" - -/datum/action/innate/flight/Activate() - var/mob/living/carbon/human/H = owner - var/datum/species/S = H.dna.species - if(S.CanFly(H)) - S.ToggleFlight(H) - if(!(H.movement_type & FLYING)) - to_chat(H, span_notice("You settle gently back onto the ground...")) - else - to_chat(H, span_notice("You beat your wings and begin to hover gently above the ground...")) - H.set_resting(FALSE, TRUE) - + var/obj/item/organ/external/wings/functional/wings = new(null, wings_icon, H.body_type) + wings.Insert(H) + handle_mutant_bodyparts(H) /** * The human species version of [/mob/living/carbon/proc/get_biological_state]. Depends on the HAS_FLESH and HAS_BONE species traits, having bones lets you have bone wounds, having flesh lets you have burn, slash, and piercing wounds */ diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 73b620121e9..b417131b5a6 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -11,8 +11,10 @@ TRAIT_CAN_USE_FLIGHT_POTION, ) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE - mutant_bodyparts = list("tail_lizard" = "Smooth", "snout" = "Round", "horns" = "None", - "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs") + mutant_bodyparts = list("tail_lizard" = "Smooth", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs") + external_organs = list(/obj/item/organ/external/horns = "None", + /obj/item/organ/external/frills = "None", + /obj/item/organ/external/snout = "Round") mutanttongue = /obj/item/organ/tongue/lizard //mutant_organs = list(/obj/item/organ/tail/lizard) //SKYRAT EDIT REMOVAL - CUSTOMIZATION coldmod = 1.5 diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index b08ac09800f..0a58f00f5ec 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -10,7 +10,8 @@ TRAIT_CAN_USE_FLIGHT_POTION, ) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG - mutant_bodyparts = list("moth_wings" = "Plain", "moth_antennae" = "Plain", "moth_markings" = "None") + mutant_bodyparts = list("moth_markings" = "None") + external_organs = list(/obj/item/organ/external/wings/moth = "Plain", /obj/item/organ/external/antennae = "Plain") attack_verb = "slash" attack_effect = ATTACK_EFFECT_CLAW attack_sound = 'sound/weapons/slash.ogg' @@ -44,28 +45,6 @@ return randname -/datum/species/moth/handle_fire(mob/living/carbon/human/H, delta_time, times_fired, no_protection = FALSE) - . = ..() - if(.) //if the mob is immune to fire, don't burn wings off. - return - if(H.dna.features["moth_wings"] != "Burnt Off" && H.bodytemperature >= 800 && H.fire_stacks > 0) //do not go into the extremely hot light. you will not survive - to_chat(H, span_danger("Your precious wings burn to a crisp!")) - SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "burnt_wings", /datum/mood_event/burnt_wings) - if(!H.dna.features["original_moth_wings"]) //Fire apparently destroys DNA, so let's preserve that elsewhere, checks if an original was already stored to prevent bugs - H.dna.features["original_moth_wings"] = H.dna.features["moth_wings"] - H.dna.features["moth_wings"] = "Burnt Off" - if(!H.dna.features["original_moth_antennae"]) //Stores antennae type for if they get restored later - H.dna.features["original_moth_antennae"] = H.dna.features["moth_antennae"] - H.dna.features["moth_antennae"] = "Burnt Off" - if(flying_species) //This is all exclusive to if the person has the effects of a potion of flight - if(H.movement_type & FLYING) - ToggleFlight(H) - H.Knockdown(1.5 SECONDS) - fly.Remove(H) - QDEL_NULL(fly) - H.dna.features["wings"] = "None" - handle_mutant_bodyparts(H) - /datum/species/moth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, delta_time, times_fired) . = ..() if(chem.type == /datum/reagent/toxin/pestkiller) @@ -77,13 +56,6 @@ return 10 //flyswatters deal 10x damage to moths return 1 -/datum/species/moth/space_move(mob/living/carbon/human/H) - . = ..() - if(H.loc && !isspaceturf(H.loc) && H.dna.features["moth_wings"] != "Burnt Off" && !flying_species) //"flying_species" is exclusive to the potion of flight, which has its flying mechanics. If they want to fly they can use that instead - var/datum/gas_mixture/current = H.loc.return_air() - if(current && (current.return_pressure() >= ONE_ATMOSPHERE*0.85)) //as long as there's reasonable pressure and no gravity, flight is possible - return TRUE - //SKYRAT EDIT REMOVAL BEGIN /* /datum/species/moth/randomize_main_appearance_element(mob/living/carbon/human/human_mob) @@ -95,18 +67,3 @@ human_mob.update_body() */ //SKYRAT EDIT REMOVAL END - -/datum/species/moth/spec_fully_heal(mob/living/carbon/human/H) - . = ..() - if(H.dna.features["original_moth_wings"] != null) - H.dna.features["moth_wings"] = H.dna.features["original_moth_wings"] - - if(H.dna.features["original_moth_wings"] == null && H.dna.features["moth_wings"] == "Burnt Off") - H.dna.features["moth_wings"] = "Plain" - - if(H.dna.features["original_moth_antennae"] != null) - H.dna.features["moth_antennae"] = H.dna.features["original_moth_antennae"] - - if(H.dna.features["original_moth_antennae"] == null && H.dna.features["moth_antennae"] == "Burnt Off") - H.dna.features["moth_antennae"] = "Plain" - handle_mutant_bodyparts(H) diff --git a/code/modules/surgery/advanced/wingreconstruction.dm b/code/modules/surgery/advanced/wingreconstruction.dm index 9670ce11765..e03c639583c 100644 --- a/code/modules/surgery/advanced/wingreconstruction.dm +++ b/code/modules/surgery/advanced/wingreconstruction.dm @@ -35,14 +35,11 @@ display_results(user, target, span_notice("You succeed in reconstructing [target]'s wings."), span_notice("[user] successfully reconstructs [target]'s wings!"), span_notice("[user] completes the surgery on [target]'s wings.")) - if(human_target.dna.features["original_moth_wings"] != null) - human_target.dna.features["moth_wings"] = human_target.dna.features["original_moth_wings"] - else - human_target.dna.features["moth_wings"] = "Plain" - //SKYRAT EDIT REMOVAL BEGIN - CUSTOMIZATION - /* - human_target.dna.update_uf_block(DNA_MOTH_WINGS_BLOCK) - */ - //SKYRAT EDIT REMOVAL END - human_target.update_mutant_bodyparts() + var/obj/item/organ/external/wings/moth/wings = target.getorganslot(ORGAN_SLOT_EXTERNAL_WINGS) + wings?.heal_wings() + + var/obj/item/organ/external/antennae/antennae = target.getorganslot(ORGAN_SLOT_EXTERNAL_ANTENNAE) //i mean we might aswell heal their antennae too + antennae?.heal_antennae() + + human_target.update_body_parts() return ..() diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 00f9d9ae5ba..e3ad9a19888 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -118,6 +118,9 @@ var/rendered_bp_icon //SKYRAT EDIT ADDITION - CUSTOMIZATION var/organic_render = TRUE //SKYRAT EDIT ADDITION - CUSTOMIZATION + ///A list of all the external organs we've got stored to draw horns, wings and stuff with (special because we are actually in the limbs unlike normal organs :/ ) + var/list/obj/item/organ/external/external_organs = list() + /obj/item/bodypart/Initialize(mapload) . = ..() diff --git a/code/modules/surgery/organs/external/_external_organs.dm b/code/modules/surgery/organs/external/_external_organs.dm index 95f63277c23..851d60ffd4e 100644 --- a/code/modules/surgery/organs/external/_external_organs.dm +++ b/code/modules/surgery/organs/external/_external_organs.dm @@ -34,9 +34,15 @@ */ /obj/item/organ/external/Initialize(mapload, mob_sprite) . = ..() + if(mob_sprite) set_sprite(mob_sprite) + cache_key = generate_icon_cache() + // SKYRAT EDIT: we have like 145+ fucking dna blocks lmao + dna_block = GLOB.dna_mutant_bodypart_blocks[preference] + + /obj/item/organ/external/Insert(mob/living/carbon/reciever, special, drop_if_replaced) var/obj/item/bodypart/limb = reciever.get_bodypart(zone) @@ -72,8 +78,7 @@ /obj/item/organ/external/proc/get_overlays(list/overlay_list, image_dir, image_layer, body_type, image_color) if(!sprite_datum) return - if(owner && HAS_TRAIT(owner, TRAIT_INVISIBLE_MAN)) - return + var/gender = (body_type == FEMALE) ? "f" : "m" var/finished_icon_state = (sprite_datum.gender_specific ? gender : "m") + "_" + preference + "_" + sprite_datum.icon_state + mutant_bodyparts_layertext(image_layer) var/mutable_appearance/appearance = mutable_appearance(sprite_datum.icon, finished_icon_state, layer = -image_layer) @@ -100,22 +105,22 @@ */ /obj/item/organ/external/proc/mutant_bodyparts_layertext(layer) switch(layer) - if(BODY_BEHIND_LAYER) + if(EXTERNAL_BEHIND_LAYER) return "_BEHIND" - if(BODY_ADJ_LAYER) + if(EXTERNAL_ADJACENT_LAYER) return "_ADJ" - if(BODY_FRONT_LAYER) + if(EXTERNAL_FRONT_LAYER) return "_FRONT" ///Converts a bitflag to the right layer. I'd love to make this a static index list, but byond made an attempt on my life when i did /obj/item/organ/external/proc/bitflag_to_layer(layer) switch(layer) if(EXTERNAL_BEHIND) - return BODY_BEHIND_LAYER + return EXTERNAL_BEHIND_LAYER if(EXTERNAL_ADJACENT) - return BODY_ADJ_LAYER + return EXTERNAL_ADJACENT_LAYER if(EXTERNAL_FRONT) - return BODY_FRONT_LAYER + return EXTERNAL_FRONT_LAYER ///Because all the preferences have names like "Beautiful Sharp Snout" we need to get the sprite datum with the actual important info /obj/item/organ/external/proc/get_sprite_datum(sprite) @@ -141,32 +146,30 @@ ///The horns of a lizard! /obj/item/organ/external/horns + name = "horns" zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_HORNS layers = EXTERNAL_ADJACENT preference = "horns" - dna_block = DNA_HORNS_BLOCK - /obj/item/organ/external/horns/can_draw_on_bodypart(mob/living/carbon/human/human) if(!(human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR)) return TRUE return FALSE /obj/item/organ/external/horns/get_global_feature_list() - return GLOB.horns_list + return GLOB.sprite_accessories["horns"] ///The frills of a lizard (like weird fin ears) /obj/item/organ/external/frills + name = "frills" zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_FRILLS layers = EXTERNAL_ADJACENT preference = "frills" - dna_block = DNA_FRILLS_BLOCK - /obj/item/organ/external/frills/can_draw_on_bodypart(mob/living/carbon/human/human) if(!(human.head?.flags_inv & HIDEEARS)) return TRUE @@ -174,36 +177,34 @@ /obj/item/organ/external/frills/get_global_feature_list() - return GLOB.frills_list + return GLOB.sprite_accessories["frills"] ///Guess what part of the lizard this is? /obj/item/organ/external/snout + name = "snout" zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_SNOUT layers = EXTERNAL_ADJACENT preference = "snout" - dna_block = DNA_SNOUT_BLOCK - /obj/item/organ/external/snout/can_draw_on_bodypart(mob/living/carbon/human/human) if(!(human.wear_mask?.flags_inv & HIDESNOUT) && !(human.head?.flags_inv & HIDESNOUT)) return TRUE return FALSE /obj/item/organ/external/snout/get_global_feature_list() - return GLOB.snouts_list + return GLOB.sprite_accessories["snouts"] ///A moth's antennae /obj/item/organ/external/antennae + name = "antennae" zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_ANTENNAE layers = EXTERNAL_FRONT | EXTERNAL_BEHIND preference = "moth_antennae" - dna_block = DNA_MOTH_ANTENNAE_BLOCK - ///Are we burned? var/burnt = FALSE ///Store our old sprite here for if our antennae wings are healed @@ -221,10 +222,12 @@ UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL)) /obj/item/organ/external/antennae/get_global_feature_list() - return GLOB.moth_antennae_list + return GLOB.sprite_accessories["moth_antennae"] /obj/item/organ/external/antennae/can_draw_on_bodypart(mob/living/carbon/human/human) - return TRUE + if(!(human.head?.flags_inv & HIDEHAIR) || (human.wear_mask?.flags_inv & HIDEHAIR)) + return TRUE + return FALSE ///For moth antennae and wings we make an exception. If their features are burnt, we only update our original sprite /obj/item/organ/external/antennae/set_sprite(sprite) diff --git a/code/modules/surgery/organs/stomach/external/wings.dm b/code/modules/surgery/organs/external/wings.dm similarity index 93% rename from code/modules/surgery/organs/stomach/external/wings.dm rename to code/modules/surgery/organs/external/wings.dm index 3205355818b..e4f511e9093 100644 --- a/code/modules/surgery/organs/stomach/external/wings.dm +++ b/code/modules/surgery/organs/external/wings.dm @@ -15,7 +15,7 @@ return TRUE return FALSE -///The true wings that you can use to fly and shit (you cant actually shit with them, but it does wing stuff) +///The true wings that you can use to fly and shit (you cant actually shit with them) /obj/item/organ/external/wings/functional ///The flight action object var/datum/action/innate/flight/fly @@ -29,10 +29,8 @@ var/wings_open = FALSE /obj/item/organ/external/wings/functional/get_global_feature_list() - if(wings_open) - return GLOB.wings_open_list - else - return GLOB.wings_list + // SKYRAT EDIT TODO: Add support for wings_open + return GLOB.sprite_accessories["wings"] /obj/item/organ/external/wings/functional/Insert(mob/living/carbon/reciever, special, drop_if_replaced) . = ..() @@ -160,7 +158,7 @@ preference = "moth_wings" layers = EXTERNAL_BEHIND | EXTERNAL_FRONT - dna_block = DNA_MOTH_WINGS_BLOCK + //dna_block = DNA_MOTH_WINGS_BLOCK SKYRAT EDIT REMOVAL ///Are we burned? var/burnt = FALSE @@ -168,7 +166,7 @@ var/original_sprite = "" /obj/item/organ/external/wings/moth/get_global_feature_list() - return GLOB.moth_wings_list + return GLOB.sprite_accessories["wings"] //SKYRAT EDIT CHANGE /obj/item/organ/external/wings/moth/can_draw_on_bodypart(mob/living/carbon/human/human) return TRUE @@ -186,13 +184,6 @@ UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL, COMSIG_MOVABLE_PRE_MOVE)) REMOVE_TRAIT(organ_owner, TRAIT_FREE_FLOAT_MOVEMENT, src) -///For moth antennae and wings we make an exception. If their features are burnt, we only update our original sprite -/obj/item/organ/external/wings/moth/set_sprite(sprite) - if(!burnt) - return ..() //no one listens to the return value, I just need to call the parent proc and end the code - - original_sprite = sprite - ///Check if we can flutter around /obj/item/organ/external/wings/moth/proc/update_float_move() SIGNAL_HANDLER diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm index 863ebfe7e79..5e63626e9cb 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/wings.dm @@ -36,7 +36,7 @@ icon = 'modular_skyrat/master_files/icons/mob/sprite_accessory/moth_wings.dmi' //Needs new icon to suit new naming convention default_color = "FFF" recommended_species = list(SPECIES_MOTH, SPECIES_SYNTHMAMMAL, SPECIES_MAMMAL, SPECIES_INSECT) //Mammals too, I guess. They wont get flight though, see the wing organs for that logic - organ_type = /obj/item/organ/wings/moth + organ_type = /obj/item/organ/external/wings/moth relevent_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) /datum/sprite_accessory/wings/moth/none diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_update_icons.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_update_icons.dm index 8f18ac6997b..fd3b2ae59f3 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_update_icons.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/human_update_icons.dm @@ -1,7 +1,7 @@ //used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body. /mob/living/carbon/human/proc/update_mutant_bodyparts(force_update=FALSE) dna.species.handle_mutant_bodyparts(src, force_update = force_update) - + update_body_parts() // basically a better and cooler handle_mutant_bodyparts (at least until handle_mutant_bodyparts is annihilated) /mob/living/carbon/human/update_inv_w_uniform() remove_overlay(UNIFORM_LAYER) diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm index aef44d15659..b0cffe7af71 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm @@ -389,6 +389,14 @@ GLOBAL_LIST_EMPTY(customizable_races) else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand C.put_in_hands(new mutanthands()) + if(ishuman(C)) + var/mob/living/carbon/human/human = C + for(var/obj/item/organ/external/organ_path as anything in external_organs) + //Load a persons preferences from DNA + var/preference_name = human.dna.features[initial(organ_path.preference)] + var/obj/item/organ/external/new_organ = new organ_path(null, preference_name, human.body_type) + new_organ.Insert(human) + for(var/X in inherent_traits) ADD_TRAIT(C, X, SPECIES_TRAIT) diff --git a/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm b/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm index 771bde0be39..30369a7c67e 100644 --- a/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm +++ b/modular_skyrat/modules/customization/modules/surgery/bodyparts/_bodyparts.dm @@ -73,9 +73,9 @@ limb.overlays += limb_em_block return - + var/draw_color if(should_draw_greyscale) - var/draw_color = mutation_color || species_color || (skin_tone && skintone2hex(skin_tone)) + draw_color = mutation_color || species_color || (skin_tone && skintone2hex(skin_tone)) if(draw_color) limb.color = "#[draw_color]" if(aux_zone) @@ -141,3 +141,11 @@ aux_em_block.dir = image_dir aux_em_block.color = GLOB.em_block_color aux.overlays += aux_em_block + //Draw external organs like horns and frills + for(var/obj/item/organ/external/external_organ in external_organs) + if(!dropped && !external_organ.can_draw_on_bodypart(owner)) + continue + //Some externals have multiple layers for background, foreground and between + for(var/external_layer in external_organ.all_layers) + if(external_organ.layers & external_layer) + external_organ.get_overlays(., image_dir, external_organ.bitflag_to_layer(external_layer), icon_gender, "#[draw_color]") diff --git a/tgstation.dme b/tgstation.dme index 3de53515f98..24b828b3fe6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3654,6 +3654,8 @@ #include "code\modules\surgery\organs\tails.dm" #include "code\modules\surgery\organs\tongue.dm" #include "code\modules\surgery\organs\vocal_cords.dm" +#include "code\modules\surgery\organs\external\_external_organs.dm" +#include "code\modules\surgery\organs\external\wings.dm" #include "code\modules\surgery\organs\stomach\_stomach.dm" #include "code\modules\surgery\organs\stomach\stomach_ethereal.dm" #include "code\modules\swarmers\swarmer.dm"