diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index db9e10b6ae17..3f3599fcf7d7 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -102,6 +102,7 @@ GLOBAL_LIST_INIT(turfs_openspace, typecacheof(list( #define isgoblin(A) (is_species(A, /datum/species/goblin)) //Monkestation Addition #define isfloran(A) (is_species(A, /datum/species/floran)) //Monkestation Addition #define isarachnid(A) (is_species(A, /datum/species/arachnid)) //Monkestation Addition +#define isteratoma(A) (is_species(A, /datum/species/teratoma)) //Monkestation Addition //More carbon mobs diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 714d416b75b8..7d3d5d8e7bbb 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -133,6 +133,7 @@ #define SPECIES_GOBLIN "goblin" //Monkestation Addition #define SPECIES_FLORAN "floran" //Monkestation Addition #define SPECIES_SATYR "satyr" //Monkestation Addition +#define SPECIES_TERATOMA "teratoma" //Monkestation Addition // Like species IDs, but not specifically attached a species. #define BODYPART_ID_ALIEN "alien" #define BODYPART_ID_ROBOTIC "robotic" diff --git a/code/__DEFINES/research/anomalies.dm b/code/__DEFINES/research/anomalies.dm index b53f5bd1ae98..faf1163efd8a 100644 --- a/code/__DEFINES/research/anomalies.dm +++ b/code/__DEFINES/research/anomalies.dm @@ -24,7 +24,7 @@ GLOBAL_LIST_INIT(bioscrambler_parts_blacklist, typecacheof(list( /obj/item/bodypart/leg/left/monkey, /obj/item/bodypart/leg/right/monkey, /obj/item/bodypart/leg/left/tallboy, - /obj/item/bodypart/leg/right/tallboy + /obj/item/bodypart/leg/right/tallboy, ))) /// Blacklist of limb IDs which should not appear when bioscrambled, mostly because they looks awful and buggy. @@ -32,7 +32,8 @@ GLOBAL_LIST_INIT(bioscrambler_limb_id_blacklist, list( BODYPART_ID_PSYKER, SPECIES_SIMIAN, SPECIES_MONKEY, - SPECIES_GOBLIN + SPECIES_GOBLIN, + SPECIES_TERATOMA, )) /// Blacklist of organs which should not appear when bioscrambled. diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 32ee82b6d9f8..a43a50cda5a2 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -535,7 +535,7 @@ GLOBAL_LIST_EMPTY(species_list) /proc/passtable_on(target, source) var/mob/living/L = target - if (!HAS_TRAIT(L, TRAIT_PASSTABLE) && L.pass_flags & PASSTABLE) + if (!HAS_TRAIT(L, TRAIT_PASSTABLE) && (L.pass_flags & PASSTABLE)) ADD_TRAIT(L, TRAIT_PASSTABLE, INNATE_TRAIT) ADD_TRAIT(L, TRAIT_PASSTABLE, source) L.pass_flags |= PASSTABLE diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm index eee6e1b92910..2a7fd69ead2a 100644 --- a/code/_globalvars/lists/poll_ignore.dm +++ b/code/_globalvars/lists/poll_ignore.dm @@ -10,6 +10,7 @@ #define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support" #define POLL_IGNORE_CONSTRUCT "construct" #define POLL_IGNORE_CORTICAL_BORER "cortical_borer" // MONKESTATION ADDITION -- CORTICAL_BORERS +#define POLL_IGNORE_TERATOMA "teratoma" // MONKESTATION ADDITION -- TERATOMAS #define POLL_IGNORE_DRONE "drone" #define POLL_IGNORE_FIRE_SHARK "fire_shark" #define POLL_IGNORE_FUGITIVE "fugitive" @@ -49,6 +50,7 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list( POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit", POLL_IGNORE_CONSTRUCT = "Construct", POLL_IGNORE_CORTICAL_BORER = "Cortical Borer", // MONKESTATION ADDITION -- CORTICAL_BORERS + POLL_IGNORE_TERATOMA = "Teratoma", // MONKESTATION ADDITION -- TERATOMAS POLL_IGNORE_DRONE = "Drone shells", POLL_IGNORE_FIRE_SHARK = "Fire Shark", POLL_IGNORE_FUGITIVE = "Fugitive Hunter", diff --git a/code/modules/antagonists/changeling/powers/spiders.dm b/code/modules/antagonists/changeling/powers/spiders.dm index ce23fc0eb1b5..ff2ae524dc6f 100644 --- a/code/modules/antagonists/changeling/powers/spiders.dm +++ b/code/modules/antagonists/changeling/powers/spiders.dm @@ -1,3 +1,4 @@ +/* monkestation removal: replaced by teratomas in [monkestation\code\modules\antagonists\changeling\powers\teratomas.dm] /datum/action/changeling/spiders name = "Spread Infestation" desc = "Our form divides, creating a cluster of eggs which will grow into a deadly arachnid. Costs 45 chemicals." @@ -12,3 +13,4 @@ ..() new /obj/effect/mob_spawn/ghost_role/spider/bloody(user.loc) return TRUE +*/ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_teratoma.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_teratoma.png new file mode 100644 index 000000000000..ffb7cd7284fd Binary files /dev/null and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_teratoma.png differ diff --git a/monkestation/code/modules/antagonists/changeling/powers/teratomas.dm b/monkestation/code/modules/antagonists/changeling/powers/teratomas.dm new file mode 100644 index 000000000000..013f2445a236 --- /dev/null +++ b/monkestation/code/modules/antagonists/changeling/powers/teratomas.dm @@ -0,0 +1,49 @@ +/datum/action/changeling/teratoma + name = "Birth Teratoma" + desc = "Our form divides, creating an egg that will soon hatch into a living tumor, fixated on causing mayhem." + helptext = "The tumor will not be loyal to us or our cause. Requires 3 changeling absorptions." + button_icon_state = "spread_infestation" + chemical_cost = 60 + dna_cost = 2 + req_absorbs = 3 + +/datum/action/changeling/teratoma/sting_action(mob/living/user) + ..() + if(create_teratoma(user)) + playsound(user.loc, 'sound/effects/blobattack.ogg', 50, 1) + user.spawn_gibs() + user.visible_message(span_danger("Something horrible bursts out of [user]'s chest!"), \ + span_danger("Living teratoma bursts out of your chest!"), \ + span_hear("You hear flesh tearing!"), COMBAT_MESSAGE_RANGE) + return FALSE //create_teratoma() handles the chemicals anyway so there is no reason to take them again + +/datum/action/changeling/teratoma/proc/create_teratoma(mob/living/user) + var/datum/antagonist/changeling/ling = user?.mind?.has_antag_datum(/datum/antagonist/changeling) + if(!ling) + return FALSE + ling.adjust_chemicals(-chemical_cost) + var/list/candidates = SSpolling.poll_ghost_candidates( + "Do you want to play as a living teratoma?", + poll_time = 7.5 SECONDS, + ignore_category = POLL_IGNORE_TERATOMA, + alert_pic = /datum/antagonist/teratoma, + role_name_text = "living teratoma", + chat_text_border_icon = /datum/antagonist/teratoma, + ) + if(!length(candidates)) //if we got at least one candidate, they're teratoma now + to_chat(user, span_warning("You fail at creating a tumor. Perhaps you should try again later?")) + ling.adjust_chemicals(chemical_cost) + return FALSE + var/mob/dead/observer/candidate = pick(candidates) + if(QDELETED(candidate)) + to_chat(user, span_warning("You fail at creating a tumor. Perhaps you should try again later?")) + ling.adjust_chemicals(chemical_cost) + return FALSE + var/mob/living/carbon/human/species/teratoma/goober = new(user.drop_location()) + goober.key = candidate.key + if(!goober.mind) + goober.mind_initialize() + goober.mind.add_antag_datum(/datum/antagonist/teratoma) + to_chat(goober, span_notice("You burst out from [user]'s chest!")) + SEND_SOUND(goober, sound('sound/effects/blobattack.ogg')) + return TRUE diff --git a/monkestation/code/modules/antagonists/teratoma/teratoma.dm b/monkestation/code/modules/antagonists/teratoma/teratoma.dm new file mode 100644 index 000000000000..653b291c8461 --- /dev/null +++ b/monkestation/code/modules/antagonists/teratoma/teratoma.dm @@ -0,0 +1,54 @@ +/datum/team/teratoma + name = "Teratomas" + member_name = "teratoma" + +/datum/antagonist/teratoma + name = "\improper Teratoma" + show_in_antagpanel = TRUE + antagpanel_category = ANTAG_GROUP_ABOMINATIONS + show_to_ghosts = TRUE + var/datum/team/teratoma/team + +/datum/antagonist/teratoma/greet() + var/list/parts = list() + parts += span_big("You are a living teratoma!") + parts += span_changeling("By all means, you should not exist. Your very existence is a sin against nature itself.") + parts += span_changeling("You are loyal to nobody, except the forces of chaos itself.") + parts += span_info("You are able to easily vault tables and ventcrawl, however you cannot use many things like guns, batons, and you are also illiterate and quite fragile.") + parts += span_hypnophrase("Spread misery and chaos upon the station.") + to_chat(owner.current, examine_block(parts.Join("\n")), type = MESSAGE_TYPE_INFO) + +/datum/antagonist/teratoma/can_be_owned(datum/mind/new_owner) + if(!isteratoma(new_owner.current)) + return FALSE + return ..() + +/datum/antagonist/teratoma/create_team(datum/team/teratoma/new_team) + var/static/datum/team/teratoma/main_teratoma_team + if(!new_team) + if(!main_teratoma_team) + main_teratoma_team = new + main_teratoma_team.add_objective(new /datum/objective/teratoma) + new_team = main_teratoma_team + if(!istype(new_team)) + stack_trace("Wrong team type passed to [type] initialization.") + team = new_team + objectives |= team.objectives + +/datum/antagonist/teratoma/get_team() + return team + +/datum/antagonist/teratoma/get_base_preview_icon() + RETURN_TYPE(/icon) + var/static/icon/teratoma_icon + if(!teratoma_icon) + var/mob/living/carbon/human/species/teratoma/teratoma = new + teratoma.setDir(SOUTH) + teratoma_icon = getFlatIcon(teratoma, no_anim = TRUE) + QDEL_NULL(teratoma) + return teratoma_icon + +/datum/objective/teratoma + name = "Spread misery and chaos" + explanation_text = "Spread misery and chaos upon the station." + completed = TRUE diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm new file mode 100644 index 000000000000..a34c3c15b1cd --- /dev/null +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm @@ -0,0 +1,120 @@ +/datum/species/teratoma + name = "Teratoma" + id = SPECIES_TERATOMA + bodytype = BODYTYPE_ORGANIC | BODYTYPE_MONKEY + mutanttongue = /obj/item/organ/internal/tongue/monkey + mutantbrain = /obj/item/organ/internal/brain/primate + + species_traits = list( + NOAUGMENTS, + NOBLOODOVERLAY, + NOEYESPRITES, + NOTRANSSTING, + NOZOMBIE, + NO_DNA_COPY, + NO_UNDERWEAR, + ) + inherent_traits = list( + TRAIT_BADDNA, + TRAIT_CAN_STRIP, + TRAIT_CHUNKYFINGERS, + TRAIT_EASILY_WOUNDED, + TRAIT_GENELESS, + TRAIT_ILLITERATE, + TRAIT_KLEPTOMANIAC, + TRAIT_NO_DNA_COPY, + TRAIT_NO_JUMPSUIT, + TRAIT_NO_ZOMBIFY, + TRAIT_PASSTABLE, + TRAIT_PRIMITIVE, + TRAIT_UNCONVERTABLE, // DEAR GOD NO + TRAIT_VAULTING, + TRAIT_VENTCRAWLER_ALWAYS, + TRAIT_WEAK_SOUL, + ) + + bodypart_overrides = list( + BODY_ZONE_CHEST = /obj/item/bodypart/chest/teratoma, + BODY_ZONE_HEAD = /obj/item/bodypart/head/teratoma, + BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/teratoma, + BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/teratoma, + BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/teratoma, + BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/teratoma, + ) + + maxhealthmod = 0.75 + stunmod = 1.4 + speedmod = -0.15 // stupid gremlins + + no_equip_flags = ITEM_SLOT_ICLOTHING | ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_SUITSTORE + changesource_flags = MIRROR_BADMIN + liked_food = MEAT | BUGS | GORE | GROSS | RAW + disliked_food = CLOTH + sexes = FALSE + species_language_holder = /datum/language_holder/monkey + + fire_overlay = "monkey" + dust_anim = "dust-m" + gib_anim = "gibbed-m" + + var/datum/component/omen/teratoma/misfortune + +/datum/species/teratoma/on_species_gain(mob/living/carbon/human/idiot, datum/species/old_species, pref_load) + . = ..() + misfortune = idiot.AddComponent(/datum/component/omen/teratoma) + RegisterSignal(idiot, COMSIG_ATOM_EXPOSE_REAGENTS, PROC_REF(prevent_banned_reagent_exposure)) + +/datum/species/teratoma/on_species_loss(mob/living/carbon/human/idiot, datum/species/new_species, pref_load) + . = ..() + QDEL_NULL(misfortune) + UnregisterSignal(idiot, COMSIG_ATOM_EXPOSE_REAGENTS) + +/datum/species/teratoma/random_name(gender, unique, lastname) + return "teratoma ([rand(1, 999)])" + +// Don't let them use chems that could potential change them into something non-teratoma. +/datum/species/teratoma/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/goober, seconds_per_tick, times_fired) + if(is_banned_chem(chem)) + chem.holder?.del_reagent(chem.type) + return TRUE + return ..() + +// removes banned reagents from the list of reagents that'll be exposed +/datum/species/teratoma/proc/prevent_banned_reagent_exposure(datum/source, list/reagents, datum/reagents/holder, methods, volume_modifier, show_message) + SIGNAL_HANDLER + for(var/datum/reagent/reagent as anything in reagents) + if(is_banned_chem(reagent)) + reagents -= reagent + +/datum/species/teratoma/proc/is_banned_chem(reagent) + var/static/list/disallowed_chems_typecache + if(!disallowed_chems_typecache) + disallowed_chems_typecache = typecacheof(list( + /datum/reagent/aslimetoxin, + /datum/reagent/cyborg_mutation_nanomachines, + /datum/reagent/gluttonytoxin, + /datum/reagent/magillitis, + /datum/reagent/mulligan, + /datum/reagent/mutationtoxin, + /datum/reagent/xenomicrobes, + )) + return is_type_in_typecache(reagent, disallowed_chems_typecache) + +/datum/species/teratoma/get_scream_sound(mob/living/carbon/human/monkey) + return pick( + 'sound/creatures/monkey/monkey_screech_1.ogg', + 'sound/creatures/monkey/monkey_screech_2.ogg', + 'sound/creatures/monkey/monkey_screech_3.ogg', + 'sound/creatures/monkey/monkey_screech_4.ogg', + 'sound/creatures/monkey/monkey_screech_5.ogg', + 'sound/creatures/monkey/monkey_screech_6.ogg', + 'sound/creatures/monkey/monkey_screech_7.ogg', + ) + +/datum/component/omen/teratoma + permanent = TRUE + luck_mod = 0.75 + damage_mod = 0.2 + +/mob/living/carbon/human/species/teratoma + race = /datum/species/teratoma diff --git a/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm b/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm new file mode 100644 index 000000000000..807f413ff393 --- /dev/null +++ b/monkestation/code/modules/surgery/bodyparts/teratoma_bodyparts.dm @@ -0,0 +1,62 @@ +/obj/item/bodypart/head/teratoma + icon_static = 'monkestation/icons/mob/species/teratoma/bodyparts.dmi' + icon_husk = 'icons/mob/species/monkey/bodyparts.dmi' + husk_type = "monkey" + limb_id = SPECIES_TERATOMA + is_dimorphic = FALSE + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + should_draw_greyscale = FALSE + head_flags = HEAD_LIPS | HEAD_DEBRAIN + + dmg_overlay_type = "monkey" + +/obj/item/bodypart/chest/teratoma + icon_static = 'monkestation/icons/mob/species/teratoma/bodyparts.dmi' + icon_husk = 'icons/mob/species/monkey/bodyparts.dmi' + husk_type = "monkey" + limb_id = SPECIES_TERATOMA + is_dimorphic = FALSE + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + should_draw_greyscale = FALSE + + dmg_overlay_type = "monkey" + +/obj/item/bodypart/arm/left/teratoma + icon_static = 'monkestation/icons/mob/species/teratoma/bodyparts.dmi' + icon_husk = 'icons/mob/species/monkey/bodyparts.dmi' + husk_type = "monkey" + limb_id = SPECIES_TERATOMA + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + should_draw_greyscale = FALSE + + dmg_overlay_type = "monkey" + +/obj/item/bodypart/arm/right/teratoma + icon_static = 'monkestation/icons/mob/species/teratoma/bodyparts.dmi' + icon_husk = 'icons/mob/species/monkey/bodyparts.dmi' + husk_type = "monkey" + limb_id = SPECIES_TERATOMA + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + should_draw_greyscale = FALSE + + dmg_overlay_type = "monkey" + +/obj/item/bodypart/leg/left/teratoma + icon_static = 'monkestation/icons/mob/species/teratoma/bodyparts.dmi' + icon_husk = 'icons/mob/species/monkey/bodyparts.dmi' + husk_type = "monkey" + limb_id = SPECIES_TERATOMA + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + should_draw_greyscale = FALSE + footprint_sprite = FOOTPRINT_SPRITE_PAWS + +/obj/item/bodypart/leg/right/teratoma + icon_static = 'monkestation/icons/mob/species/teratoma/bodyparts.dmi' + icon_husk = 'icons/mob/species/monkey/bodyparts.dmi' + husk_type = "monkey" + limb_id = SPECIES_TERATOMA + bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + should_draw_greyscale = FALSE + footprint_sprite = FOOTPRINT_SPRITE_PAWS + + dmg_overlay_type = "monkey" diff --git a/monkestation/icons/mob/species/teratoma/bodyparts.dmi b/monkestation/icons/mob/species/teratoma/bodyparts.dmi new file mode 100644 index 000000000000..a8e8d20bea02 Binary files /dev/null and b/monkestation/icons/mob/species/teratoma/bodyparts.dmi differ diff --git a/tgstation.dme b/tgstation.dme index f2ec99a120be..9d65842d0dff 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6072,6 +6072,7 @@ #include "monkestation\code\modules\antagonists\brother\gear\_gear.dm" #include "monkestation\code\modules\antagonists\brother\gear\misc.dm" #include "monkestation\code\modules\antagonists\brother\gear\recipes.dm" +#include "monkestation\code\modules\antagonists\changeling\powers\teratomas.dm" #include "monkestation\code\modules\antagonists\changeling\powers\tiny_prick.dm" #include "monkestation\code\modules\antagonists\clock_cult\area.dm" #include "monkestation\code\modules\antagonists\clock_cult\dynamic_ruleset.dm" @@ -6210,6 +6211,7 @@ #include "monkestation\code\modules\antagonists\nukeop\nukeop.dm" #include "monkestation\code\modules\antagonists\nukeop\equipment\nuclear_bomb\bee_nuke.dm" #include "monkestation\code\modules\antagonists\space_ninja\space_ninja.dm" +#include "monkestation\code\modules\antagonists\teratoma\teratoma.dm" #include "monkestation\code\modules\antagonists\traitor\traitor_objective.dm" #include "monkestation\code\modules\antagonists\traitor\uplink_handler.dm" #include "monkestation\code\modules\antagonists\traitor\objectives\kidnapping.dm" @@ -7332,6 +7334,7 @@ #include "monkestation\code\modules\mob\living\carbon\human\species_type\shadowpeople.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\simian.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\skeletons.dm" +#include "monkestation\code\modules\mob\living\carbon\human\species_type\teratoma.dm" #include "monkestation\code\modules\mob\living\carbon\human\species_type\zombies.dm" #include "monkestation\code\modules\mob\living\silicon\death.dm" #include "monkestation\code\modules\mob\living\simple_animal\megafauna\wendigo.dm" @@ -7883,6 +7886,7 @@ #include "monkestation\code\modules\surgery\bodyparts\ethereal_bodyparts.dm" #include "monkestation\code\modules\surgery\bodyparts\floran_bodyparts.dm" #include "monkestation\code\modules\surgery\bodyparts\simian_bodyparts.dm" +#include "monkestation\code\modules\surgery\bodyparts\teratoma_bodyparts.dm" #include "monkestation\code\modules\surgery\organs\augments.dm" #include "monkestation\code\modules\surgery\organs\autosurgeon.dm" #include "monkestation\code\modules\surgery\organs\external\anime.dm"