diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 76f66521a7..11d792db93 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -25,6 +25,7 @@ #define NOBLUDGEON (1<<7) // when an item has this it produces no "X has been hit by Y with Z" message in the default attackby() #define NODROP (1<<8) // This flag makes it so that an item literally cannot be removed at all, or at least that's how it should be. Only deleted. #define ABSTRACT (1<<9) // for all things that are technically items but used for various different stuff +#define IMMUTABLE_SLOW (1<<10) // When players should not be able to change the slowdown of the item (Speed potions, etc) // Flags for the clothing_flags var on /obj/item/clothing diff --git a/code/modules/research/xenobiology/crossbreeding/_corecross.dm b/code/modules/research/xenobiology/crossbreeding/__corecross.dm similarity index 100% rename from code/modules/research/xenobiology/crossbreeding/_corecross.dm rename to code/modules/research/xenobiology/crossbreeding/__corecross.dm diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm new file mode 100644 index 0000000000..242de2eeed --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -0,0 +1,131 @@ +/* +Slimecrossing Armor + Armor added by the slimecrossing system. + Collected here for clarity. +*/ + +//Rebreather mask - Chilling Blue +/obj/item/clothing/mask/nobreath + name = "rebreather mask" + desc = "A transparent mask, resembling a conventional breath mask, but made of bluish slime. Seems to lack any air supply tube, though." + icon_state = "slime" + item_state = "slime" + body_parts_covered = 0 + w_class = WEIGHT_CLASS_SMALL + gas_transfer_coefficient = 0 + permeability_coefficient = 0.5 + flags_cover = MASKCOVERSMOUTH + resistance_flags = NONE + +/obj/item/clothing/mask/nobreath/equipped(mob/living/carbon/human/user, slot) + . = ..() + if(slot == SLOT_WEAR_MASK) + user.add_trait(TRAIT_NOBREATH, "breathmask_[REF(src)]") + user.failed_last_breath = FALSE + user.clear_alert("not_enough_oxy") + user.apply_status_effect(/datum/status_effect/rebreathing) + +/obj/item/clothing/mask/nobreath/dropped(mob/living/carbon/human/user) + ..() + user.remove_trait(TRAIT_NOBREATH, "breathmask_[REF(src)]") + user.remove_status_effect(/datum/status_effect/rebreathing) + +/obj/item/clothing/glasses/prism_glasses + name = "prism glasses" + desc = "The lenses seem to glow slightly, and reflect light into dazzling colors." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "prismglasses" + actions_types = list(/datum/action/item_action/change_prism_colour, /datum/action/item_action/place_light_prism) + var/glasses_color = "#FFFFFF" + +/obj/item/clothing/glasses/prism_glasses/item_action_slot_check(slot) + if(slot == SLOT_GLASSES) + return TRUE + +/obj/structure/light_prism + name = "light prism" + desc = "A shining crystal of semi-solid light. Looks fragile." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "lightprism" + density = FALSE + anchored = TRUE + max_integrity = 10 + +/obj/structure/light_prism/Initialize(mapload, var/newcolor) + . = ..() + color = newcolor + light_color = newcolor + set_light(5) + +/obj/structure/light_prism/attack_hand(mob/user) + to_chat(user, "You dispel [src]") + qdel(src) + +/datum/action/item_action/change_prism_colour + name = "Adjust Prismatic Lens" + icon_icon = 'icons/obj/slimecrossing.dmi' + button_icon_state = "prismcolor" + +/datum/action/item_action/change_prism_colour/Trigger() + var/obj/item/clothing/glasses/prism_glasses/glasses = target + var/new_color = input(owner, "Choose the lens color:", "Color change",glasses.glasses_color) as color|null + if(!new_color) + return + glasses.glasses_color = new_color + +/datum/action/item_action/place_light_prism + name = "Fabricate Light Prism" + icon_icon = 'icons/obj/slimecrossing.dmi' + button_icon_state = "lightprism" + +/datum/action/item_action/place_light_prism/Trigger() + var/obj/item/clothing/glasses/prism_glasses/glasses = target + if(locate(/obj/structure/light_prism) in get_turf(owner)) + to_chat(owner, "There isn't enough ambient energy to fabricate another light prism here.") + return + if(istype(glasses)) + if(!glasses.glasses_color) + to_chat(owner, "The lens is oddly opaque...") + return + to_chat(owner, "You channel nearby light into a glowing, ethereal prism.") + new /obj/structure/light_prism(get_turf(owner), glasses.glasses_color) + +/obj/item/clothing/head/peaceflower + name = "heroine bud" + desc = "An extremely addictive flower, full of peace magic." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "peaceflower" + item_state = "peaceflower" + +/obj/item/clothing/head/peaceflower/equipped(mob/living/carbon/human/user, slot) + . = ..() + if(slot == SLOT_HEAD) + user.add_trait(TRAIT_PACIFISM, "peaceflower_[REF(src)]") + +/obj/item/clothing/head/peaceflower/dropped(mob/living/carbon/human/user) + ..() + user.remove_trait(TRAIT_PACIFISM, "peaceflower_[REF(src)]") + +/obj/item/clothing/head/peaceflower/attack_hand(mob/user) + if(iscarbon(user)) + var/mob/living/carbon/C = user + if(src == C.head) + to_chat(user, "You feel at peace. Why would you want anything else?") + return + return ..() + +/obj/item/clothing/suit/armor/heavy/adamantine + name = "adamantine armor" + desc = "A full suit of adamantine plate armor. Impressively resistant to damage, but weighs about as much as you do." + icon_state = "adamsuit" + item_state = "adamsuit" + flags_inv = list() + obj_flags = IMMUTABLE_SLOW + slowdown = 4 + var/hit_reflect_chance = 40 + +/obj/item/clothing/suit/armor/heavy/adamantine/IsReflect(def_zone) + if(def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) && prob(hit_reflect_chance)) + return TRUE + else + return FALSE diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm new file mode 100644 index 0000000000..547a5c34e6 --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -0,0 +1,172 @@ +/* +Slimecrossing Items + General items added by the slimecrossing system. + Collected here for clarity. +*/ + +//Timefreeze camera - Burning Sepia +/obj/item/camera/timefreeze + name = "sepia-tinted camera" + desc = "They say a picture is like a moment stopped in time." + pictures_left = 1 + pictures_max = 1 + +/obj/item/camera/timefreeze/afterattack(atom/target, mob/user, flag) + if(!on || !pictures_left || !isturf(target.loc)) + return + new /obj/effect/timestop(get_turf(target), 2, 50, list(user)) + . = ..() + var/text = "The camera fades away" + if(disk) + text += ", leaving the disk behind!" + if(!user.put_in_hands(disk)) + disk.forceMove(user.drop_location()) + else + text += "!" + to_chat(user,"[text]") + qdel(src) + +//Hypercharged slime cell - Charged Yellow +/obj/item/stock_parts/cell/high/slime/hypercharged + name = "hypercharged slime core" + desc = "A charged yellow slime extract, infused with even more plasma. It almost hurts to touch." + rating = 7 //Roughly 1.5 times the original. + maxcharge = 20000 //2 times the normal one. + chargerate = 2250 //1.5 times the normal rate. + +//Barrier cube - Chilling Grey +/obj/item/barriercube + name = "barrier cube" + desc = "A compressed cube of slime. When squeezed, it grows to massive size!" + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "barriercube" + w_class = WEIGHT_CLASS_TINY + +/obj/item/barriercube/attack_self(mob/user) + if(locate(/obj/structure/barricade/slime) in get_turf(loc)) + to_chat(user, "You can't fit more than one barrier in the same space!") + return + to_chat(user, "You squeeze [src].") + var/obj/B = new /obj/structure/barricade/slime(get_turf(loc)) + B.visible_message("[src] suddenly grows into a large, gelatinous barrier!") + qdel(src) + +//Slime barricade - Chilling Grey +/obj/structure/barricade/slime + name = "gelatinous barrier" + desc = "A huge chunk of grey slime. Bullets might get stuck in it." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "slimebarrier" + proj_pass_rate = 40 + max_integrity = 60 + +//Melting Gel Wall - Chilling Metal +/obj/effect/forcefield/slimewall + name = "solidified gel" + desc = "A mass of solidified slime gel - completely impenetrable, but it's melting away!" + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "slimebarrier_thick" + CanAtmosPass = ATMOS_PASS_NO + opacity = TRUE + timeleft = 100 + +//Rainbow barrier - Chilling Rainbow +/obj/effect/forcefield/slimewall/rainbow + name = "rainbow barrier" + desc = "Despite others' urgings, you probably shouldn't taste this." + icon_state = "rainbowbarrier" + +//Ration pack - Chilling Silver +/obj/item/reagent_containers/food/snacks/rationpack + name = "ration pack" + desc = "A square bar that sadly looks like chocolate, packaged in a nondescript grey wrapper. Has saved soldiers' lives before - usually by stopping bullets." + icon_state = "rationpack" + bitesize = 3 + eatverb = "choke down" + junkiness = 15 + filling_color = "#964B00" + tastes = list("cardboard" = 3, "sadness" = 3) + foodtype = null //Don't ask what went into them. You're better off not knowing. + list_reagents = list("stabilizednutriment" = 10, "nutriment" = 2) //Won't make you fat. Will make you question your sanity. + +/obj/item/reagent_containers/food/snacks/rationpack/checkLiked(fraction, mob/M) //Nobody likes rationpacks. Nobody. + if(last_check_time + 50 < world.time) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.mind && !H.has_trait(TRAIT_AGEUSIA)) + to_chat(H,"That didn't taste very good...") //No disgust, though. It's just not good tasting. + GET_COMPONENT_FROM(mood, /datum/component/mood, H) + if(mood) + mood.add_event(null,"gross_food", /datum/mood_event/gross_food) + last_check_time = world.time + return + ..() + +//Ice stasis block - Chilling Dark Blue +/obj/structure/ice_stasis + name = "ice block" + desc = "A massive block of ice. You can see something vaguely humanoid inside." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "frozen" + density = TRUE + max_integrity = 100 + armor = list("melee" = 30, "bullet" = 50, "laser" = -50, "energy" = -50, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = -80, "acid" = 30) + +/obj/structure/ice_stasis/Initialize() + . = ..() + playsound(src, 'sound/magic/ethereal_exit.ogg', 50, 1) + +/obj/structure/ice_stasis/Destroy() + for(var/atom/movable/M in contents) + M.forceMove(loc) + playsound(src, 'sound/effects/glassbr3.ogg', 50, 1) + return ..() + +//Gold capture device - Chilling Gold +/obj/item/capturedevice + name = "gold capture device" + desc = "Bluespace technology packed into a roughly egg-shaped device, used to store nonhuman creatures. Can't catch them all, though - it only fits one." + w_class = WEIGHT_CLASS_SMALL + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "capturedevice" + +/obj/item/capturedevice/attack(mob/living/M, mob/user) + if(length(contents)) + to_chat(user, "The device already has something inside.") + return + if(!isanimal(M)) + to_chat(user, "The capture device only works on simple creatures.") + return + if(M.mind) + to_chat(user, "You offer the device to [M].") + if(alert(M, "Would you like to enter [user]'s capture device?", "Gold Capture Device", "Yes", "No") == "Yes") + if(user.canUseTopic(src, BE_CLOSE) && user.canUseTopic(M, BE_CLOSE)) + to_chat(user, "You store [M] in the capture device.") + to_chat(M, "The world warps around you, and you're suddenly in an endless void, with a window to the outside floating in front of you.") + store(M, user) + else + to_chat(user, "You were too far away from [M].") + to_chat(M, "You were too far away from [user].") + else + to_chat(user, "[M] refused to enter the device.") + return + else + if(istype(M, /mob/living/simple_animal/hostile) && !("neutral" in M.faction)) + to_chat(user, "This creature is too aggressive to capture.") + return + to_chat(user, "You store [M] in the capture device.") + store(M) + +/obj/item/capturedevice/attack_self(mob/user) + if(contents.len) + to_chat(user, "You open the capture device!") + release() + else + to_chat(user, "The device is empty...") + +/obj/item/capturedevice/proc/store(var/mob/living/M) + M.forceMove(src) + +/obj/item/capturedevice/proc/release() + for(var/atom/movable/M in contents) + M.forceMove(get_turf(loc)) diff --git a/code/modules/research/xenobiology/crossbreeding/_mobs.dm b/code/modules/research/xenobiology/crossbreeding/_mobs.dm new file mode 100644 index 0000000000..0d155f2f90 --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_mobs.dm @@ -0,0 +1,45 @@ +/* +Slimecrossing Mobs + Mobs and effects added by the slimecrossing system. + Collected here for clarity. +*/ + +//Slime transformation power - Burning Black +/obj/effect/proc_holder/spell/targeted/shapeshift/slimeform + name = "Slime Transformation" + desc = "Transform from a human to a slime, or back again!" + action_icon_state = "transformslime" + cooldown_min = 0 + charge_max = 0 + invocation_type = "none" + shapeshift_type = /mob/living/simple_animal/slime/transformedslime + convert_damage = TRUE + convert_damage_type = CLONE + var/remove_on_restore = FALSE + +/obj/effect/proc_holder/spell/targeted/shapeshift/slimeform/Restore(mob/living/M) + if(remove_on_restore) + if(M.mind) + M.mind.RemoveSpell(src) + ..() + +//Transformed slime - Burning Black +/mob/living/simple_animal/slime/transformedslime + +/mob/living/simple_animal/slime/transformedslime/Reproduce() //Just in case. + to_chat(src, "I can't reproduce...") + return + +//Slime corgi - Chilling Pink +/mob/living/simple_animal/pet/dog/corgi/puppy/slime + name = "\improper slime corgi puppy" + real_name = "slime corgi puppy" + desc = "An unbearably cute pink slime corgi puppy." + icon_state = "slime_puppy" + icon_living = "slime_puppy" + icon_dead = "slime_puppy_dead" + nofur = TRUE + gold_core_spawnable = NO_SPAWN + speak_emote = list("blorbles", "bubbles", "borks") + emote_hear = list("bubbles!", "splorts.", "splops!") + emote_see = list("gets goop everywhere.", "flops.", "jiggles!") diff --git a/code/modules/research/xenobiology/crossbreeding/_potions.dm b/code/modules/research/xenobiology/crossbreeding/_potions.dm new file mode 100644 index 0000000000..e7dc947955 --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_potions.dm @@ -0,0 +1,211 @@ +/* +Slimecrossing Potions + Potions added by the slimecrossing system. + Collected here for clarity. +*/ + +//Extract cloner - Charged Grey +/obj/item/slimepotion/extract_cloner + name = "extract cloning potion" + desc = "An more powerful version of the extract enhancer potion, capable of cloning regular slime extracts." + icon = 'icons/obj/chemical.dmi' + icon_state = "potpurple" + +/obj/item/slimepotion/extract_cloner/afterattack(obj/item/target, mob/user , proximity) + if(!proximity) + return + if(istype(target, /obj/item/reagent_containers)) + return ..(target, user, proximity) + if(istype(target, /obj/item/slimecross)) + to_chat(user, "[target] is too complex for the potion to clone!") + return + if(!istype(target, /obj/item/slime_extract)) + return + var/obj/item/slime_extract/S = target + if(S.recurring) + to_chat(user, "[target] is too complex for the potion to clone!") + return + var/path = S.type + var/obj/item/slime_extract/C = new path(get_turf(target)) + C.Uses = S.Uses + to_chat(user, "You pour the potion onto [target], and the fluid solidifies into a copy of it!") + qdel(src) + return + +//Peace potion - Charged Light Pink +/obj/item/slimepotion/peacepotion + name = "pacification potion" + desc = "A light pink solution of chemicals, smelling like liquid peace. And mercury salts." + icon = 'icons/obj/chemical.dmi' + icon_state = "potlightpink" + +/obj/item/slimepotion/peacepotion/attack(mob/living/M, mob/user) + if(!isliving(M) || M.stat == DEAD) + to_chat(user, "The pacification potion only works on the living.") + return ..() + if(M != user) + M.visible_message("[user] starts to feed [M] a pacification potion!", + "[user] starts to feed you a pacification!") + else + M.visible_message("[user] starts to drink the pacification potion!", + "You start to drink the pacification potion!") + + if(!do_after(user, 100, target = M)) + return + if(M != user) + to_chat(user, "You feed [M] the pacification potion!") + else + to_chat(user, "You drink the pacification potion!") + if(isanimal(M)) + M.add_trait(TRAIT_PACIFISM, MAGIC_TRAIT) + else if(iscarbon(M)) + var/mob/living/carbon/C = M + C.gain_trauma(/datum/brain_trauma/severe/pacifism, TRAUMA_RESILIENCE_SURGERY) + qdel(src) + +//Love potion - Charged Pink +/obj/item/slimepotion/lovepotion + name = "love potion" + desc = "A pink chemical mix thought to inspire feelings of love." + icon = 'icons/obj/chemical.dmi' + icon_state = "potpink" + +/obj/item/slimepotion/lovepotion/attack(mob/living/M, mob/user) + if(!isliving(M) || M.stat == DEAD) + to_chat(user, "The love potion only works on living things, sicko!") + return ..() + if(user == M) + to_chat(user, "You can't drink the love potion. What are you, a narcissist?") + return ..() + if(M.has_status_effect(STATUS_EFFECT_INLOVE)) + to_chat(user, "[M] is already lovestruck!") + return ..() + + M.visible_message("[user] starts to feed [M] a love potion!", + "[user] starts to feed you a love potion!") + + if(!do_after(user, 50, target = M)) + return + to_chat(user, "You feed [M] the love potion!") + to_chat(M, "You develop feelings for [user], and anyone [user.p_they()] like.") + if(M.mind) + M.mind.store_memory("You are in love with [user].") + M.faction |= "[REF(user)]" + M.apply_status_effect(STATUS_EFFECT_INLOVE, user) + qdel(src) + +//Pressure potion - Charged Dark Blue +/obj/item/slimepotion/spaceproof + name = "slime pressurization potion" + desc = "A potent chemical sealant that will render any article of clothing airtight. Has two uses." + icon = 'icons/obj/chemical.dmi' + icon_state = "potblue" + var/uses = 2 + +/obj/item/slimepotion/spaceproof/afterattack(obj/item/clothing/C, mob/user, proximity) + . = ..() + if(!uses) + qdel(src) + return + if(!proximity) + return + if(!istype(C)) + to_chat(user, "The potion can only be used on clothing!") + return + if(C.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && C.clothing_flags & STOPSPRESSUREDAMAGE) + to_chat(user, "The [C] is already pressure-resistant!") + return ..() + to_chat(user, "You slather the blue gunk over the [C], making it airtight.") + C.name = "pressure-resistant [C.name]" + C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + C.add_atom_colour("#000080", FIXED_COLOUR_PRIORITY) + C.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT + C.cold_protection = C.body_parts_covered + C.clothing_flags |= STOPSPRESSUREDAMAGE + uses-- + if(!uses) + qdel(src) + +//Enhancer potion - Charged Cerulean +/obj/item/slimepotion/enhancer/max + name = "extract maximizer" + desc = "An extremely potent chemical mix that will maximize a slime extract's uses." + icon = 'icons/obj/chemical.dmi' + icon_state = "potpurple" + +//Lavaproofing potion - Charged Red +/obj/item/slimepotion/lavaproof + name = "slime lavaproofing potion" + desc = "A strange, reddish goo said to repel lava as if it were water, without reducing flammability. Has two uses." + icon = 'icons/obj/chemical.dmi' + icon_state = "potred" + resistance_flags = LAVA_PROOF | FIRE_PROOF + var/uses = 2 + +/obj/item/slimepotion/lavaproof/afterattack(obj/item/C, mob/user, proximity) + . = ..() + if(!uses) + qdel(src) + return ..() + if(!proximity) + return ..() + if(!istype(C)) + to_chat(user, "You can't coat this with lavaproofing fluid!") + return ..() + to_chat(user, "You slather the red gunk over the [C], making it lavaproof.") + C.name = "lavaproof [C.name]" + C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + C.add_atom_colour("#800000", FIXED_COLOUR_PRIORITY) + C.resistance_flags |= LAVA_PROOF + if (istype(C, /obj/item/clothing)) + var/obj/item/clothing/CL = C + CL.clothing_flags |= LAVAPROTECT + uses-- + if(!uses) + qdel(src) + +//Revival potion - Charged Grey +/obj/item/slimepotion/slime_reviver + name = "slime revival potion" + desc = "Infused with plasma and compressed gel, this brings dead slimes back to life." + icon = 'icons/obj/chemical.dmi' + icon_state = "potsilver" + +/obj/item/slimepotion/slime_reviver/attack(mob/living/simple_animal/slime/M, mob/user) + if(!isslime(M)) + to_chat(user, "The potion only works on slimes!") + return ..() + if(M.stat != DEAD) + to_chat(user, "The slime is still alive!") + return + if(M.maxHealth <= 0) + to_chat(user, "The slime is too unstable to return!") + M.revive(full_heal = 1) + M.stat = CONSCIOUS + M.visible_message("[M] is filled with renewed vigor and blinks awake!") + M.maxHealth -= 10 //Revival isn't healthy. + M.health -= 10 + M.regenerate_icons() + qdel(src) + +//Stabilizer potion - Charged Blue +/obj/item/slimepotion/slime/chargedstabilizer + name = "slime omnistabilizer" + desc = "An extremely potent chemical mix that will stop a slime from mutating completely." + icon = 'icons/obj/chemical.dmi' + icon_state = "potcyan" + +/obj/item/slimepotion/slime/chargedstabilizer/attack(mob/living/simple_animal/slime/M, mob/user) + if(!isslime(M)) + to_chat(user, "The stabilizer only works on slimes!") + return ..() + if(M.stat) + to_chat(user, "The slime is dead!") + return + if(M.mutation_chance == 0) + to_chat(user, "The slime already has no chance of mutating!") + return + + to_chat(user, "You feed the slime the omnistabilizer. It will not mutate this cycle!") + M.mutation_chance = 0 + qdel(src) diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 9984bf25c5..e7c04ef87f 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -57,6 +57,156 @@ owner.visible_message("[owner]'s gel coating liquefies and dissolves away.", "Your gel second-skin dissolves!") +/datum/status_effect/slimerecall + id = "slime_recall" + duration = -1 //Will be removed by the extract. + alert_type = null + var/interrupted = FALSE + var/mob/target + var/icon/bluespace + var/datum/weakref/redirect_component + +/datum/status_effect/slimerecall/on_apply() + redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/resistField)))) + to_chat(owner, "You feel a sudden tug from an unknown force, and feel a pull to bluespace!") + to_chat(owner, "Resist if you wish avoid the force!") + bluespace = icon('icons/effects/effects.dmi',"chronofield") + owner.add_overlay(bluespace) + return ..() + +/datum/status_effect/slimerecall/proc/resistField() + interrupted = TRUE + owner.remove_status_effect(src) +/datum/status_effect/slimerecall/on_remove() + qdel(redirect_component.resolve()) + redirect_component = null + owner.cut_overlay(bluespace) + if(interrupted || !ismob(target)) + to_chat(owner, "The bluespace tug fades away, and you feel that the force has passed you by.") + return + owner.visible_message("[owner] disappears in a flurry of sparks!", + "The unknown force snatches briefly you from reality, and deposits you next to [target]!") + do_sparks(3, TRUE, owner) + owner.forceMove(target.loc) + +/obj/screen/alert/status_effect/freon/stasis + desc = "You're frozen inside of a protective ice cube! While inside, you can't do anything, but are immune to harm! Resist to get out." + +/datum/status_effect/frozenstasis + id = "slime_frozen" + status_type = STATUS_EFFECT_UNIQUE + duration = -1 //Will remove self when block breaks. + alert_type = /obj/screen/alert/status_effect/freon/stasis + var/obj/structure/ice_stasis/cube + var/datum/weakref/redirect_component + +/datum/status_effect/frozenstasis/on_apply() + redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/breakCube)))) + cube = new /obj/structure/ice_stasis(get_turf(owner)) + owner.forceMove(cube) + owner.status_flags |= GODMODE + return ..() + +/datum/status_effect/frozenstasis/tick() + if(!cube || owner.loc != cube) + owner.remove_status_effect(src) + +/datum/status_effect/frozenstasis/proc/breakCube() + owner.remove_status_effect(src) + +/datum/status_effect/frozenstasis/on_remove() + if(cube) + qdel(cube) + owner.status_flags &= ~GODMODE + qdel(redirect_component.resolve()) + redirect_component = null + +/datum/status_effect/slime_clone + id = "slime_cloned" + status_type = STATUS_EFFECT_UNIQUE + duration = -1 + alert_type = null + var/mob/living/clone + var/datum/mind/originalmind //For when the clone gibs. + +/datum/status_effect/slime_clone/on_apply() + var/typepath = owner.type + clone = new typepath(owner.loc) + var/mob/living/carbon/O = owner + var/mob/living/carbon/C = clone + if(istype(C) && istype(O)) + C.real_name = O.real_name + O.dna.transfer_identity(C) + C.updateappearance(mutcolor_update=1) + if(owner.mind) + originalmind = owner.mind + owner.mind.transfer_to(clone) + clone.apply_status_effect(/datum/status_effect/slime_clone_decay) + return ..() + +/datum/status_effect/slime_clone/tick() + if(!istype(clone) || clone.stat != CONSCIOUS) + owner.remove_status_effect(src) + +/datum/status_effect/slime_clone/on_remove() + if(clone && clone.mind && owner) + clone.mind.transfer_to(owner) + else + if(owner && originalmind) + originalmind.transfer_to(owner) + if(originalmind.key) + owner.ckey = originalmind.key + if(clone) + clone.unequip_everything() + qdel(clone) + +/obj/screen/alert/status_effect/clone_decay + name = "Clone Decay" + desc = "You are simply a construct, and cannot maintain this form forever. You will be returned to your original body if you should fall." + icon_state = "slime_clonedecay" + +/datum/status_effect/slime_clone_decay + id = "slime_clonedecay" + status_type = STATUS_EFFECT_UNIQUE + duration = -1 + alert_type = /obj/screen/alert/status_effect/clone_decay + +/datum/status_effect/slime_clone_decay/tick() + owner.adjustToxLoss(1, 0) + owner.adjustOxyLoss(1, 0) + owner.adjustBruteLoss(1, 0) + owner.adjustFireLoss(1, 0) + owner.color = "#007BA7" + +/obj/screen/alert/status_effect/bloodchill + name = "Bloodchilled" + desc = "You feel a shiver down your spine after getting hit with a glob of cold blood. You'll move slower and get frostbite for a while!" + icon_state = "bloodchill" + +/datum/status_effect/bloodchill + id = "bloodchill" + duration = 100 + alert_type = /obj/screen/alert/status_effect/bloodchill + +/datum/status_effect/bloodchill/on_apply() + owner.add_movespeed_modifier("bloodchilled", TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = 3) + return ..() + +/datum/status_effect/bloodchill/tick() + if(prob(50)) + owner.adjustFireLoss(2) + +/datum/status_effect/bloodchill/on_remove() + owner.remove_movespeed_modifier("bloodchilled") + +/datum/status_effect/rebreathing + id = "rebreathing" + duration = -1 + alert_type = null + +datum/status_effect/rebreathing/tick() + owner.adjustOxyLoss(-6, 0) //Just a bit more than normal breathing. + /////////////////////////////////////////////////////// //////////////////CONSUMING EXTRACTS/////////////////// /////////////////////////////////////////////////////// diff --git a/code/modules/research/xenobiology/crossbreeding/_weapons.dm b/code/modules/research/xenobiology/crossbreeding/_weapons.dm new file mode 100644 index 0000000000..2327181eaa --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_weapons.dm @@ -0,0 +1,112 @@ +/* +Slimecrossing Weapons + Weapons added by the slimecrossing system. + Collected here for clarity. +*/ + +//Boneblade - Burning Green +/obj/item/melee/arm_blade/slime + name = "slimy boneblade" + desc = "What remains of the bones in your arm. Incredibly sharp, and painful for both you and your opponents." + force = 15 + force_string = "painful" + +/obj/item/melee/arm_blade/slime/attack(mob/living/L, mob/user) + . = ..() + if(prob(20)) + user.emote("scream") + +//Rainbow knife - Burning Rainbow +/obj/item/kitchen/knife/rainbowknife + name = "rainbow knife" + desc = "A strange, transparent knife which constantly shifts color. It hums slightly when moved." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "rainbowknife" + item_state = "rainbowknife" + force = 15 + throwforce = 15 + damtype = BRUTE + +/obj/item/kitchen/knife/rainbowknife/afterattack(atom/O, mob/user, proximity) + if(proximity && istype(O, /mob/living)) + damtype = pick(BRUTE, BURN, TOX, OXY, CLONE) + switch(damtype) + if(BRUTE) + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("slashed","sliced","cut") + if(BURN) + hitsound = 'sound/weapons/sear.ogg' + attack_verb = list("burned","singed","heated") + if(TOX) + hitsound = 'sound/weapons/pierce.ogg' + attack_verb = list("poisoned","dosed","toxified") + if(OXY) + hitsound = 'sound/effects/space_wind.ogg' + attack_verb = list("suffocated","winded","vacuumed") + if(CLONE) + hitsound = 'sound/items/geiger/ext1.ogg' + attack_verb = list("irradiated","mutated","maligned") + return ..() + +//Adamantine shield - Chilling Adamantine +/obj/item/twohanded/required/adamantineshield + name = "adamantine shield" + desc = "A gigantic shield made of solid adamantium." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "adamshield" + item_state = "adamshield" + w_class = WEIGHT_CLASS_HUGE + armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70) + slot_flags = ITEM_SLOT_BACK + block_chance = 75 + throw_range = 1 //How far do you think you're gonna throw a solid crystalline shield...? + throw_speed = 2 + force = 15 //Heavy, but hard to wield. + attack_verb = list("bashed","pounded","slammed") + item_flags = SLOWS_WHILE_IN_HAND + +//Bloodchiller - Chilling Green +/obj/item/gun/magic/bloodchill + name = "blood chiller" + desc = "A horrifying weapon made of your own bone and blood vessels. It shoots slowing globules of your own blood. Ech." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "bloodgun" + item_state = "bloodgun" + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + item_flags = ABSTRACT | NODROP | DROPDEL + w_class = WEIGHT_CLASS_HUGE + force = 5 + max_charges = 1 //Recharging costs blood. + recharge_rate = 1 + ammo_type = /obj/item/ammo_casing/magic/bloodchill + fire_sound = 'sound/effects/attackblob.ogg' + +/obj/item/gun/magic/bloodchill/process() + charge_tick++ + if(charge_tick < recharge_rate || charges >= max_charges) + return 0 + charge_tick = 0 + var/mob/living/M = loc + if(istype(M) && M.blood_volume >= 20) + charges++ + M.blood_volume -= 20 + if(charges == 1) + recharge_newshot() + return 1 + +/obj/item/ammo_casing/magic/bloodchill + projectile_type = /obj/item/projectile/magic/bloodchill + +/obj/item/projectile/magic/bloodchill + name = "blood ball" + icon_state = "pulse0_bl" + damage = 0 + damage_type = OXY + nodamage = 1 + hitsound = 'sound/effects/splat.ogg' + +/obj/item/projectile/magic/bloodchill/on_hit(mob/living/target) + . = ..() + if(isliving(target)) + target.apply_status_effect(/datum/status_effect/bloodchill) diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index 683088f149..718a8b229e 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -287,135 +287,3 @@ Burning extracts: user.visible_message("[src] flattens into a glowing rainbow blade.") new /obj/item/kitchen/knife/rainbowknife(get_turf(user)) ..() - -//Misc. things added - -/obj/item/camera/timefreeze - name = "sepia-tinted camera" - desc = "They say a picture is like a moment stopped in time." - pictures_left = 1 - pictures_max = 1 - -/obj/item/camera/timefreeze/afterattack(atom/target, mob/user, flag) - if(!on || !pictures_left || !isturf(target.loc)) - return - new /obj/effect/timestop(get_turf(target), 2, 50, list(user)) - . = ..() - var/text = "The camera fades away" - if(disk) - text += ", leaving the disk behind!" - user.put_in_hands(disk) - else - text += "!" - to_chat(user,"[text]") - qdel(src) - -/obj/item/slimepotion/extract_cloner - name = "extract cloning potion" - desc = "An more powerful version of the extract enhancer potion, capable of cloning regular slime extracts." - icon = 'icons/obj/chemical.dmi' - icon_state = "potpurple" - -/obj/item/slimepotion/extract_cloner/afterattack(obj/item/target, mob/user , proximity) - if(!proximity) - return - if(istype(target, /obj/item/reagent_containers)) - return ..(target, user, proximity) - if(istype(target, /obj/item/slimecross)) - to_chat(user, "[target] is too complex for the potion to clone!") - return - if(!istype(target, /obj/item/slime_extract)) - return - var/obj/item/slime_extract/S = target - if(S.recurring) - to_chat(user, "[target] is too complex for the potion to clone!") - return - var/path = S.type - var/obj/item/slime_extract/C = new path(get_turf(target)) - C.Uses = S.Uses - to_chat(user, "You pour the potion onto [target], and the fluid solidifies into a copy of it!") - qdel(src) - return - -/obj/item/melee/arm_blade/slime - name = "slimy boneblade" - desc = "What remains of the bones in your arm. Incredibly sharp, and painful for both you and your opponents." - force = 15 - force_string = "painful" - -/obj/item/melee/arm_blade/slime/attack(mob/living/L, mob/user) - . = ..() - if(prob(20)) - user.emote("scream") - -/obj/item/kitchen/knife/rainbowknife - name = "rainbow knife" - desc = "A strange, transparent knife which constantly shifts color. It hums slightly when moved." - icon = 'icons/obj/slimecrossing.dmi' - icon_state = "rainbowknife" - item_state = "rainbowknife" - force = 15 - throwforce = 15 - damtype = BRUTE - -/obj/item/kitchen/knife/rainbowknife/afterattack(atom/O, mob/user, proximity) - if(proximity && istype(O, /mob/living)) - damtype = pick(BRUTE, BURN, TOX, OXY, CLONE) - switch(damtype) - if(BRUTE) - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("slashed","sliced","cut") - if(BURN) - hitsound = 'sound/weapons/sear.ogg' - attack_verb = list("burned","singed","heated") - if(TOX) - hitsound = 'sound/weapons/pierce.ogg' - attack_verb = list("poisoned","dosed","toxified") - if(OXY) - hitsound = 'sound/effects/space_wind.ogg' - attack_verb = list("suffocated","winded","vacuumed") - if(CLONE) - hitsound = 'sound/items/geiger/ext1.ogg' - attack_verb = list("irradiated","mutated","maligned") - return ..() - -/obj/item/twohanded/required/adamantineshield - name = "adamantine shield" - desc = "A gigantic shield made of solid adamantium." - icon = 'icons/obj/slimecrossing.dmi' - icon_state = "adamshield" - item_state = "adamshield" - w_class = WEIGHT_CLASS_HUGE - armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70) - slot_flags = ITEM_SLOT_BACK - block_chance = 75 - throw_range = 1 //How far do you think you're gonna throw a solid crystalline shield...? - throw_speed = 2 - force = 15 //Heavy, but hard to wield. - attack_verb = list("bashed","pounded","slammed") - item_flags = SLOWS_WHILE_IN_HAND - - -/obj/effect/proc_holder/spell/targeted/shapeshift/slimeform - name = "Slime Transformation" - desc = "Transform from a human to a slime, or back again!" - action_icon_state = "transformslime" - cooldown_min = 0 - charge_max = 0 - invocation_type = "none" - shapeshift_type = /mob/living/simple_animal/slime/transformedslime - convert_damage = TRUE - convert_damage_type = CLONE - var/remove_on_restore = FALSE - -/obj/effect/proc_holder/spell/targeted/shapeshift/slimeform/Restore(mob/living/M) - if(remove_on_restore) - if(M.mind) - M.mind.RemoveSpell(src) - ..() - -/mob/living/simple_animal/slime/transformedslime - -/mob/living/simple_animal/slime/transformedslime/Reproduce() //Just in case. - to_chat(src, "I can't reproduce...") - return diff --git a/code/modules/research/xenobiology/crossbreeding/charged.dm b/code/modules/research/xenobiology/crossbreeding/charged.dm index b92ca079ae..05dd854c61 100644 --- a/code/modules/research/xenobiology/crossbreeding/charged.dm +++ b/code/modules/research/xenobiology/crossbreeding/charged.dm @@ -253,183 +253,3 @@ Charged extracts: var/mob/living/simple_animal/slime/S = new(get_turf(user)) S.random_colour() ..() - -////////////Unique things. - -/obj/item/slimepotion/slime_reviver - name = "slime revival potion" - desc = "Infused with plasma and compressed gel, this brings dead slimes back to life." - icon = 'icons/obj/chemical.dmi' - icon_state = "potsilver" - -/obj/item/slimepotion/slime_reviver/attack(mob/living/simple_animal/slime/M, mob/user) - if(!isslime(M)) - to_chat(user, "The potion only works on slimes!") - return ..() - if(M.stat != DEAD) - to_chat(user, "The slime is still alive!") - return - if(M.maxHealth <= 0) - to_chat(user, "The slime is too unstable to return!") - M.revive(full_heal = 1) - M.stat = CONSCIOUS - M.visible_message("[M] is filled with renewed vigor and blinks awake!") - M.maxHealth -= 10 //Revival isn't healthy. - M.health -= 10 - M.regenerate_icons() - qdel(src) - -/obj/item/slimepotion/slime/chargedstabilizer - name = "slime omnistabilizer" - desc = "An extremely potent chemical mix that will stop a slime from mutating completely." - icon = 'icons/obj/chemical.dmi' - icon_state = "potcyan" - -/obj/item/slimepotion/slime/chargedstabilizer/attack(mob/living/simple_animal/slime/M, mob/user) - if(!isslime(M)) - to_chat(user, "The stabilizer only works on slimes!") - return ..() - if(M.stat) - to_chat(user, "The slime is dead!") - return - if(M.mutation_chance == 0) - to_chat(user, "The slime already has no chance of mutating!") - return - - to_chat(user, "You feed the slime the omnistabilizer. It will not mutate this cycle!") - M.mutation_chance = 0 - qdel(src) - -/obj/item/stock_parts/cell/high/slime/hypercharged - name = "hypercharged slime core" - desc = "A charged yellow slime extract, infused with even more plasma. It almost hurts to touch." - rating = 7 //Roughly 1.5 times the original. - maxcharge = 20000 //2 times the normal one. - chargerate = 2250 //1.5 times the normal rate. - -/obj/item/slimepotion/spaceproof - name = "slime pressurization potion" - desc = "A potent chemical sealant that will render any article of clothing airtight. Has two uses." - icon = 'icons/obj/chemical.dmi' - icon_state = "potblue" - var/uses = 2 - -/obj/item/slimepotion/spaceproof/afterattack(obj/item/clothing/C, mob/user, proximity) - . = ..() - if(!uses) - qdel(src) - return - if(!proximity) - return - if(!istype(C)) - to_chat(user, "The potion can only be used on clothing!") - return - if(C.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && C.clothing_flags & STOPSPRESSUREDAMAGE) - to_chat(user, "The [C] is already pressure-resistant!") - return ..() - to_chat(user, "You slather the blue gunk over the [C], making it airtight.") - C.name = "pressure-resistant [C.name]" - C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - C.add_atom_colour("#000080", FIXED_COLOUR_PRIORITY) - C.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - C.cold_protection = C.body_parts_covered - C.clothing_flags |= STOPSPRESSUREDAMAGE - uses-- - if(!uses) - qdel(src) - -/obj/item/slimepotion/enhancer/max - name = "extract maximizer" - desc = "An extremely potent chemical mix that will maximize a slime extract's uses." - icon = 'icons/obj/chemical.dmi' - icon_state = "potpurple" - -/obj/item/slimepotion/lavaproof - name = "slime lavaproofing potion" - desc = "A strange, reddish goo said to repel lava as if it were water, without reducing flammability. Has two uses." - icon = 'icons/obj/chemical.dmi' - icon_state = "potred" - resistance_flags = LAVA_PROOF | FIRE_PROOF - var/uses = 2 - -/obj/item/slimepotion/lavaproof/afterattack(obj/item/C, mob/user, proximity) - . = ..() - if(!uses) - qdel(src) - return ..() - if(!proximity) - return ..() - if(!istype(C)) - to_chat(user, "You can't coat this with lavaproofing fluid!") - return ..() - to_chat(user, "You slather the red gunk over the [C], making it lavaproof.") - C.name = "lavaproof [C.name]" - C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - C.add_atom_colour("#800000", FIXED_COLOUR_PRIORITY) - C.resistance_flags |= LAVA_PROOF - if (istype(C, /obj/item/clothing)) - var/obj/item/clothing/CL = C - CL.clothing_flags |= LAVAPROTECT - uses-- - if(!uses) - qdel(src) - -/obj/item/slimepotion/lovepotion - name = "love potion" - desc = "A pink chemical mix thought to inspire feelings of love." - icon = 'icons/obj/chemical.dmi' - icon_state = "potpink" - -/obj/item/slimepotion/lovepotion/attack(mob/living/M, mob/user) - if(!isliving(M) || M.stat == DEAD) - to_chat(user, "The love potion only works on living things, sicko!") - return ..() - if(user == M) - to_chat(user, "You can't drink the love potion. What are you, a narcissist?") - return ..() - if(M.has_status_effect(STATUS_EFFECT_INLOVE)) - to_chat(user, "[M] is already lovestruck!") - return ..() - - M.visible_message("[user] starts to feed [M] a love potion!", - "[user] starts to feed you a love potion!") - - if(!do_after(user, 50, target = M)) - return - to_chat(user, "You feed [M] the love potion!") - to_chat(M, "You develop feelings for [user], and anyone [user.p_they()] like.") - if(M.mind) - M.mind.store_memory("You are in love with [user].") - M.faction |= "[REF(user)]" - M.apply_status_effect(STATUS_EFFECT_INLOVE, user) - qdel(src) - -/obj/item/slimepotion/peacepotion - name = "pacification potion" - desc = "A light pink solution of chemicals, smelling like liquid peace. And mercury salts." - icon = 'icons/obj/chemical.dmi' - icon_state = "potlightpink" - -/obj/item/slimepotion/peacepotion/attack(mob/living/M, mob/user) - if(!isliving(M) || M.stat == DEAD) - to_chat(user, "The pacification potion only works on the living.") - return ..() - if(M != user) - M.visible_message("[user] starts to feed [M] a pacification potion!", - "[user] starts to feed you a love potion!") - else - M.visible_message("[user] starts to drink the pacification potion!", - "You start to drink the pacification potion!") - - if(!do_after(user, 100, target = M)) - return - if(M != user) - to_chat(user, "You feed [M] the pacification potion!") - else - to_chat(user, "You drink the pacification potion!") - if(isanimal(M)) - M.add_trait(TRAIT_PACIFISM, MAGIC_TRAIT) - else if(iscarbon(M)) - var/mob/living/carbon/C = M - C.gain_trauma(/datum/brain_trauma/severe/pacifism, TRAUMA_RESILIENCE_SURGERY) - qdel(src) diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm new file mode 100644 index 0000000000..1a5c4c6800 --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -0,0 +1,310 @@ +/* +Chilling extracts: + Have a unique, primarily defensive effect when + filled with 10u plasma and activated in-hand. +*/ +/obj/item/slimecross/chilling + name = "chilling extract" + desc = "It's cold to the touch, as if frozen solid." + effect = "chilling" + container_type = INJECTABLE | DRAWABLE + icon_state = "chilling" +/obj/item/slimecross/chilling/Initialize() + . = ..() + create_reagents(10) + +/obj/item/slimecross/chilling/attack_self(mob/user) + if(!reagents.has_reagent("plasma",10)) + to_chat(user, "This extract needs to be full of plasma to activate!") + return + reagents.remove_reagent("plasma",10) + to_chat(user, "You squeeze the extract, and it absorbs the plasma!") + playsound(src, 'sound/effects/bubbles.ogg', 50, 1) + playsound(src, 'sound/effects/glassbr1.ogg', 50, 1) + do_effect(user) + +/obj/item/slimecross/chilling/proc/do_effect(mob/user) //If, for whatever reason, you don't want to delete the extract, don't do ..() + qdel(src) + return + +/obj/item/slimecross/chilling/grey + colour = "grey" + +/obj/item/slimecross/chilling/grey/do_effect(mob/user) + user.visible_message("[src] produces a few small, grey cubes") + for(var/i in 1 to 3) + new /obj/item/barriercube(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/orange + colour = "orange" + +/obj/item/slimecross/chilling/orange/do_effect(mob/user) + user.visible_message("[src] shatters, and lets out a jet of heat!") + for(var/turf/T in orange(get_turf(user),2)) + if(get_dist(get_turf(user), T) > 1) + new /obj/effect/hotspot(T) + ..() + +/obj/item/slimecross/chilling/purple + colour = "purple" + +/obj/item/slimecross/chilling/purple/do_effect(mob/user) + var/area/A = get_area(get_turf(user)) + if(A.outdoors) + to_chat(user, "[src] can't affect such a large area.") + return + user.visible_message("[src] shatters, and a healing aura fills the room briefly.") + for(var/mob/living/carbon/C in A) + C.reagents.add_reagent("regen_jelly",10) + ..() + +/obj/item/slimecross/chilling/blue + colour = "blue" + +/obj/item/slimecross/chilling/blue/do_effect(mob/user) + user.visible_message("[src] cracks, and spills out a liquid goo, which reforms into a mask!") + new /obj/item/clothing/mask/nobreath(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/metal + colour = "metal" + +/obj/item/slimecross/chilling/metal/do_effect(mob/user) + user.visible_message("[src] melts like quicksilver, and surrounds [user] in a wall!") + for(var/turf/T in orange(get_turf(user),1)) + if(get_dist(get_turf(user), T) > 0) + new /obj/effect/forcefield/slimewall(T) + ..() + +/obj/item/slimecross/chilling/yellow + colour = "yellow" + +/obj/item/slimecross/chilling/yellow/do_effect(mob/user) + var/area/A = get_area(get_turf(user)) + user.visible_message("[src] shatters, and a the air suddenly feels charged for a moment.") + for(var/obj/machinery/power/apc/C in A) + if(C.cell) + C.cell.charge = min(C.cell.charge + C.cell.maxcharge/2, C.cell.maxcharge) + ..() + +/obj/item/slimecross/chilling/darkpurple + colour = "dark purple" + +/obj/item/slimecross/chilling/darkpurple/do_effect(mob/user) + var/area/A = get_area(get_turf(user)) + if(A.outdoors) + to_chat(user, "[src] can't affect such a large area.") + return + var/filtered = FALSE + for(var/turf/open/T in A) + var/datum/gas_mixture/G = T.air + if(istype(G)) + G.assert_gas(/datum/gas/plasma) + G.gases[/datum/gas/plasma][MOLES] = 0 + filtered = TRUE + G.garbage_collect() + T.air_update_turf() + if(filtered) + user.visible_message("Cracks spread throughout [src], and some air is sucked in!") + else + user.visible_message("[src] cracks, but nothing happens.") + ..() + +/obj/item/slimecross/chilling/darkblue + colour = "dark blue" + +/obj/item/slimecross/chilling/darkblue/do_effect(mob/user) + if(isliving(user)) + user.visible_message("[src] freezes over [user]'s entire body!") + var/mob/living/M = user + M.apply_status_effect(/datum/status_effect/frozenstasis) + ..() + +/obj/item/slimecross/chilling/silver + colour = "silver" + +/obj/item/slimecross/chilling/silver/do_effect(mob/user) + user.visible_message("[src] crumbles into icy powder, leaving behind several emergency food supplies!") + var/amount = rand(5, 10) + for(var/i in 1 to amount) + new /obj/item/reagent_containers/food/snacks/rationpack(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/bluespace + colour = "bluespace" + var/list/allies = list() + var/active = FALSE + +/obj/item/slimecross/chilling/bluespace/afterattack(atom/target, mob/user, proximity) + if(!proximity || !isliving(target) || active) + return + if(target in allies) + allies -= target + to_chat(user, "You unlink [src] with [target].") + else + allies |= target + to_chat(user, "You link [src] with [target].") + return + +/obj/item/slimecross/chilling/bluespace/do_effect(mob/user) + if(allies.len <= 0) + to_chat(user, "[src] is not linked to anyone!") + return + to_chat(user, "You feel [src] pulse as it begins charging bluespace energies...") + active = TRUE + for(var/mob/living/M in allies) + var/datum/status_effect/slimerecall/S = M.apply_status_effect(/datum/status_effect/slimerecall) + S.target = user + if(do_after(user, 100, target=src)) + to_chat(user, "[src] shatters as it tears a hole in reality, snatching the linked individuals from the void!") + for(var/mob/living/M in allies) + var/datum/status_effect/slimerecall/S = M.has_status_effect(/datum/status_effect/slimerecall) + M.remove_status_effect(S) + else + to_chat(user, "[src] falls dark, dissolving into nothing as the energies fade away.") + for(var/mob/living/M in allies) + var/datum/status_effect/slimerecall/S = M.has_status_effect(/datum/status_effect/slimerecall) + if(istype(S)) + S.interrupted = TRUE + M.remove_status_effect(S) + ..() + +/obj/item/slimecross/chilling/sepia + colour = "sepia" + var/list/allies = list() + +/obj/item/slimecross/chilling/sepia/afterattack(atom/target, mob/user, proximity) + if(!proximity || !isliving(target)) + return + if(target in allies) + allies -= target + to_chat(user, "You unlink [src] with [target].") + else + allies |= target + to_chat(user, "You link [src] with [target].") + return + +/obj/item/slimecross/chilling/sepia/do_effect(mob/user) + user.visible_message("[src] shatters, freezing time itself!") + new /obj/effect/timestop(get_turf(user), 2, 300, allies) + +/obj/item/slimecross/chilling/cerulean + colour = "cerulean" + +/obj/item/slimecross/chilling/cerulean/do_effect(mob/user) + if(isliving(user)) + user.visible_message("[src] creaks and shifts into a clone of [user]!") + var/mob/living/M = user + M.apply_status_effect(/datum/status_effect/slime_clone) + ..() + +/obj/item/slimecross/chilling/pyrite + colour = "pyrite" + +/obj/item/slimecross/chilling/pyrite/do_effect(mob/user) + user.visible_message("[src] crystallizes into a pair of spectacles!") + new /obj/item/clothing/glasses/prism_glasses(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/red + colour = "red" + +/obj/item/slimecross/chilling/red/do_effect(mob/user) + var/slimesfound = FALSE + for(var/mob/living/simple_animal/slime/S in view(get_turf(user), 7)) + slimesfound = TRUE + S.docile = TRUE + if(slimesfound) + user.visible_message("[src] lets out a peaceful ring as it shatters, and nearby slimes seem calm.") + else + user.visible_message("[src] lets out a peaceful ring as it shatters, but nothing happens...") + ..() + +/obj/item/slimecross/chilling/green + colour = "green" + +/obj/item/slimecross/chilling/green/do_effect(mob/user) + var/which_hand = "l_hand" + if(!(user.active_hand_index % 2)) + which_hand = "r_hand" + var/mob/living/L = user + if(!istype(user)) + return + var/obj/item/held = L.get_active_held_item() //This should be itself, but just in case... + L.dropItemToGround(held) + var/obj/item/gun/magic/bloodchill/gun = new(user) + if(!L.put_in_hands(gun)) + qdel(gun) + user.visible_message("[src] flash-freezes [user]'s arm, cracking the flesh horribly!") + else + user.visible_message("[src] chills and snaps off the front of the bone on [user]'s arm, leaving behind a strange, gun-like structure!") + user.emote("scream") + L.apply_damage(30,BURN,which_hand) + ..() + +/obj/item/slimecross/chilling/pink + colour = "pink" + +/obj/item/slimecross/chilling/pink/do_effect(mob/user) + user.visible_message("[src] cracks like an egg, and an adorable puppy comes tumbling out!") + new /mob/living/simple_animal/pet/dog/corgi/puppy/slime(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/gold + colour = "gold" + +/obj/item/slimecross/chilling/gold/do_effect(mob/user) + user.visible_message("[src] lets off golden light as it melts and reforms into an egg-like device!") + new /obj/item/capturedevice(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/oil + colour = "oil" + +/obj/item/slimecross/chilling/oil/do_effect(mob/user) + user.visible_message("[src] begins to shake with muted intensity!") + addtimer(CALLBACK(src, .proc/boom), 50) + +/obj/item/slimecross/chilling/oil/proc/boom() + explosion(get_turf(src), -1, -1, 3, 10) //Large radius, but mostly light damage. + qdel(src) + +/obj/item/slimecross/chilling/black + colour = "black" + +/obj/item/slimecross/chilling/black/do_effect(mob/user) + if(ishuman(user)) + user.visible_message("[src] crystallizes along [user]'s skin, turning into metallic scales!") + var/mob/living/carbon/human/H = user + H.set_species(/datum/species/golem/random) + ..() + +/obj/item/slimecross/chilling/lightpink + colour = "light pink" + +/obj/item/slimecross/chilling/lightpink/do_effect(mob/user) + user.visible_message("[src] blooms into a beautiful flower!") + new /obj/item/clothing/head/peaceflower(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/adamantine + colour = "adamantine" + +/obj/item/slimecross/chilling/adamantine/do_effect(mob/user) + user.visible_message("[src] creaks and breaks as it shifts into a heavy set of armor!") + new /obj/item/clothing/suit/armor/heavy/adamantine(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/rainbow + colour = "rainbow" + +/obj/item/slimecross/chilling/rainbow/do_effect(mob/user) + var/area/area = get_area(user) + if(area.outdoors) + to_chat(user, "[src] can't affect such a large area.") + return + user.visible_message("[src] reflects an array of dazzling colors and light, energy rushing to nearby doors!") + for(var/obj/machinery/door/airlock/door in area) + new /obj/effect/forcefield/slimewall/rainbow(door.loc) + return ..() diff --git a/code/modules/research/xenobiology/crossbreeding/consuming.dm b/code/modules/research/xenobiology/crossbreeding/consuming.dm index b51a7b2553..b1790dead0 100644 --- a/code/modules/research/xenobiology/crossbreeding/consuming.dm +++ b/code/modules/research/xenobiology/crossbreeding/consuming.dm @@ -70,7 +70,10 @@ Consuming extracts: fed = TRUE M.visible_message("[user] forces [M] to eat [src]!", "[user] forces you to eat [src].") if(fed) - to_chat(M, "Tastes like [taste].") + var/mob/living/carbon/human/H = M + + if(!istype(H) || !H.has_trait(TRAIT_AGEUSIA)) + to_chat(M, "Tastes like [taste].") playsound(get_turf(M), 'sound/items/eatfood.ogg', 20, 1) if(nutrition) M.reagents.add_reagent("nutriment",nutrition) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 798560b43f..1f326120b1 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -840,7 +840,7 @@ return if(isitem(C)) var/obj/item/I = C - if(I.slowdown <= 0) + if(I.slowdown <= 0 || I.obj_flags & IMMUTABLE_SLOW) to_chat(user, "The [C] can't be made any faster!") return ..() I.slowdown = 0 diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index 4bbe27f09d..627d2bc94c 100644 Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index dc55d8c3a5..6c637585e8 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi index 5198f3bda9..1bb231e79f 100644 Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi index afbd091d13..c7a1d54b8d 100644 Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index d51b938c6e..0df012dce4 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/pets.dmi b/icons/mob/pets.dmi index d0983a8fab..a9e8c5fcb3 100644 Binary files a/icons/mob/pets.dmi and b/icons/mob/pets.dmi differ diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi index 8142e03498..d60fe75e95 100644 Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 749da877e9..257c4b29a7 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 12dd04004b..108d55399b 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 7c2729758c..22b9c0001e 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index a053eab792..81e6528d64 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/icons/obj/slimecrossing.dmi b/icons/obj/slimecrossing.dmi index f187e77063..6d74116a18 100644 Binary files a/icons/obj/slimecrossing.dmi and b/icons/obj/slimecrossing.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 0ae367c188..9c25008fd8 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2516,10 +2516,16 @@ #include "code\modules\research\techweb\all_nodes.dm" #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" -#include "code\modules\research\xenobiology\crossbreeding\_corecross.dm" +#include "code\modules\research\xenobiology\crossbreeding\__corecross.dm" +#include "code\modules\research\xenobiology\crossbreeding\_clothing.dm" +#include "code\modules\research\xenobiology\crossbreeding\_misc.dm" +#include "code\modules\research\xenobiology\crossbreeding\_mobs.dm" +#include "code\modules\research\xenobiology\crossbreeding\_potions.dm" #include "code\modules\research\xenobiology\crossbreeding\_status_effects.dm" +#include "code\modules\research\xenobiology\crossbreeding\_weapons.dm" #include "code\modules\research\xenobiology\crossbreeding\burning.dm" #include "code\modules\research\xenobiology\crossbreeding\charged.dm" +#include "code\modules\research\xenobiology\crossbreeding\chilling.dm" #include "code\modules\research\xenobiology\crossbreeding\consuming.dm" #include "code\modules\research\xenobiology\crossbreeding\industrial.dm" #include "code\modules\research\xenobiology\crossbreeding\prismatic.dm"