diff --git a/SQL/beestation_schema.sql b/SQL/beestation_schema.sql index 773a6212a0079..01005fe4a8185 100644 --- a/SQL/beestation_schema.sql +++ b/SQL/beestation_schema.sql @@ -141,6 +141,14 @@ CREATE TABLE IF NOT EXISTS `SS13_characters` ( `feature_human_tail` VARCHAR(64) COLLATE 'utf8mb4_general_ci', `feature_human_ears` VARCHAR(64) COLLATE 'utf8mb4_general_ci', `feature_psyphoza_cap` VARCHAR(64) COLLATE 'utf8mb4_general_ci', + `feature_diona_leaves` VARCHAR(64) COLLATE 'utf8mb4_general_ci', + `feature_diona_thorns` VARCHAR(64) COLLATE 'utf8mb4_general_ci', + `feature_diona_flowers` VARCHAR(64) COLLATE 'utf8mb4_general_ci', + `feature_diona_moss` VARCHAR(64) COLLATE 'utf8mb4_general_ci', + `feature_diona_mushroom` VARCHAR(64) COLLATE 'utf8mb4_general_ci', + `feature_diona_antennae` VARCHAR(64) COLLATE 'utf8mb4_general_ci', + `feature_diona_eyes` VARCHAR(64) COLLATE 'utf8mb4_general_ci', + `feature_diona_pbody` VARCHAR(64) COLLATE 'utf8mb4_general_ci', `helmet_style` VARCHAR(64) COLLATE 'utf8mb4_general_ci', `preferred_ai_core_display` VARCHAR(64) COLLATE 'utf8mb4_general_ci', `preferred_security_department` VARCHAR(32) COLLATE 'utf8mb4_general_ci', diff --git a/SQL/database_changelog.txt b/SQL/database_changelog.txt index 0b634e2470bd5..54147f09077e5 100644 --- a/SQL/database_changelog.txt +++ b/SQL/database_changelog.txt @@ -1,15 +1,27 @@ Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255. -The latest database version is 7.2; The query to update the schema revision table is: +The latest database version is 7.3; The query to update the schema revision table is: -INSERT INTO `schema_revision` (`major`, `minor`) VALUES (7, 2); +INSERT INTO `schema_revision` (`major`, `minor`) VALUES (7, 3); or -INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (7, 2); +INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (7, 3); In any query remember to add a prefix to the table names if you use one. ----------------------------------------------------- +Version 7.3, 30 April 2024, by XeonMations +Dionae - Species Addition + +ALTER TABLE `SS13_characters` + ADD COLUMN IF NOT EXISTS `feature_diona_leaves` VARCHAR(64) COLLATE 'utf8mb4_general_ci' AFTER `feature_psyphoza_cap`, + ADD COLUMN IF NOT EXISTS `feature_diona_thorns` VARCHAR(64) COLLATE 'utf8mb4_general_ci' AFTER `feature_diona_leaves`, + ADD COLUMN IF NOT EXISTS `feature_diona_flowers` VARCHAR(64) COLLATE 'utf8mb4_general_ci' AFTER `feature_diona_thorns`, + ADD COLUMN IF NOT EXISTS `feature_diona_moss` VARCHAR(64) COLLATE 'utf8mb4_general_ci' AFTER `feature_diona_flowers`, + ADD COLUMN IF NOT EXISTS `feature_diona_mushroom` VARCHAR(64) COLLATE 'utf8mb4_general_ci' AFTER `feature_diona_moss`, + ADD COLUMN IF NOT EXISTS `feature_diona_antennae` VARCHAR(64) COLLATE 'utf8mb4_general_ci' AFTER `feature_diona_mushroom`, + ADD COLUMN IF NOT EXISTS `feature_diona_eyes` VARCHAR(64) COLLATE 'utf8mb4_general_ci' AFTER `feature_diona_antennae`, + ADD COLUMN IF NOT EXISTS `feature_diona_pbody` VARCHAR(64) COLLATE 'utf8mb4_general_ci' AFTER `feature_diona_eyes`; ----------------------------------------------------- diff --git a/_maps/RandomRooms/10x10/sk_rdm148_botany_apiary.dmm b/_maps/RandomRooms/10x10/sk_rdm148_botany_apiary.dmm index fadfd4cc4a8f4..06e10c8e996aa 100644 --- a/_maps/RandomRooms/10x10/sk_rdm148_botany_apiary.dmm +++ b/_maps/RandomRooms/10x10/sk_rdm148_botany_apiary.dmm @@ -150,7 +150,7 @@ /area/template_noop) "O" = ( /obj/machinery/hydroponics/soil, -/obj/item/seeds/replicapod, +/obj/item/seeds/dionapod, /turf/open/floor/grass, /area/template_noop) "P" = ( diff --git a/_maps/RandomRooms/5x3/sk_rdm071_pubbykitchen.dmm b/_maps/RandomRooms/5x3/sk_rdm071_pubbykitchen.dmm index 8d602b26eda63..e9618c8efda05 100644 --- a/_maps/RandomRooms/5x3/sk_rdm071_pubbykitchen.dmm +++ b/_maps/RandomRooms/5x3/sk_rdm071_pubbykitchen.dmm @@ -52,7 +52,7 @@ /obj/item/shovel/spade, /obj/item/storage/bag/plants/portaseeder, /obj/item/seeds/wheat/rice, -/obj/item/seeds/replicapod, +/obj/item/seeds/dionapod, /obj/item/seeds/carrot, /obj/item/seeds/tomato, /obj/item/reagent_containers/glass/bottle/nutrient/ez, diff --git a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm index 467208977640a..a84a0ece122b4 100644 --- a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm +++ b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm @@ -2211,8 +2211,8 @@ /obj/item/food/meat/slab/xeno, /obj/item/food/meat/slab/human/mutant/lizard, /obj/item/food/meat/slab/human/mutant/lizard, -/obj/item/food/meat/slab/human/mutant/plant, -/obj/item/food/meat/slab/human/mutant/plant, +/obj/item/food/meat/slab/human/mutant/diona, +/obj/item/food/meat/slab/human/mutant/diona, /turf/open/floor/iron/freezer, /area/ruin/space/has_grav/hotel/bar) "hv" = ( @@ -2230,8 +2230,8 @@ /obj/item/food/meat/slab/xeno, /obj/item/food/meat/slab/human/mutant/lizard, /obj/item/food/meat/slab/human/mutant/lizard, -/obj/item/food/meat/slab/human/mutant/plant, -/obj/item/food/meat/slab/human/mutant/plant, +/obj/item/food/meat/slab/human/mutant/diona, +/obj/item/food/meat/slab/human/mutant/diona, /turf/open/floor/iron/freezer, /area/ruin/space/has_grav/hotel/bar) "hw" = ( diff --git a/_maps/shuttles/ferry/ferry_meat.dmm b/_maps/shuttles/ferry/ferry_meat.dmm index 4e0aa4cb7d80f..4f5ad569d381b 100644 --- a/_maps/shuttles/ferry/ferry_meat.dmm +++ b/_maps/shuttles/ferry/ferry_meat.dmm @@ -49,8 +49,8 @@ /obj/item/food/meat/slab/human/mutant/lizard{ name = "lizard meat" }, -/obj/item/food/meat/slab/human/mutant/plant{ - name = "podperson meat" +/obj/item/food/meat/slab/human/mutant/diona{ + name = "dionae meat" }, /obj/item/food/meat/slab/human/mutant/shadow{ name = "shadowling meat" diff --git a/beestation.dme b/beestation.dme index f6d5d032728b9..5893f28daa170 100644 --- a/beestation.dme +++ b/beestation.dme @@ -382,6 +382,7 @@ #include "code\_onclick\hud\minebot.dm" #include "code\_onclick\hud\monkey.dm" #include "code\_onclick\hud\movable_screen_objects.dm" +#include "code\_onclick\hud\nymph.dm" #include "code\_onclick\hud\pai.dm" #include "code\_onclick\hud\parallax.dm" #include "code\_onclick\hud\picture_in_picture.dm" @@ -2396,6 +2397,7 @@ #include "code\modules\client\preferences\entries\character\quirks\smoker.dm" #include "code\modules\client\preferences\entries\character\species_features\apid.dm" #include "code\modules\client\preferences\entries\character\species_features\basic.dm" +#include "code\modules\client\preferences\entries\character\species_features\diona.dm" #include "code\modules\client\preferences\entries\character\species_features\ethereal.dm" #include "code\modules\client\preferences\entries\character\species_features\felinid.dm" #include "code\modules\client\preferences\entries\character\species_features\fly.dm" @@ -2799,6 +2801,7 @@ #include "code\modules\hydroponics\grown\cocoa_vanilla.dm" #include "code\modules\hydroponics\grown\corn.dm" #include "code\modules\hydroponics\grown\cotton.dm" +#include "code\modules\hydroponics\grown\dionapod.dm" #include "code\modules\hydroponics\grown\eggplant.dm" #include "code\modules\hydroponics\grown\flowers.dm" #include "code\modules\hydroponics\grown\garlic.dm" @@ -2814,7 +2817,6 @@ #include "code\modules\hydroponics\grown\pumpkin.dm" #include "code\modules\hydroponics\grown\rainbow_bunch.dm" #include "code\modules\hydroponics\grown\random.dm" -#include "code\modules\hydroponics\grown\replicapod.dm" #include "code\modules\hydroponics\grown\root.dm" #include "code\modules\hydroponics\grown\tea_coffee.dm" #include "code\modules\hydroponics\grown\tobacco.dm" @@ -3123,6 +3125,7 @@ #include "code\modules\mob\living\carbon\human\species_types\android.dm" #include "code\modules\mob\living\carbon\human\species_types\apid.dm" #include "code\modules\mob\living\carbon\human\species_types\debug.dm" +#include "code\modules\mob\living\carbon\human\species_types\diona.dm" #include "code\modules\mob\living\carbon\human\species_types\dullahan.dm" #include "code\modules\mob\living\carbon\human\species_types\ethereal.dm" #include "code\modules\mob\living\carbon\human\species_types\felinid.dm" @@ -3136,7 +3139,6 @@ #include "code\modules\mob\living\carbon\human\species_types\mothmen.dm" #include "code\modules\mob\living\carbon\human\species_types\oozelings.dm" #include "code\modules\mob\living\carbon\human\species_types\plasmamen.dm" -#include "code\modules\mob\living\carbon\human\species_types\podpeople.dm" #include "code\modules\mob\living\carbon\human\species_types\psyphoza.dm" #include "code\modules\mob\living\carbon\human\species_types\pumpkin_man.dm" #include "code\modules\mob\living\carbon\human\species_types\shadowpeople.dm" @@ -3317,6 +3319,7 @@ #include "code\modules\mob\living\simple_animal\hostile\retaliate\dolphin.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\frog.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\ghost.dm" +#include "code\modules\mob\living\simple_animal\hostile\retaliate\nymph.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\spaceman.dm" #include "code\modules\mob\living\simple_animal\slime\death.dm" @@ -3502,6 +3505,7 @@ #include "code\modules\pool\pool_items.dm" #include "code\modules\pool\pool_moodlets.dm" #include "code\modules\pool\components\swimming.dm" +#include "code\modules\pool\components\swimming_diona.dm" #include "code\modules\pool\components\swimming_dissolve.dm" #include "code\modules\pool\components\swimming_ethereal.dm" #include "code\modules\pool\components\swimming_felinid.dm" @@ -4049,6 +4053,7 @@ #include "code\modules\surgery\bodyparts\helpers.dm" #include "code\modules\surgery\bodyparts\robot_bodyparts.dm" #include "code\modules\surgery\bodyparts\species_parts\apid_bodyparts.dm" +#include "code\modules\surgery\bodyparts\species_parts\diona_bodyparts.dm" #include "code\modules\surgery\bodyparts\species_parts\ethereal_bodyparts.dm" #include "code\modules\surgery\bodyparts\species_parts\ipc_bodyparts.dm" #include "code\modules\surgery\bodyparts\species_parts\lizard_bodyparts.dm" diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 7380ed01d45fd..132effc767fd6 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -57,6 +57,7 @@ #define ACIDOOZE /datum/mutation/acidooze #define MEDIEVAL /datum/mutation/medieval #define SPORES /datum/mutation/spores +#define DRONE /datum/mutation/drone #define UI_CHANGED "ui changed" #define UE_CHANGED "ue changed" @@ -165,6 +166,11 @@ #define ORGAN_SLOT_BRAIN_SURGICAL_IMPLANT "brain_surgical" #define ORGAN_SLOT_TAIL "tail" #define ORGAN_SLOT_WINGS "wings" +#define ORGAN_SLOT_R_ARM_NYMPH "r_arm_nymph" //I can't think of any way of doing this better, please tell me if there is a better way. +#define ORGAN_SLOT_L_ARM_NYMPH "l_arm_nymph" +#define ORGAN_SLOT_R_LEG_NYMPH "r_leg_nymph" +#define ORGAN_SLOT_L_LEG_NYMPH "l_leg_nymph" +#define ORGAN_SLOT_CHEST_NYMPH "chest_nymph" //organ defines #define STANDARD_ORGAN_THRESHOLD 100 diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 2dd680c073300..71ab790799e09 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -82,7 +82,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isgolem(A) (is_species(A, /datum/species/golem)) #define islizard(A) (is_species(A, /datum/species/lizard)) #define isplasmaman(A) (is_species(A, /datum/species/plasmaman)) -#define ispodperson(A) (is_species(A, /datum/species/pod)) +#define isdiona(A) (is_species(A, /datum/species/diona)) #define isflyperson(A) (is_species(A, /datum/species/fly)) #define isslimeperson(A) (is_species(A, /datum/species/oozeling/slime)) #define isluminescent(A) (is_species(A, /datum/species/oozeling/luminescent)) @@ -122,6 +122,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isdevil(A) (istype(A, /mob/living/carbon/true_devil)) +#define isnymph(A) (istype(A, /mob/living/simple_animal/hostile/retaliate/nymph)) + //Silicon mobs #define issilicon(A) (istype(A, /mob/living/silicon)) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index be398a7d46e8e..bbd25cb42a426 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -603,3 +603,6 @@ GLOBAL_LIST_INIT(available_random_trauma_list, list( #define STANDING_UP 0 /// Mob is lying down, usually associated with lying_angle values of 90 or 270. #define LYING_DOWN 1 + +// Species related bitflags go here. +#define NOT_TRANSMORPHIC (1<<0) // This race can't become a changeling antagonist. diff --git a/code/__DEFINES/species.dm b/code/__DEFINES/species.dm index 37cfa87983886..1bd7b69f2f158 100644 --- a/code/__DEFINES/species.dm +++ b/code/__DEFINES/species.dm @@ -18,7 +18,7 @@ #define SPECIES_SLIMEPERSON "slime" #define SPECIES_STARGAZER "stargazer" #define SPECIES_PLASMAMAN "plasmaman" -#define SPECIES_PODPERSON "pod" +#define SPECIES_DIONA "diona" #define SPECIES_PUMPKINPERSON "pumpkin_man" #define SPECIES_SHADOWPERSON "shadow" #define SPECIES_SKELETON "skeleton" @@ -73,6 +73,9 @@ #define FLAG_DEBUG_SPECIES (1<<10) #define FLAG_MONKEY (1<<11) #define FLAG_PSYPHOZA (1<<12) +#define FLAG_DIONA (1<<13) + +#define FEATURE_NONE "None" //For usage in species_features, for checking for marking names. // Defines for used in creating "perks" for the species preference pages. /// A key that designates UI icon displayed on the perk. diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index ed91e45473c6e..1212a395abae4 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -47,6 +47,8 @@ #define STATUS_EFFECT_ANTIMAGIC /datum/status_effect/antimagic //! grants antimagic (and reapplies if lost) for the duration +#define STATUS_EFFECT_PLANTHEALING /datum/status_effect/planthealing //! Grants the user healing at a given amount, used for diona health regeneration. + //---------// // DEBUFFS // //---------// diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm index 81cb41cfe0f39..587ae630473ab 100644 --- a/code/__DEFINES/tools.dm +++ b/code/__DEFINES/tools.dm @@ -19,6 +19,7 @@ #define TOOL_ROLLINGPIN "rollingpin" #define TOOL_RUSTSCRAPER "rustscraper" #define TOOL_BIKEHORN "bike horn" +#define TOOL_SEED "seed" // If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY, // tool sound is only played when op is started. If not, it's played twice. #define MIN_TOOL_SOUND_DELAY 20 diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 8e5d0d5446fd5..ec85d708cbd62 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -29,6 +29,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_INCAPACITATED "incapacitated" //In some kind of critical condition. Is able to succumb. #define TRAIT_CRITICAL_CONDITION "critical-condition" +// Grants them the ability to move even when without any limbs. +#define TRAIT_MOBILE "mobile" //mob traits #define TRAIT_BLIND "blind" @@ -67,6 +69,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_RESISTHIGHPRESSURE "resist_high_pressure" #define TRAIT_RESISTLOWPRESSURE "resist_low_pressure" #define TRAIT_RADIMMUNE "rad_immunity" +#define TRAIT_NORADDAMAGE "no_rad_damage" #define TRAIT_VIRUSIMMUNE "virus_immunity" #define TRAIT_PIERCEIMMUNE "pierce_immunity" #define TRAIT_NODISMEMBER "dismember_immunity" @@ -131,6 +134,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_XENO_IMMUNE "xeno_immune" //prevents facehuggers implanting races that wouldn't be able to host an egg #define TRAIT_NECROPOLIS_INFECTED "necropolis-infection" #define TRAIT_BEEFRIEND "beefriend" +#define TRAIT_PLANTHEALING "planthealing" #define TRAIT_MEDICAL_HUD "med_hud" #define TRAIT_SECURITY_HUD "sec_hud" #define TRAIT_DIAGNOSTIC_HUD "diag_hud" diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index be10e350a6a82..9198ea42d2bb7 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -45,6 +45,15 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/apid_stripes, GLOB.apid_stripes_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/apid_headstripes, GLOB.apid_headstripes_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/psyphoza_cap, GLOB.psyphoza_cap_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_leaves, GLOB.diona_leaves_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_thorns, GLOB.diona_thorns_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_flowers, GLOB.diona_flowers_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_moss, GLOB.diona_moss_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_mushroom, GLOB.diona_mushroom_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_antennae, GLOB.diona_antennae_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_eyes, GLOB.diona_eyes_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_pbody, GLOB.diona_pbody_list) + //Species for(var/spath in subtypesof(/datum/species)) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 96bba3a97a2dd..9243905a875e0 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -100,6 +100,24 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/apid_headstripes, GLOB.apid_headstripes_list) if(!GLOB.psyphoza_cap_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/psyphoza_cap, GLOB.psyphoza_cap_list) + if(!GLOB.diona_leaves_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_leaves, GLOB.diona_leaves_list) + if(!GLOB.diona_thorns_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_thorns, GLOB.diona_thorns_list) + if(!GLOB.diona_flowers_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_flowers, GLOB.diona_flowers_list) + if(!GLOB.diona_moss_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_moss, GLOB.diona_moss_list) + if(!GLOB.diona_mushroom_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_mushroom, GLOB.diona_mushroom_list) + if(!GLOB.diona_antennae_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_antennae, GLOB.diona_antennae_list) + if(!GLOB.diona_eyes_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_eyes, GLOB.diona_eyes_list) + if(!GLOB.diona_pbody_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/diona_pbody, GLOB.diona_pbody_list) + + //For now we will always return none for tail_human and ears. return( list( @@ -128,7 +146,15 @@ "apid_stripes" = pick(GLOB.apid_stripes_list), "apid_headstripes" = pick(GLOB.apid_headstripes_list), "body_model" = gender == MALE ? MALE : gender == FEMALE ? FEMALE : pick(MALE, FEMALE), - "psyphoza_cap" = pick(GLOB.psyphoza_cap_list) + "psyphoza_cap" = pick(GLOB.psyphoza_cap_list), + "diona_leaves" = pick(GLOB.diona_leaves_list), + "diona_thorns" = pick(GLOB.diona_thorns_list), + "diona_flowers" = pick(GLOB.diona_flowers_list), + "diona_moss" = pick(GLOB.diona_moss_list), + "diona_mushroom" = pick(GLOB.diona_mushroom_list), + "diona_antennae" = pick(GLOB.diona_antennae_list), + "diona_eyes" = pick(GLOB.diona_eyes_list), + "diona_pbody" = pick(GLOB.diona_pbody_list) ) ) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 1d42389c7ab66..bc34924147d97 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -57,6 +57,15 @@ GLOBAL_LIST_EMPTY(apid_antenna_list) GLOBAL_LIST_EMPTY(apid_stripes_list) GLOBAL_LIST_EMPTY(apid_headstripes_list) GLOBAL_LIST_EMPTY(psyphoza_cap_list) +GLOBAL_LIST_EMPTY(diona_leaves_list) +GLOBAL_LIST_EMPTY(diona_thorns_list) +GLOBAL_LIST_EMPTY(diona_flowers_list) +GLOBAL_LIST_EMPTY(diona_moss_list) +GLOBAL_LIST_EMPTY(diona_mushroom_list) +GLOBAL_LIST_EMPTY(diona_antennae_list) +GLOBAL_LIST_EMPTY(diona_eyes_list) +GLOBAL_LIST_EMPTY(diona_pbody_list) + GLOBAL_LIST_INIT(color_list_ethereal, list( "Cyan" = "00ffff", diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm index e212e2b2096de..1f7ecc0bcc904 100644 --- a/code/_globalvars/lists/names.dm +++ b/code/_globalvars/lists/names.dm @@ -29,6 +29,7 @@ GLOBAL_LIST_INIT(oozeling_first_names, world.file2list("strings/names/ooze_first GLOBAL_LIST_INIT(oozeling_last_names, world.file2list("strings/names/ooze_last.txt")) GLOBAL_LIST_INIT(psyphoza_first_names, world.file2list("strings/names/psyphoza_first.txt")) GLOBAL_LIST_INIT(psyphoza_last_names, world.file2list("strings/names/psyphoza_last.txt")) +GLOBAL_LIST_INIT(diona_names, world.file2list("strings/names/diona.txt")) GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt")) GLOBAL_LIST_INIT(ing_verbs, world.file2list("strings/names/ing_verbs.txt")) diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index b95624dcb8a12..4e498da8cb96d 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -172,7 +172,10 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRACKED_SENSORS_TRAIT" = TRACKED_SENSORS_TRAIT, "TRAIT_SUIT_SENSORS" = TRAIT_SUIT_SENSORS, "TRAIT_NANITE_SENSORS" = TRAIT_NANITE_SENSORS, - "TRAIT_PSYCHIC_SENSE" = TRAIT_PSYCHIC_SENSE + "TRAIT_PSYCHIC_SENSE" = TRAIT_PSYCHIC_SENSE, + "TRAIT_PLANTHEALING" = TRAIT_PLANTHEALING, + "TRAIT_NORADDAMAGE" = TRAIT_NORADDAMAGE, + "TRAIT_MOBILE" = TRAIT_MOBILE ), /obj/item/integrated_circuit = list( "TRAIT_COMPONENT_MMI" = TRAIT_COMPONENT_MMI, diff --git a/code/_onclick/hud/nymph.dm b/code/_onclick/hud/nymph.dm new file mode 100644 index 0000000000000..9132393cbdb13 --- /dev/null +++ b/code/_onclick/hud/nymph.dm @@ -0,0 +1,8 @@ +/datum/hud/nymph + ui_style = 'icons/hud/screen_gen.dmi' + +/datum/hud/nymph/New(mob/living/simple_animal/hostile/retaliate/nymph/owner) + ..() + healths = new /atom/movable/screen/healths() + healths.hud = src + infodisplay += healths diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index f1b1031d1e335..2c4ef3bc58f3d 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -245,7 +245,7 @@ /datum/config_entry/string/alert_delta config_entry_value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill." -/datum/config_entry/flag/revival_pod_plants +/datum/config_entry/flag/diona_ghost_spawn /datum/config_entry/flag/revival_cloning diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm index a207e34b66854..3cb9ddc494716 100644 --- a/code/controllers/subsystem/traumas.dm +++ b/code/controllers/subsystem/traumas.dm @@ -235,8 +235,7 @@ SUBSYSTEM_DEF(traumas) "conspiracies" = typecacheof(list(/datum/species/abductor, /datum/species/lizard)), "robots" = typecacheof(list(/datum/species/android)), "the supernatural" = typecacheof(list(/datum/species/golem/clockwork, /datum/species/golem/runic)), - "aliens" = typecacheof(list(/datum/species/abductor, /datum/species/pod, - /datum/species/shadow)), + "aliens" = typecacheof(list(/datum/species/abductor, /datum/species/diona, /datum/species/shadow)), "anime" = typecacheof(list(/datum/species/human/felinid)) ) diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm index fdf6d67e24a07..a086dc49f19d3 100644 --- a/code/datums/mutations/actions.dm +++ b/code/datums/mutations/actions.dm @@ -289,3 +289,76 @@ S.start() if(holder?.my_atom) holder.clear_reagents() + +//Diona species mutation +/datum/mutation/drone + name = "Nymph Drone" + desc = "An ancient mutation that gives diona the ability to send out a nymph drone." + quality = POSITIVE + difficulty = 12 + locked = TRUE + power = /obj/effect/proc_holder/spell/self/drone + instability = 30 + energy_coeff = 1 + power_coeff = 1 + species_allowed = list(SPECIES_DIONA) + +/obj/effect/proc_holder/spell/self/drone + name = "Release/Control Drone" + desc = "A rare genome that allows the diona to evict a nymph from their gestalt and gain the ability to control them." + school = "evocation" + invocation = "" + clothes_req = FALSE + charge_max = 60 + invocation_type = INVOCATION_NONE + base_icon_state = "control" + action_icon_state = "control" + var/has_drone = FALSE //If the diona has a drone active or not, for their special mutation. + var/datum/weakref/drone_ref + +/obj/effect/proc_holder/spell/self/drone/cast(list/targets, mob/user = usr) + . = ..() + var/mob/living/carbon/human/C = user + if(!isdiona(C)) + return + CHECK_DNA_AND_SPECIES(C) + var/datum/species/diona/S = C.dna.species + if(has_drone) + var/mob/living/simple_animal/hostile/retaliate/nymph/drone = drone_ref?.resolve() + if(drone.stat == DEAD || QDELETED(drone)) + to_chat(C, "You can't seem to find the psychic link with your nymph.") + has_drone = FALSE + else + to_chat(C, "Switching to nymph...") + SwitchTo(C) + else + if(!do_after(C, 5 SECONDS, C, NONE, TRUE)) + return + has_drone = TRUE + var/mob/living/simple_animal/hostile/retaliate/nymph/nymph = new(C.loc) + nymph.is_drone = TRUE + nymph.drone_parent = C + nymph.switch_ability = new + nymph.switch_ability.Grant(nymph) + drone_ref = WEAKREF(nymph) + S.drone_ref = WEAKREF(nymph) + +/obj/effect/proc_holder/spell/self/drone/proc/SwitchTo(mob/living/carbon/M) + var/mob/living/simple_animal/hostile/retaliate/nymph/drone = drone_ref?.resolve() + if(!drone) + return + if(drone.stat == DEAD || QDELETED(drone)) //sanity check + return + var/datum/mind/C = M.mind + if(M.stat == CONSCIOUS) + M.visible_message("[M] \ + stops moving and starts staring vacantly into space.", + "You stop moving this form...") + else + to_chat(C, "You abandon this nymph...") + C.transfer_to(drone) + drone.mind = C + drone.visible_message("[drone] blinks and looks \ + around.", + "...and move this one instead.") + diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index b9e27e45d1814..424ababd42754 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -599,6 +599,29 @@ qdel(anti_magic) owner.visible_message("[owner]'s dull aura fades away...") +/datum/status_effect/planthealing + id = "Photosynthesis" + status_type = STATUS_EFFECT_UNIQUE + duration = -1 + tick_interval = 25 + alert_type = /atom/movable/screen/alert/status_effect/planthealing + examine_text = "Their leaves seem to be flourishing in the light!" + +/atom/movable/screen/alert/status_effect/planthealing + name = "Photosynthesis" + desc = "Your wounds seem to be healing from the light." + icon_state = "blooming" + +/datum/status_effect/planthealing/on_apply() + ADD_TRAIT(owner, TRAIT_PLANTHEALING, "Light Source") + return ..() + +/datum/status_effect/planthealing/on_remove() + REMOVE_TRAIT(owner, TRAIT_PLANTHEALING, "Light Source") + +/datum/status_effect/planthealing/tick() + owner.heal_overall_damage(1,1, 0, BODYTYPE_ORGANIC) //one unit of brute and burn healing should be good with the amount of times this is ran. Much slower than spec_life + /datum/status_effect/crucible_soul id = "Blessing of Crucible Soul" status_type = STATUS_EFFECT_REFRESH diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index 8c714e6eda9f0..7ebfa32c8d215 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -34,7 +34,7 @@ if(prob(40)) if(ishuman(L)) var/mob/living/carbon/human/H = L - if(H.dna && !HAS_TRAIT(H, TRAIT_RADIMMUNE)) + if(H.dna && !HAS_TRAIT(H, TRAIT_RADIMMUNE) && !isdiona(L)) if(prob(max(0,100-resist))) H.randmuti() if(prob(50)) diff --git a/code/game/machinery/scan_gate.dm b/code/game/machinery/scan_gate.dm index 048f2588fb97d..465da244caa87 100644 --- a/code/game/machinery/scan_gate.dm +++ b/code/game/machinery/scan_gate.dm @@ -14,7 +14,7 @@ #define SCANGATE_PLASMAMAN "plasma" #define SCANGATE_MOTH "moth" #define SCANGATE_OOZE "oozeling" -#define SCANGATE_POD "pod" +#define SCANGATE_DIONA "diona" #define SCANGATE_GOLEM "golem" #define SCANGATE_ZOMBIE "zombie" @@ -145,8 +145,8 @@ scan_species = /datum/species/moth if(SCANGATE_OOZE) scan_species = /datum/species/oozeling - if(SCANGATE_POD) - scan_species = /datum/species/pod + if(SCANGATE_DIONA) + scan_species = /datum/species/diona if(SCANGATE_GOLEM) scan_species = /datum/species/golem if(SCANGATE_ZOMBIE) @@ -268,6 +268,6 @@ #undef SCANGATE_PLASMAMAN #undef SCANGATE_MOTH #undef SCANGATE_OOZE -#undef SCANGATE_POD +#undef SCANGATE_DIONA #undef SCANGATE_GOLEM #undef SCANGATE_ZOMBIE diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index f6ddb377e1aac..4d10584e00747 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -227,6 +227,8 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) ///Icons used to show the item in vendors instead of the item's actual icon, drawn from the item's icon file (just chemical.dm for now) var/icon_state_preview = null + // If the item is able to be used as a seed in a hydroponics tray. + var/obj/item/seeds/fake_seed /obj/item/Initialize(mapload) diff --git a/code/game/objects/items/food/meatslab.dm b/code/game/objects/items/food/meatslab.dm index 86c3d3c2bb629..b3ffa37c0309a 100644 --- a/code/game/objects/items/food/meatslab.dm +++ b/code/game/objects/items/food/meatslab.dm @@ -73,10 +73,11 @@ /obj/item/food/meat/slab/human/mutant/lizard/make_grillable() AddComponent(/datum/component/grillable, /obj/item/food/meat/steak/plain/human/lizard, rand(30 SECONDS, 90 SECONDS), TRUE, TRUE) -/obj/item/food/meat/slab/human/mutant/plant +/obj/item/food/meat/slab/human/mutant/diona + name = "diona meat" icon_state = "plantmeat" desc = "All the joys of healthy eating with all the fun of cannibalism." - tastes = list("salad" = 1, "wood" = 1) + tastes = list("salad" = 1, "wood" = 1, "bitterness" = 1) foodtypes = VEGETABLES /obj/item/food/meat/slab/human/mutant/shadow diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index 6fa312c6cf393..2ae9f7b16a853 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -24,6 +24,7 @@ var/occupant_weight = 0 var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants + COOLDOWN_DECLARE(movement_cooldown) /obj/item/pet_carrier/Destroy() if(occupants.len) @@ -120,8 +121,10 @@ container_resist(user) /obj/item/pet_carrier/container_resist(mob/living/user) + if(!COOLDOWN_FINISHED(src, movement_cooldown)) + return user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT + COOLDOWN_START(src, movement_cooldown, CLICK_CD_BREAKOUT) if(user.mob_size <= MOB_SIZE_SMALL) to_chat(user, "You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)") to_chat(loc, "You see [user] reach through the bars and fumble for the lock switch!") @@ -171,13 +174,13 @@ user.visible_message("[user] starts loading [target] into [src].", \ "You start loading [target] into [src]...", null, null, target) to_chat(target, "[user] starts loading you into [user.p_their()] [name]!") - if(!do_after(user, 3 SECONDS, target)) - return if(target in occupants) return if(pet_carrier_full(src)) //Run the checks again, just in case to_chat(user, "[src] is already carrying too much!") return + if(target.mob_size >= MOB_SIZE_HUMAN && !do_after(user, 3 SECONDS, target)) // If the mob is small or smaller, no need for a do_after. + return user.visible_message("[user] loads [target] into [src]!", \ "You load [target] into [src].", null, null, target) to_chat(target, "[user] loads you into [user.p_their()] [name]!") diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index 418374583223a..a3cf1351c17b6 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -10,7 +10,7 @@ density = TRUE roundstart = FALSE death = FALSE - mob_species = /datum/species/pod + mob_species = /datum/species/diona short_desc = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed." flavour_text = "Your masters, benevolent as they were, created uncounted seed vaults and spread them across \ the universe to every planet they could chart. You are in one such seed vault. \ @@ -21,13 +21,10 @@ banType = ROLE_LIFEBRINGER /obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn) - var/plant_name = pick("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \ - "Venus", "Sprout","Cocoa", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper") - new_spawn.fully_replace_character_name(null,plant_name) - if(ishuman(new_spawn)) - var/mob/living/carbon/human/H = new_spawn - H.underwear = "Nude" //You're a plant, partner - H.update_body() + var/mob/living/carbon/human/species/diona/H = new_spawn + H.fully_replace_character_name(null, H.dna.species.random_name(gender)) + H.underwear = "Nude" //You're a plant, partner + H.update_body() /obj/effect/mob_spawn/human/seed_vault/Destroy() new/obj/structure/fluff/empty_terrarium(get_turf(src)) diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 0d265de68aa80..4d8a36fa8fc30 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -41,6 +41,14 @@ H.dna.features["apid_headstripes"] = pick(GLOB.apid_headstripes_list) H.dna.features["body_model"] = H.gender H.dna.features["psyphoza_cap"] = pick(GLOB.psyphoza_cap_list) + H.dna.features["diona_leaves"] = pick(GLOB.diona_leaves_list) + H.dna.features["diona_thorns"] = pick(GLOB.diona_thorns_list) + H.dna.features["diona_flowers"] = pick(GLOB.diona_flowers_list) + H.dna.features["diona_moss"] = pick(GLOB.diona_moss_list) + H.dna.features["diona_mushroom"] = pick(GLOB.diona_mushroom_list) + H.dna.features["diona_antennae"] = pick(GLOB.diona_antennae_list) + H.dna.features["diona_eyes"] = pick(GLOB.diona_eyes_list) + H.dna.features["diona_pbody"] = pick(GLOB.diona_pbody_list) H.update_body() H.update_hair() diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 6dc905f595d3b..cff87dbf03113 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -350,7 +350,7 @@ /datum/antagonist/changeling/proc/create_initial_profile() var/mob/living/carbon/C = owner.current //only carbons have dna now, so we have to typecaste - if(isipc(C)) + if(C.dna.species.species_bitflags & NOT_TRANSMORPHIC) C.set_species(/datum/species/human) C.fully_replace_character_name(C.real_name, C.client.prefs.read_character_preference(/datum/preference/name/backup_human)) for(var/datum/data/record/E in GLOB.data_core.general) diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index 1fdd34360450f..31b7d4608542e 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -2389,9 +2389,9 @@ max_supply = 3 access_budget = ACCESS_HYDROPONICS contains = list(/obj/item/seeds/nettle, - /obj/item/seeds/replicapod, - /obj/item/seeds/replicapod, - /obj/item/seeds/replicapod, + /obj/item/seeds/dionapod, + /obj/item/seeds/dionapod, + /obj/item/seeds/dionapod, /obj/item/seeds/plump, /obj/item/seeds/liberty, /obj/item/seeds/amanita, diff --git a/code/modules/client/preferences/entries/character/species_features/diona.dm b/code/modules/client/preferences/entries/character/species_features/diona.dm new file mode 100644 index 0000000000000..d11c7ff173fdf --- /dev/null +++ b/code/modules/client/preferences/entries/character/species_features/diona.dm @@ -0,0 +1,356 @@ +/datum/preference/choiced/diona_leaves + db_key = "feature_diona_leaves" + preference_type = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_FEATURES + main_feature_name = "Diona Leaves" + should_generate_icons = TRUE + relevant_mutant_bodypart = "diona_leaves" + +/datum/preference/choiced/diona_leaves/init_possible_values() + var/list/values = list() + + var/datum/universal_icon/diona_body = uni_icon('icons/effects/effects.dmi', "nothing") + + var/list/body_parts = list( + BODY_ZONE_HEAD, + BODY_ZONE_CHEST, + BODY_ZONE_L_ARM, + BODY_ZONE_R_ARM, + BODY_ZONE_L_LEG, + BODY_ZONE_R_LEG + ) + + for (var/body_part in body_parts) + diona_body.blend_icon(uni_icon('icons/mob/species/diona/bodyparts.dmi', "diona_[body_part]", dir = SOUTH), ICON_OVERLAY) + + for (var/markings_name in GLOB.diona_leaves_list) + var/datum/sprite_accessory/markings = GLOB.diona_leaves_list[markings_name] + var/datum/universal_icon/icon_with_markings = diona_body.copy() + + if (markings_name != FEATURE_NONE) + for (var/body_part in body_parts) + var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "m_[relevant_mutant_bodypart]_[markings.icon_state]_ADJ", dir = SOUTH) + body_part_icon.crop(1, 1, 32, 32) + icon_with_markings.blend_icon(body_part_icon, ICON_OVERLAY) + + icon_with_markings.blend_icon(uni_icon('icons/mob/diona_markings.dmi', "m_diona_leaves_ADJ"), ICON_OVERLAY) + + // Zoom in on the top of the head and the chest + icon_with_markings.scale(64, 64) + icon_with_markings.crop(15, 64 - 31, 15 + 31, 64) + + values[markings.name] = icon_with_markings + + return values + +/datum/preference/choiced/diona_leaves/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["diona_leaves"] = value + +//---------------------------------------------------------------------------------------------------------------------- + +/datum/preference/choiced/diona_thorns + db_key = "feature_diona_thorns" + preference_type = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_FEATURES + main_feature_name = "Diona Thorns" + should_generate_icons = TRUE + relevant_mutant_bodypart = "diona_thorns" + +/datum/preference/choiced/diona_thorns/init_possible_values() + var/list/values = list() + + var/datum/universal_icon/diona_body = uni_icon('icons/effects/effects.dmi', "nothing") + + var/list/body_parts = list( + BODY_ZONE_HEAD, + BODY_ZONE_CHEST + ) + + for (var/body_part in body_parts) + diona_body.blend_icon(uni_icon('icons/mob/species/diona/bodyparts.dmi', "diona_[body_part]", dir = SOUTH), ICON_OVERLAY) + + for (var/markings_name in GLOB.diona_thorns_list) + var/datum/sprite_accessory/markings = GLOB.diona_thorns_list[markings_name] + var/datum/universal_icon/icon_with_markings = diona_body.copy() + + if (markings_name != "None") + for (var/body_part in body_parts) + var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "m_[relevant_mutant_bodypart]_[markings.icon_state]_ADJ", dir = SOUTH) + body_part_icon.crop(1, 1, 32, 32) + icon_with_markings.blend_icon(body_part_icon, ICON_OVERLAY) + + icon_with_markings.blend_icon(uni_icon('icons/mob/diona_markings.dmi', "m_diona_thorns_ADJ"), ICON_OVERLAY) + + // Zoom in on the top of the head and the chest + icon_with_markings.scale(64, 64) + icon_with_markings.crop(15, 64 - 31, 15 + 31, 64) + + values[markings.name] = icon_with_markings + + return values + +/datum/preference/choiced/diona_thorns/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["diona_thorns"] = value + +//---------------------------------------------------------------------------------------------------------------------- + +/datum/preference/choiced/diona_flowers + db_key = "feature_diona_flowers" + preference_type = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_FEATURES + main_feature_name = "Diona Flowers" + should_generate_icons = TRUE + relevant_mutant_bodypart = "diona_flowers" + +/datum/preference/choiced/diona_flowers/init_possible_values() + var/list/values = list() + + var/datum/universal_icon/diona_body = uni_icon('icons/effects/effects.dmi', "nothing") + + var/list/body_parts = list( + BODY_ZONE_HEAD, + BODY_ZONE_CHEST + ) + + for (var/body_part in body_parts) + diona_body.blend_icon(uni_icon('icons/mob/species/diona/bodyparts.dmi', "diona_[body_part]", dir = SOUTH), ICON_OVERLAY) + + for (var/markings_name in GLOB.diona_flowers_list) + var/datum/sprite_accessory/markings = GLOB.diona_flowers_list[markings_name] + var/datum/universal_icon/icon_with_markings = diona_body.copy() + + if (markings_name != "None") + for (var/body_part in body_parts) + var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "m_[relevant_mutant_bodypart]_[markings.icon_state]_ADJ", dir = SOUTH) + body_part_icon.crop(1, 1, 32, 32) + icon_with_markings.blend_icon(body_part_icon, ICON_OVERLAY) + + icon_with_markings.blend_icon(uni_icon('icons/mob/diona_markings.dmi', "m_diona_flowers_ADJ"), ICON_OVERLAY) + + // Zoom in on the top of the head and the chest + icon_with_markings.scale(64, 64) + icon_with_markings.crop(15, 64 - 31, 15 + 31, 64) + + values[markings.name] = icon_with_markings + + return values + +/datum/preference/choiced/diona_flowers/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["diona_flowers"] = value + +//---------------------------------------------------------------------------------------------------------------------- + +/datum/preference/choiced/diona_moss + db_key = "feature_diona_moss" + preference_type = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_FEATURES + main_feature_name = "Diona Moss" + should_generate_icons = TRUE + relevant_mutant_bodypart = "diona_moss" + +/datum/preference/choiced/diona_moss/init_possible_values() + var/list/values = list() + + var/datum/universal_icon/diona_body = uni_icon('icons/effects/effects.dmi', "nothing") + + var/list/body_parts = list( + BODY_ZONE_CHEST + ) + + for (var/body_part in body_parts) + diona_body.blend_icon(uni_icon('icons/mob/species/diona/bodyparts.dmi', "diona_[body_part]", dir = SOUTH), ICON_OVERLAY) + + for (var/markings_name in GLOB.diona_moss_list) + var/datum/sprite_accessory/markings = GLOB.diona_moss_list[markings_name] + var/datum/universal_icon/icon_with_markings = diona_body.copy() + + if (markings_name != "None") + for (var/body_part in body_parts) + var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "m_[relevant_mutant_bodypart]_[markings.icon_state]_ADJ", dir = SOUTH) + body_part_icon.crop(1, 1, 32, 32) + icon_with_markings.blend_icon(body_part_icon, ICON_OVERLAY) + + icon_with_markings.blend_icon(uni_icon('icons/mob/diona_markings.dmi', "m_diona_moss_ADJ"), ICON_OVERLAY) + + // Zoom in on the top of the head and the chest + icon_with_markings.scale(64, 64) + icon_with_markings.crop(15, 64 - 31, 15 + 31, 64) + + values[markings.name] = icon_with_markings + + return values + +/datum/preference/choiced/diona_moss/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["diona_moss"] = value + +//---------------------------------------------------------------------------------------------------------------------- + +/datum/preference/choiced/diona_mushroom + db_key = "feature_diona_mushroom" + preference_type = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_FEATURES + main_feature_name = "Diona Mushrooms" + should_generate_icons = TRUE + relevant_mutant_bodypart = "diona_mushroom" + +/datum/preference/choiced/diona_mushroom/init_possible_values() + var/list/values = list() + + var/datum/universal_icon/diona_body = uni_icon('icons/effects/effects.dmi', "nothing") + + var/list/body_parts = list( + BODY_ZONE_HEAD + ) + + for (var/body_part in body_parts) + diona_body.blend_icon(uni_icon('icons/mob/species/diona/bodyparts.dmi', "diona_[body_part]", dir = SOUTH), ICON_OVERLAY) + + for (var/markings_name in GLOB.diona_mushroom_list) + var/datum/sprite_accessory/markings = GLOB.diona_mushroom_list[markings_name] + var/datum/universal_icon/icon_with_markings = diona_body.copy() + + if (markings_name != "None") + for (var/body_part in body_parts) + var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "m_[relevant_mutant_bodypart]_[markings.icon_state]_ADJ", dir = SOUTH) + body_part_icon.crop(1, 1, 32, 32) + icon_with_markings.blend_icon(body_part_icon, ICON_OVERLAY) + + icon_with_markings.blend_icon(uni_icon('icons/mob/diona_markings.dmi', "m_diona_mushroom_ADJ"), ICON_OVERLAY) + + // Zoom in on the top of the head and the chest + icon_with_markings.scale(64, 64) + icon_with_markings.crop(15, 64 - 31, 15 + 31, 64) + + values[markings.name] = icon_with_markings + + return values + +/datum/preference/choiced/diona_mushroom/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["diona_mushroom"] = value + +//---------------------------------------------------------------------------------------------------------------------- + +/datum/preference/choiced/diona_antennae + db_key = "feature_diona_antennae" + preference_type = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_FEATURES + main_feature_name = "Diona Antennae" + should_generate_icons = TRUE + relevant_mutant_bodypart = "diona_antennae" + +/datum/preference/choiced/diona_antennae/init_possible_values() + var/list/values = list() + + var/datum/universal_icon/diona_body = uni_icon('icons/effects/effects.dmi', "nothing") + + var/list/body_parts = list( + BODY_ZONE_HEAD + ) + + for (var/body_part in body_parts) + diona_body.blend_icon(uni_icon('icons/mob/species/diona/bodyparts.dmi', "diona_[body_part]", dir = SOUTH), ICON_OVERLAY) + + for (var/markings_name in GLOB.diona_antennae_list) + var/datum/sprite_accessory/markings = GLOB.diona_antennae_list[markings_name] + var/datum/universal_icon/icon_with_markings = diona_body.copy() + + if (markings_name != "None") + for (var/body_part in body_parts) + var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "m_[relevant_mutant_bodypart]_[markings.icon_state]_ADJ", dir = SOUTH) + body_part_icon.crop(1, 1, 32, 32) + icon_with_markings.blend_icon(body_part_icon, ICON_OVERLAY) + + icon_with_markings.blend_icon(uni_icon('icons/mob/diona_markings.dmi', "m_diona_antennae_ADJ"), ICON_OVERLAY) + + // Zoom in on the top of the head and the chest + icon_with_markings.scale(64, 64) + icon_with_markings.crop(15, 64 - 31, 15 + 31, 64) + + values[markings.name] = icon_with_markings + + return values + +/datum/preference/choiced/diona_antennae/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["diona_antennae"] = value + +//------------------------------------------------------------------------------------------------------------------------------ + +/datum/preference/choiced/diona_eyes + db_key = "feature_diona_eyes" + preference_type = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_FEATURES + main_feature_name = "Diona Eyes" + should_generate_icons = TRUE + relevant_mutant_bodypart = "diona_eyes" + +/datum/preference/choiced/diona_eyes/init_possible_values() + var/list/values = list() + + var/datum/universal_icon/diona_body = uni_icon('icons/effects/effects.dmi', "nothing") + + for (var/markings_name in GLOB.diona_eyes_list) + var/datum/sprite_accessory/markings = GLOB.diona_eyes_list[markings_name] + var/datum/universal_icon/icon_with_markings = diona_body.copy() + + if (markings_name != "None") + var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "m_[relevant_mutant_bodypart]_[markings.icon_state]_ADJ", dir = SOUTH) + body_part_icon.crop(1, 1, 32, 32) + icon_with_markings.blend_icon(body_part_icon, ICON_OVERLAY) + + icon_with_markings.blend_icon(uni_icon('icons/mob/diona_markings.dmi', "m_diona_eyes_ADJ"), ICON_OVERLAY) + + // Zoom in on the top of the head and the chest + icon_with_markings.scale(64, 64) + icon_with_markings.crop(15, 64 - 31, 15 + 31, 64) + + values[markings.name] = icon_with_markings + + return values + +/datum/preference/choiced/diona_eyes/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["diona_eyes"] = value + +//------------------------------------------------------------------------------------------------------------------------------ + +/datum/preference/choiced/diona_pbody + db_key = "feature_diona_pbody" + preference_type = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_FEATURES + main_feature_name = "Diona P-Body" + should_generate_icons = TRUE + relevant_mutant_bodypart = "diona_pbody" + +/datum/preference/choiced/diona_pbody/init_possible_values() + var/list/values = list() + + var/datum/universal_icon/diona_body = uni_icon('icons/effects/effects.dmi', "nothing") + + var/list/body_parts = list( + BODY_ZONE_CHEST + ) + + for (var/body_part in body_parts) + diona_body.blend_icon(uni_icon('icons/mob/species/diona/bodyparts.dmi', "diona_[body_part]", dir = SOUTH), ICON_OVERLAY) + + for (var/markings_name in GLOB.diona_pbody_list) + var/datum/sprite_accessory/markings = GLOB.diona_pbody_list[markings_name] + var/datum/universal_icon/icon_with_markings = diona_body.copy() + + if (markings_name != "None") + for (var/body_part in body_parts) + var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "m_[relevant_mutant_bodypart]_[markings.icon_state]_ADJ", dir = SOUTH) + body_part_icon.crop(1, 1, 32, 32) + icon_with_markings.blend_icon(body_part_icon, ICON_OVERLAY) + + icon_with_markings.blend_icon(uni_icon('icons/mob/diona_markings.dmi', "m_diona_pbody_ADJ"), ICON_OVERLAY) + + // Zoom in on the top of the head and the chest + icon_with_markings.scale(64, 64) + icon_with_markings.crop(15, 64 - 31, 15 + 31, 64) + + values[markings.name] = icon_with_markings + + return values + +/datum/preference/choiced/diona_pbody/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["diona_pbody"] = value diff --git a/code/modules/client/preferences/entries/character/species_features/ipc.dm b/code/modules/client/preferences/entries/character/species_features/ipc.dm index b041497c4eaaa..13538b3889edc 100644 --- a/code/modules/client/preferences/entries/character/species_features/ipc.dm +++ b/code/modules/client/preferences/entries/character/species_features/ipc.dm @@ -13,7 +13,7 @@ var/datum/sprite_accessory/screen = GLOB.ipc_screens_list[screen_name] var/datum/universal_icon/icon_with_screen = uni_icon('icons/mob/species/ipc/bodyparts.dmi', "mcgipc_head", dir = SOUTH) - if (screen.icon_state != "none") + if (screen_name != FEATURE_NONE) var/datum/universal_icon/screen_icon = uni_icon(screen.icon, "m_ipc_screen_[screen.icon_state]_ADJ", dir = SOUTH) icon_with_screen.blend_icon(screen_icon, ICON_OVERLAY) icon_with_screen.scale(64, 64) diff --git a/code/modules/client/preferences/entries/character/species_features/lizard.dm b/code/modules/client/preferences/entries/character/species_features/lizard.dm index 0b013b24c9472..552fac975480d 100644 --- a/code/modules/client/preferences/entries/character/species_features/lizard.dm +++ b/code/modules/client/preferences/entries/character/species_features/lizard.dm @@ -15,7 +15,7 @@ var/datum/universal_icon/final_icon = lizard.copy() - if (sprite_accessory.icon_state != "none") + if (name != FEATURE_NONE) var/datum/universal_icon/accessory_icon = uni_icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ", dir = EAST) final_icon.blend_icon(accessory_icon, ICON_OVERLAY) diff --git a/code/modules/client/preferences/entries/character/species_features/moth.dm b/code/modules/client/preferences/entries/character/species_features/moth.dm index 8ab2db9deb384..94ca51ff68469 100644 --- a/code/modules/client/preferences/entries/character/species_features/moth.dm +++ b/code/modules/client/preferences/entries/character/species_features/moth.dm @@ -51,7 +51,7 @@ var/datum/sprite_accessory/markings = GLOB.moth_markings_roundstart_list[markings_name] var/datum/universal_icon/icon_with_markings = moth_body.copy() - if (markings_name != "None") + if (markings_name != FEATURE_NONE) for (var/body_part in body_parts) var/datum/universal_icon/body_part_icon = uni_icon(markings.icon, "[markings.icon_state]_[body_part]", dir = SOUTH) body_part_icon.crop(1, 1, 32, 32) diff --git a/code/modules/client/preferences/entries/character/species_features/psyphoza.dm b/code/modules/client/preferences/entries/character/species_features/psyphoza.dm index 4108d1039382f..d9f1dfda7d730 100644 --- a/code/modules/client/preferences/entries/character/species_features/psyphoza.dm +++ b/code/modules/client/preferences/entries/character/species_features/psyphoza.dm @@ -13,7 +13,7 @@ var/datum/sprite_accessory/cap = GLOB.psyphoza_cap_list[cap_name] var/datum/universal_icon/icon_with_cap = uni_icon('icons/mob/species/psyphoza/bodyparts.dmi', "psyphoza_head", dir = SOUTH) - if (cap.icon_state != "none") + if (cap_name != FEATURE_NONE) var/datum/universal_icon/screen_icon = uni_icon(cap.icon, "m_psyphoza_cap_[cap.icon_state]_ADJ", dir = SOUTH) icon_with_cap.blend_icon(screen_icon, ICON_OVERLAY) icon_with_cap.scale(64, 64) diff --git a/code/modules/hydroponics/grown/dionapod.dm b/code/modules/hydroponics/grown/dionapod.dm new file mode 100644 index 0000000000000..dfff78f6fb8d0 --- /dev/null +++ b/code/modules/hydroponics/grown/dionapod.dm @@ -0,0 +1,60 @@ +// A very special plant, deserving it's own file. + +/obj/item/seeds/dionapod + name = "pack of diona seeds" + desc = "These seeds grow into diona nymphs. They say these are used to grow new dionae, just add blood!" + icon_state = "seed-dionapod" + species = "diona" + plantname = "Diona Pod" + product = /mob/living/simple_animal/hostile/retaliate/nymph + lifespan = 50 + endurance = 8 + maturation = 8 + production = 1 + yield = 1 + potency = 30 + growthstages = 3 + var/volume = 5 + var/list/result = list() + +/obj/item/seeds/dionapod/harvest(mob/user) + var/obj/machinery/hydroponics/parent = src.loc + if(CONFIG_GET(flag/diona_ghost_spawn)) + var/mob/living/simple_animal/hostile/retaliate/nymph/child = new /mob/living/simple_animal/hostile/retaliate/nymph(get_turf(parent)) + child.is_ghost_spawn = TRUE + var/seed_count = 1 + if(prob(getYield() * 20)) + seed_count++ + var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc //needed for TK + while(seed_count) + var/obj/item/seeds/dionapod/harvestseeds = src.Copy() + result.Add(harvestseeds) + harvestseeds.forceMove(output_loc) + seed_count-- + parent.update_tray() + return result + + +/obj/item/seeds/nymph + name = "Dead Nymph" + icon_state = "seed-dionapod" + species = "diona" + plantname = "Dead Nymph" + product = /mob/living/simple_animal/hostile/retaliate/nymph + lifespan = 50 + endurance = 8 + maturation = 8 + production = 1 + yield = 1 + potency = 30 + growthstages = 3 + var/volume = 5 + var/list/result = list() + +/obj/item/seeds/nymph/harvest(mob/user) + var/obj/machinery/hydroponics/parent = src.loc + var/mob/living/simple_animal/hostile/retaliate/nymph/child = new /mob/living/simple_animal/hostile/retaliate/nymph(get_turf(parent)) + mind.transfer_to(child) + child.grab_ghost() + parent.update_tray() + return result diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm index 8325f7e12dff4..4f3822bc9c8d5 100644 --- a/code/modules/hydroponics/grown/misc.dm +++ b/code/modules/hydroponics/grown/misc.dm @@ -82,7 +82,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/item/seeds/galaxythistle) growthstages = 1 growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' genes = list(/datum/plant_gene/trait/repeated_harvest) - mutatelist = list(/obj/item/seeds/replicapod) + mutatelist = list(/obj/item/seeds/dionapod) reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) /obj/item/food/grown/cabbage diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm deleted file mode 100644 index 1db9569cfde09..0000000000000 --- a/code/modules/hydroponics/grown/replicapod.dm +++ /dev/null @@ -1,165 +0,0 @@ -// A very special plant, deserving it's own file. - -/obj/item/seeds/replicapod - name = "pack of replica pod seeds" - desc = "These seeds grow into replica pods. They say these are used to harvest humans." - icon_state = "seed-replicapod" - species = "replicapod" - plantname = "Replica Pod" - product = /mob/living/carbon/human //verrry special -- Urist - lifespan = 50 - endurance = 8 - maturation = 8 - production = 1 - yield = 1 //seeds if there isn't a dna inside - potency = 30 - var/volume = 5 - var/ckey - var/realName - var/datum/mind/mind - var/blood_gender - var/blood_type - var/list/features - var/factions - var/list/quirks - var/sampleDNA - var/contains_sample = FALSE - var/being_harvested = FALSE - -/obj/item/seeds/replicapod/Initialize(mapload) - . = ..() - - create_reagents(volume, INJECTABLE|DRAWABLE) - -/obj/item/seeds/replicapod/on_reagent_change(changetype) - if(changetype == ADD_REAGENT) - var/datum/reagent/blood/B = reagents.has_reagent(/datum/reagent/blood) - if(B) - if(B.data["mind"] && B.data["cloneable"]) - mind = B.data["mind"] - ckey = B.data["ckey"] - realName = B.data["real_name"] - blood_gender = B.data["gender"] - blood_type = B.data["blood_type"] - features = B.data["features"] - factions = B.data["factions"] - sampleDNA = B.data["blood_DNA"] - contains_sample = TRUE - visible_message("The [src] is injected with a fresh blood sample.") - log_cloning("[key_name(mind)]'s cloning record was added to [src] at [AREACOORD(src)].") - else - visible_message("The [src] rejects the sample!") - - if(!reagents.has_reagent(/datum/reagent/blood)) - mind = null - ckey = null - realName = null - blood_gender = null - blood_type = null - features = null - factions = null - sampleDNA = null - contains_sample = FALSE - -/obj/item/seeds/replicapod/get_analyzer_text() - var/text = ..() - if(contains_sample) - text += "\n It contains a blood sample with blood DNA ([sampleDNA])." //blood DNA (UE) shows in medical records and is readable by forensics scanners - return text - - -/obj/item/seeds/replicapod/harvest(mob/user) //now that one is fun -- Urist - var/obj/machinery/hydroponics/parent = loc - var/make_podman = FALSE - var/ckey_holder = null - var/list/result = list() - if(CONFIG_GET(flag/revival_pod_plants)) - if(ckey) - for(var/mob/M in GLOB.player_list) - if(isobserver(M)) - var/mob/dead/observer/O = M - if(O.ckey == ckey && O.can_reenter_corpse) - make_podman = TRUE - break - else - if(M.ckey == ckey && M.stat == DEAD && !M.suiciding) - make_podman = TRUE - // Devil code - if(isliving(M)) - var/mob/living/L = M - make_podman = !L.ishellbound() - break - else //If the player has ghosted from his corpse before blood was drawn, his ckey is no longer attached to the mob, so we need to match up the cloned player through the mind key - for(var/mob/M in GLOB.player_list) - if(mind && M.mind && ckey(M.mind.key) == ckey(mind.key) && M.ckey && M.client && M.stat == DEAD && !M.suiciding) - if(isobserver(M)) - var/mob/dead/observer/O = M - if(!O.can_reenter_corpse) - break - make_podman = TRUE - // Devil code - if(isliving(M)) - var/mob/living/L = M - make_podman = !L.ishellbound() - ckey_holder = M.ckey - break - - // No podman player, give one or two seeds. - if(!make_podman) - // Prevent accidental harvesting. Make sure the user REALLY wants to do this if there's a chance of this coming from a living creature. - if(mind || ckey) - if(alert("The pod is currently devoid of soul. There is a possibility that a soul could claim this creature, or you could harvest it for seeds.", "Harvest Seeds?", "Harvest Seeds", "Cancel") != "Harvest Seeds") - return result - - // If this plant has already been harvested, return early. - // parent.update_tray() qdels this seed. - if(QDELETED(src)) - to_chat(user, text = "This pod has already had its seeds harvested!", type = MESSAGE_TYPE_INFO) - return result - - // Make sure they can still interact with the parent hydroponics tray. - if(!parent.can_interact(user)) - to_chat(user, text = "You are no longer able to harvets the seeds from [parent]!", type = MESSAGE_TYPE_INFO) - return result - - var/seed_count = 1 - if(prob(getYield() * 20)) - seed_count++ - var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc //needed for TK - while(seed_count) - var/obj/item/seeds/replicapod/harvestseeds = src.Copy() - result.Add(harvestseeds) - harvestseeds.forceMove(output_loc) - seed_count-- - parent.update_tray() - return result - - // All conditions met! - var/mob/living/carbon/human/podman = new /mob/living/carbon/human(parent.loc) - if(realName) - podman.real_name = realName - else - podman.real_name = "Pod Person ([rand(1,999)])" - mind.transfer_to(podman) - if(ckey) - podman.ckey = ckey - else - podman.ckey = ckey_holder - podman.gender = blood_gender - podman.faction |= factions - if(!features["mcolor"]) - features["mcolor"] = "#59CE00" - for(var/V in quirks) - new V(podman) - podman.hardset_dna(null,null,podman.real_name,blood_type, new /datum/species/pod,features,null)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman - podman.set_cloned_appearance() - // On harvest - to_chat(podman, "There is a bright flash!
You feel like a new being.
") - var/postclonemessage = CONFIG_GET(string/policy_postclonetext) - if(postclonemessage) - to_chat(podman, postclonemessage) - podman.flash_act() - log_cloning("[key_name(mind)] cloned as a podman via [src] in [parent] at [AREACOORD(parent)].") - - parent.update_tray() - return result diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 64f02071a6094..ad4b611b81595 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -782,12 +782,14 @@ reagent_source.update_icon() return 1 - else if(istype(O, /obj/item/seeds) && !istype(O, /obj/item/seeds/sample)) + else if(O.tool_behaviour == TOOL_SEED && !istype(O, /obj/item/seeds/sample)) if(!myseed) if(istype(O, /obj/item/seeds/kudzu)) investigate_log("had Kudzu planted in it by [key_name(user)] at [AREACOORD(src)]","kudzu") if(!user.transferItemToLoc(O, src)) return + if(!istype(O, /obj/item/seeds)) //If the given item is supposed to be a seed, but isn't a subtype of /obj/item/seed + O = O.fake_seed // use the item's fake_seed variable instead. to_chat(user, "You plant [O].") dead = 0 myseed = O @@ -901,7 +903,7 @@ /obj/machinery/hydroponics/proc/update_tray(mob/user) harvest = 0 lastproduce = age - if(istype(myseed, /obj/item/seeds/replicapod)) + if(istype(myseed, /obj/item/seeds/dionapod)) to_chat(user, "You harvest from the [myseed.plantname].") else if(myseed.getYield() <= 0) to_chat(user, "You fail to harvest anything useful!") diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index 38cc920c9b115..4a36f0db737cf 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -405,7 +405,7 @@ /datum/plant_gene/trait/repeated_harvest/can_add(obj/item/seeds/S) if(!..()) return FALSE - if(istype(S, /obj/item/seeds/replicapod)) + if(istype(S, /obj/item/seeds/dionapod)) return FALSE return TRUE diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index bdf361f941047..3b7fafb41bfb4 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -9,6 +9,7 @@ worn_icon_state = "seed" w_class = WEIGHT_CLASS_TINY resistance_flags = FLAMMABLE + tool_behaviour = TOOL_SEED var/plantname = "Plants" // Name of plant when planted. var/plantdesc var/product // A type path. The thing that is created when the plant is harvested. @@ -30,6 +31,7 @@ var/rarity = 0 // How rare the plant is. Used for giving points to cargo when shipping off to CentCom. var/list/mutatelist = list() // The type of plants that this plant can mutate into. var/list/genes = list() // Plant genes are stored here, see plant_genes.dm for more info. + var/datum/mind/mind // For if the seed can hold a mind. Used for diona related stuffs. var/list/reagents_add = list() // A list of reagents to add to product. // Format: "reagent_id" = potency multiplier diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index 82fd421ee9af3..e5c6e65c03d49 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -404,7 +404,7 @@ Key procs spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), /datum/language/buzzwords = list(LANGUAGE_ATOM)) -/datum/language_holder/plant +/datum/language_holder/diona understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), /datum/language/sylvan = list(LANGUAGE_ATOM)) spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm index f3ab4495cb86c..8325031545515 100644 --- a/code/modules/mapping/mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers.dm @@ -310,7 +310,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) /obj/effect/mapping_helpers/dead_body_placer/proc/spawn_dead_human_in_tray(atom/container) var/mob/living/carbon/human/corpse = new(container) - var/list/possible_alt_species = GLOB.roundstart_races.Copy() - list(SPECIES_HUMAN, SPECIES_IPC) + var/list/possible_alt_species = GLOB.roundstart_races.Copy() - list(SPECIES_HUMAN, SPECIES_IPC, SPECIES_DIONA) if(prob(15) && length(possible_alt_species)) corpse.set_species(GLOB.species_list[pick(possible_alt_species)]) corpse.give_random_dormant_disease(25, min_symptoms = 1, max_symptoms = 5) // slightly more likely that an average stationgoer to have a dormant disease, bc who KNOWS how they died? diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm index 619dcf3d7b8b9..add25a6e3ee06 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -2631,6 +2631,207 @@ name = "Helvella" icon_state = "sponge" +//dionae + +/datum/sprite_accessory/diona_leaves + icon = 'icons/mob/diona_markings.dmi' + color_src = null + +/datum/sprite_accessory/diona_leaves/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/diona_leaves/leaves + name = "Diona Leaves" + +/datum/sprite_accessory/diona_leaves/leaves/head + name = "Diona Leaves" + icon_state = "head" +/datum/sprite_accessory/diona_leaves/leaves/r_arm + name = "Diona Leaves" + icon_state = "r_arm" +/datum/sprite_accessory/diona_leaves/leaves/l_arm + name = "Diona Leaves" + icon_state = "l_arm" +/datum/sprite_accessory/diona_leaves/leaves/r_leg + name = "Diona Leaves" + icon_state = "r_leg" +/datum/sprite_accessory/diona_leaves/leaves/l_leg + name = "Diona Leaves" + icon_state = "l_leg" +/datum/sprite_accessory/diona_leaves/leaves/torso + name = "Diona Leaves" + icon_state = "chest" + +///////////////////////////////////////////////////// +/datum/sprite_accessory/diona_thorns + icon = 'icons/mob/diona_markings.dmi' + color_src = null + +/datum/sprite_accessory/diona_thorns/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/diona_thorns/head + name = "Diona Thorns (Head)" + icon_state = "head" + +/datum/sprite_accessory/diona_thorns/torso + name = "Diona Thorns (Torso)" + icon_state = "chest" +///////////////////////////////////////////////////// +/datum/sprite_accessory/diona_flowers + icon = 'icons/mob/diona_markings.dmi' + color_src = null + +/datum/sprite_accessory/diona_flowers/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/diona_flowers/head + name = "Diona Flowers (Head)" + icon_state = "head" + +/datum/sprite_accessory/diona_flowers/torso + name = "Diona Flowers (Torso)" + icon_state = "chest" +///////////////////////////////////////////////////// +/datum/sprite_accessory/diona_moss + icon = 'icons/mob/diona_markings.dmi' + color_src = null + +/datum/sprite_accessory/diona_moss/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/diona_moss/torso + name = "Diona Moss" + icon_state = "chest" +///////////////////////////////////////////////////// +/datum/sprite_accessory/diona_mushroom + icon = 'icons/mob/diona_markings.dmi' + color_src = null + +/datum/sprite_accessory/diona_mushroom/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/diona_mushroom/head + name = "Diona Mushroom" + icon_state = "head" +///////////////////////////////////////////////////// +/datum/sprite_accessory/diona_antennae + icon = 'icons/mob/diona_markings.dmi' + color_src = null + +/datum/sprite_accessory/diona_antennae/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/diona_antennae/head + name = "Diona Antennae" + icon_state = "head" +///////////////////////////////////////////////////// +/datum/sprite_accessory/diona_eyes + icon = 'icons/mob/diona_markings.dmi' + color_src = null + +/datum/sprite_accessory/diona_eyes/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/diona_eyes/bug_eyes + name = "Bug Eyes" + icon_state = "bugeyes_head" + +/datum/sprite_accessory/diona_eyes/human_eyes + name = "Human Eyes" + icon_state = "humaneyes_head" + +/datum/sprite_accessory/diona_eyes/small_horns + name = "Small Horns" + icon_state = "smallhorns_head" + +/datum/sprite_accessory/diona_eyes/horns + name = "Horns" + icon_state = "horns_head" + +/datum/sprite_accessory/diona_eyes/treebeard + name = "Treebeard" + icon_state = "treebeard_head" + +/datum/sprite_accessory/diona_eyes/tinyeye + name = "Tiny Eye" + icon_state = "tinyeye_head" + +/datum/sprite_accessory/diona_eyes/eyebrow + name = "Eyebrow" + icon_state = "eyebrow_head" + +/datum/sprite_accessory/diona_eyes/bullhorn + name = "Bullhorn" + icon_state = "bullhorn_head" + +/datum/sprite_accessory/diona_eyes/mono_eye + name = "Mono Eye" + icon_state = "monoeye_head" + +/datum/sprite_accessory/diona_eyes/trioptics + name = "Trioptics" + icon_state = "trioptics_head" + +/datum/sprite_accessory/diona_eyes/lopsided + name = "Lopsided" + icon_state = "lopsided_head" + +/datum/sprite_accessory/diona_eyes/helmethead + name = "Helmethead" + icon_state = "helmethead_head" + +/datum/sprite_accessory/diona_eyes/eyestalk + name = "Eyestalk" + icon_state = "eyestalk_head" + +/datum/sprite_accessory/diona_eyes/periscope + name = "Periscope" + icon_state = "periscope_head" + +/datum/sprite_accessory/diona_eyes/glorp + name = "Glorp" + icon_state = "glorp_head" + +/datum/sprite_accessory/diona_eyes/oak + name = "Oak" + icon_state = "oak_head" + +/datum/sprite_accessory/diona_eyes/smallhorns + name = "Small Horns" + icon_state = "smallhorns_head" + +/datum/sprite_accessory/diona_eyes/stump + name = "Stump" + icon_state = "stump_head" + +/datum/sprite_accessory/diona_eyes/snout + name = "Snout" + icon_state = "snout_head" +///////////////////////////////////////////////////// +/datum/sprite_accessory/diona_pbody + icon = 'icons/mob/diona_markings.dmi' + color_src = null + +/datum/sprite_accessory/diona_pbody/none + name = "None" + icon_state = "none" + +/datum/sprite_accessory/diona_pbody/pbody + name = "P-Body" + icon_state = "chest" +/datum/sprite_accessory/diona_pbody/blinking + name = "Blinking P-Body" + icon_state = "blinking_chest" +///////////////////////////////////////////////////// + //apids /datum/sprite_accessory/apid_antenna diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 7736f6cd65da6..5c6633ac29519 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -220,6 +220,18 @@ desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?" icon_state = "brain-x" +/obj/item/organ/brain/diona + name = "diona nymph" + desc = "A small mass of roots and plant matter, it looks to be moving." + icon_state = "diona_brain" + decoy_override = TRUE + +/obj/item/organ/brain/diona/Remove(mob/living/carbon/C, special, no_id_transfer, pref_load) + if(special) + return + C.dna.species.spec_death(FALSE, src) + QDEL_NULL(src) + /obj/item/organ/brain/positron name = "positronic brain" slot = ORGAN_SLOT_BRAIN diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 07d3be791b2a2..17b2471b720a9 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -93,6 +93,14 @@ GLOBAL_LIST_EMPTY(dummy_mob_list) target.dna.features["ipc_antenna"] = "None" target.dna.features["ipc_chassis"] = "Morpheus Cyberkinetics (Custom)" target.dna.features["psyphoza_cap"] = "Portobello" + target.dna.features["diona_leaves"] = "None" + target.dna.features["diona_thorns"] = "None" + target.dna.features["diona_flowers"] = "None" + target.dna.features["diona_moss"] = "None" + target.dna.features["diona_mushroom"] = "None" + target.dna.features["diona_antennae"] = "None" + target.dna.features["diona_eyes"] = "None" + target.dna.features["diona_pbody"] = "None" /// Provides a dummy that is consistently bald, white, naked, etc. /mob/living/carbon/human/dummy/consistent diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 9ee26290729d5..1f58b92024368 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -337,3 +337,31 @@ /datum/emote/living/carbon/human/robot_tongue/clown/sad/run_emote(mob/user, params) if(..()) playsound(user.loc, 'sound/misc/sadtrombone.ogg', 50) + +/datum/emote/living/carbon/human/diona + // allow mothroach as well as human base mob - species check is done in can_run_emote + mob_type_allowed_typecache = list(/mob/living/carbon/human,/mob/living/simple_animal/hostile/retaliate/nymph) + +/datum/emote/living/carbon/human/diona/can_run_emote(mob/user, status_check = TRUE, intentional) + if(!..()) + return FALSE + if(ishuman(user)) + return isdiona(user) + return istype(user, /mob/living/simple_animal/hostile/retaliate/nymph) + +/datum/emote/living/carbon/human/diona/chitter + key = "chitter" + key_third_person = "chitters" + message = "chitters" + emote_type = EMOTE_AUDIBLE + vary = TRUE + sound = 'sound/emotes/diona/chitter.ogg' + +/datum/emote/living/carbon/human/diona/cricket + key = "cricket" + key_third_person = "chirps" + message = "chirps" + emote_type = EMOTE_AUDIBLE + vary = TRUE + sound = 'sound/emotes/diona/cricket.ogg' + sound_volume = 30 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 527cdc8687b31..ac5bab90d2496 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1301,8 +1301,8 @@ CREATION_TEST_IGNORE_SUBTYPES(/mob/living/carbon/human/species) /mob/living/carbon/human/species/plasma race = /datum/species/plasmaman -/mob/living/carbon/human/species/pod - race = /datum/species/pod +/mob/living/carbon/human/species/diona + race = /datum/species/diona /mob/living/carbon/human/species/shadow race = /datum/species/shadow @@ -1329,7 +1329,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/mob/living/carbon/human/species) race = /datum/species/human/krokodil_addict /mob/living/carbon/human/species/pumpkin_man - race = /datum/species/pod/pumpkin_man + race = /datum/species/pumpkin_man /mob/living/carbon/human/species/psyphoza race = /datum/species/psyphoza diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index b5291a76da879..b63851160131f 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -153,6 +153,9 @@ GLOBAL_LIST_EMPTY(features_by_species) /// What bleed status effect should we apply? var/bleed_effect = STATUS_EFFECT_BLEED + // Species specific bitflags. Used for things like if the race is unable to become a changeling. + var/species_bitflags = NONE + /////////// // PROCS // /////////// @@ -338,7 +341,7 @@ GLOBAL_LIST_EMPTY(features_by_species) continue var/obj/item/organ/I = C.getorgan(mutantorgan) if(I) - I.Remove(C) + I.Remove(C, TRUE) required_organs -= I.type QDEL_NULL(I) @@ -902,6 +905,30 @@ GLOBAL_LIST_EMPTY(features_by_species) if(mutant_bodyparts["psyphoza_cap"]) if(!H.dna.features["psyphoza_cap"] || H.dna.features["psyphoza_cap"] == "None" || !HD) bodyparts_to_add -= "psyphoza_cap" + if("diona_leaves" in mutant_bodyparts) + if(!H.dna.features["diona_leaves"] || H.dna.features["diona_leaves"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) + bodyparts_to_add -= "diona_leaves" + if("diona_thorns" in mutant_bodyparts) + if(!H.dna.features["diona_thorns"] || H.dna.features["diona_thorns"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) + bodyparts_to_add -= "diona_thorns" + if("diona_flowers" in mutant_bodyparts) + if(!H.dna.features["diona_flowers"] || H.dna.features["diona_flowers"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) + bodyparts_to_add -= "diona_flowers" + if("diona_moss" in mutant_bodyparts) + if(!H.dna.features["diona_moss"] || H.dna.features["diona_moss"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) + bodyparts_to_add -= "diona_moss" + if("diona_mushroom" in mutant_bodyparts) + if(!H.dna.features["diona_mushroom"] || H.dna.features["diona_mushroom"] == "None" || !HD) + bodyparts_to_add -= "diona_mushroom" + if("diona_antennae" in mutant_bodyparts) + if(!H.dna.features["diona_antennae"] || H.dna.features["diona_antennae"] == "None" || !HD) + bodyparts_to_add -= "diona_antennae" + if("diona_eyes" in mutant_bodyparts) + if(!H.dna.features["diona_eyes"] || H.dna.features["diona_eyes"] == "None" || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEYES)) || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD) + bodyparts_to_add -= "diona_eyes" + if("diona_pbody" in mutant_bodyparts) + if(!H.dna.features["diona_pbody"] || H.dna.features["diona_pbody"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) + bodyparts_to_add -= "diona_pbody" ////PUT ALL YOUR WEIRD ASS REAL-LIMB HANDLING HERE @@ -1001,6 +1028,24 @@ GLOBAL_LIST_EMPTY(features_by_species) S = GLOB.apid_headstripes_list[H.dna.features["apid_headstripes"]] if("psyphoza_cap") S = GLOB.psyphoza_cap_list[H.dna.features["psyphoza_cap"]] + if("diona_leaves") + S = GLOB.diona_leaves_list[H.dna.features["diona_leaves"]] + if("diona_thorns") + S = GLOB.diona_thorns_list[H.dna.features["diona_thorns"]] + if("diona_flowers") + S = GLOB.diona_flowers_list[H.dna.features["diona_flowers"]] + if("diona_moss") + S = GLOB.diona_moss_list[H.dna.features["diona_moss"]] + if("diona_mushroom") + S = GLOB.diona_mushroom_list[H.dna.features["diona_mushroom"]] + if("diona_antennae") + S = GLOB.diona_antennae_list[H.dna.features["diona_antennae"]] + if("diona_eyes") + S = GLOB.diona_eyes_list[H.dna.features["diona_eyes"]] + if("diona_pbody") + S = GLOB.diona_pbody_list[H.dna.features["diona_pbody"]] + + if(!S || S.icon_state == "none") continue diff --git a/code/modules/mob/living/carbon/human/species_types/IPC.dm b/code/modules/mob/living/carbon/human/species_types/IPC.dm index 9b8a854c94a2c..90696ecee5f1c 100644 --- a/code/modules/mob/living/carbon/human/species_types/IPC.dm +++ b/code/modules/mob/living/carbon/human/species_types/IPC.dm @@ -34,6 +34,7 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK species_language_holder = /datum/language_holder/synthetic special_step_sounds = list('sound/effects/servostep.ogg') + species_bitflags = NOT_TRANSMORPHIC species_chest = /obj/item/bodypart/chest/ipc species_head = /obj/item/bodypart/head/ipc diff --git a/code/modules/mob/living/carbon/human/species_types/diona.dm b/code/modules/mob/living/carbon/human/species_types/diona.dm new file mode 100644 index 0000000000000..2fb42c6c151b6 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species_types/diona.dm @@ -0,0 +1,380 @@ +/datum/species/diona + name = "\improper Diona" + plural_form = "Dionae" + id = SPECIES_DIONA + sexes = 0 + bodyflag = FLAG_DIONA + default_color = "59CE00" + species_traits = list(MUTCOLORS,EYECOLOR,AGENDER,NOHUSK,NO_DNA_COPY,NO_UNDERWEAR,NOSOCKS,NOTRANSSTING,NOEYESPRITES) + inherent_traits = list(TRAIT_ALWAYS_CLEAN, TRAIT_BEEFRIEND, TRAIT_NONECRODISEASE, TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTCOLD, TRAIT_NORADDAMAGE) + inherent_biotypes = list(MOB_HUMANOID, MOB_BUG) + mutant_bodyparts = list("diona_leaves", "diona_thorns", "diona_flowers", "diona_moss", "diona_mushroom", "diona_antennae", "diona_eyes", "diona_pbody") + mutant_organs = list(/obj/item/organ/nymph_organ/r_arm, /obj/item/organ/nymph_organ/l_arm, /obj/item/organ/nymph_organ/l_leg, /obj/item/organ/nymph_organ/r_leg, /obj/item/organ/nymph_organ/chest) + inherent_factions = list("plants", "vines", "diona") + attack_verb = "slash" + attack_sound = 'sound/emotes/diona/hit.ogg' + burnmod = 1.25 + heatmod = 1.5 + brutemod = 0.8 + staminamod = 0.7 + meat = /obj/item/food/meat/slab/human/mutant/diona + exotic_blood = /datum/reagent/consumable/chlorophyll + species_gibs = null //Someone please make this like, xeno gibs or something in the future. I cant be bothered to fuck around with gib code right now. + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP + species_language_holder = /datum/language_holder/diona + bodytemp_normal = (BODYTEMP_NORMAL - 22) // Body temperature for dionae is much lower then humans as they are plants, supposed to be 15 celsius + speedmod = 1.2 // Dionae are slow. + species_height = SPECIES_HEIGHTS(0, -1, -2) //Naturally tall. + swimming_component = /datum/component/swimming/diona + inert_mutation = DRONE + deathsound = "sound/emotes/diona/death.ogg" + species_bitflags = NOT_TRANSMORPHIC + + mutanteyes = /obj/item/organ/eyes/diona //SS14 sprite + mutanttongue = /obj/item/organ/tongue/diona //Dungeon's sprite + mutantbrain = /obj/item/organ/brain/diona //SS14 sprite + mutantliver = /obj/item/organ/liver/diona //Dungeon's sprite + mutantlungs = /obj/item/organ/lungs/diona //Dungeon's sprite + mutantstomach = /obj/item/organ/stomach/diona //SS14 sprite + mutantears = /obj/item/organ/ears/diona //SS14 sprite + mutantheart = /obj/item/organ/heart/diona //Dungeon's sprite + + species_chest = /obj/item/bodypart/chest/diona + species_head = /obj/item/bodypart/head/diona + species_l_arm = /obj/item/bodypart/l_arm/diona + species_r_arm = /obj/item/bodypart/r_arm/diona + species_l_leg = /obj/item/bodypart/l_leg/diona + species_r_leg = /obj/item/bodypart/r_leg/diona + + var/datum/action/diona/split/split_ability //All dionae start with this, this is for splitting apart completely. + var/datum/action/diona/partition/partition_ability //All dionae start with this as well, this is for splitting off a nymph from food. + var/datum/weakref/drone_ref + + var/time_spent_in_light + var/informed_nymph = FALSE //If the user was informed that they can release a nymph via food. + +/datum/species/diona/spec_life(mob/living/carbon/human/H) + if(H.fire_stacks < 1) + H.adjust_fire_stacks(1) //VERY flammable + if(H.nutrition < NUTRITION_LEVEL_STARVING) + H.take_overall_damage(1,0) + if(H.stat != CONSCIOUS) + H.remove_status_effect(STATUS_EFFECT_PLANTHEALING) + if((H.health <= H.crit_threshold)) //Shit, we're dying! Scatter! + split_ability.Trigger(TRUE) + if(H.nutrition > NUTRITION_LEVEL_WELL_FED && !informed_nymph) + informed_nymph = TRUE + to_chat(H, "You feel sufficiently satiated to allow a nymph to split off from your gestalt!") + if(partition_ability) + partition_ability.UpdateButtonIcon() + if(H.nutrition > NUTRITION_LEVEL_ALMOST_FULL) + H.set_nutrition(NUTRITION_LEVEL_ALMOST_FULL) + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(!isturf(H.loc)) //else, there's considered to be no light + H.remove_status_effect(STATUS_EFFECT_PLANTHEALING) + time_spent_in_light = 0 //No light? Reset the timer. + return + var/turf/T = H.loc + light_amount = min(1,T.get_lumcount()) - 0.5 + H.adjust_nutrition(light_amount * 7) + if(light_amount > 0.2) //Is there light here? + time_spent_in_light++ //If so, how long have we been somewhere with light? + if(time_spent_in_light > 5) //More than 5 seconds spent in the light + if(H.stat != CONSCIOUS) + H.remove_status_effect(STATUS_EFFECT_PLANTHEALING) + return + H.apply_status_effect(STATUS_EFFECT_PLANTHEALING) + +/datum/species/diona/spec_updatehealth(mob/living/carbon/human/H) + var/mob/living/simple_animal/hostile/retaliate/nymph/drone = drone_ref?.resolve() + if(H.stat != CONSCIOUS && !H.mind && drone) //If the home body is not fully conscious, they dont have a mind and have a drone + drone.switch_ability.Trigger(H) //Bring them home. + +/datum/species/diona/handle_mutations_and_radiation(mob/living/carbon/human/H) + . = FALSE + var/radiation = H.radiation + //Dionae heal and eat radiation for a living. + H.adjust_nutrition(clamp(radiation, 0, 7)) + if(radiation > 50) + H.heal_overall_damage(1,1, 0, BODYTYPE_ORGANIC) + H.adjustToxLoss(-2) + H.adjustOxyLoss(-1) + +/datum/species/diona/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.type == /datum/reagent/toxin/plantbgone) + H.adjustToxLoss(3) + H.reagents.remove_reagent(chem.type, chem.metabolization_rate) + return TRUE + if(chem.type == /datum/reagent/toxin/mutagen) + H.adjustToxLoss(-3) + H.reagents.remove_reagent(chem.type, chem.metabolization_rate) + return TRUE + if(chem.type == /datum/reagent/plantnutriment) + H.adjustBruteLoss(-1) + H.adjustFireLoss(-1) + H.reagents.remove_reagent(chem.type, chem.metabolization_rate) + return TRUE + return ..() + +/datum/species/diona/on_hit(obj/projectile/P, mob/living/carbon/human/H) + if(P.type == (/obj/projectile/energy/floramut || /obj/projectile/energy/florayield)) + H.set_nutrition(min(H.nutrition+30, NUTRITION_LEVEL_FULL)) + +/datum/species/diona/spec_death(gibbed, mob/living/carbon/human/H) + drone_ref = null + if(gibbed) + QDEL_NULL(H) + return + split_ability.Trigger(TRUE) + +/datum/species/diona/on_species_gain(mob/living/carbon/human/H) + . = ..() + var/obj/item/organ/appendix/appendix = H.getorganslot("appendix") //No appendixes for plant people + if(appendix) + appendix.Remove(H) + QDEL_NULL(appendix) + split_ability = new + split_ability.Grant(H) + partition_ability = new + partition_ability.Grant(H) + ADD_TRAIT(H, TRAIT_MOBILE, "diona") + +/datum/species/diona/on_species_loss(mob/living/carbon/human/H, datum/species/new_species, pref_load) + . = ..() + split_ability.Remove(H) + QDEL_NULL(split_ability) + partition_ability.Remove(H) + QDEL_NULL(partition_ability) + REMOVE_TRAIT(H, TRAIT_MOBILE, "diona") + qdel(drone_ref) + for(var/status_effect as anything in H.status_effects) + if(status_effect == STATUS_EFFECT_PLANTHEALING) + H.remove_status_effect(STATUS_EFFECT_PLANTHEALING) + +/datum/species/diona/random_name(gender, unique, lastname, attempts) + . = "[pick(GLOB.diona_names)]" + if(unique && attempts < 10 && findname(.)) + return ..(gender, TRUE, null, ++attempts) + +/datum/species/diona/help(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) + . = ..() + if(. && target != user && target.on_fire) + user.balloon_alert(user, "[user] you hug [target]") + target.visible_message("[user] catches fire from hugging [target]!", "[user] catches fire hugging you!", "You hear a fire crackling.") + user.fire_stacks = target.fire_stacks + if(user.fire_stacks > 0) + user.IgniteMob() + +//////////////////////////////////////// Action abilities /////////////////////////////////////////////// + +/datum/action/diona/split + name = "Split" + desc = "Split into our seperate nymphs." + background_icon_state = "bg_default" + icon_icon = 'icons/hud/actions/actions_spells.dmi' + button_icon_state = "split" + var/Activated = FALSE + +/datum/action/diona/split/Trigger(special) + . = ..() + var/mob/living/carbon/human/user = owner + if(!isdiona(user)) + return FALSE + if(special) + fakeDeath(FALSE, user) //This runs when you are dead. + return TRUE + if(user.incapacitated(ignore_restraints = TRUE)) //Are we incapacitated right now? + return FALSE + if(tgui_alert(usr, "Are we sure we wish to devolve ourselves and split into separated nymphs?",,list("Yes", "No")) != "Yes") + return FALSE + if(do_after(user, 8 SECONDS, user, IGNORE_RESTRAINED, TRUE)) + if(user.incapacitated(ignore_restraints = TRUE)) //Second check incase the ability was activated RIGHT as we were being cuffed, and thus now in cuffs when this triggers + return FALSE + fakeDeath(FALSE, user) //This runs when you manually activate the ability. + return TRUE + +/datum/action/diona/split/proc/fakeDeath(gibbed, mob/living/carbon/H) + if(Activated || gibbed) + return + Activated = TRUE + H.death() //Ha ha, we're totally dead right now + addtimer(CALLBACK(src, PROC_REF(split), gibbed, H), 5 SECONDS, TIMER_DELETE_ME) //Or are we? + +/datum/action/diona/split/proc/split(gibbed, mob/living/carbon/human/H) + if(gibbed) + H.gib(TRUE, TRUE, TRUE) //Gib the corpse with nothing left of use. After all the nymphs are ALL dead. + return + var/list/alive_nymphs = list() + var/mob/living/simple_animal/hostile/retaliate/nymph/nymph = new(H.loc) //Spawn the player nymph, including this one, should be six total nymphs + for(var/obj/item/bodypart/BP as anything in H.bodyparts) + if(BP.limb_id != SPECIES_DIONA) //Robot limb? Ignore it. + BP.drop_limb() + continue + if(istype(BP, /obj/item/bodypart/head)) + nymph.adjustBruteLoss(BP.brute_dam) + nymph.adjustFireLoss(BP.burn_dam) + nymph.updatehealth() + continue //Exclude the head nymph from the alive_nymphs list, since that list is used for secondary consciousness transfer. + var/mob/living/simple_animal/hostile/retaliate/nymph/limb_nymph = new /mob/living/simple_animal/hostile/retaliate/nymph(H.loc) + limb_nymph.adjustBruteLoss(BP.brute_dam) + limb_nymph.adjustFireLoss(BP.burn_dam) + limb_nymph.updatehealth() + if(limb_nymph.stat != DEAD) + alive_nymphs += limb_nymph + + var/mob/living/simple_animal/hostile/retaliate/nymph/gambling_nymph = alive_nymphs[rand(1, alive_nymphs)] // Let's go gambling! + gambling_nymph.adjustBruteLoss(50) // Aw dangit. + alive_nymphs -= gambling_nymph //Remove it from the alive_nymphs list. + + if(nymph.stat == DEAD) //If the head nymph is dead, transfer all consciousness to the next best thing - an alive limb nymph! + nymph = pick(alive_nymphs) + for(var/obj/item/I in H.contents) //Drop the player's items on the ground + H.dropItemToGround(I, TRUE) + I.pixel_x = rand(-10, 10) + I.pixel_y = rand(-10, 10) + nymph.old_name = H.real_name + nymph.features = H.dna.features + H.mind.transfer_to(nymph) //Move the player's mind datum to the player nymph + H.mind.grab_ghost() // Throw the fucking ghost back into the nymph. + H.gib(TRUE, TRUE, TRUE) //Gib the old corpse with nothing left of use + +/datum/action/diona/partition + name = "Partition" + desc = "Allow a nymph to partition from our gestalt self." + background_icon_state = "bg_default" + icon_icon = 'icons/hud/actions/actions_spells.dmi' + button_icon_state = "grow" + var/ability_partition_cooldown + +/datum/action/diona/partition/Trigger(special) + . = ..() + if(!IsAvailable()) + return + var/mob/living/carbon/human/H = owner + ability_partition_cooldown = world.time + 5 MINUTES + H.nutrition = NUTRITION_LEVEL_STARVING + playsound(H, 'sound/creatures/venus_trap_death.ogg', 25, 1) + new /mob/living/simple_animal/hostile/retaliate/nymph(H.loc) + +/datum/action/diona/partition/IsAvailable() + if(..()) + var/mob/living/carbon/human/H = owner + if(H.nutrition >= NUTRITION_LEVEL_WELL_FED && (ability_partition_cooldown <= world.time)) + return TRUE + return FALSE + +/////////////////////////////////// Dionae organs down here, special behavior stuffs /////////////////////////////////////// +/obj/item/organ/nymph_organ + name = "diona nymph" + desc = "You should not be seeing this, if you are, please contact a coder." + icon = 'icons/mob/animal.dmi' + icon_state = "nymph" + +/obj/item/organ/nymph_organ/Remove(mob/living/carbon/organ_owner, special, pref_load) + . = ..() + if(istype(organ_owner, /mob/living/carbon/human/dummy) || special) + return + var/obj/item/bodypart/body_part = organ_owner.get_bodypart(zone) + for(var/datum/surgery/organ_manipulation/surgery in organ_owner.surgeries) + surgery.Destroy() + if(istype(body_part, /obj/item/bodypart/chest)) //Does the same things as removing the brain would, since the torso is what keeps the diona together. + organ_owner.dna.species.spec_death(FALSE, src) + QDEL_NULL(src) + return + new /mob/living/simple_animal/hostile/retaliate/nymph(organ_owner.loc) + QDEL_NULL(body_part) + QDEL_NULL(src) + organ_owner.update_body() + +/obj/item/organ/nymph_organ/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C) + Remove(C, FALSE) + forceMove(LB) + +/obj/item/organ/nymph_organ/r_arm + zone = BODY_ZONE_R_ARM + slot = ORGAN_SLOT_R_ARM_NYMPH + +/obj/item/organ/nymph_organ/l_arm + zone = BODY_ZONE_L_ARM + slot = ORGAN_SLOT_L_ARM_NYMPH + +/obj/item/organ/nymph_organ/r_leg + zone = BODY_ZONE_R_LEG + slot = ORGAN_SLOT_R_LEG_NYMPH + +/obj/item/organ/nymph_organ/l_leg + zone = BODY_ZONE_L_LEG + slot = ORGAN_SLOT_L_LEG_NYMPH + +/obj/item/organ/nymph_organ/chest + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_CHEST_NYMPH + + +////////////////////////////////////// Preferences menu stuffs //////////////////////////////////////////////////////////// +/datum/species/diona/get_species_description() + return "Dionae are the equivalent to a shambling mound of bug-like sentient plants \ + wearing a trenchoat and pretending to be a human. Commonly found basking in the \ + supermatter chamber during lunch breaks." + +/datum/species/diona/get_species_lore() + return list( + "Dionae are a space-faring species of intensely curious sapient plant-bug-creatures, formed \ + by a collective of independent Diona, named 'Nymphs', gathering together to form a collective named a 'Gestalt', commonly \ + vaugely resembling a humanoid, although older collectives may grow into structures, or even floating asteroids in space.", + + "Dionae culture, for the most part, is nomadic, with Parent Gestalts splitting off a bud \ + that then goes off into the world to explore and gain knowledge for itself. Rarely, a handful of Gestalts may link up \ + in an agreed upon location to share knowledge, or to form a larger structure.", + + "As a collective of various individual nymphs with varying experiences, \ + names can become rather tricky, thus, Dionae Gestalts settle upon a single core memory shared between all Nymphs \ + most commonly something from their younger years and expanding over time as they relook upon their memories, though \ + it's not unheard of for a Gestalt to fully change their name if they find a fresher memory represents them more." + ) + +/datum/species/diona/create_pref_unique_perks() + var/list/to_add = list() + + to_add += list( + list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = "sun-plant-wilt", + SPECIES_PERK_NAME = "Photosynthetic", + SPECIES_PERK_DESC = "You find radiation and light pretty tasty, but you can't live long without either!", + ), + list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = "bugs", + SPECIES_PERK_NAME = "Bugsplosion", + SPECIES_PERK_DESC = "When you're about to die, you explode into a pile of bugs to escape, but you are very vulnerable in this state!", + ), + list( + SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, + SPECIES_PERK_ICON = "leaf", + SPECIES_PERK_NAME = "Planty", + SPECIES_PERK_DESC = "You're a plant! Bees quite like you, while you LOVE fertilizer and hate weedkiller.", + ), + list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = "fire", + SPECIES_PERK_NAME = "Flammable", + SPECIES_PERK_DESC = "The smallest flame can set you on fire, be careful!", + ), + list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = "weight-hanging", + SPECIES_PERK_NAME = "Bulky", + SPECIES_PERK_DESC = "As a plant, you aren't very nimble, walking takes more time for you.", + ), + ) + return to_add + +/datum/species/diona/get_laugh_sound(mob/living/carbon/user) + return 'sound/emotes/diona/laugh.ogg' + +/datum/species/diona/get_scream_sound(mob/living/carbon/user) + return 'sound/emotes/diona/scream.ogg' + +/datum/species/diona/get_sneeze_sound(mob/living/carbon/user) + return 'sound/emotes/diona/sneeze.ogg' diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm deleted file mode 100644 index c0d55d51c3204..0000000000000 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ /dev/null @@ -1,70 +0,0 @@ -/datum/species/pod - // A mutation caused by a human being ressurected in a revival pod. These regain health in light, and begin to wither in darkness. - name = "\improper Podperson" - plural_form = "Podpeople" - id = SPECIES_PODPERSON - default_color = "59CE00" - species_traits = list(MUTCOLORS,EYECOLOR) - inherent_traits = list(TRAIT_ALWAYS_CLEAN, TRAIT_BEEFRIEND, TRAIT_NONECRODISEASE) - inherent_factions = list("plants", "vines") - fixed_mut_color = "59CE00" - attack_verb = "slash" - attack_sound = 'sound/weapons/slice.ogg' - miss_sound = 'sound/weapons/slashmiss.ogg' - burnmod = 1.25 - heatmod = 1.5 - meat = /obj/item/food/meat/slab/human/mutant/plant - changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT - species_language_holder = /datum/language_holder/plant - - species_chest = /obj/item/bodypart/chest/pod - species_head = /obj/item/bodypart/head/pod - species_l_arm = /obj/item/bodypart/l_arm/pod - species_r_arm = /obj/item/bodypart/r_arm/pod - species_l_leg = /obj/item/bodypart/l_leg/pod - species_r_leg = /obj/item/bodypart/r_leg/pod - mutanttongue = /obj/item/organ/tongue/podperson - -/datum/species/pod/spec_life(mob/living/carbon/human/H) - if(H.stat == DEAD) - return - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(isturf(H.loc)) //else, there's considered to be no light - var/turf/T = H.loc - light_amount = min(1,T.get_lumcount()) - 0.5 - H.adjust_nutrition(light_amount * 10) - if(H.nutrition > NUTRITION_LEVEL_ALMOST_FULL) - H.set_nutrition(NUTRITION_LEVEL_ALMOST_FULL) - if(light_amount > 0.2) //if there's enough light, heal - H.heal_overall_damage(1,1, 0, BODYTYPE_ORGANIC) - H.adjustToxLoss(-1) - H.adjustOxyLoss(-1) - - if(H.nutrition < NUTRITION_LEVEL_STARVING + 50) - H.take_overall_damage(2,0) - -/datum/species/pod/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) - if(chem.type == /datum/reagent/toxin/plantbgone) - H.adjustToxLoss(3) - H.reagents.remove_reagent(chem.type, chem.metabolization_rate) - return TRUE - return ..() - -/datum/species/pod/on_hit(obj/projectile/P, mob/living/carbon/human/H) - switch(P.type) - if(/obj/projectile/energy/floramut) - if(prob(15)) - H.rad_act(rand(30,80)) - H.Paralyze(100) - H.visible_message("[H] writhes in pain as [H.p_their()] vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.") - if(prob(80)) - H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) - else - H.easy_randmut(POSITIVE) - H.randmuti() - H.domutcheck() - else - H.adjustFireLoss(rand(5,15)) - H.show_message("The radiation beam singes you!") - if(/obj/projectile/energy/florayield) - H.set_nutrition(min(H.nutrition+30, NUTRITION_LEVEL_FULL)) diff --git a/code/modules/mob/living/carbon/human/species_types/pumpkin_man.dm b/code/modules/mob/living/carbon/human/species_types/pumpkin_man.dm index 431564f384c1b..fc44046ead173 100644 --- a/code/modules/mob/living/carbon/human/species_types/pumpkin_man.dm +++ b/code/modules/mob/living/carbon/human/species_types/pumpkin_man.dm @@ -1,17 +1,26 @@ -/datum/species/pod/pumpkin_man +/datum/species/pumpkin_man name = "\improper Pumpkinperson" plural_form = "Pumpkinpeople" id = SPECIES_PUMPKINPERSON sexes = 0 meat = /obj/item/food/pieslice/pumpkin - species_traits = list(NOEYESPRITES) + species_traits = list(NOEYESPRITES,MUTCOLORS,EYECOLOR) + inherent_traits = list(TRAIT_ALWAYS_CLEAN, TRAIT_BEEFRIEND, TRAIT_NONECRODISEASE) + inherent_factions = list("plants", "vines") + burnmod = 1.25 + heatmod = 1.5 + meat = /obj/item/food/meat/slab/human/mutant/diona + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT + species_language_holder = /datum/language_holder/diona + + attack_verb = "punch" attack_sound = 'sound/weapons/punch1.ogg' miss_sound = 'sound/weapons/punchmiss.ogg' changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | ERT_SPAWN mutantbrain = /obj/item/organ/brain/pumpkin_brain - mutanttongue = /obj/item/organ/tongue/podperson/pumpkin + mutanttongue = /obj/item/organ/tongue/diona/pumpkin species_chest = /obj/item/bodypart/chest/pumpkin_man species_head = /obj/item/bodypart/head/pumpkin_man @@ -21,28 +30,72 @@ species_r_leg = /obj/item/bodypart/r_leg/pumpkin_man //Only allow race roundstart on Halloween -/datum/species/pod/pumpkin_man/check_roundstart_eligible() +/datum/species/pumpkin_man/check_roundstart_eligible() if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) return TRUE return ..() -/datum/species/pod/pumpkin_man/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) +/datum/species/pumpkin_man/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) . = ..() //They can't speak! //Register signal for carving RegisterSignal(C, COMSIG_MOB_ITEM_ATTACKBY, PROC_REF(handle_carving)) -/datum/species/pod/pumpkin_man/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) +/datum/species/pumpkin_man/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) . = ..() UnregisterSignal(C, COMSIG_MOB_ITEM_ATTACKBY) -/datum/species/pod/pumpkin_man/get_species_description() - return "A rare subspecies of the Podpeople, Pumpkinpeople are gourdy and orange, appearing every halloween." +/datum/species/pumpkin_man/spec_life(mob/living/carbon/human/H) + if(H.stat == DEAD) + return + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(isturf(H.loc)) //else, there's considered to be no light + var/turf/T = H.loc + light_amount = min(1,T.get_lumcount()) - 0.5 + H.adjust_nutrition(light_amount * 10) + if(H.nutrition > NUTRITION_LEVEL_ALMOST_FULL) + H.set_nutrition(NUTRITION_LEVEL_ALMOST_FULL) + if(light_amount > 0.2) //if there's enough light, heal + H.heal_overall_damage(1,1, 0, BODYTYPE_ORGANIC) + H.adjustToxLoss(-1) + H.adjustOxyLoss(-1) + + if(H.nutrition < NUTRITION_LEVEL_STARVING + 50) + H.take_overall_damage(2,0) + +/datum/species/pumpkin_man/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.type == /datum/reagent/toxin/plantbgone) + H.adjustToxLoss(3) + H.reagents.remove_reagent(chem.type, chem.metabolization_rate) + return TRUE + return ..() -/datum/species/pod/pumpkin_man/get_species_lore() +/datum/species/pumpkin_man/on_hit(obj/projectile/P, mob/living/carbon/human/H) + switch(P.type) + if(/obj/projectile/energy/floramut) + if(prob(15)) + H.rad_act(rand(30,80)) + H.Paralyze(100) + H.visible_message("[H] writhes in pain as [H.p_their()] vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.") + if(prob(80)) + H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) + else + H.easy_randmut(POSITIVE) + H.randmuti() + H.domutcheck() + else + H.adjustFireLoss(rand(5,15)) + H.show_message("The radiation beam singes you!") + if(/obj/projectile/energy/florayield) + H.set_nutrition(min(H.nutrition+30, NUTRITION_LEVEL_FULL)) + +/datum/species/pumpkin_man/get_species_description() + return "A rare species of Pumpkinpeople, gourdy and orange, appearing every halloween." + +/datum/species/pumpkin_man/get_species_lore() return null -/datum/species/pod/pumpkin_man/create_pref_unique_perks() +/datum/species/pumpkin_man/create_pref_unique_perks() var/list/to_add = list() to_add += list( @@ -57,7 +110,7 @@ return to_add //Handler for face carving! -/datum/species/pod/pumpkin_man/proc/handle_carving(datum/_source, mob/living/_user, obj/item/_item) +/datum/species/pumpkin_man/proc/handle_carving(datum/_source, mob/living/_user, obj/item/_item) //Check if the item is sharp - give owner a random face if applicable var/mob/living/carbon/human/M = _source var/obj/item/bodypart/head/pumpkin_man/head = M.get_bodypart(BODY_ZONE_HEAD) @@ -76,7 +129,7 @@ M.update_body_parts_head_only() to_chat(_user, "You carve a face into [_source].") //Adjust the tongue - var/obj/item/organ/tongue/podperson/pumpkin/P = M.internal_organs_slot[ORGAN_SLOT_TONGUE] + var/obj/item/organ/tongue/diona/pumpkin/P = M.internal_organs_slot[ORGAN_SLOT_TONGUE] if(istype(P)) P?.carved = TRUE else diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 46c7eb35afe58..5bc2b1a9cf534 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1153,7 +1153,7 @@ /mob/living/rad_act(amount) . = ..() - if(!amount || (amount < RAD_MOB_SKIN_PROTECTION) || HAS_TRAIT(src, TRAIT_RADIMMUNE)) + if(!amount || (amount < RAD_MOB_SKIN_PROTECTION) || HAS_TRAIT(src, TRAIT_RADIMMUNE) || HAS_TRAIT(src, TRAIT_NORADDAMAGE)) return amount -= RAD_BACKGROUND_RADIATION // This will always be at least 1 because of how skin protection is calculated diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index fe44f472f868a..22bbed72e029a 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -120,7 +120,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( return if(is_muted(original_message, ignore_spam, forced) || check_emote(original_message, forced)) - return + return TRUE if(!language) // get_message_mods() proc finds a language key, and add the language to LANGUAGE_EXTENSION language = message_mods[LANGUAGE_EXTENSION] diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 8946084dfaec6..3be955412f16c 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -93,7 +93,7 @@ . = ..() if(. && ishuman(target)) var/mob/living/carbon/human/H = target - if(istype(H.dna.species, /datum/species/pod)) + if(isdiona(H)) var/obj/item/bodypart/NB = pick(H.bodyparts) H.visible_message("[src] takes a big chomp out of [H]!", \ "[src] takes a big chomp out of your [NB]!") diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/nymph.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/nymph.dm new file mode 100644 index 0000000000000..6ed5076220c3b --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/nymph.dm @@ -0,0 +1,389 @@ +// This code is for dionae nymphs that get spread out in the room when a diona dies. One is player controlled. + +/mob/living/simple_animal/hostile/retaliate/nymph + name = "diona nymph" + desc = "Is that a plant?" + icon = 'icons/mob/animal.dmi' + icon_state = "nymph" + icon_living = "nymph" + icon_dead = "nymph_dead" + faction = list("diona") + gender = NEUTER + gold_core_spawnable = FRIENDLY_SPAWN + ventcrawler = VENTCRAWLER_ALWAYS + pass_flags = PASSTABLE | PASSMOB + density = FALSE + mob_size = MOB_SIZE_SMALL + mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + can_be_held = TRUE + worn_slot_flags = ITEM_SLOT_HEAD + head_icon = 'icons/mob/pets_held.dmi' + held_state = "nymph" + footstep_type = FOOTSTEP_MOB_CLAW + hud_type = /datum/hud/nymph + butcher_results = list(/obj/item/food/meat/slab/human/mutant/diona = 4) + initial_language_holder = /datum/language_holder/diona + + var/brute_damage = 0 + var/fire_damage = 0 + health = 50 + maxHealth = 50 + melee_damage = 1.5 + obj_damage = 10 + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + attack_sound = 'sound/emotes/diona/hit.ogg' + minbodytemp = 2.7 + var/can_namepick_as_adult = FALSE + var/death_msg = "expires with a pitiful chirrup..." + + var/amount_grown = 0 + var/max_grown = 150 + var/time_of_birth + var/instance_num + var/is_ghost_spawn = TRUE //For if a ghost can become this. + var/is_drone = FALSE //Is a remote controlled nymph from a diona. + var/drone_parent //The diona which can control the nymph, if there is one + var/old_name // The diona nymph's old name. + var/datum/action/nymph/evolve/evolve_ability //The ability to grow up into a diona by yourself. + var/datum/action/nymph/SwitchFrom/switch_ability //The ability to switch back to the parent diona as a drone. + var/list/features = list() + var/time_spent_in_light + var/assimilating = FALSE + var/grown_message_sent = FALSE + +/mob/living/simple_animal/hostile/retaliate/nymph/Initialize(mapload) + . = ..() + time_of_birth = world.time + evolve_ability = new + evolve_ability.Grant(src) + instance_num = rand(1, 1000) + name = "[initial(name)] ([instance_num])" + real_name = name + regenerate_icons() + ADD_TRAIT(src, TRAIT_MUTE, "nymph") + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) + GLOB.poi_list |= src + +/mob/living/simple_animal/hostile/retaliate/nymph/get_stat_tab_status() + var/list/tab_data = ..() + tab_data["Health"] = GENERATE_STAT_TEXT("[round((health / maxHealth) * 100)]%") + if(!is_drone) + tab_data["Growth"] = GENERATE_STAT_TEXT("[(round(amount_grown / max_grown * 100))]%") + return tab_data + +/mob/living/simple_animal/hostile/retaliate/nymph/Life(delta_time, times_fired) + . = ..() + if(!is_drone) + update_progression() + get_stat_tab_status() + if(stat != CONSCIOUS) + remove_status_effect(STATUS_EFFECT_PLANTHEALING) + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(isturf(loc)) //else, there's considered to be no light + var/turf/T = loc + light_amount = min(1,T.get_lumcount()) - 0.5 + if(light_amount > 0.2) //Is there light here? + time_spent_in_light++ //If so, how long have we been somewhere with light? + if(time_spent_in_light > 5) //More than 5 seconds spent in the light + if(stat != CONSCIOUS) + remove_status_effect(STATUS_EFFECT_PLANTHEALING) + return + apply_status_effect(STATUS_EFFECT_PLANTHEALING) + else + remove_status_effect(STATUS_EFFECT_PLANTHEALING) + time_spent_in_light = 0 //No light? Reset the timer. + +/mob/living/simple_animal/hostile/retaliate/nymph/death(gibbed) + GLOB.poi_list -= src + evolve_ability.Remove(src) + if(is_drone) + if(mind) + switch_ability.Trigger(drone_parent, TRUE) //If we have someone conscious in the drone, throw them out. + switch_ability.Remove(src) + return ..(gibbed,death_msg) + +/mob/living/simple_animal/hostile/retaliate/nymph/adjustBruteLoss(amount, updating_health, forced) + brute_damage = brute_damage + amount * damage_coeff[BRUTE] * CONFIG_GET(number/damage_multiplier) + . = ..() + +/mob/living/simple_animal/hostile/retaliate/nymph/adjustFireLoss(amount, updating_health, forced) + fire_damage = fire_damage + amount * damage_coeff[BURN] * CONFIG_GET(number/damage_multiplier) + . = ..() + +/mob/living/simple_animal/hostile/retaliate/nymph/UnarmedAttack(atom/A, proximity) + melee_damage = 1.5 + . = ..() + +/mob/living/simple_animal/hostile/retaliate/nymph/attack_animal(mob/living/L) + if(istype(L, /mob/living/simple_animal/hostile/retaliate/nymph) && stat != DEAD) + var/mob/living/simple_animal/hostile/retaliate/nymph/user = L + if(mind == null) // No RRing fellow nymphs + if(user.is_drone) + to_chat(user, "You can't grow up as a lone nymph drone!") + return + if(user.assimilating) + return + user.assimilating = TRUE + playsound(user, 'sound/creatures/venus_trap_death.ogg', 25, 1) + balloon_alert(user, "[user] starts assimilating [src]") + toggle_ai(AI_OFF) + if(do_after(user, 30 SECONDS, src)) + user.evolve(src) + return + else + toggle_ai(AI_ON) + user.assimilating = FALSE + return + else + user.melee_damage = 0 + . = ..() + +/mob/living/simple_animal/hostile/retaliate/nymph/spawn_gibs() + new /obj/effect/decal/cleanable/insectguts(drop_location()) + playsound(drop_location(), 'sound/effects/blobattack.ogg', 60, TRUE) + +/mob/living/simple_animal/hostile/retaliate/nymph/attack_ghost(mob/dead/observer/user) + if(client || key || ckey) + to_chat(user, "\The [src] already has a player.") + return + if(!is_ghost_spawn || stat == DEAD || is_drone) + to_chat(user, "\The [src] is not possessable!") + return + var/control_ask = tgui_alert(usr, "Do you wish to take control of \the [src]", "Chirp Time?", list("Yes", "No")) + if(control_ask != "Yes" || !src || QDELETED(src) || QDELETED(user)) + return FALSE + if(QDELETED(src) || QDELETED(user) || !user.client) + return + var/mob/living/simple_animal/hostile/retaliate/nymph/newnymph = src + newnymph.key = user.key + newnymph.unique_name = TRUE + to_chat(newnymph, "Remember that you have forgotten all of your past lives and are a new person!") + +/mob/living/simple_animal/hostile/retaliate/nymph/proc/update_progression() + if(amount_grown < max_grown) + amount_grown++ + if(amount_grown > max_grown) + amount_grown = max_grown + if(!grown_message_sent && amount_grown == max_grown) + to_chat(src, "You feel like you're ready to grow up by yourself!") + grown_message_sent = TRUE + +/mob/living/simple_animal/hostile/retaliate/nymph/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) + if(isdiona(arrived)) + if(mind != null || stat == DEAD || is_drone) //Does the nymph on the ground have a mind, dead or a drone? + return // If so, ignore the diona + var/mob/living/carbon/human/H = arrived + var/list/limbs_to_heal = H.get_missing_limbs() + if(!LAZYLEN(limbs_to_heal)) + return + playsound(H, 'sound/creatures/venus_trap_hit.ogg', 25, 1) + var/obj/item/bodypart/healed_limb = pick(limbs_to_heal) + H.regenerate_limb(healed_limb) + for(var/obj/item/bodypart/body_part in H.bodyparts) + if(body_part.body_zone == healed_limb) + body_part.brute_dam = brute_damage + body_part.burn_dam = fire_damage + balloon_alert(H, "[H] assimilates [src]") + QDEL_NULL(src) + +/mob/living/simple_animal/hostile/retaliate/nymph/handle_mutations_and_radiation() + if(radiation > 50) + heal_overall_damage(1,1, 0, BODYTYPE_ORGANIC) + . = ..() + +/mob/living/simple_animal/hostile/retaliate/nymph/proc/evolve(var/mob/living/simple_animal/hostile/retaliate/nymph/nymphs) + if(istype(loc, /obj/item/clothing/head/mob_holder)) + var/obj/item/clothing/head/mob_holder/L = loc + src.loc = L.loc + qdel(L) + + src.visible_message( + ("[src] begins to shift and quiver, and after engulfing another nymph, erupts in a shower of shed bark as it splits into a tangle of a new diona gestalt."), + ("You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients and, along with a friend, surge with growth, splitting into a tangle of at least a dozen new vines. We have attained our gestalt form. Our friends should help with obtaining the rest of our limbs...") + ) + + var/mob/living/simple_animal/hostile/retaliate/nymph/helpers + if(!nymphs) + helpers = new /mob/living/simple_animal/hostile/retaliate/nymph(src.loc) + else + helpers = nymphs + var/mob/living/carbon/human/species/diona/adult = new /mob/living/carbon/human/species/diona(src.loc) + adult.set_species(SPECIES_DIONA) + + for(var/obj/item/bodypart/body_part in adult.bodyparts) //No limbs for you, small diona. + if(istype(body_part, /obj/item/bodypart/chest)) + body_part.brute_dam = helpers.brute_damage + body_part.burn_dam = helpers.fire_damage + else if(istype(body_part, /obj/item/bodypart/head)) + body_part.brute_dam = brute_damage + body_part.burn_dam = fire_damage + else // If its not a chest AND not a head + for(var/obj/item/organ/nymph_organ/I in body_part) + QDEL_NULL(I) + body_part.drop_limb(TRUE) + + if(!("neutral" in src.faction)) + adult.faction = src.faction + if(old_name) + adult.real_name = old_name + adult.dna.features = features + else + adult.fully_replace_character_name(name, adult.dna.species.random_name(gender)) + adult.dna.features["mcolor"] = sanitize_hexcolor(RANDOM_COLOUR) + if(mind) + mind.transfer_to(adult) + else + adult.key = src.key + + adult.dna.update_dna_identity() + adult.update_body() + adult.updateappearance() + adult.nutrition = NUTRITION_LEVEL_HUNGRY + REMOVE_TRAIT(adult, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + QDEL_NULL(helpers) + qdel(src) + +/mob/living/simple_animal/hostile/retaliate/nymph/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced) + if(!..()) + emote("chitter") + +/datum/action/nymph/evolve + name = "Evolve" + desc = "Evolve into your adult form with the help of another nymph." + background_icon_state = "bg_default" + icon_icon = 'icons/hud/actions/actions_spells.dmi' + button_icon_state = "grow" + +/datum/action/nymph/evolve/Trigger() + . = ..() + var/mob/living/simple_animal/hostile/retaliate/nymph/user = owner + if(!isnymph(user)) + return + if(user.is_drone) + to_chat(user, "You can't grow up as a drone!") + return + if(user.movement_type & VENTCRAWLING) + to_chat(user, "You cannot evolve while in a vent.") + return + if(user.stat != CONSCIOUS) + return + if(user.amount_grown >= user.max_grown) + if(user.incapacitated()) //something happened to us while we were choosing. + return + playsound(user, 'sound/creatures/venus_trap_death.ogg', 25, 1) + user.evolve() + else + to_chat(user, "You are not ready to grow up by yourself.") + return FALSE + +/datum/action/nymph/SwitchFrom + name = "Return" + desc = "Return back into your adult form." + background_icon_state = "bg_default" + icon_icon = 'icons/hud/actions/actions_spells.dmi' + button_icon_state = "return" + +/datum/action/nymph/SwitchFrom/Trigger(drone_parent, forced) + . = ..() + var/mob/living/simple_animal/hostile/retaliate/nymph/user = owner + var/mob/living/carbon/human/drone_diona = user.drone_parent + if(forced) + SwitchFrom(user, drone_parent) + if(!isnymph(user)) + return + if(user.movement_type & VENTCRAWLING) + to_chat(user, "You cannot switch while in a vent.") + return + if(QDELETED(drone_diona)) // FUCK SOMETHING HAPPENED TO THE MAIN DIONA, ABORT ABORT ABORT + user.is_drone = FALSE //We're not a drone anymore!!!! Panic! + to_chat(user, "You feel like your gestalt is gone! Something must have gone wrong...") + user.switch_ability.Remove(user) + return + SwitchFrom(user, drone_parent) + +/datum/action/nymph/SwitchFrom/proc/SwitchFrom(mob/living/simple_animal/hostile/retaliate/nymph/user, mob/living/carbon/M) + var/datum/mind/C = user.mind + M = user.drone_parent + if(user.stat == CONSCIOUS) + user.visible_message("[user] \ + stops moving and starts staring vacantly into space.", + "You stop moving this form...") + else + to_chat(M, "You abandon this nymph...") + C.transfer_to(M) + M.mind = C + M.visible_message("[M] blinks and looks \ + around.", + "...and move this one instead.") + +/mob/living/simple_animal/hostile/retaliate/nymph/mob_try_pickup(mob/living/user) + if(!ishuman(user)) + return + if(user.get_active_held_item()) + to_chat(user, "Your hands are full!") + return FALSE + if(buckled) + to_chat(user, "[src] is buckled to something!") + return FALSE + mob_pickup(user) + return TRUE + +/mob/living/simple_animal/hostile/retaliate/nymph/mob_pickup(mob/living/L) + if(resting) + resting = FALSE + update_resting() + toggle_ai(AI_OFF) + var/obj/item/clothing/head/mob_holder/nymph/holder = new(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags) + if(stat == DEAD && mind) + holder.tool_behaviour = TOOL_SEED + L.visible_message("[L] scoops up [src]!") + L.put_in_hands(holder) + +/obj/item/clothing/head/mob_holder/nymph + var/moving_cooldown + var/on_head + //Variables for planting a dead nymph into a hydroponics tray + tool_behaviour = null + fake_seed = null + grind_results = list(/datum/reagent/consumable/chlorophyll = 20) + juice_results = list(/datum/reagent/consumable/chlorophyll = 20) + +/obj/item/clothing/head/mob_holder/nymph/Initialize(mapload, mob/living/M, worn_state, head_icon, lh_icon, rh_icon, worn_slot_flags) + if(M.mind) + fake_seed = new /obj/item/seeds/nymph + fake_seed.mind = M.mind + . = ..() + +/obj/item/clothing/head/mob_holder/nymph/relaymove(mob/user) // Hold nymph like petulant child... + if(moving_cooldown <= world.time) + moving_cooldown = world.time + 50 + user.visible_message("[user] starts to squirm in [loc]'s hands!", + "You start to squirm in [loc]'s hands...") + if(on_head) + release() + if(do_after(held_mob, 8 SECONDS, user, NONE, TRUE)) + release() + +/obj/item/clothing/head/mob_holder/nymph/microwave_act(obj/machinery/microwave/M) + . = ..() + M.muck() + held_mob.adjustFireLoss(50) + Destroy() + +/obj/item/clothing/head/mob_holder/nymph/release() + on_head = FALSE + var/mob/living/simple_animal/hostile/retaliate/nymph/nymph_mob = held_mob + nymph_mob.toggle_ai(AI_ON) + . = ..() + +/obj/item/clothing/head/mob_holder/nymph/equipped() + . = ..() + on_head = TRUE + +/obj/item/clothing/head/mob_holder/nymph/on_grind() + playsound(held_mob, 'sound/effects/splat.ogg', 50, 1) + qdel(held_mob) + . = ..() diff --git a/code/modules/pool/components/swimming_diona.dm b/code/modules/pool/components/swimming_diona.dm new file mode 100644 index 0000000000000..a9d23be84910c --- /dev/null +++ b/code/modules/pool/components/swimming_diona.dm @@ -0,0 +1,7 @@ +/datum/component/swimming/diona/enter_pool() + +/datum/component/swimming/diona/process(delta_time) + ..() + var/mob/living/L = parent + if(DT_PROB(20, delta_time)) + L.reagents.add_reagent(/datum/reagent/water, 2) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 16eb6462d09b5..46ef2ca6a52ef 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -2107,12 +2107,12 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/bug_spray/on_mob_life(mob/living/carbon/M) //Bugs should not drink Bug spray. - if(ismoth(M) || isflyperson(M)) + if(ismoth(M) || isflyperson(M) || isdiona(M)) M.adjustToxLoss(1,0) return ..() /datum/reagent/consumable/ethanol/bug_spray/on_mob_metabolize(mob/living/carbon/M) - if(ismoth(M) || isflyperson(M)) + if(ismoth(M) || isflyperson(M) || isdiona(M)) M.emote("scream") return ..() diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index edc67bc114664..391fbce6488c9 100755 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -797,6 +797,14 @@ playsound(M, "sparks", 50, 1) return ..() +/datum/reagent/consumable/chlorophyll + name = "Liquid Chlorophyll" + description = "A plant-specific elixir of life." + nutriment_factor = 5 * REAGENTS_METABOLISM + color = "#00df30" + chem_flags = CHEMICAL_RNG_GENERAL | CHEMICAL_RNG_FUN | CHEMICAL_RNG_BOTANY + taste_description = "bitter, dry, broccoli soup" + /datum/reagent/consumable/astrotame name = "Astrotame" description = "A space age artifical sweetener." diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 33bc534df3190..f82fb4d96635a 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -560,7 +560,6 @@ /datum/species/fly, /datum/species/moth, /datum/species/apid, - /datum/species/pod, /datum/species/oozeling, /datum/species/abductor, /datum/species/skeleton) @@ -604,12 +603,12 @@ race = /datum/species/apid taste_description = "honey" -/datum/reagent/mutationtoxin/pod - name = "Podperson Mutation Toxin" +/datum/reagent/mutationtoxin/diona //Admin only, besides maint pills because funny + name = "Diona Mutation Toxin" description = "A vegetalizing toxin." color = "#5EFF3B" //RGB: 94, 255, 59 - chem_flags = CHEMICAL_RNG_FUN | CHEMICAL_RNG_BOTANY - race = /datum/species/pod + chem_flags = CHEMICAL_RNG_FUN + race = /datum/species/diona taste_description = "flowers" /datum/reagent/mutationtoxin/jelly diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index 7dbf4739d8a8e..83835d7a0cb36 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -859,12 +859,6 @@ results = list(/datum/reagent/mutationtoxin/apid = 5) required_reagents = list(/datum/reagent/mutationtoxin/unstable = 5, /datum/reagent/consumable/honey = 20) // beeeeeeeeeeeeeeeeeeeeees -/datum/chemical_reaction/mutationtoxin/pod - name = /datum/reagent/mutationtoxin/pod - id = /datum/reagent/mutationtoxin/pod - results = list(/datum/reagent/mutationtoxin/pod = 5) - required_reagents = list(/datum/reagent/mutationtoxin/unstable = 5, /datum/reagent/plantnutriment/eznutriment = 10) - /datum/chemical_reaction/mutationtoxin/golem name = /datum/reagent/mutationtoxin/golem id = /datum/reagent/mutationtoxin/golem diff --git a/code/modules/religion/sects/plant_sect.dm b/code/modules/religion/sects/plant_sect.dm index 646f14b3bf523..1ce4e08282f03 100644 --- a/code/modules/religion/sects/plant_sect.dm +++ b/code/modules/religion/sects/plant_sect.dm @@ -8,7 +8,7 @@ desired_items = list( /obj/item/seeds) rites_list = list( - /datum/religion_rites/create_podperson, + /datum/religion_rites/create_diona, /datum/religion_rites/create_sandstone, /datum/religion_rites/grass_generator, /datum/religion_rites/summon_animals) @@ -60,10 +60,10 @@ for(var/mob/living/L in range(5, src)) if(L.health == L.maxHealth) continue - if(!ispodperson(L) && !L.mind?.holy_role) + if(!isdiona(L) && !L.mind?.holy_role) continue new /obj/effect/temp_visual/heal(get_turf(src), "#47ac05") - if(ispodperson(L) || L.mind?.holy_role) + if(isdiona(L) || L.mind?.holy_role) L.adjustBruteLoss(-2*delta_time, 0) L.adjustToxLoss(-2*delta_time, 0) L.adjustOxyLoss(-2*delta_time, 0) @@ -177,7 +177,7 @@ /datum/religion_rites/grass_generator name = "Blessing of Nature" - desc = "Summon a moveable object that slowly generates grass and fairy-grass around itself while healing any Pod-People or Holy people nearby." + desc = "Summon a moveable object that slowly generates grass and fairy-grass around itself while healing any Dionae or Holy people nearby." ritual_length = 60 SECONDS ritual_invocations = list( "Let the plantlife grow ...", @@ -194,7 +194,7 @@ new /obj/structure/destructible/religion/nature_pylon(T) return ..() -/datum/religion_rites/create_podperson +/datum/religion_rites/create_diona name = "Nature Conversion" desc = "Convert a human-esque individual into a being of nature. Buckle a human to convert them, otherwise it will convert you." ritual_length = 30 SECONDS @@ -205,7 +205,7 @@ invoke_msg = "... May the grass be greener on the other side, show us what it means to be one with nature!!" favor_cost = 300 -/datum/religion_rites/create_podperson/perform_rite(mob/living/user, atom/religious_tool) +/datum/religion_rites/create_diona/perform_rite(mob/living/user, atom/religious_tool) if(!ismovable(religious_tool)) to_chat(user,"This rite requires a religious device that individuals can be buckled to.") return FALSE @@ -218,13 +218,13 @@ if(!movable_reltool.can_buckle) //yes, if you have somehow managed to have someone buckled to something that now cannot buckle, we will still let you perform the rite! to_chat(user,"This rite requires a religious device that individuals can be buckled to.") return FALSE - if(ispodperson(user)) + if(isdiona(user)) to_chat(user,"You've already converted yourself. To convert others, they must be buckled to [movable_reltool].") return FALSE to_chat(user,"You're going to convert yourself with this ritual.") return ..() -/datum/religion_rites/create_podperson/invoke_effect(mob/living/user, atom/religious_tool) +/datum/religion_rites/create_diona/invoke_effect(mob/living/user, atom/religious_tool) ..() if(!ismovable(religious_tool)) CRASH("[name]'s perform_rite had a movable atom that has somehow turned into a non-movable!") @@ -239,6 +239,6 @@ break if(!rite_target) return FALSE - rite_target.set_species(/datum/species/pod) + rite_target.set_species(/datum/species/diona) rite_target.visible_message("[rite_target] has been converted by the rite of [name]!") return TRUE diff --git a/code/modules/surgery/advanced/bioware/experimental_dissection.dm b/code/modules/surgery/advanced/bioware/experimental_dissection.dm index 741e4164e8e41..6e049dd7761d9 100644 --- a/code/modules/surgery/advanced/bioware/experimental_dissection.dm +++ b/code/modules/surgery/advanced/bioware/experimental_dissection.dm @@ -42,7 +42,7 @@ return 8000 if(isgolem(H) || iszombie(H)) return 4000 - if(isslimeperson(H) || isluminescent(H) || isstargazer(H) || ispodperson(H)) + if(isslimeperson(H) || isluminescent(H) || isstargazer(H) || isdiona(H)) return 3000 return 2000 diff --git a/code/modules/surgery/bodyparts/species_parts/diona_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/diona_bodyparts.dm new file mode 100644 index 0000000000000..d88a8883b2b78 --- /dev/null +++ b/code/modules/surgery/bodyparts/species_parts/diona_bodyparts.dm @@ -0,0 +1,45 @@ +///Dionae Body parts, used to be podpeople +/obj/item/bodypart/head/diona + static_icon = 'icons/mob/species/diona/bodyparts.dmi' + icon = 'icons/mob/species/diona/bodyparts.dmi' + limb_id = SPECIES_DIONA + is_dimorphic = FALSE + dismemberable = 0 + uses_mutcolor = TRUE + is_pseudopart = TRUE + +/obj/item/bodypart/chest/diona + static_icon = 'icons/mob/species/diona/bodyparts.dmi' + icon = 'icons/mob/species/diona/bodyparts.dmi' + limb_id = SPECIES_DIONA + is_dimorphic = FALSE + uses_mutcolor = TRUE + is_pseudopart = TRUE + +/obj/item/bodypart/l_arm/diona + static_icon = 'icons/mob/species/diona/bodyparts.dmi' + icon = 'icons/mob/species/diona/bodyparts.dmi' + limb_id = SPECIES_DIONA + uses_mutcolor = TRUE + is_pseudopart = TRUE + +/obj/item/bodypart/r_arm/diona + static_icon = 'icons/mob/species/diona/bodyparts.dmi' + icon = 'icons/mob/species/diona/bodyparts.dmi' + limb_id = SPECIES_DIONA + uses_mutcolor = TRUE + is_pseudopart = TRUE + +/obj/item/bodypart/l_leg/diona + static_icon = 'icons/mob/species/diona/bodyparts.dmi' + icon = 'icons/mob/species/diona/bodyparts.dmi' + limb_id = SPECIES_DIONA + uses_mutcolor = TRUE + is_pseudopart = TRUE + +/obj/item/bodypart/r_leg/diona + static_icon = 'icons/mob/species/diona/bodyparts.dmi' + icon = 'icons/mob/species/diona/bodyparts.dmi' + limb_id = SPECIES_DIONA + uses_mutcolor = TRUE + is_pseudopart = TRUE diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 4f8c20b65098f..36d8ed0d99c63 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -116,27 +116,6 @@ limb_id = "zombie" should_draw_greyscale = FALSE -///PODPEOPLE -/obj/item/bodypart/head/pod - limb_id = "pod" - is_dimorphic = TRUE - -/obj/item/bodypart/chest/pod - limb_id = "pod" - is_dimorphic = TRUE - -/obj/item/bodypart/l_arm/pod - limb_id = "pod" - -/obj/item/bodypart/r_arm/pod - limb_id = "pod" - -/obj/item/bodypart/l_leg/pod - limb_id = "pod" - -/obj/item/bodypart/r_leg/pod - limb_id = "pod" - ///FLY /obj/item/bodypart/head/fly limb_id = "fly" diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index 147108d0f464f..8467f138e462b 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -166,3 +166,8 @@ owner.Knockdown(100) to_chat(owner, "Alert: Audio sensors malfunctioning") owner.apply_status_effect(STATUS_EFFECT_IPC_EMP) + +/obj/item/organ/ears/diona + name = "trichomes" + icon_state = "diona_ears" + desc = "A pair of plant matter based ears." diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 9a3b2cd892f3f..0c2294f1f1d9c 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -439,4 +439,11 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/effect/abstract/eye_lighting) P?.remove() return ..() +/obj/item/organ/eyes/diona + name = "receptor node" + desc = "A combination of plant matter and neurons used to produce visual feedback." + icon_state = "diona_eyeballs" + organ_flags = ORGAN_UNREMOVABLE + flash_protect = -1 + #undef RGB2EYECOLORSTRING diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index ffecb68a2d0a7..860b57b037acd 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -240,3 +240,8 @@ owner.heal_overall_damage(15, 15, 0, BODYTYPE_ORGANIC) if(owner.reagents.get_reagent_amount(/datum/reagent/medicine/ephedrine) < 20) owner.reagents.add_reagent(/datum/reagent/medicine/ephedrine, 10) + +/obj/item/organ/heart/diona + name = "polypment segment" + desc = "A segment of plant matter that is resposible for pumping nutrients around the body." + icon_state = "diona_heart" diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm index 71dae581957a3..d4962a1048ba2 100755 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -136,5 +136,10 @@ if(2) owner.toxloss += 5 +/obj/item/organ/liver/diona + name = "liverwort" + desc = "A mass of plant vines and leaves, seeming to be responsible for chemical digestion." + icon_state = "diona_liver" + #undef LIVER_DEFAULT_TOX_TOLERANCE #undef LIVER_DEFAULT_TOX_LETHALITY diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index d816c0bb7a5df..2f00674d27b44 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -433,6 +433,12 @@ GAS_CO2 = 45, GAS_PLASMA = MOLES_GAS_VISIBLE ) + +/obj/item/organ/lungs/diona + name = "diona leaves" + desc = "A small mass concentrated leaves, used for breathing." + icon_state = "diona_lungs" + #undef PP #undef PP_MOLES diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm index e6e63abf3bac0..7fa8137a84036 100755 --- a/code/modules/surgery/organs/stomach.dm +++ b/code/modules/surgery/organs/stomach.dm @@ -220,3 +220,8 @@ COOLDOWN_START(src, severe_cooldown, 10 SECONDS) if(prob(emp_vulnerability/severity)) //Chance of permanent effects organ_flags |= ORGAN_FAILING //Starts organ failure - gonna need replacing soon. + +/obj/item/organ/stomach/diona + name = "nutrient vessel" + desc = "A group of plant matter and vines, useful for digestion of light and radiation." + icon_state = "diona_stomach" diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 8debda384483d..b1cead0edcf8f 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -364,18 +364,23 @@ disliked_food = CLOTH liked_food = JUNKFOOD | FRIED | GROSS | RAW | GORE -/obj/item/organ/tongue/podperson - name = "plant tongue" +/obj/item/organ/tongue/diona + name = "diona tongue" desc = "It's an odd tongue, seemingly made of plant matter." - disliked_food = MEAT | DAIRY - liked_food = VEGETABLES | FRUIT | GRAIN | CLOTH //cannibals apparently - -/obj/item/organ/tongue/podperson/pumpkin + icon_state = "diona_tongue" + say_mod = "rustles" + ask_mod = "quivers" + yell_mod = "shrieks" + exclaim_mod = "ripples" + disliked_food = DAIRY | FRUIT | GRAIN | CLOTH | VEGETABLES + liked_food = MEAT | RAW + +/obj/item/organ/tongue/diona/pumpkin modifies_speech = TRUE ///Is this tongue carved? var/carved = FALSE -/obj/item/organ/tongue/podperson/pumpkin/handle_speech(datum/source, list/speech_args) +/obj/item/organ/tongue/diona/pumpkin/handle_speech(datum/source, list/speech_args) var/message = speech_args[SPEECH_MESSAGE] if((message[1] != "*" || message[1] != "#") && !carved) message = "..." diff --git a/code/modules/vending/megaseed.dm b/code/modules/vending/megaseed.dm index f7ad7fb1c1982..790051ae6f56e 100644 --- a/code/modules/vending/megaseed.dm +++ b/code/modules/vending/megaseed.dm @@ -30,7 +30,7 @@ /obj/item/seeds/potato = 3, /obj/item/seeds/flower/poppy = 3, /obj/item/seeds/pumpkin = 3, - /obj/item/seeds/replicapod = 3, + /obj/item/seeds/dionapod = 3, /obj/item/seeds/wheat/rice = 3, /obj/item/seeds/soya = 3, /obj/item/seeds/sunflower = 3, diff --git a/config/game_options.txt b/config/game_options.txt index ca1df12f76e5e..d6640f5e05b08 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -492,6 +492,7 @@ ROUNDSTART_RACES lizard ROUNDSTART_RACES moth #ROUNDSTART_RACES fly ROUNDSTART_RACES psyphoza +ROUNDSTART_RACES diona ## Races that are better than humans in some ways, but worse in others ROUNDSTART_RACES apid diff --git a/icons/hud/actions/actions_spells.dmi b/icons/hud/actions/actions_spells.dmi index 51c928fd5e1d4..9e08d7d7b5e13 100644 Binary files a/icons/hud/actions/actions_spells.dmi and b/icons/hud/actions/actions_spells.dmi differ diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index b99c973312bd8..f4a8c1314275a 100644 Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index c69321f2c7bd6..be6f07cbfbc99 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ diff --git a/icons/mob/diona_markings.dmi b/icons/mob/diona_markings.dmi new file mode 100644 index 0000000000000..89bbe65aabadc Binary files /dev/null and b/icons/mob/diona_markings.dmi differ diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi index a3580d68d08f2..7da5f21284b4f 100644 Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ diff --git a/icons/mob/mutant_bodyparts.dmi b/icons/mob/mutant_bodyparts.dmi index 61e0b3607bcf8..aebaace8d8fe8 100644 Binary files a/icons/mob/mutant_bodyparts.dmi and b/icons/mob/mutant_bodyparts.dmi differ diff --git a/icons/mob/pets_held.dmi b/icons/mob/pets_held.dmi index bb27927e482ab..25a3a0d2d0a52 100644 Binary files a/icons/mob/pets_held.dmi and b/icons/mob/pets_held.dmi differ diff --git a/icons/mob/pets_held_lh.dmi b/icons/mob/pets_held_lh.dmi index 16b68243c5611..d3336a9ff9109 100644 Binary files a/icons/mob/pets_held_lh.dmi and b/icons/mob/pets_held_lh.dmi differ diff --git a/icons/mob/pets_held_rh.dmi b/icons/mob/pets_held_rh.dmi index a9ee09f0810d6..68d72b507f3c2 100644 Binary files a/icons/mob/pets_held_rh.dmi and b/icons/mob/pets_held_rh.dmi differ diff --git a/icons/mob/species/diona/bodyparts.dmi b/icons/mob/species/diona/bodyparts.dmi new file mode 100644 index 0000000000000..e479f73d76f65 Binary files /dev/null and b/icons/mob/species/diona/bodyparts.dmi differ diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi index 492436057b13a..3a8064821709a 100644 Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi index 8bbdb0e489486..ac8fe34c60143 100644 Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index fbbee2b685527..91da670af4212 100755 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/sound/emotes/diona/chitter.ogg b/sound/emotes/diona/chitter.ogg new file mode 100644 index 0000000000000..423b40826f770 Binary files /dev/null and b/sound/emotes/diona/chitter.ogg differ diff --git a/sound/emotes/diona/cricket.ogg b/sound/emotes/diona/cricket.ogg new file mode 100644 index 0000000000000..1c956805cb5d9 Binary files /dev/null and b/sound/emotes/diona/cricket.ogg differ diff --git a/sound/emotes/diona/death.ogg b/sound/emotes/diona/death.ogg new file mode 100644 index 0000000000000..a5f714477a2b7 Binary files /dev/null and b/sound/emotes/diona/death.ogg differ diff --git a/sound/emotes/diona/hit.ogg b/sound/emotes/diona/hit.ogg new file mode 100644 index 0000000000000..0e6a752a504ed Binary files /dev/null and b/sound/emotes/diona/hit.ogg differ diff --git a/sound/emotes/diona/laugh.ogg b/sound/emotes/diona/laugh.ogg new file mode 100644 index 0000000000000..327aabb43cc2f Binary files /dev/null and b/sound/emotes/diona/laugh.ogg differ diff --git a/sound/emotes/diona/scream.ogg b/sound/emotes/diona/scream.ogg new file mode 100644 index 0000000000000..c4eb9caee2321 Binary files /dev/null and b/sound/emotes/diona/scream.ogg differ diff --git a/sound/emotes/diona/sneeze.ogg b/sound/emotes/diona/sneeze.ogg new file mode 100644 index 0000000000000..d5fc10836ccd2 Binary files /dev/null and b/sound/emotes/diona/sneeze.ogg differ diff --git a/strings/names/diona.txt b/strings/names/diona.txt new file mode 100644 index 0000000000000..348883c47e7c3 --- /dev/null +++ b/strings/names/diona.txt @@ -0,0 +1,198 @@ +Joining A Chorus +Digging Into Soil +Discovering A Bug +Crunching A Stone +Yearning For Yams +Searching For Kin +Creating A Gestalt +Swimming In A Pond +Diving For Pearls +Getting Stuck In Furniture +Watching The Crowd +Calling For Urgent Aid +Hiding Beneath A Rock +Tasting Of Snow +Learning Of Cooking +Screaming At A Clown +Hiding Beneath Couch +Finding A New Friend +Enjoying The Hot Sun +Nibbling Upon A Rock +Dancing With Friends +Sifting Warm Sand +Laying On A Warm Rock +Making A Fool Of Self +Leaping With New Legs +Longingly Staring Out +Tapping Of The Pencil +Drifting With Longing +Seeing A Fearsome Bug +Splitting From Gestalt +Running Behind A Plant +Tripping Over Own Legs +Dropping Papers In Mud +Soaking A Canvas With Dye +Watching Dust Drift Drearily +Playing Under The Grass +Learning The First Song +Dashing Under A Blanket +Singing A Warbling Note In A Song +Hearing Pipes In Walls Creaking +Finding First Friend +Jittering During A Review +Discovering Spicy Food +Smelling Sultry Food +Listening To Leaves Rustling In Winds +Fearing Loud Noises From The Sky +Dancing Upon The Hilltop +Watching The Ducks Feast +Staring Into A Birds Eye +Drifting Without Gravity +Poking Things With Stick +Foolishly Eating Plastic +Understanding The Light In The Darkness +Gazing Upon Swans Dancing In The Lake +Feeling The Heat Of The Sun Upon Body +Joyfully Making A Snowman +Falling Upon The Tin Roof +Stirring The Muddy Waters +Breaking A Treasured Gift +Sticking Nose Into Places +Frightfully Sitting Alone +Enjoying The Taste Of Dirt +Getting Scared After Noises +Tasting Water Falling From The Sky +Watching Night Turn To Day +Experiencing The Cold Snow +Singing For The First Time +Swimming Through A Current +Gnawing Upon Unriped Fruit +Hearing Soft Patters Down The Hall +Cooking Smells Wafting Out +Getting Scared After Noises +Spilling Pen Ink Everywhere +Discovering A Snack On Street +Driving Alone Upon The Road +Rolling In On The Open Road +Adventuring Out From Parent +Curiously Prodding The Frog +Searching For Lost Trinkets +Getting Glue Stuck To Shell +Drawing Faces Upon The Glass +Tuning Into The Radio Static +Pensively Pondering The Pond +Gleefully Gorging Upon Candy +Crackling Frost Coated Glass +Understanding Place In World +Dancing Upon The Muddy Puddle +Breathing In Clean Atmosphere +Tracking Mud Within The Abode +Hearing First Song From Parent +Frightfully Falling From Cliff +Eating A Terrible Tasting Frog +Experiencing Nuclear Armageddon +Tinkering Joyfully With Gadgets +Jumping Into Feathery Soft Snow +Getting Hit By A Sack Of Cement +Hearing A Sad Song Upon The Hills +Attempting To Converse Disastrously +Tapping On Tortoise Shell +Scooping Up A Sea Creature +Stung By A Sea Creature +Tending To A Foolish Child +Returning A Creature To Sea +Softly Sitting On The Sand +Burning Scraps Of Paper +Blowing Rings Of Smoke +Popping Bubbles As They Float +Catching A Frisbee +Honoring The Dead +Shaving Flakes Off The Wood +Scrubbing The Hull +Overflowing Cup Of Tea +Pouring Out A Failed Experiment +Turning Clay Upon The Table +Carelessly Climbing The Cliff +Kneading The Dough +Mourning The Lost Parent +Picking Up The Scattered Windchimes +Sweeping The Shattered Glass +Carving Tool Shattering Upon Rock +Hiding Away In The Soil +Digging Up The Dead +Stepping Into The Silent Temple +Knocking Over The Statue +Grasping At Shattered Shards +Smashing Bottles Together +Rewinding The Spool Of Thread +Digging Through The Garbage Pile +Proudly Painting The Wooden Sign +Making First Steps Towards New Purpose +Filming A Miraculous Event +Tying Together Thousands of Threads +Tasting The Rocks In The Cave +Gnawing Away At The Bars +Pitifully Clawing At Walls +Walking In Unison +Standing Victorious On The Podium +Shamefully Slinking Behind The Curtain +Hauling Furnishings Into The Abode +Questioning The Odd Suspect +Gratefully Accepting The Gift +Bouncing Down The Hill +Staring At The Ships Burning +Knitting A Scratchy Sweater +Jostling An Insect Nest +Berating An Idiot +Failing An Operation +Blaming Those Who Do Not Deserve It +Whittling The Flint Spear +Turning The Artifact In Hand +Playing Softly On The Xylophone +Chipping Away At The Gemstone +Throwing A Rock Down A Well +Watching A Struggling Bug +Staring At A Wall +Talking Through The Night +Delicately Nibbling On Bread +Sneaking Upon Many Feet +Dancing All Day and Night +Weeping Softly Upon the Stone +Lost In The Caverns +Politely Declining Terrible Pay +Creating Truly Terrible Artwork +Frowning Softly At The Sky +Intently Listening At The Door +Peeking When One Should Not +Cheating At A Childhood Game +Eating Pieces Of A Puzzle +Chewing Through A Letter +Shaking Hands Opening a Note +Fighting Off A Terrible Beast +Testing A New Creation +Freezing Under A Scornful Gaze +Crunching Salt Crystals +Regrowing A Shell +Committing Foolishness At Night +Reading A Poem To Children +Aiding Our First Patient Home +Delivering The Last Parcel +Grinding Spices For A Stew +Unearthing Long Lost Treasures +Dragging Feet To The Speech +Marking Lines Upon The Paper +Gleefully Digging Into The Sand +Arming The Explosive +Swimming In Murky Waters +Violently Shredding Legal Notice +Diligently Cleaning A Grave +Staring In Horror Through Window +Doing Nothing In Particular +Lounging Under The Sun After Long Day +Cursing Under Breath +Singing Softly To Young +Spinning Thread Through Fingers +Proudly Staring At New Toy +Stitching Torn Cloth Together +Furiously Scribbling Foul Words +Snapping Scattered Sticks diff --git a/tools/UpdatePaths/Scripts/10919_Podperson_to_Diona.txt b/tools/UpdatePaths/Scripts/10919_Podperson_to_Diona.txt new file mode 100644 index 0000000000000..aa4161e98a7da --- /dev/null +++ b/tools/UpdatePaths/Scripts/10919_Podperson_to_Diona.txt @@ -0,0 +1,4 @@ +#comment This replaces all references of podpeople with their diona counterparts. https://github.com/BeeStation/BeeStation-Hornet/pull/10919 + +/obj/item/food/meat/slab/human/mutant/plant : /obj/item/food/meat/slab/human/mutant/diona{@OLD} +/obj/item/seeds/replicapod : /obj/item/seeds/dionapod{@OLD}