Merge remote-tracking branch 'origin/master' into donator_grouping

This commit is contained in:
kevinz000
2019-08-15 14:40:44 -07:00
616 changed files with 20136 additions and 9207 deletions
@@ -5,20 +5,22 @@
icon = 'modular_citadel/icons/obj/genitals/breasts.dmi'
zone = "chest"
slot = "breasts"
size = BREASTS_SIZE_DEF
w_class = 3
size = BREASTS_SIZE_DEF //SHOULD BE A LETTER, starts as a number...???
var/cached_size = null //for enlargement SHOULD BE A NUMBER
var/prev_size //For flavour texts SHOULD BE A LETTER
//var/breast_sizes = list ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "huge", "flat")
var/breast_values = list ("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0)
var/statuscheck = FALSE
fluid_id = "milk"
var/amount = 2
producing = TRUE
shape = "pair"
shape = "Pair"
can_masturbate_with = TRUE
masturbation_verb = "massage"
can_climax = TRUE
fluid_transfer_factor = 0.5
/obj/item/organ/genital/breasts/Initialize()
. = ..()
reagents.add_reagent(fluid_id, fluid_max_volume)
/obj/item/organ/genital/breasts/on_life()
if(QDELETED(src))
return
@@ -26,6 +28,14 @@
return
reagents.maximum_volume = fluid_max_volume
if(fluid_id && producing)
if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
fluid_rate = 0.1
else
fluid_rate = CUM_RATE
if(reagents.total_volume >= 5)
fluid_mult = 0.5
else
fluid_mult = 1
generate_milk()
/obj/item/organ/genital/breasts/proc/generate_milk()
@@ -45,10 +55,15 @@
desc = "You see three sets of breasts, running from their chest to their belly."
else
desc = "You see some breasts, they seem to be quite exotic."
if (size)
desc += " You estimate that they're [uppertext(size)]-cups."
else
desc += " You wouldn't measure them in cup sizes."
if(cached_size > 16)
desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(cached_size)]cm in diameter."
else if (!isnum(size))
if (size == "flat")
desc += " They're very small and flatchested, however."
else
desc += " You estimate that they're [uppertext(size)]-cups."
//string = "breasts_[lowertext(shape)]_[size]-s"
if(producing && aroused_state)
desc += " They're leaking [fluid_id]."
var/string
@@ -65,3 +80,57 @@
var/mob/living/carbon/human/H = owner
icon_state = sanitize_text(string)
H.update_genitals()
icon_state = sanitize_text(string)
//Allows breasts to grow and change size, with sprite changes too.
//maximum wah
//Comical sizes slow you down in movement and actions.
//Rediculous sizes makes you more cumbersome.
//this is far too lewd wah
/obj/item/organ/genital/breasts/update_size()//wah
if(!ishuman(owner) || !owner)
return
if(cached_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
to_chat(owner, "<span class='warning'>You feel your breasts shrinking away from your body as your chest flattens out.</b></span>")
src.Remove(owner)
switch(round(cached_size))
if(0) //If flatchested
size = "flat"
if(owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
owner.remove_status_effect(/datum/status_effect/chem/breast_enlarger)
statuscheck = FALSE
if(1 to 8) //If modest size
size = breast_values[round(cached_size)]
if(owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
owner.remove_status_effect(/datum/status_effect/chem/breast_enlarger)
statuscheck = FALSE
if(9 to 15) //If massive
size = breast_values[round(cached_size)]
if(!owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
owner.apply_status_effect(/datum/status_effect/chem/breast_enlarger)
statuscheck = TRUE
if(16 to INFINITY) //if Rediculous
size = cached_size
if(round(cached_size) < 16)//Because byond doesn't count from 0, I have to do this.
if (prev_size == 0)
prev_size = "flat"
if(size == 0)//Bloody byond with it's counting from 1
size = "flat"
if(isnum(prev_size))
prev_size = breast_values[prev_size]
if (breast_values[size] > breast_values[prev_size])
to_chat(owner, "<span class='warning'>Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.</b></span>")
var/mob/living/carbon/human/H = owner
H.Force_update_genitals()
else if ((breast_values[size] < breast_values[prev_size]) && (breast_values[size] > 0.5))
to_chat(owner, "<span class='warning'>Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.</b></span>")
var/mob/living/carbon/human/H = owner
H.Force_update_genitals()
prev_size = size
else if (cached_size >= 16)
size = "huge"
@@ -1,7 +1,7 @@
/obj/item/organ/genital
color = "#fcccb3"
w_class = WEIGHT_CLASS_NORMAL
var/shape = "human"
var/shape = "Human" //Changed to be uppercase, let me know if this breaks everything..!!
var/sensitivity = AROUSAL_START_VALUE
var/list/genital_flags = list()
var/can_masturbate_with = FALSE
@@ -10,7 +10,7 @@
var/fluid_transfer_factor = 0.0 //How much would a partner get in them if they climax using this?
var/size = 2 //can vary between num or text, just used in icon_state strings
var/fluid_id = null
var/fluid_max_volume = 50
var/fluid_max_volume = 15
var/fluid_efficiency = 1
var/fluid_rate = 1
var/fluid_mult = 1
@@ -172,6 +172,8 @@
P.length = dna.features["cock_length"]
P.girth_ratio = dna.features["cock_girth_ratio"]
P.shape = dna.features["cock_shape"]
P.prev_length = P.length
P.cached_length = P.length
P.update()
/mob/living/carbon/human/proc/give_balls()
@@ -214,8 +216,21 @@
else
B.color = "#[dna.features["breasts_color"]]"
B.size = dna.features["breasts_size"]
if(!isnum(B.size))
if(B.size == "flat")
B.cached_size = 0
B.prev_size = 0
else if (B.cached_size == "huge")
B.prev_size = "huge"
else
B.cached_size = B.breast_values[B.size]
B.prev_size = B.size
else
B.cached_size = B.size
B.prev_size = B.size
B.shape = dna.features["breasts_shape"]
B.fluid_id = dna.features["breasts_fluid"]
B.producing = dna.features["breasts_producing"]
B.update()
@@ -256,8 +271,8 @@
switch(layer)
if(GENITALS_BEHIND_LAYER)
return "BEHIND"
if(GENITALS_ADJ_LAYER)
return "ADJ"
/*if(GENITALS_ADJ_LAYER)
return "ADJ"*/
if(GENITALS_FRONT_LAYER)
return "FRONT"
@@ -279,27 +294,65 @@
if(src && !QDELETED(src))
dna.species.handle_genitals(src)
/datum/species/proc/handle_genitals(mob/living/carbon/human/H)
//fermichem procs
/mob/living/carbon/human/proc/Force_update_genitals(mob/living/carbon/human/H) //called in fermiChem
dna.species.handle_genitals(src)//should work.
//dna.species.handle_breasts(src)
//Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours.
/mob/living/carbon/human/proc/emergent_genital_call()
var/organCheck = FALSE
var/breastCheck = FALSE
var/willyCheck = FALSE
if(!canbearoused)
ADD_TRAIT(src, TRAIT_PHARMA, "pharma")//Prefs prevent unwanted organs.
return
for(var/obj/item/organ/O in internal_organs)
if(istype(O, /obj/item/organ/genital))
organCheck = TRUE
if(/obj/item/organ/genital/penis)
//dna.features["has_cock"] = TRUE
willyCheck = TRUE
if(/obj/item/organ/genital/breasts)
//dna.features["has_breasts"] = TRUE//Goddamnit get in there.
breastCheck = TRUE
if(organCheck == FALSE)
if(ishuman(src) && dna.species.id == "human")
dna.features["genitals_use_skintone"] = TRUE
dna.species.use_skintones = TRUE
if(MUTCOLORS)
if(src.dna.species.fixed_mut_color)
dna.features["cock_color"] = "[src.dna.species.fixed_mut_color]"
dna.features["breasts_color"] = "[src.dna.species.fixed_mut_color]"
return
//So people who haven't set stuff up don't get rainbow surprises.
dna.features["cock_color"] = "[dna.features["mcolor"]]"
dna.features["breasts_color"] = "[dna.features["mcolor"]]"
else //If there's a new organ, make it the same colour.
if(breastCheck == FALSE)
dna.features["breasts_color"] = dna.features["cock_color"]
else if (willyCheck == FALSE)
dna.features["cock_color"] = dna.features["breasts_color"]
return
/datum/species/proc/handle_genitals(mob/living/carbon/human/H)//more like handle sadness
if(!H)//no args
CRASH("H = null")
if(!LAZYLEN(H.internal_organs))//if they have no organs, we're done
return
if(NOGENITALS in species_traits)//golems and such
if((NOGENITALS in species_traits) && (H.genital_override = FALSE))//golems and such - things that shouldn't
return
if(HAS_TRAIT(H, TRAIT_HUSK))
return
var/list/genitals_to_add = list()
var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_ADJ_LAYER, GENITALS_FRONT_LAYER)
var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER) //GENITALS_ADJ_LAYER removed
var/list/standing = list()
var/size
var/aroused_state
for(var/L in relevant_layers) //Less hardcode
H.remove_overlay(L)
//start scanning for genitals
//var/list/worn_stuff = H.get_equipped_items()//cache this list so it's not built again
for(var/obj/item/organ/O in H.internal_organs)
if(isgenital(O))
var/obj/item/organ/genital/G = O
@@ -308,7 +361,6 @@
if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes
genitals_to_add += H.getorganslot(G.slot)
//Now we added all genitals that aren't internal and should be rendered
//start applying overlays
for(var/layer in relevant_layers)
var/layertext = genitals_layertext(layer)
@@ -326,6 +378,9 @@
if(/obj/item/organ/genital/breasts)
S = GLOB.breasts_shapes_list[G.shape]
if(!S || S.icon_state == "none")
continue
@@ -31,6 +31,19 @@
icon_state = "tapered"
name = "Tapered"
/datum/sprite_accessory/penis/tentacle
icon_state = "tentacle"
name = "Tentacled"
/datum/sprite_accessory/penis/hemi
icon_state = "hemi"
name = "Hemi"
/datum/sprite_accessory/penis/hemiknot
icon_state = "hemiknot"
name = "Knotted Hemi"
////////////////////////
// Taur cocks go here //
////////////////////////
@@ -111,6 +124,10 @@
icon_state = "furred"
name = "Furred"
/datum/sprite_accessory/vagina/gaping
icon_state = "gaping"
name = "Gaping"
//BREASTS BE HERE
/datum/sprite_accessory/breasts
icon = 'modular_citadel/icons/obj/genitals/breasts_onmob.dmi'
@@ -12,28 +12,61 @@
size = 2 //arbitrary value derived from length and girth for sprites.
var/length = 6 //inches
var/cached_length //used to detect a change in length
var/girth = 0
var/girth = 4.38
var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm
var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF
var/list/dickflags = list()
var/list/knotted_types = list("knotted", "barbed, knotted")
var/prev_length = 6 //really should be renamed to prev_length
/obj/item/organ/genital/penis/Initialize()
. = ..()
/* I hate genitals.*/
/obj/item/organ/genital/penis/update_size()
if(length == cached_length)
var/mob/living/carbon/human/o = owner
if(!ishuman(o) || !o)
return
switch(length)
if(-INFINITY to 5)
if(cached_length < 0)//I don't actually know what round() does to negative numbers, so to be safe!!
var/obj/item/organ/genital/penis/P = o.getorganslot("penis")
to_chat(o, "<span class='warning'>You feel your tallywacker shrinking away from your body as your groin flattens out!</b></span>")
P.Remove(o)
switch(round(cached_length))
if(0 to 4) //If modest size
length = cached_length
size = 1
if(5 to 9)
if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
if(5 to 10) //If modest size
length = cached_length
size = 2
if(15 to INFINITY)
size = 3//no new sprites for anything larger yet
/* if(9 to 15)
if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
if(11 to 20) //If massive
length = cached_length
size = 3
if(15 to INFINITY)
size = 3*/
girth = (length * girth_ratio)
cached_length = length
if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
if(21 to 35) //If massive and due for large effects
length = cached_length
size = 3
if(!owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
o.apply_status_effect(/datum/status_effect/chem/penis_enlarger)
if(36 to INFINITY) //If comical
length = cached_length
size = 4 //no new sprites for anything larger yet
if(!owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
o.apply_status_effect(/datum/status_effect/chem/penis_enlarger)
if (round(length) > round(prev_length))
to_chat(o, "<span class='warning'>Your [pick(GLOB.gentlemans_organ_names)] [pick("swells up to", "flourishes into", "expands into", "bursts forth into", "grows eagerly into", "amplifys into")] a [uppertext(round(length))] inch penis.</b></span>")
else if ((round(length) < round(prev_length)) && (length > 0.5))
to_chat(o, "<span class='warning'>Your [pick(GLOB.gentlemans_organ_names)] [pick("shrinks down to", "decreases into", "diminishes into", "deflates into", "shrivels regretfully into", "contracts into")] a [uppertext(round(length))] inch penis.</b></span>")
prev_length = length
icon_state = sanitize_text("penis_[shape]_[size]")
girth = (length * girth_ratio)//Is it just me or is this ludicous, why not make it exponentially decay?
//I have no idea on how to update sprites and I hate it
/obj/item/organ/genital/penis/update_appearance()
var/string
@@ -16,14 +16,18 @@
can_climax = TRUE
var/sent_full_message = TRUE //defaults to 1 since they're full to start
/obj/item/organ/genital/testicles/Initialize()
. = ..()
reagents.add_reagent(fluid_id, fluid_max_volume)
/obj/item/organ/genital/testicles/on_life()
if(QDELETED(src))
return
if(reagents && producing)
if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
fluid_rate = 0.1
else
fluid_rate = CUM_RATE
if(reagents.total_volume >= 5)
fluid_mult = 0.5
else
fluid_mult = 1
generate_cum()
/obj/item/organ/genital/testicles/proc/generate_cum()
@@ -9,14 +9,18 @@
fluid_id = "femcum"
producing = TRUE
/obj/item/organ/genital/womb/Initialize()
. = ..()
reagents.add_reagent(fluid_id, fluid_max_volume)
/obj/item/organ/genital/womb/on_life()
if(QDELETED(src))
return
if(reagents && producing)
if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
fluid_rate = 0.1
else
fluid_rate = CUM_RATE
if(reagents.total_volume >= 5)
fluid_mult = 0.5
else
fluid_mult = 1
generate_femcum()
/obj/item/organ/genital/womb/proc/generate_femcum()
@@ -49,7 +49,7 @@
/datum/outfit/lavaknight/captain
name ="Cydonian Knight Captain"
l_pocket = /obj/item/twohanded/hypereutactic
l_pocket = /obj/item/twohanded/dualsaber/hypereutactic
/datum/outfit/lavaknight/captain/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
if(visualsOnly)
@@ -220,13 +220,13 @@
/datum/gear/torisword
name = "Rainbow Zweihander"
category = SLOT_IN_BACKPACK
path = /obj/item/twohanded/hypereutactic/toy/rainbow
path = /obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow
ckeywhitelist = list("annoymous35")
/datum/gear/darksabre
name = "Dark Sabre"
category = SLOT_IN_BACKPACK
path = /obj/item/toy/sword/darksabre
path = /obj/item/toy/darksabre
ckeywhitelist = list("inferno707")
datum/gear/darksabresheath
@@ -434,3 +434,17 @@ datum/gear/darksabresheath
category = SLOT_NECK
path = /obj/item/bedsheet/captain
ckeywhitelist = list("tikibomb")
/datum/gear/borgplush
name = "Robot Plush"
category = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/borgplushie
ckeywhitelist = list("nicholaiavenicci")
/datum/gear/donorberet
name = "Atmos Beret"
category = SLOT_HEAD
path = /obj/item/clothing/head/blueberet
ckeywhitelist = list("foxystalin")
@@ -23,11 +23,6 @@
category = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/lampplushie
/datum/gear/plushrng
name = "Random plushie"
category = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/random
/datum/gear/tennis
name = "Classic Tennis Ball"
category = SLOT_IN_BACKPACK
@@ -84,8 +79,24 @@
path = /obj/item/toy/katana
cost = 3
//datum/gear/lumeyes
// name = "Luminescent eye auto surgeon"
// category = SLOT_IN_BACKPACK
// path = /obj/item/autosurgeon/gloweyes
// cost = 4
/datum/gear/box
name = "Spare box"
category = SLOT_IN_BACKPACK
path = /obj/item/storage/box
cost = 2
/datum/gear/crowbar
name = "Pocket Crowbar"
category = SLOT_IN_BACKPACK
path = /obj/item/crowbar
cost = 2
/datum/gear/tapeplayer
name = "Taperecorder"
category = SLOT_IN_BACKPACK
path = /obj/item/taperecorder
/datum/gear/tape
name = "Spare cassette tape"
category = SLOT_IN_BACKPACK
path = /obj/item/tape/random
@@ -15,6 +15,7 @@
var/arousable = TRUE
var/widescreenpref = TRUE
var/autostand = TRUE
var/lewdchem = TRUE
//vore prefs
var/toggleeatingnoise = TRUE
@@ -53,5 +54,6 @@ datum/preferences/copy_to(mob/living/carbon/human/character, icon_updates = 1)
character.give_genitals(TRUE)
character.flavor_text = features["flavor_text"] //Let's update their flavor_text at least initially
character.canbearoused = arousable
character.client?.prefs.lewdchem = lewdchem
if(icon_updates)
character.update_genitals()
@@ -65,6 +65,7 @@
WRITE_FILE(S["feature_breasts_shape"], features["breasts_shape"])
WRITE_FILE(S["feature_breasts_color"], features["breasts_color"])
WRITE_FILE(S["feature_breasts_fluid"], features["breasts_fluid"])
WRITE_FILE(S["feature_breasts_producing"], features["breasts_producing"])
//vagina features
WRITE_FILE(S["feature_has_vag"], features["has_vag"])
WRITE_FILE(S["feature_vag_shape"], features["vag_shape"])
@@ -5,7 +5,8 @@
*//////////////////////////////////////////////////////////////////////////////////
// <3 Nienhaus && Joan.
// I made the Voy and DS9 stuff tho. - Poojy
// Armor lists for even Heads of Staff is Nulled out do round start armor as well most armor going onto the suit itself rather then a armor slot - Trilby
///////////////////////////////////////////////////////////////////////////////////
/obj/item/clothing/under/rank/trek
@@ -22,7 +23,7 @@
desc = "The uniform worn by command officers in the mid 2260s."
icon_state = "trek_command"
item_state = "trek_command"
armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 10, "rad" = 10, "fire" = 0, "acid" = 0) // Considering only staff heads get to pick it
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/under/rank/trek/engsec
name = "Operations Uniform"
@@ -104,7 +105,7 @@
/obj/item/reagent_containers/glass/bottle/vial,/obj/item/reagent_containers/glass/beaker,
/obj/item/reagent_containers/pill,/obj/item/storage/pill_bottle, /obj/item/restraints/handcuffs,/obj/item/hypospray
)
armor = list("melee" = 10, "bullet" = 5, "laser" = 5,"energy" = 5, "bomb" = 5, "bio" = 5, "rad" = 10, "fire" = 10, "acid" = 0)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/suit/storage/trek/ds9/admiral // Only for adminuz
name = "Admiral Overcoat"
@@ -135,7 +136,6 @@
/obj/item/clothing/suit/storage/fluff/fedcoat
name = "Federation Uniform Jacket"
desc = "A uniform jacket from the United Federation. Set phasers to awesome."
icon = 'modular_citadel/icons/obj/clothing/trek_item_icon.dmi'
alternate_worn_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi'
icon_state = "fedcoat"
@@ -160,7 +160,7 @@
/obj/item/reagent_containers/glass/beaker,
/obj/item/storage/pill_bottle,
/obj/item/taperecorder)
armor = list("melee" = 10, "bullet" = 5, "laser" = 5,"energy" = 5, "bomb" = 5, "bio" = 5, "rad" = 10, "fire" = 10, "acid" = 0)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
var/unbuttoned = 0
verb/toggle()
@@ -214,7 +214,7 @@
/obj/item/reagent_containers/glass/bottle/vial,/obj/item/reagent_containers/glass/beaker,
/obj/item/reagent_containers/pill,/obj/item/storage/pill_bottle, /obj/item/restraints/handcuffs,/obj/item/hypospray
)
armor = list("melee" = 10, "bullet" = 5, "laser" = 5,"energy" = 5, "bomb" = 5, "bio" = 5, "rad" = 10, "fire" = 10, "acid" = 0)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
//Variants
/obj/item/clothing/suit/storage/fluff/modernfedcoat/medsci
@@ -231,6 +231,7 @@
/obj/item/clothing/head/caphat/formal/fedcover
name = "Federation Officer's Cap"
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
desc = "An officer's cap that demands discipline from the one who wears it."
icon = 'modular_citadel/icons/obj/clothing/trek_item_icon.dmi'
icon_state = "fedcapofficer"
@@ -5,26 +5,6 @@
*//////////////////////////////////////////////////////////////////////////////////
/obj/item/clothing/under/rank/security/skirt
name = "security skirt"
desc = "A tactical security skirt for officers complete with Nanotrasen belt buckle."
icon = 'modular_citadel/icons/obj/clothing/cit_clothes.dmi'
icon_state = "secskirt"
alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
item_state = "r_suit"
item_color = "secskirt"
body_parts_covered = CHEST|GROIN|ARMS
/obj/item/clothing/under/rank/head_of_security/skirt
name = "head of security's skirt"
desc = "A security skirt decorated for those few with the dedication to achieve the position of Head of Security."
icon = 'modular_citadel/icons/obj/clothing/cit_clothes.dmi'
icon_state = "hosskirt"
alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
item_state = "gy_suit"
item_color = "hosskirt"
body_parts_covered = CHEST|GROIN|ARMS
/obj/item/clothing/under/corporateuniform
name = "corporate uniform"
desc = "A comfortable, tight fitting jumpsuit made of premium materials. Not space-proof."
@@ -49,7 +49,7 @@
item_color = "steele"
medaltype = "medal-silver"
/obj/item/toy/sword/darksabre
/obj/item/toy/darksabre
name = "Kiara's Sabre"
desc = "This blade looks as dangerous as its owner."
icon = 'icons/obj/custom.dmi'
@@ -58,9 +58,13 @@
item_state = "darksabre"
lefthand_file = 'modular_citadel/icons/mob/inhands/stunsword_left.dmi'
righthand_file = 'modular_citadel/icons/mob/inhands/stunsword_right.dmi'
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("attacked", "struck", "hit")
/obj/item/toy/darksabre/get_belt_overlay()
return mutable_appearance('icons/obj/custom.dmi', "darksheath-darksabre")
/obj/item/toy/darksabre/get_worn_belt_overlay(icon_file)
return mutable_appearance(icon_file, "darksheath-darksabre")
/obj/item/storage/belt/sabre/darksabre
name = "Ornate Sheathe"
@@ -69,32 +73,8 @@
alternate_worn_icon = 'icons/mob/custom_w.dmi'
icon_state = "darksheath"
item_state = "darksheath"
w_class = WEIGHT_CLASS_BULKY
/obj/item/storage/belt/sabre/darksabre/ComponentInitialize()
. = ..()
GET_COMPONENT(STR, /datum/component/storage)
STR.max_items = 1
STR.rustle_sound = FALSE
STR.max_w_class = WEIGHT_CLASS_BULKY
STR.can_hold = typecacheof(list(
/obj/item/toy/sword/darksabre
))
/obj/item/storage/belt/sabre/darksabre/update_icon()
icon_state = "darksheath"
item_state = "darksheath"
if(contents.len)
icon_state += "-darksabre"
item_state += "-darksabre"
if(loc && isliving(loc))
var/mob/living/L = loc
L.regenerate_icons()
..()
/obj/item/storage/belt/sabre/darksabre/PopulateContents()
new /obj/item/toy/sword/darksabre(src)
update_icon()
fitting_swords = list(/obj/item/toy/darksabre)
starting_sword = /obj/item/toy/darksabre
/obj/item/clothing/suit/armor/vest/darkcarapace
name = "Dark Armor"
@@ -528,3 +508,11 @@
icon = 'icons/obj/custom.dmi'
alternate_worn_icon = 'icons/mob/custom_w.dmi'
mutantrace_variation = NO_MUTANTRACE_VARIATION
/obj/item/clothing/head/blueberet
name = "Atmos Beret"
desc = "A fitted beret designed to be worn by Atmos Techs."
icon_state = "blueberet"
item_state = "blueberet"
icon = 'icons/obj/custom.dmi'
alternate_worn_icon = 'icons/mob/custom_w.dmi'
@@ -4,7 +4,6 @@
/datum/job/hop
minimal_player_age = 20
head_announce = list("Service")
exp_type_department = EXP_TYPE_SERVICE
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
@@ -185,22 +185,6 @@
emote_type = EMOTE_AUDIBLE
restraint_check = TRUE
/datum/emote/living/dab/run_emote(mob/living/user, params)
if (ishuman(user))
var/def_zone = BODY_ZONE_CHEST
var/luck = (rand(1,100))
if(luck >= 65)
user.adjustStaminaLoss(70)
if(luck >= 80)
def_zone = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
user.apply_damage(20, BRUTE, def_zone)
if(luck >= 95)
user.adjustBrainLoss(100)
. = ..()
/datum/emote/living/mothsqueak
key = "msqueak"
key_third_person = "lets out a tiny squeak"
@@ -80,10 +80,23 @@
else
target.Move(target_shove_turf, shove_dir)
if(get_turf(target) == target_oldturf)
target_table = locate(/obj/structure/table) in target_shove_turf.contents
shove_blocked = TRUE
if(target_shove_turf.density)
shove_blocked = TRUE
else
var/thoushallnotpass = FALSE
for(var/obj/O in target_shove_turf)
if(istype(O, /obj/structure/table))
target_table = O
else if(!O.CanPass(src, target_shove_turf))
shove_blocked = TRUE
thoushallnotpass = TRUE
if(thoushallnotpass)
target_table = null
if(shove_blocked && !target.is_shove_knockdown_blocked())
if(target.is_shove_knockdown_blocked())
return
if(shove_blocked || target_table)
var/directional_blocked = FALSE
if(shove_dir in GLOB.cardinals) //Directional checks to make sure that we're not shoving through a windoor or something like that
var/target_turf = get_turf(target)
@@ -15,7 +15,6 @@
say_mod = "says"
hair_color = "mutcolor"
hair_alpha = 160 //a notch brighter so it blends better.
liked_food = MEAT
coldmod = 3
heatmod = 1
burnmod = 1
@@ -1,10 +0,0 @@
/mob/living/Knockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg) //Can't go below remaining duration
if(((status_flags & CANKNOCKDOWN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE)) || ignore_canknockdown)
if(absorb_stun(isnull(override_hardstun)? amount : override_hardstun, ignore_canknockdown))
return
var/datum/status_effect/incapacitating/knockdown/K = IsKnockdown()
if(K)
K.duration = max(world.time + (isnull(override_hardstun)? amount : override_hardstun), K.duration)
else if((amount || override_hardstun) > 0)
K = apply_status_effect(STATUS_EFFECT_KNOCKDOWN, amount, updating, override_hardstun, override_stamdmg)
return K
@@ -9,13 +9,3 @@
return 0
else
return ..()
/obj/item/gun/proc/getinaccuracy(mob/living/user)
if(!iscarbon(user))
return 0
else
var/mob/living/carbon/holdingdude = user
if(istype(holdingdude) && holdingdude.combatmode)
return max((holdingdude.lastdirchange + weapon_weight * 25) - world.time,0)
else
return weapon_weight * 25
@@ -1,117 +0,0 @@
//////Flechette Launcher//////
///projectiles///
/obj/item/projectile/bullet/cflechetteap //shreds armor
name = "flechette (armor piercing)"
damage = 8
armour_penetration = 80
/obj/item/projectile/bullet/cflechettes //shreds flesh and forces bleeding
name = "flechette (serrated)"
damage = 15
dismemberment = 10
armour_penetration = -80
/obj/item/projectile/bullet/cflechettes/on_hit(atom/target, blocked = FALSE)
if((blocked != 100) && iscarbon(target))
var/mob/living/carbon/C = target
C.bleed(10)
return ..()
///ammo casings (CASELESS AMMO CASINGS WOOOOOOOO)///
/obj/item/ammo_casing/caseless/flechetteap
name = "flechette (armor piercing)"
desc = "A flechette made with a tungsten alloy."
projectile_type = /obj/item/projectile/bullet/cflechetteap
caliber = "flechette"
throwforce = 1
throw_speed = 3
/obj/item/ammo_casing/caseless/flechettes
name = "flechette (serrated)"
desc = "A serrated flechette made of a special alloy intended to deform drastically upon penetration of human flesh."
projectile_type = /obj/item/projectile/bullet/cflechettes
caliber = "flechette"
throwforce = 2
throw_speed = 3
embedding = list("embedded_pain_multiplier" = 0, "embed_chance" = 40, "embedded_fall_chance" = 10)
///magazine///
/obj/item/ammo_box/magazine/flechette
name = "flechette magazine (armor piercing)"
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "flechettemag"
ammo_type = /obj/item/ammo_casing/caseless/flechetteap
caliber = "flechette"
max_ammo = 40
multiple_sprites = 2
/obj/item/ammo_box/magazine/flechette/s
name = "flechette magazine (serrated)"
ammo_type = /obj/item/ammo_casing/caseless/flechettes
///the gun itself///
/obj/item/gun/ballistic/automatic/flechette
name = "\improper CX Flechette Launcher"
desc = "A flechette launching machine pistol with an unconventional bullpup frame."
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "flechettegun"
item_state = "gun"
w_class = WEIGHT_CLASS_NORMAL
slot_flags = 0
/obj/item/firing_pin/implant/pindicate
mag_type = /obj/item/ammo_box/magazine/flechette/
fire_sound = 'sound/weapons/gunshot_smg.ogg'
can_suppress = 0
burst_size = 5
fire_delay = 1
casing_ejector = 0
spread = 10
recoil = 0.05
/obj/item/gun/ballistic/automatic/flechette/update_icon()
..()
if(magazine)
cut_overlays()
add_overlay("flechettegun-magazine")
else
cut_overlays()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
///unique variant///
/obj/item/projectile/bullet/cflechetteshredder
name = "flechette (shredder)"
damage = 5
dismemberment = 40
/obj/item/ammo_casing/caseless/flechetteshredder
name = "flechette (shredder)"
desc = "A serrated flechette made of a special alloy that forms a monofilament edge."
projectile_type = /obj/item/projectile/bullet/cflechettes
/obj/item/ammo_box/magazine/flechette/shredder
name = "flechette magazine (shredder)"
icon_state = "shreddermag"
ammo_type = /obj/item/ammo_casing/caseless/flechetteshredder
/obj/item/gun/ballistic/automatic/flechette/shredder
name = "\improper CX Shredder"
desc = "A flechette launching machine pistol made of ultra-light CFRP optimized for firing serrated monofillament flechettes."
w_class = WEIGHT_CLASS_SMALL
mag_type = /obj/item/ammo_box/magazine/flechette/shredder
spread = 15
recoil = 0.1
/obj/item/gun/ballistic/automatic/flechette/shredder/update_icon()
..()
if(magazine)
cut_overlays()
add_overlay("shreddergun-magazine")
else
cut_overlays()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
@@ -86,7 +86,7 @@
/obj/item/ammo_box/magazine/mmag/small
name = "magpistol magazine (non-lethal disabler)"
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "nlmagmag"
icon_state = "smallmagmag"
ammo_type = /obj/item/ammo_casing/caseless/anlmags
caliber = "mags"
max_ammo = 15
@@ -56,7 +56,7 @@
/obj/item/ammo_box/magazine/mmag_e/small
name = "magpistol magazine (non-lethal disabler)"
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "nlmagmag"
icon_state = "smallmagmag"
ammo_type = /obj/item/ammo_casing/caseless/mag_e/anlmags
caliber = "mag_e"
max_ammo = 16
@@ -123,8 +123,8 @@
item_state = "gun"
w_class = WEIGHT_CLASS_NORMAL
slot_flags = 0
/obj/item/firing_pin/implant/pindicate
mag_type = /obj/item/ammo_box/magazine/flechette/
pin = /obj/item/firing_pin/implant/pindicate
mag_type = /obj/item/ammo_box/magazine/flechette
fire_sound = 'sound/weapons/gunshot_smg.ogg'
can_suppress = 0
burst_size = 5
@@ -134,12 +134,9 @@
recoil = 0.05
/obj/item/gun/ballistic/automatic/flechette/update_icon()
..()
cut_overlays()
if(magazine)
cut_overlays()
add_overlay("flechettegun-magazine")
else
cut_overlays()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
///unique variant///
@@ -163,17 +160,13 @@
name = "\improper CX Shredder"
desc = "A flechette launching machine pistol made of ultra-light CFRP optimized for firing serrated monofillament flechettes."
w_class = WEIGHT_CLASS_SMALL
mag_type = /obj/item/ammo_box/magazine/flechette/shredder
spread = 15
recoil = 0.1
/obj/item/gun/ballistic/automatic/flechette/shredder/update_icon()
..()
cut_overlays()
if(magazine)
cut_overlays()
add_overlay("shreddergun-magazine")
else
cut_overlays()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
/*/////////////////////////////////////////////////////////////
@@ -0,0 +1,373 @@
/*
////////////////////////////////////////
// MKULTA //
////////////////////////////////////////
The magnum opus of FermiChem -
Long and complicated, I highly recomend you look at the two other files heavily involved in this
modular_citadel/code/datums/status_effects/chems.dm - handles the subject's reactions
code/modules/surgery/organs/vocal_cords.dm - handles the enchanter speaking
HOW IT WORKS
Fermis_Reagent.dm
There's 3 main ways this chemical works; I'll start off with discussing how it's set up.
Upon reacting with blood as a catalyst, the blood is used to define who the enthraller is - thus only the creator is/can choose who the master will be. As a side note, you can't adminbus this chem, even admins have to earn it.
This uses the fermichem only proc; FermiCreate, which is basically the same as On_new, except it doesn't require "data" which is something to do with blood and breaks everything so I said bugger it and made my own proc. It basically sets up vars.
When it's first made, the creator has to drink some of it, in order to give them the vocal chords needed.
When it's given to someone, it gives them the status effect and kicks off that side of things. For every metabolism tick, it increases the enthrall tally.
Finally, if you manage to pump 100u into some poor soul, you overload them, and mindbreak them. Making them your willing, but broken slave. Which can only be reversed by; fixing their brain with mannitol and neurine (100 / 50u respectively) (or less with both),
vocal_cords.dm
This handles when the enchanter speaks - basically uses code from voice of god, but only for people with the staus effect. Most of the words are self explainitory, and has a smaller range of commands. If you're not sure what one does, it likely affects the enthrall tally, or the resist tally.
list of commands:
-mixables-
enthral_words
reward_words
punish_words
0
saymyname_words
wakeup_words
1
silence_words
antiresist_words
resist_words
forget_words
attract_words
orgasm_words
2
awoo_words
nya_words
sleep_words
strip_words
walk_words
run_words
knockdown_words
3
statecustom_words
custom_words
objective_words
heal_words
stun_words
hallucinate_words
hot_words
cold_words
getup_words
pacify_words
charge_words
Mixables can be used intersperced with other commands, 0 is commands that work on sleeper against (i.e. players enthralled to state 3, then ordered to wake up and forget, they can be triggered back instantly)
1 is for players who immediately are injected with the chem - no stuns, only a silence and something that draws them towrds them. This is the best time to try to fight it and you're likely to win by spamming resist, unless the enchantress has plans.
2 is the seconds stage, which allows removal of clothes, slowdown and light stunning. You can also make them nya and awoo, because cute.
3 is the finaly state, which allows application of a few status effects (see chem.dm) and allows custom triggers to be installed (kind of like nanites), again, see chem.dm
In a nutshell, this is the way you enthrall people, by typing messages into chat and managing cooldowns on the stronger words. You have to type words and your message strength is increases with the number of characters - if you type short messages the cooldown will be too much and the other player will overcome the chem.
I suppose people could spam gdjshogndjoadphgiuaodp but, the truth of this chem is that it mostly allows a casus beli for subs to give in, and everyones a sub on cit (mostly), so if you aujigbnadjgipagdsjk then they might resist harder cause you're a baddie and baddies don't deserve pets.
Also, the use of this chem as a murder aid is antithetic to it's design, the subject gains bonus resistance if they're hurt or hungry (I'd like to expland this more, I like the idea that you have to look after all of them otherwise they aren't as effective, kind of like tamagachis!). If this becomes a problem, I'll deal with it, I'm not happy with people abusing this chem for an easy murder. (I might make it so you an't strike your pet when health is too low.)
Additionaly, in lieu of previous statement - the pet is ordered to not kill themselves, even if ordered to.
chem.dm
oof
There's a few basic things that have to be understood with this status effect
1. There is a min loop which calculates the enthrall state of the subject, when the entrall tally is over a certain amount, it will push you up 1 phase.
0 - Sleeper
1 - initial
2 - enthralled
3 - Fully entranced
4 - mindbroken
4 can only be reached via OD, whereas you can increment up from 1 > 2 > 3. 0 is only obtainable on a state 3 pet, and it toggles between the two.
1.5 Chem warfare
Since this is a chem, it's expected that you will use all of the chemicals at your disposal. Using aphro and aphro+ will weaken the resistance of the subject, while ananphro, anaphro+, mannitol and neurine will strengthen it.
Additionally, the more aroused you are, the weaker your resistance will be, as a result players immune to aphro and anaphro give a flat bonus to the enthraller.
using furranium and hatmium on the enchanter weakens their power considerably, because they sound rediculous. "Youwe fweewing wery sweepy uwu" This completely justifies their existance.
The impure toxin for this chem increases resistance too, so if they're a bad chemist it'll be unlikely they have a good ratio (and as a secret bonus, really good chemists cann purposely make the impure chem, to use either to combat the use of it against them, or as smoke grenades to deal with a large party)
2. There is a resistance proc which occurs whenever the player presses resist. You have to press it a lot, this is intentional. If you're trying to fight the enchanter, then you can't click both. You usually will win if you just mash resist and the enchanter does nothing, so you've got to react.
Each step futher it becomes harder to resist, in state 2 it's longer, but resisting is still worthwhile. If you're not in state 3, and you've not got MKultra inside of you, you generate resistance very fast. So in some cases the better option will be to stall out any attempts to entrance you.
At the moment, resistance doesn't affect the commands - mostly because it's a way to tell if a state 3 is trying to resist. But this might change if it gets too hard to fight them off.
Durign state 3, it's impossible to resist if the enthraller is in your presence (8 tiles), you generate no resistance if so. If they're out of your range, then you start to go into the addiction processed
As your resistance is tied to your arousal, sometimes your best option is to wah
3. The addition process starts when the enthraller is out of range, it roughtly follows the five stages of grief; denial, anger, bargaining, depression and acceptance.
What it mostly does makes you sad, hurts your brain, and sometimes you lash out in anger.
Denial - minor brain damaged
bargaining - 50:50 chance of brain damage and brain healing
anger - randomly lashing out and hitting people
depression - massive mood loss, stuttering, jittering, hallucinations and brain damage
depression, again - random stunning and crying, brain damage, and resistance
acceptance - minor brain damage and resistance.
You can also resist while out of range, but you can only break free of a stange 3 enthrallment by hitting the acceptance phase with a high enough resistance.
Finally, being near your enthraller reverts the damages caused.
It is expected that if you intend to break free you'll need to use psicodine and mannitol or you'll end up in a bad, but not dead, state. This gives more work for medical!! Finally the true rational of this complicated chem comes out.
4. Status effects in status effects.
There's a few commands that give status effects, such as antiresist, which will cause resistance presses to increase the enthrallment instead, theses are called from the vocal chords.
They're mostly self explainitory; antiresist, charge, pacify and heal. Heals quite weak for obvious reasons. I'd like to add more, maybe some weak adneals with brute/exhaustion costs after the status is over. A truth serum might be neat too.
State 4 pets don't get status effects.
5. Custom triggers
Because it wasnt complicated enough already.
Custom triggers are set by stating a trigger word, which will call a sub proc, which is also defined when the trigger is Called
The effects avalible at the moment are:
Speak - forces pet to say a preallocated phrase in response to the trigger
Echo - sends a message to that player only (i.e. makes them think something)
Shock - gives them a seizure/zaps them
You can look this one up yourself - it's what you expect, it's cit
kneel - gives a short knockdown
strip - strips jumpsuit only
objective - gives the pet a new objective. This requires a high ammount of mental capasity - which is determined by how much you resist. If you resist enough during phase 1 and 2, then they can't give you an objective.
Feel free to add more.
triggers work when said by ANYONE, not just the enchanter.
This is only state 3 pets, state 4 pets cannot get custom triggers, you broke them you bully.
7. If you're an antage you get a bonus to resistance AND to enthralling. Thus it can be worth using this on both sides. It shouldn't be hard to resist as an antag. There are futher bonuses to command, Chaplains and chemist.
If you give your pet a collar then their resistance reduced too.
(I think thats everything?)
Failstates:
Blowing up the reaction produces a gas that causes everyone to fall in love with one another.
Creating a chem with a low purity will make you permanently fall in love with someone, and tasked with keeping them safe. If someone else drinks it, you fall for them.
*/
/datum/reagent/fermi/enthrall
name = "MKUltra"
id = "enthrall"
description = "A forbidden deep red mixture that overwhelms a foreign body with waves of pleasure, intoxicating them into servitude. When taken by the creator, it will enhance the draw of their voice to those affected by it."
color = "#660015" // rgb: , 0, 255
taste_description = "synthetic chocolate, a base tone of alcohol, and high notes of roses"
overdose_threshold = 100 //If this is too easy to get 100u of this, then double it please.
DoNotSplit = TRUE
metabolization_rate = 0.1//It has to be slow, so there's time for the effect.
data = list("creatorID" = null, "creatorGender" = null, "creatorName" = null)
var/creatorID //ckey
var/creatorGender
var/creatorName
var/mob/living/creator
pH = 10
OnMobMergeCheck = TRUE //Procs on_mob_add when merging into a human
can_synth = FALSE
/datum/reagent/fermi/enthrall/test
name = "MKUltraTest"
id = "enthrallTest"
description = "A forbidden deep red mixture that overwhelms a foreign body with waves of joy, intoxicating them into servitude. When taken by the creator, it will enhance the draw of their voice to those affected by it."
data = list("creatorID" = "honkatonkbramblesnatch", "creatorGender" = "Mistress", "creatorName" = "Fermis Yakumo")
creatorID = "honkatonkbramblesnatch"//ckey
creatorGender = "Mistress"
creatorName = "Fermis Yakumo"
purity = 1
DoNotSplit = TRUE
/datum/reagent/fermi/enthrall/test/on_new()
id = "enthrall"
..()
creator = get_mob_by_key(creatorID)
/datum/reagent/fermi/enthrall/on_new(list/data)
creatorID = data.["creatorID"]
creatorGender = data.["creatorGender"]
creatorName = data.["creatorName"]
creator = get_mob_by_key(creatorID)
/datum/reagent/fermi/enthrall/on_mob_add(mob/living/carbon/M)
. = ..()
if(!ishuman(M))//Just to make sure screwy stuff doesn't happen.
return
if(!creatorID)
//This happens when the reaction explodes.
return
if(purity < 0.5)//Impure chems don't function as you expect
return
var/datum/status_effect/chem/enthrall/E = M.has_status_effect(/datum/status_effect/chem/enthrall)
if(E)
if(E.enthrallID == M.ckey && creatorID != M.ckey)//If you're enthralled to yourself (from OD) and someone else tries to enthrall you, you become thralled to them instantly.
E.enthrallID = creatorID
E.enthrallGender = creatorGender
E.master = get_mob_by_key(creatorID)
to_chat(M, to_chat(M, "<span class='big love'><i>Your aldled, plastic, mind bends under the chemical influence of a new [(M.client?.prefs.lewdchem?"master":"leader")]. Your highest priority is now to stay by [creatorName]'s side, following and aiding them at all costs.</i></span>")) //THIS SHOULD ONLY EVER APPEAR IF YOU MINDBREAK YOURSELF AND THEN GET INJECTED FROM SOMEONE ELSE.
log_game("FERMICHEM: Narcissist [M] ckey: [M.key] been rebound to [creatorName], ID: [creatorID]")
return
if((M.ckey == creatorID) && (creatorName == M.real_name)) //same name AND same player - same instance of the player. (should work for clones?)
log_game("FERMICHEM: [M] ckey: [M.key] has been given velvetspeech")
var/obj/item/organ/vocal_cords/Vc = M.getorganslot(ORGAN_SLOT_VOICE)
var/obj/item/organ/vocal_cords/nVc = new /obj/item/organ/vocal_cords/velvet
if(Vc)
Vc.Remove(M)
nVc.Insert(M)
qdel(Vc)
to_chat(M, "<span class='notice'><i>You feel your vocal chords tingle as your voice comes out in a more sultry tone.</span>")
else
log_game("FERMICHEM: MKUltra: [creatorName], [creatorID], is enthralling [M.name], [M.ckey]")
M.apply_status_effect(/datum/status_effect/chem/enthrall)
log_game("FERMICHEM: [M] ckey: [M.key] has taken MKUltra")
/datum/reagent/fermi/enthrall/on_mob_life(mob/living/carbon/M)
. = ..()
if(purity < 0.5)//DO NOT SPLIT INTO DIFFERENT CHEM: This relies on DoNotSplit - has to be done this way.
if(volume < 0.5)//You don't get to escape that easily
FallInLove(pick(GLOB.player_list), M)
M.reagents.remove_reagent(id, volume)
if (M.ckey == creatorID && creatorName == M.real_name)//If the creator drinks it, they fall in love randomly. If someone else drinks it, the creator falls in love with them.
if(M.has_status_effect(STATUS_EFFECT_INLOVE))//Can't be enthralled when enthralled, so to speak.
return
var/list/seen = viewers(7, get_turf(M))
for(var/victim in seen)
if(ishuman(victim))
var/mob/living/carbon/V = victim
if((V == M) || (!V.client) || (V.stat == DEAD))
seen = seen - victim
else
seen = seen - victim
if(LAZYLEN(seen))
return
M.reagents.remove_reagent(id, volume)
FallInLove(M, pick(seen))
return
else // If someone else drinks it, the creator falls in love with them!
var/mob/living/carbon/C = get_mob_by_key(creatorID)
if(M.has_status_effect(STATUS_EFFECT_INLOVE))
return
if((C in viewers(7, get_turf(M))) && (C.client))
M.reagents.remove_reagent(id, volume)
FallInLove(C, M)
return
if (M.ckey == creatorID && creatorName == M.real_name)//If you yourself drink it, it supresses the vocal effects, for stealth. NEVERMIND ADD THIS LATER I CAN'T GET IT TO WORK
return
if(!M.client)
metabolization_rate = 0 //Stops powergamers from quitting to avoid affects. but prevents affects on players that don't exist for performance.
return
if(metabolization_rate == 0)
metabolization_rate = 0.1
var/datum/status_effect/chem/enthrall/E = M.has_status_effect(/datum/status_effect/chem/enthrall)//If purity is over 5, works as intended
if(!E)
return
else
E.enthrallTally += 1
..()
/datum/reagent/fermi/enthrall/overdose_start(mob/living/carbon/M)//I made it so the creator is set to gain the status for someone random.
. = ..()
metabolization_rate = 1//Mostly to manage brain damage and reduce server stress
if (M.ckey == creatorID && creatorName == M.real_name)//If the creator drinks 100u, then you get the status for someone random (They don't have the vocal chords though, so it's limited.)
if (!M.has_status_effect(/datum/status_effect/chem/enthrall))
to_chat(M, "<span class='love'><i>You are unable to resist your own charms anymore, and become a full blown narcissist.</i></span>")
/*Old way of handling, left in as an option B
var/list/seen = viewers(7, get_turf(M))//Sound and sight checkers
for(var/mob/living/carbon/victim in seen)
if(victim == M)//as much as I want you to fall for beepsky, he doesn't have a ckey
seen = seen - victim
if(!victim.ckey)
seen = seen - victim
var/mob/living/carbon/chosen = pick(seen)
creatorID = chosen.ckey
if (chosen.gender == "female")
creatorGender = "Mistress"
else
creatorGender = "Master"
creatorName = chosen.real_name
creator = get_mob_by_key(creatorID)
*/
ADD_TRAIT(M, TRAIT_PACIFISM, "MKUltra")
var/datum/status_effect/chem/enthrall/E
if (!M.has_status_effect(/datum/status_effect/chem/enthrall))
M.apply_status_effect(/datum/status_effect/chem/enthrall)
E = M.has_status_effect(/datum/status_effect/chem/enthrall)
E.enthrallID = creatorID
E.enthrallGender = creatorGender
E.master = creator
else
E = M.has_status_effect(/datum/status_effect/chem/enthrall)
if(M.client?.prefs.lewdchem)
to_chat(M, "<span class='big love'><i>Your mind shatters under the volume of the mild altering chem inside of you, breaking all will and thought completely. Instead the only force driving you now is the instinctual desire to obey and follow [creatorName]. Your highest priority is now to stay by their side and protect them at all costs.</i></span>")
else
to_chat(M, "<span class='big warning'><i>The might volume of chemicals in your system overwhelms your mind, and you suddenly agree with what [creatorName] has been saying. Your highest priority is now to stay by their side and protect them at all costs.</i></span>")
log_game("FERMICHEM: [M] ckey: [M.key] has been mindbroken for [creatorName] ckey: [creatorID]")
M.slurring = 100
M.confused = 100
E.phase = 4
E.mental_capacity = 0
E.customTriggers = list()
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Thralls mindbroken")
/datum/reagent/fermi/enthrall/overdose_process(mob/living/carbon/M)
M.adjustBrainLoss(0.2)//should be ~30 in total
..()
//Creates a gas cloud when the reaction blows up, causing everyone in it to fall in love with someone/something while it's in their system.
/datum/reagent/fermi/enthrallExplo//Created in a gas cloud when it explodes
name = "MKUltra"
id = "enthrallExplo"
description = "A forbidden deep red mixture that overwhelms a foreign body with waves of desire, inducing a chemial love for another. Also, how the HECC did you get this?"
color = "#2C051A" // rgb: , 0, 255
metabolization_rate = 0.1
taste_description = "synthetic chocolate, a base tone of alcohol, and high notes of roses."
DoNotSplit = TRUE
can_synth = FALSE
var/mob/living/carbon/love
/datum/reagent/fermi/enthrallExplo/on_mob_life(mob/living/carbon/M)//Love gas, only affects while it's in your system,Gives a positive moodlet if close, gives brain damagea and a negative moodlet if not close enough.
if(HAS_TRAIT(M, TRAIT_MINDSHIELD))
return ..()
if(!M.has_status_effect(STATUS_EFFECT_INLOVE))
var/list/seen = viewers(7, get_turf(M))//Sound and sight checkers
for(var/victim in seen)
if((istype(victim, /mob/living/simple_animal/pet/)) || (victim == M) || (M.stat == DEAD) || (!isliving(victim)))
seen = seen - victim
if(seen.len == 0)
return
love = pick(seen)
if(!love)
return
M.apply_status_effect(STATUS_EFFECT_INLOVE, love)
to_chat(M, "[(M.client?.prefs.lewdchem?"<span class='love'>":"<span class='warning'>")][(M.client?.prefs.lewdchem?"You develop a sudden crush on [love], your heart beginning to race as you look upon them with new eyes.":"You suddenly feel like making friends with [love].")] You feel strangely drawn towards them.</span>")
log_game("FERMICHEM: [M] ckey: [M.key] has temporarily bonded with [love] ckey: [love.key]")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have bonded")
else
if(get_dist(M, love) < 8)
if(HAS_TRAIT(M, TRAIT_NYMPHO)) //Add this back when merged/updated.
M.adjustArousalLoss(5)
var/message = "[(M.client?.prefs.lewdchem?"I'm next to my crush..! Eee!":"I'm making friends with [love]!")]"
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "InLove", /datum/mood_event/InLove, message)
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "MissingLove")
else
var/message = "[(M.client?.prefs.lewdchem?"I can't keep my crush off my mind, I need to see them again!":"I really want to make friends with [love]!")]"
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "MissingLove", /datum/mood_event/MissingLove, message)
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "InLove")
if(prob(5))
M.Stun(10)
M.emote("whimper")//does this exist?
to_chat(M, "[(M.client?.prefs.lewdchem?"<span class='love'>":"<span class='warning'>")] You're overcome with a desire to see [love].</span>")
M.adjustBrainLoss(0.5)//I found out why everyone was so damaged!
..()
/datum/reagent/fermi/enthrallExplo/on_mob_delete(mob/living/carbon/M)
if(HAS_TRAIT(M, TRAIT_MINDSHIELD))
return ..()
M.remove_status_effect(STATUS_EFFECT_INLOVE)
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "InLove")
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "MissingLove")
to_chat(M, "[(M.client?.prefs.lewdchem?"<span class='love'>":"<span class='warning'>")]Your feelings for [love] suddenly vanish!")
log_game("FERMICHEM: [M] ckey: [M.key] is no longer in temp bond")
..()
/datum/reagent/fermi/proc/FallInLove(mob/living/carbon/Lover, mob/living/carbon/Love)
if(Lover.has_status_effect(STATUS_EFFECT_INLOVE))
to_chat(Lover, "<span class='warning'>You are already fully devoted to someone else!</span>")
return
to_chat(Lover, "[(Lover.client?.prefs.lewdchem?"<span class='love'>":"<span class='warning'>")]You develop a deep and sudden bond with [Love][(Lover.client?.prefs.lewdchem?", your heart beginning to race as your mind filles with thoughts about them.":".")] You are determined to keep them safe and happy, and feel drawn towards them.</span>")
if(Lover.mind)
Lover.mind.store_memory("You are in love with [Love].")
Lover.faction |= "[REF(Love)]"
Lover.apply_status_effect(STATUS_EFFECT_INLOVE, Love)
forge_valentines_objective(Lover, Love, TRUE)
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have become infatuated.")
log_game("FERMICHEM: [Lover] ckey: [Lover.key] has been chemically made to fall for [Love] ckey: [Love.key]")
return
//For addiction see chem.dm
//For vocal commands see vocal_cords.dm
@@ -0,0 +1,364 @@
/*SDGF
////////////////////////////////////////////////////
// synthetic-derived growth factor //
//////////////////////////////////////////////////
other files that are relivant:
modular_citadel/code/datums/status_effects/chems.dm - SDGF
WHAT IT DOES
Several outcomes are possible (in priority order):
Before the chem is even created, there is a risk of the reaction "exploding", which produces an angry teratoma that attacks the player.
0. Before the chem is activated, the purity is checked, if the purity of the reagent is less than 0.5, then sythetic-derived zombie factor is metabolised instead
0.1 If SDZF is injected, the chem appears to act the same as normal, with nutrition gain, until the end, where it becomes toxic instead, giving a short window of warning to the player
0.1.2 If the player can take pent in time, the player will spawn a hostile teratoma on them (less damaging), if they don't, then a zombie is spawned instead, with a small defence increase propotional to the volume
0.2 If the purity is above 0.5, then the remaining impure volume created SDGFtox instead, which reduces blood volume and causes clone damage
1.Normal function creates a (another)player controlled clone of the player, which is spawned nude, with damage to the clone
1.1 The remaining volume is transferred to the clone, which heals it over time, thus the player has to make a substantial ammount of the chem in order to produce a healthy clone
1.2 If the player is infected with a zombie tumor, the tumor is transferred to the ghost controlled clone ONLY.
2. If no player can be found, a brainless clone is created over a long period of time, this body has no controller.
2.1 If the player dies with a clone, then they play as the clone instead. However no memories are retained after splitting.
3. If there is already a clone, then SDGF heals clone, fire and brute damage slowly. This shouldn't normalise this chem as the de facto clone healing chem, as it will always try to make a ghost clone, and then a brainless clone first.
4. If there is insuffient volume to complete the cloning process, there are two outcomes
4.1 At lower volumes, the players nutrition and blood is refunded, with light healing
4.2 At higher volumes a stronger heal is applied to the user
IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
1. The most important factor is the required volume, this is easily edited with the metabolism rate, this chem is HARD TO MAKE, You need to make a lot of it and it's a substantial effort on the players part. There is also a substantial risk; you could spawn a hotile teratoma during the reation, you could damage yourself with clone damage, you could accidentally spawn a zombie... Basically, you've a good chance of killing yourself.
1.1 Additionally, if you're trying to make SDZF purposely, you've no idea if you have or not, and that reaction is even harder to do. Plus, the player has a huge time window to get to medical to deal with it. If you take pent while it's in you, it'll be removed before it can spawn, and only spawns a teratoma if it's late stage.
2. The rate in which the clone is made, This thing takes time to produce fruits, it slows you down and makes you useless in combat/working. Basically you can't do anything during it. It will only get you killed if you use it in combat, If you do use it and you spawn a player clone, they're gimped for a long time, as they have to heal off the clone damage.
3. The healing - it's pretty low and a cyropod is more Useful
4. If you're an antag, you've a 50% chance of making a clone that will help you with your efforts, and you've no idea if they will or not. While clones can't directly harm you and care for you, they can hinder your efforts.
5. If people are being arses when they're a clone, slap them for it, they are told to NOT bugger around with someone else character, if it gets bad I'll add a blacklist, or do a check to see if you've played X amount of hours.
5.1 Another solution I'm okay with is to rename the clone to [M]'s clone, so it's obvious, this obviously ruins anyone trying to clone themselves to get an alibi however. I'd prefer this to not be the case.
5.2 Additionally, this chem is a soft buff to changelings, which apparently need a buff!
5.3 Other similar things exist already though in the codebase; impostors, split personalites, abductors, ect.
6. Giving this to someone without concent is against space law and gets you sent to gulag.
*/
//Clone serum #chemClone
/datum/reagent/fermi/SDGF //vars, mostly only care about keeping track if there's a player in the clone or not.
name = "synthetic-derived growth factor"
id = "SDGF"
description = "A rapidly diving mass of Embryonic stem cells. These cells are missing a nucleus and quickly replicate a hosts DNA before growing to form an almost perfect clone of the host. In some cases neural replication takes longer, though the underlying reason underneath has yet to be determined."
color = "#a502e0" // rgb: 96, 0, 255
var/playerClone = FALSE
var/unitCheck = FALSE
metabolization_rate = 0.5 * REAGENTS_METABOLISM
taste_description = "a weird chemical fleshy flavour"
//var/datum/status_effect/chem/SDGF/candidates/candies
var/list/candies = list()
//var/polling = FALSE
var/list/result = list()
var/list/group = null
var/pollStarted = FALSE
var/location_created
var/startHunger
ImpureChem = "SDGFtox"
InverseChemVal = 0.5
InverseChem = "SDZF"
can_synth = TRUE
//Main SDGF chemical
/datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone.
//Setup clone
switch(current_cycle)
if(1)
startHunger = M.nutrition
if(pollStarted == FALSE)
pollStarted = TRUE
candies = pollGhostCandidates("Do you want to play as a clone of [M], and do you agree to respect their character and act in a similar manner to them? Do not engage in ERP as them unless you have LOOC permission from them, and ensure it is permission from the original, not a clone.")
log_game("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.")
if(20 to INFINITY)
if(LAZYLEN(candies) && playerClone == FALSE) //If there's candidates, clone the person and put them in there!
log_game("FERMICHEM: [M] ckey: [M.key] is creating a clone, controlled by [candies]")
to_chat(M, "<span class='warning'>The cells reach a critical micelle concentration, nucleating rapidly within your body!</span>")
var/typepath = M.type
var/mob/living/carbon/human/fermi_Gclone = new typepath(M.loc)
var/mob/living/carbon/human/SM = fermi_Gclone
if(istype(SM) && istype(M))
SM.real_name = M.real_name
M.dna.transfer_identity(SM)
SM.updateappearance(mutcolor_update=1)
var/mob/dead/observer/C = pick(candies)
message_admins("Ghost candidate found! [C] key [C.key] is becoming a clone of [M] key: [M.key] (They agreed to respect the character they're becoming, and agreed to not ERP without express permission from the original.)")
SM.key = C.key
SM.mind.enslave_mind_to_creator(M)
//If they're a zombie, they can try to negate it with this.
//I seriously wonder if anyone will ever use this function.
if(M.getorganslot(ORGAN_SLOT_ZOMBIE))//sure, it "treats" it, but "you've" still got it. Doesn't always work as well; needs a ghost.
var/obj/item/organ/zombie_infection/ZI = M.getorganslot(ORGAN_SLOT_ZOMBIE)
ZI.Remove(M)
ZI.Insert(SM)
log_game("FERMICHEM: [M] ckey: [M.key]'s zombie_infection has been transferred to their clone")
to_chat(SM, "<span class='warning'>You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with your original, a perfect clone of your origin.</span>")
if(prob(50))
to_chat(SM, "<span class='userdanger'>While you find your newfound existence strange, you share the same memories as [M.real_name]. However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original.</span>")
log_game("FERMICHEM: [SM] ckey: [SM.key]'s is not bound by [M] ckey [M.key]'s will, and is free to determine their own goals, while respecting and acting as their origin.")
else
to_chat(SM, "<span class='userdanger'>While you find your newfound existence strange, you share the same memories as [M.real_name]. Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.</span>")
log_game("FERMICHEM: [SM] ckey: [SM.key]'s is bound by [M] ckey [M.key]'s objectives, and is encouraged to help them complete them.")
to_chat(M, "<span class='warning'>You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.</span>")
M.visible_message("[M] suddenly shudders, and splits into two identical twins!")
SM.copy_known_languages_from(M, FALSE)
playerClone = TRUE
M.next_move_modifier = 1
M.nutrition -= 500
//Damage the clone
SM.blood_volume = (BLOOD_VOLUME_NORMAL*SM.blood_ratio)/2
SM.adjustCloneLoss(60, 0)
SM.setBrainLoss(40)
SM.nutrition = startHunger/2
//Transfer remaining reagent to clone. I think around 30u will make a healthy clone, otherwise they'll have clone damage, blood loss, brain damage and hunger.
SM.reagents.add_reagent("SDGFheal", volume)
M.reagents.remove_reagent(id, volume)
log_game("FERMICHEM: [volume]u of SDGFheal has been transferred to the clone")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Sentient clones made")
return
else if(playerClone == FALSE) //No candidates leads to two outcomes; if there's already a braincless clone, it heals the user, as well as being a rare souce of clone healing (thematic!).
unitCheck = TRUE
if(M.has_status_effect(/datum/status_effect/chem/SGDF)) // Heal the user if they went to all this trouble to make it and can't get a clone, the poor fellow.
switch(current_cycle)
if(21)
to_chat(M, "<span class='notice'>The cells fail to catalyse around a nucleation event, instead merging with your cells.</span>") //This stuff is hard enough to make to rob a user of some benefit. Shouldn't replace Rezadone as it requires the user to not only risk making a player controlled clone, but also requires them to have split in two (which also requires 30u of SGDF).
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC)
log_game("FERMICHEM: [M] ckey: [M.key] is being healed by SDGF")
if(22 to INFINITY)
M.adjustCloneLoss(-1, 0)
M.adjustBruteLoss(-1, 0)
M.adjustFireLoss(-1, 0)
M.heal_bodypart_damage(1,1)
M.reagents.remove_reagent(id, 1)//faster rate of loss.
else //If there's no ghosts, but they've made a large amount, then proceed to make flavourful clone, where you become fat and useless until you split.
switch(current_cycle)
if(21)
to_chat(M, "<span class='notice'>You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.</span>")
if(22 to 29)
M.nutrition = M.nutrition + (M.nutrition/10)
if(30)
to_chat(M, "<span class='notice'>You feel the synethic cells grow and expand within yourself, bloating your body outwards.</span>")
if(31 to 49)
M.nutrition = M.nutrition + (M.nutrition/5)
if(50)
to_chat(M, "<span class='notice'>The synthetic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.</span>")
M.next_move_modifier += 4//If this makes you fast then please fix it, it should make you slow!!
//candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies
if(51 to 79)
M.nutrition = M.nutrition + (M.nutrition/2)
if(80)
to_chat(M, "<span class='notice'>The cells begin to precipitate outwards of your body, you feel like you'll split soon...</span>")
if (M.nutrition < 20000)
M.nutrition = 20000 //https://www.youtube.com/watch?v=Bj_YLenOlZI
if(86)//Upon splitting, you get really hungry and are capable again. Deletes the chem after you're done.
M.nutrition = 15//YOU BEST BE EATTING AFTER THIS YOU CUTIE
M.next_move_modifier -= 4
to_chat(M, "<span class='notice'>Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.</span>")
//clone
var/typepath = M.type
var/mob/living/fermi_Clone = new typepath(M.loc)
var/mob/living/carbon/C = fermi_Clone
if(istype(C) && istype(M))
C.real_name = M.real_name
M.dna.transfer_identity(C, transfer_SE=1)
C.updateappearance(mutcolor_update=1)
C.apply_status_effect(/datum/status_effect/chem/SGDF)
var/datum/status_effect/chem/SGDF/S = C.has_status_effect(/datum/status_effect/chem/SGDF)
S.original = M
S.originalmind = M.mind
S.status_set = TRUE
log_game("FERMICHEM: [M] ckey: [M.key] has created a mindless clone of themselves")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Braindead clones made")
if(87 to INFINITY)
M.reagents.remove_reagent(id, volume)//removes SGDF on completion. Has to do it this way because of how i've coded it. If some madlab gets over 1k of SDGF, they can have the clone healing.
..()
/datum/reagent/fermi/SDGF/on_mob_delete(mob/living/M) //When the chem is removed, a few things can happen, mostly consolation prizes.
pollStarted = FALSE
if (playerClone == TRUE)//If the player made a clone with it, then thats all they get.
playerClone = FALSE
return
if (M.next_move_modifier == 4 && !M.has_status_effect(/datum/status_effect/chem/SGDF))//checks if they're ingested over 20u of the stuff, but fell short of the required 30u to make a clone.
to_chat(M, "<span class='notice'>You feel the cells begin to merge with your body, unable to reach nucleation, they instead merge with your body, healing any wounds.</span>")
M.adjustCloneLoss(-10, 0) //I don't want to make Rezadone obsolete.
M.adjustBruteLoss(-25, 0)// Note that this takes a long time to apply and makes you fat and useless when it's in you, I don't think this small burst of healing will be useful considering how long it takes to get there.
M.adjustFireLoss(-25, 0)
M.blood_volume += 250
M.heal_bodypart_damage(1,1)
M.next_move_modifier = 1
if (M.nutrition < 1500)
M.nutrition += 250
else if (unitCheck == TRUE && !M.has_status_effect(/datum/status_effect/chem/SGDF))// If they're ingested a little bit (10u minimum), then give them a little healing.
unitCheck = FALSE
to_chat(M, "<span class='notice'>the cells fail to hold enough mass to generate a clone, instead diffusing into your system.</span>")
M.adjustBruteLoss(-10, 0)
M.adjustFireLoss(-10, 0)
M.blood_volume += 100
M.next_move_modifier = 1
if (M.nutrition < 1500)
M.nutrition += 500
/datum/reagent/fermi/SDGF/reaction_mob(mob/living/carbon/human/M, method=TOUCH, reac_volume)
if(volume<5)
M.visible_message("<span class='warning'>The growth factor froths upon [M]'s body, failing to do anything of note.</span>")
return
if(M.stat == DEAD)
if(M.suiciding || (HAS_TRAIT(M, TRAIT_NOCLONE)) || M.hellbound)
M.visible_message("<span class='warning'>The growth factor inertly sticks to [M]'s body, failing to do anything of note.</span>")
return
if(!M.mind)
M.visible_message("<span class='warning'>The growth factor shudders, merging with [M]'s body, but is unable to replicate properly.</span>")
var/bodydamage = (M.getBruteLoss() + M.getFireLoss())
var/typepath = M.type
volume =- 5
var/mob/living/carbon/human/fermi_Gclone = new typepath(M.loc)
var/mob/living/carbon/human/SM = fermi_Gclone
if(istype(SM) && istype(M))
SM.real_name = M.real_name
M.dna.transfer_identity(SM)
SM.updateappearance(mutcolor_update=1)
M.mind.transfer_to(SM)
M.visible_message("<span class='warning'>[M]'s body shudders, the growth factor rapidly splitting into a new clone of [M].</span>")
if(bodydamage>50)
SM.adjustOxyLoss(-(bodydamage/10), 0)
SM.adjustToxLoss(-(bodydamage/10), 0)
SM.blood_volume = (BLOOD_VOLUME_NORMAL*SM.blood_ratio)/1.5
SM.adjustCloneLoss((bodydamage/10), 0)
SM.setBrainLoss((bodydamage/10))
SM.nutrition = 400
if(bodydamage>200)
SM.gain_trauma_type(BRAIN_TRAUMA_MILD)
if(bodydamage>300)
var/obj/item/bodypart/l_arm = SM.get_bodypart(BODY_ZONE_L_ARM) //We get the body parts we want this way.
var/obj/item/bodypart/r_arm = SM.get_bodypart(BODY_ZONE_R_ARM)
l_arm.drop_limb()
r_arm.drop_limb()
if(bodydamage>400)
var/obj/item/bodypart/l_leg = SM.get_bodypart(BODY_ZONE_L_LEG) //We get the body parts we want this way.
var/obj/item/bodypart/r_leg = SM.get_bodypart(BODY_ZONE_R_LEG)
l_leg.drop_limb()
r_leg.drop_limb()
if(bodydamage>500)
SM.gain_trauma_type(BRAIN_TRAUMA_SEVERE)
if(bodydamage>600)
var/datum/species/mutation = pick(subtypesof(/datum/species))
SM.set_species(mutation)
//Transfer remaining reagent to clone. I think around 30u will make a healthy clone, otherwise they'll have clone damage, blood loss, brain damage and hunger.
SM.reagents.add_reagent("SDGFheal", volume)
M.reagents.remove_reagent(id, volume)
SM.updatehealth()
SM.emote("gasp")
log_combat(M, M, "SDGF clone-vived", src)
..()
//Unobtainable, used in clone spawn.
/datum/reagent/fermi/SDGFheal
name = "synthetic-derived growth factor"
id = "SDGFheal"
metabolization_rate = 1
can_synth = FALSE
/datum/reagent/fermi/SDGFheal/on_mob_life(mob/living/carbon/M)//Used to heal the clone after splitting, the clone spawns damaged. (i.e. insentivies players to make more than required, so their clone doesn't have to be treated)
if(M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio))
M.blood_volume += 10
M.adjustCloneLoss(-2, 0)
M.setBrainLoss(-1)
M.nutrition += 10
..()
//Unobtainable, used if SDGF is impure but not too impure
/datum/reagent/fermi/SDGFtox
name = "synthetic-derived growth factor"
id = "SDGFtox"
description = "A chem that makes a certain chemcat angry at you if you're reading this, how did you get this???"//i.e. tell me please, figure it's a good way to get pinged for bugfixes.
metabolization_rate = 1
can_synth = FALSE
/datum/reagent/fermi/SDGFtox/on_mob_life(mob/living/carbon/M)//Damages the taker if their purity is low. Extended use of impure chemicals will make the original die. (thus can't be spammed unless you've very good)
M.blood_volume -= 10
M.adjustCloneLoss(2, 0)
..()
//Fail state of SDGF
/datum/reagent/fermi/SDZF
name = "synthetic-derived growth factor"
id = "SDZF"
description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. This message should never appear, how did you manage to get a hold of this?"
color = "#a502e0" // rgb: 96, 0, 255
metabolization_rate = 0.5 * REAGENTS_METABOLISM
var/startHunger
can_synth = TRUE
/datum/reagent/fermi/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead.
switch(current_cycle)//Pretends to be normal
if(20)
to_chat(M, "<span class='notice'>You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.</span>")
startHunger = M.nutrition
if(21 to 29)
M.nutrition = M.nutrition + (M.nutrition/10)
if(30)
to_chat(M, "<span class='notice'>You feel the synethic cells grow and expand within yourself, bloating your body outwards.</span>")
if(31 to 49)
M.nutrition = M.nutrition + (M.nutrition/5)
if(50)
to_chat(M, "<span class='notice'>The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.</span>")
M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!!
if(51 to 73)
M.nutrition = M.nutrition + (M.nutrition/2)
if(74)
to_chat(M, "<span class='notice'>The cells begin to precipitate outwards of your body, but... something is wrong, the sythetic cells are beginnning to rot...</span>")
if (M.nutrition < 20000) //whoever knows the maxcap, please let me know, this seems a bit low.
M.nutrition = 20000 //https://www.youtube.com/watch?v=Bj_YLenOlZI
if(75 to 85)
M.adjustToxLoss(1, 0)// the warning!
if(86)//mean clone time!
if (!M.reagents.has_reagent("pen_acid"))//Counterplay is pent.)
message_admins("(non-infectious) SDZF: Zombie spawned at [M] [COORD(M)]!")
M.nutrition = startHunger - 500//YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE
M.next_move_modifier = 1
to_chat(M, "<span class='warning'>Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.</span>")
M.visible_message("[M] suddenly shudders, and splits into a funky smelling copy of themselves!")
M.emote("scream")
M.adjustToxLoss(30, 0)
var/mob/living/simple_animal/hostile/unemployedclone/ZI = new(get_turf(M.loc))
ZI.damage_coeff = list(BRUTE = ((1 / volume)**0.25) , BURN = ((1 / volume)**0.1), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
ZI.real_name = M.real_name//Give your offspring a big old kiss.
ZI.name = M.real_name
ZI.desc = "[M]'s clone, gone horribly wrong."
log_game("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying zombie instead")
M.reagents.remove_reagent(id, 20)
else//easier to deal with
to_chat(M, "<span class='notice'>The pentetic acid seems to have stopped the decay for now, clumping up the cells into a horrifying tumour!</span>")
M.nutrition = startHunger - 500
var/mob/living/simple_animal/slime/S = new(get_turf(M.loc),"grey") //TODO: replace slime as own simplemob/add tumour slime cores for science/chemistry interplay
S.damage_coeff = list(BRUTE = ((1 / volume)**0.1) , BURN = 2, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
S.name = "Living teratoma"
S.real_name = "Living teratoma"//horrifying!!
S.rabid = 1//Make them an angery boi
M.reagents.remove_reagent(id, volume)
to_chat(M, "<span class='warning'>A large glob of the tumour suddenly splits itself from your body. You feel grossed out and slimey...</span>")
log_game("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying teratoma instead")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Zombie clones made!")
if(87 to INFINITY)
M.adjustToxLoss(1, 0)
..()
@@ -0,0 +1,152 @@
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
// ASTROGEN
///////////////////////////////////////////////////////////////////////////////////////////////////
More fun chems!
When you take it, it spawns a ghost that the player controls. (No access to deadchat)
This ghost moves pretty quickly and is mostly invisible, but is still visible for people with eyes.
When it's out of your system, you return back to yourself. It doesn't last long and metabolism of the chem is exponential.
Addiction is particularlly brutal, it slowly turns you invisible with flavour text, then kills you at a low enough alpha. (i've also added something to prevent geneticists speeding this up)
There's afairly major catch regarding the death though. I'm not gonna say here, go read the code, it explains it and puts my comments on it in context. I know that anyone reading it without understanding it is going to freak out so, this is my attempt to get you to read it and understand it.
I'd like to point out from my calculations it'll take about 60-80 minutes to die this way too. Plenty of time to visit me and ask for some pills to quench your addiction.
*/
/datum/reagent/fermi/astral // Gives you the ability to astral project for a moment!
name = "Astrogen"
id = "astral"
description = "An opalescent murky liquid that is said to distort your soul from your being."
color = "#A080H4" // rgb: , 0, 255
taste_description = "your mind"
metabolization_rate = 0//Removal is exponential, see code
overdose_threshold = 20
addiction_threshold = 24.5
addiction_stage1_end = 9999//Should never end. There is no escape make your time
var/mob/living/carbon/origin
var/mob/living/simple_animal/astral/G = null
var/datum/mind/originalmind
var/antiGenetics = 255
var/sleepytime = 0
InverseChemVal = 0.25
can_synth = FALSE
/datum/action/chem/astral
name = "Return to body"
var/mob/living/carbon/origin = null
var/mob/living/simple_animal/hostile/retaliate/ghost = null
/datum/action/chem/astral/Trigger()
ghost.mind.transfer_to(origin)
qdel(src)
/datum/reagent/fermi/astral/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
var/turf/open/floor/F = T
F.PlaceOnTop(/turf/open/floor/fakespace)
..()
/datum/reagent/fermi/astral/reaction_obj(obj/O, reac_volume)
if(istype(O, /obj/item/bedsheet))
new /obj/item/bedsheet/cosmos(get_turf(O))
qdel(O)
/datum/reagent/fermi/astral/on_mob_life(mob/living/carbon/M) // Gives you the ability to astral project for a moment!
M.alpha = 255
if(current_cycle == 0)
originalmind = M.mind
log_game("FERMICHEM: [M] ckey: [M.key] became an astral ghost")
origin = M
if (G == null)
G = new(get_turf(M.loc))
G.name = "[M]'s astral projection"
var/datum/action/chem/astral/AS = new(G)
AS.origin = M
AS.ghost = G
if(M.mind)
M.mind.transfer_to(G)
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Astral projections")
if(overdosed)
if(prob(50))
to_chat(G, "<span class='warning'>The high conentration of Astrogen in your blood causes you to lapse your concentration for a moment, bringing your projection back to yourself!</b></span>")
do_teleport(G, M.loc)
M.reagents.remove_reagent(id, current_cycle/10, FALSE)//exponent
sleepytime+=5
if(G)//This is a mess because of how slow qdel is, so this is all to stop runtimes.
if(G.mind)
if(G.stat == DEAD || G.pseudo_death == TRUE)
G.mind.transfer_to(M)
qdel(G)
..()
/datum/reagent/fermi/astral/on_mob_delete(mob/living/carbon/M)
if(!G)
if(M.mind)
var/mob/living/simple_animal/astral/G = new(get_turf(M.loc))
M.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end.
to_chat(G, "<span class='warning'>[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'</b></span>")
log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!")
originalmind.transfer_to(M)
else if(G.mind)
G.mind.transfer_to(origin)
qdel(G)
if(overdosed)
to_chat(M, "<span class='warning'>The high volume of astrogen you just took causes you to black out momentarily as your mind snaps back to your body.</b></span>")
M.Sleeping(sleepytime, 0)
antiGenetics = 255
if(G)//just in case
qdel(G)
log_game("FERMICHEM: [M] has astrally returned to their body!")
..()
//Okay so, this might seem a bit too good, but my counterargument is that it'll likely take all round to eventually kill you this way, then you have to be revived without a body. It takes approximately 50-80 minutes to die from this.
/datum/reagent/fermi/astral/addiction_act_stage1(mob/living/carbon/M)
if(addiction_stage < 2)
antiGenetics = 255
M.alpha = 255 //Antigenetics is to do with stopping geneticists from turning people invisible to kill them.
if(prob(70))
M.alpha--
antiGenetics--
switch(antiGenetics)
if(245)
to_chat(M, "<span class='warning'>You notice your body starting to disappear, maybe you took too much Astrogen...?</b></span>")
M.alpha--
antiGenetics--
log_game("FERMICHEM: [M] ckey: [M.key] has become addicted to Astrogen")
if(220)
to_chat(M, "<span class='notice'>Your addiction is only getting worse as your body disappears. Maybe you should get some more, and fast?</b></span>")
M.alpha--
antiGenetics--
if(200)
to_chat(M, "<span class='notice'>You feel a substantial part of your soul flake off into the ethereal world, rendering yourself unclonable.</b></span>")
M.alpha--
antiGenetics--
ADD_TRAIT(M, TRAIT_NOCLONE, "astral") //So you can't scan yourself, then die, to metacomm. You can only use your memories if you come back as something else.
M.hellbound = TRUE
if(180)
to_chat(M, "<span class='notice'>You feel fear build up in yourself as more and more of your body and consciousness begins to fade.</b></span>")
M.alpha--
antiGenetics--
if(120)
to_chat(M, "<span class='notice'>As you lose more and more of yourself, you start to think that maybe shedding your mortality isn't too bad.</b></span>")
M.alpha--
antiGenetics--
if(80)
to_chat(M, "<span class='notice'>You feel a thrill shoot through your body as what's left of your mind contemplates your forthcoming oblivion.</b></span>")
M.alpha--
antiGenetics--
if(45)
to_chat(M, "<span class='warning'>The last vestiges of your mind eagerly await your imminent annihilation.</b></span>")
M.alpha--
antiGenetics--
if(-INFINITY to 30)
to_chat(M, "<span class='warning'>Your body disperses from existence, as you become one with the universe.</b></span>")
to_chat(M, "<span class='userdanger'>As your body disappears, your consciousness doesn't. Should you find a way back into the mortal coil, your memories of your previous life remain with you. (At the cost of staying in character while dead. Failure to do this may get you banned from this chem. You are still obligated to follow your directives if you play a midround antag, you do not remember the afterlife IC)</span>")//Legalised IC OOK? I have a suspicion this won't make it past the review. At least it'll be presented as a neat idea! If this is unacceptable how about the player can retain living memories across lives if they die in this way only.
deadchat_broadcast("<span class='warning'>[M] has become one with the universe, meaning that their IC conciousness is continuous in a new life. If they find a way back to life, they are allowed to remember their previous life. Be careful what you say. If they abuse this, bwoink the FUCK outta them.</span>")
M.visible_message("[M] suddenly disappears, their body evaporating from existence, freeing [M] from their mortal coil.")
message_admins("[M] (ckey: [M.ckey]) has become one with the universe, and have continuous memories thoughout their lives should they find a way to come back to life (such as an inteligence potion, midround antag, ghost role).")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Astral obliterations")
qdel(M) //Approx 60minutes till death from initial addiction
log_game("FERMICHEM: [M] ckey: [M.key] has been obliterated from Astrogen addiction")
..()
@@ -0,0 +1,203 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// EIGENSTASIUM
///////////////////////////////////////////////////////////////////////////////////////////////////
//eigenstate Chem
//Teleports you to chemistry and back
//OD teleports you randomly around the Station
//Addiction send you on a wild ride and replaces you with an alternative reality version of yourself.
//During the process you get really hungry, then your items start teleporting randomly,
//then alternative versions of yourself are brought in from a different universe and they yell at you.
//and finally you yourself get teleported to an alternative universe, and character your playing is replaced with said alternative
/datum/reagent/fermi/eigenstate
name = "Eigenstasium"
id = "eigenstate"
description = "A strange mixture formed from a controlled reaction of bluespace with plasma, that causes localised eigenstate fluxuations within the patient"
taste_description = "wiggly cosmic dust."
color = "#5020F4" // rgb: 50, 20, 255
overdose_threshold = 15
addiction_threshold = 15
metabolization_rate = 1.2 * REAGENTS_METABOLISM
addiction_stage2_end = 30
addiction_stage3_end = 41
addiction_stage4_end = 44 //Incase it's too long
data = list("location_created" = null)
var/turf/location_created
var/obj/effect/overlay/holo_pad_hologram/Eigenstate
var/turf/open/location_return = null
var/addictCyc3 = 0
var/mob/living/carbon/fermi_Tclone = null
var/teleBool = FALSE
pH = 3.7
can_synth = TRUE
/datum/reagent/fermi/eigenstate/on_new(list/data)
location_created = data.["location_created"]
//Main functions
/datum/reagent/fermi/eigenstate/on_mob_life(mob/living/M) //Teleports to chemistry!
if(current_cycle == 0)
log_game("FERMICHEM: [M] ckey: [M.key] took eigenstasium")
//make hologram at return point
Eigenstate = new(loc)
Eigenstate.appearance = M.appearance
Eigenstate.alpha = 170
Eigenstate.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
Eigenstate.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it.
Eigenstate.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
Eigenstate.setAnchored(TRUE)//So space wind cannot drag it.
Eigenstate.name = "[M]'s' eigenstate"//If someone decides to right click.
Eigenstate.set_light(2) //hologram lighting
location_return = get_turf(M) //sets up return point
to_chat(M, "<span class='userdanger'>You feel your wavefunction split!</span>")
if(purity > 0.9) //Teleports you home if it's pure enough
if(!location_created && data) //Just in case
location_created = data.["location_created"]
log_game("FERMICHEM: [M] ckey: [M.key] returned to [location_created] using eigenstasium")
do_sparks(5,FALSE,M)
do_teleport(M, location_created, 0, asoundin = 'sound/effects/phasein.ogg')
do_sparks(5,FALSE,M)
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Pure eigentstate jumps")
if(prob(20))
do_sparks(5,FALSE,M)
..()
/datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location
do_sparks(5,FALSE,M)
to_chat(M, "<span class='userdanger'>You feel your wavefunction collapse!</span>")
do_teleport(M, location_return, 0, asoundin = 'sound/effects/phasein.ogg') //Teleports home
do_sparks(5,FALSE,M)
qdel(Eigenstate)
..()
/datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly
. = ..()
to_chat(M, "<span class='userdanger'>Oh god, you feel like your wavefunction is about to tear.</span>")
log_game("FERMICHEM: [M] ckey: [M.key] has overdosed on eigenstasium")
M.Jitter(20)
metabolization_rate += 0.5 //So you're not stuck forever teleporting.
/datum/reagent/fermi/eigenstate/overdose_process(mob/living/M) //Overdose, makes you teleport randomly, probably one of my favourite effects. Sometimes kills you.
do_sparks(5,FALSE,M)
do_teleport(M, get_turf(M), 10, asoundin = 'sound/effects/phasein.ogg')
do_sparks(5,FALSE,M)
..()
//Addiction
/datum/reagent/fermi/eigenstate/addiction_act_stage1(mob/living/M) //Welcome to Fermis' wild ride.
if(addiction_stage == 1)
to_chat(M, "<span class='userdanger'>Your wavefunction feels like it's been ripped in half. You feel empty inside.</span>")
log_game("FERMICHEM: [M] ckey: [M.key] has become addicted to eigenstasium")
M.Jitter(10)
M.nutrition = M.nutrition - (M.nutrition/15)
..()
/datum/reagent/fermi/eigenstate/addiction_act_stage2(mob/living/M)
if(addiction_stage == 11)
to_chat(M, "<span class='userdanger'>You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.</span>")
M.Jitter(200)
M.Knockdown(200)
M.Stun(80)
var/items = M.get_contents()
if(!LAZYLEN(items))
return ..()
var/obj/item/I = pick(items)
if(istype(I, /obj/item/implant))
qdel(I)
to_chat(M, "<span class='userdanger'>You feel your implant rip itself out of you, sent flying off to another dimention!</span>")
else
M.dropItemToGround(I, TRUE)
do_sparks(5,FALSE,I)
do_teleport(I, get_turf(I), 5, no_effects=TRUE);
do_sparks(5,FALSE,I)
..()
/datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around!
//Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in
switch(addictCyc3) //Loops 0 -> 1 -> 2 -> 1 -> 2 -> 1 ...ect.
if(0)
M.Jitter(100)
to_chat(M, "<span class='userdanger'>Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the event horizon.</span>")
if(1)
var/typepath = M.type
fermi_Tclone = new typepath(M.loc)
var/mob/living/carbon/C = fermi_Tclone
fermi_Tclone.appearance = M.appearance
C.real_name = M.real_name
M.visible_message("[M] collapses in from an alternative reality!")
do_teleport(C, get_turf(C), 2, no_effects=TRUE) //teleports clone so it's hard to find the real one!
do_sparks(5,FALSE,C)
C.emote("spin")
M.emote("spin")
M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE)
C.emote("me",1,"[pick("says", "cries", "mewls", "giggles", "shouts", "screams", "gasps", "moans", "whispers", "announces")], \"[pick("Bugger me, whats all this then?", "Hot damn, where is this?", "sacre bleu! Ou suis-je?!", "Yee haw! This is one hell of a hootenanny!", "WHAT IS HAPPENING?!", "Picnic!", "Das ist nicht deutschland. Das ist nicht akzeptabel!!!", "I've come from the future to warn you to not take eigenstasium! Oh no! I'm too late!", "You fool! You took too much eigenstasium! You've doomed us all!", "What...what's with these teleports? It's like one of my Japanese animes...!", "Ik stond op het punt om mehki op tafel te zetten, en nu, waar ben ik?", "This must be the will of Stein's gate.", "Fermichem was a mistake", "This is one hell of a beepsky smash.", "Now neither of us will be virgins!")]\"")
if(2)
var/mob/living/carbon/C = fermi_Tclone
do_sparks(5,FALSE,C)
qdel(C) //Deletes CLONE, or at least I hope it is.
M.visible_message("[M] is snapped across to a different alternative reality!")
addictCyc3 = 0 //counter
fermi_Tclone = null
addictCyc3++
do_teleport(M, get_turf(M), 2, no_effects=TRUE) //Teleports player randomly
do_sparks(5,FALSE,M)
..()
/datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery.
if(addiction_stage == 42)
do_sparks(5,FALSE,M)
do_teleport(M, get_turf(M), 2, no_effects=TRUE) //teleports clone so it's hard to find the real one!
do_sparks(5,FALSE,M)
M.Sleeping(100, 0)
M.Jitter(50)
M.Knockdown(100)
to_chat(M, "<span class='userdanger'>You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.</span>")
M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE)
log_game("FERMICHEM: [M] ckey: [M.key] has become an alternative universe version of themselves.")
M.reagents.remove_all_type(/datum/reagent, 100, 0, 1)
/*
for(var/datum/mood_event/Me in M)
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, Me) //Why does this not work?
*/
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate)
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Wild rides ridden")
if(prob(20))
do_sparks(5,FALSE,M)
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "[id]_overdose")//holdover until above fix works
..()
/datum/reagent/fermi/eigenstate/reaction_turf(turf/T, reac_volume)
//if(cached_purity < 0.99) To add with next batch of fixes and tweaks.
var/obj/structure/closet/First
var/obj/structure/closet/Previous
for(var/obj/structure/closet/C in T.contents)
if(C.eigen_teleport == TRUE)
C.visible_message("[C] fizzes, it's already linked to something else!")
continue
if(!Previous)
First = C
Previous = C
continue
C.eigen_teleport = TRUE
C.eigen_target = Previous
C.color = "#9999FF" //Tint the locker slightly.
C.alpha = 200
do_sparks(5,FALSE,C)
Previous = C
if(!First)
return
if(Previous == First)
return
First.eigen_teleport = TRUE
First.eigen_target = Previous
First.color = "#9999FF"
First.alpha = 200
do_sparks(5,FALSE,First)
First.visible_message("The lockers' eigenstates spilt and merge, linking each of their contents together.")
//eigenstate END
@@ -0,0 +1,365 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// BREAST ENLARGE
///////////////////////////////////////////////////////////////////////////////////////////////////
//Other files that are relivant:
//modular_citadel/code/datums/status_effects/chems.dm
//modular_citadel/code/modules/arousal/organs/breasts.dm
//breast englargement
//Honestly the most requested chems
//I'm not a very kinky person, sorry if it's not great
//I tried to make it interesting..!!
//Normal function increases your breast size by 0.05, 10units = 1 cup.
//If you get stupid big, it presses against your clothes, causing brute and oxydamage. Then rips them off.
//If you keep going, it makes you slower, in speed and action.
//decreasing your size will return you to normal.
//(see the status effect in chem.dm)
//Overdosing on (what is essentially space estrogen) makes you female, removes balls and shrinks your dick.
//OD is low for a reason. I'd like fermichems to have low ODs, and dangerous ODs, and since this is a meme chem that everyone will rush to make, it'll be a lesson learnt early.
/datum/reagent/fermi/breast_enlarger
name = "Succubus milk"
id = "breast_enlarger"
description = "A volatile collodial mixture derived from milk that encourages mammary production via a potent estrogen mix."
color = "#E60584" // rgb: 96, 0, 255
taste_description = "a milky ice cream like flavour."
overdose_threshold = 17
metabolization_rate = 0.25
ImpureChem = "BEsmaller" //If you make an inpure chem, it stalls growth
InverseChemVal = 0.35
InverseChem = "BEsmaller" //At really impure vols, it just becomes 100% inverse
can_synth = FALSE
/datum/reagent/fermi/breast_enlarger/on_mob_add(mob/living/carbon/M)
. = ..()
if(!ishuman(M)) //The monkey clause
if(volume >= 15) //To prevent monkey breast farms
var/turf/T = get_turf(M)
var/obj/item/organ/genital/breasts/B = new /obj/item/organ/genital/breasts(T)
var/list/seen = viewers(8, T)
for(var/mob/S in seen)
to_chat(S, "<span class='warning'>A pair of breasts suddenly fly out of the [M]!</b></span>")
//var/turf/T2 = pick(turf in view(5, M))
var/T2 = get_random_station_turf()
M.adjustBruteLoss(25)
M.Knockdown(50)
M.Stun(50)
B.throw_at(T2, 8, 1)
M.reagents.remove_reagent(id, volume)
return
log_game("FERMICHEM: [M] ckey: [M.key] has ingested Sucubus milk")
var/mob/living/carbon/human/H = M
H.genital_override = TRUE
var/obj/item/organ/genital/breasts/B = H.getorganslot("breasts")
if(!B)
H.emergent_genital_call()
return
if(!B.size == "huge")
var/sizeConv = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5)
B.prev_size = B.size
B.cached_size = sizeConv[B.size]
/datum/reagent/fermi/breast_enlarger/on_mob_life(mob/living/carbon/M) //Increases breast size
if(!ishuman(M))//Just in case
return..()
var/mob/living/carbon/human/H = M
var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
if(!B) //If they don't have breasts, give them breasts.
//If they have Acute hepatic pharmacokinesis, then route processing though liver.
if(HAS_TRAIT(M, TRAIT_PHARMA))
var/obj/item/organ/liver/L = M.getorganslot("liver")
if(L)
L.swelling+= 0.05
return..()
else
M.adjustToxLoss(1)
return..()
//otherwise proceed as normal
var/obj/item/organ/genital/breasts/nB = new
nB.Insert(M)
if(nB)
if(M.dna.species.use_skintones && M.dna.features["genitals_use_skintone"])
nB.color = skintone2hex(H.skin_tone)
else if(M.dna.features["breasts_color"])
nB.color = "#[M.dna.features["breasts_color"]]"
else
nB.color = skintone2hex(H.skin_tone)
nB.size = "flat"
nB.cached_size = 0
nB.prev_size = 0
to_chat(M, "<span class='warning'>Your chest feels warm, tingling with newfound sensitivity.</b></span>")
M.reagents.remove_reagent(id, 5)
B = nB
//If they have them, increase size. If size is comically big, limit movement and rip clothes.
B.cached_size = B.cached_size + 0.05
if (B.cached_size >= 8.5 && B.cached_size < 9)
if(H.w_uniform || H.wear_suit)
var/target = M.get_bodypart(BODY_ZONE_CHEST)
to_chat(M, "<span class='warning'>Your breasts begin to strain against your clothes tightly!</b></span>")
M.adjustOxyLoss(5, 0)
M.apply_damage(1, BRUTE, target)
B.update()
..()
/datum/reagent/fermi/breast_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a female if male and ODing, doesn't touch nonbinary and object genders.
//Acute hepatic pharmacokinesis.
if(HAS_TRAIT(M, TRAIT_PHARMA))
var/obj/item/organ/liver/L = M.getorganslot("liver")
L.swelling+= 0.05
return ..()
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
var/obj/item/organ/genital/vagina/V = M.getorganslot("vagina")
var/obj/item/organ/genital/womb/W = M.getorganslot("womb")
if(M.gender == MALE)
M.gender = FEMALE
M.visible_message("<span class='boldnotice'>[M] suddenly looks more feminine!</span>", "<span class='boldwarning'>You suddenly feel more feminine!</span>")
if(P)
P.cached_length = P.cached_length - 0.05
P.update()
if(T)
T.Remove(M)
if(!V)
var/obj/item/organ/genital/vagina/nV = new
nV.Insert(M)
V = nV
if(!W)
var/obj/item/organ/genital/womb/nW = new
nW.Insert(M)
W = nW
..()
/datum/reagent/fermi/BEsmaller
name = "Modesty milk"
id = "BEsmaller"
description = "A volatile collodial mixture derived from milk that encourages mammary reduction via a potent estrogen mix."
color = "#E60584" // rgb: 96, 0, 255
taste_description = "a milky ice cream like flavour."
metabolization_rate = 0.25
can_synth = FALSE
/datum/reagent/fermi/BEsmaller/on_mob_life(mob/living/carbon/M)
var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
if(!B)
//Acute hepatic pharmacokinesis.
if(HAS_TRAIT(M, TRAIT_PHARMA))
var/obj/item/organ/liver/L = M.getorganslot("liver")
L.swelling-= 0.05
return ..()
//otherwise proceed as normal
return..()
B.cached_size = B.cached_size - 0.05
B.update()
..()
/datum/reagent/fermi/BEsmaller_hypo
name = "Rectify milk" //Rectify
id = "BEsmaller_hypo"
color = "#E60584"
taste_description = "a milky ice cream like flavour."
metabolization_rate = 0.25
description = "A medicine used to treat organomegaly in a patient's breasts."
var/sizeConv = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5)
can_synth = TRUE
/datum/reagent/fermi/BEsmaller_hypo/on_mob_add(mob/living/carbon/M)
. = ..()
if(!M.getorganslot("vagina"))
if(M.dna.features["has_vag"])
var/obj/item/organ/genital/vagina/nV = new
nV.Insert(M)
if(!M.getorganslot("womb"))
if(M.dna.features["has_womb"])
var/obj/item/organ/genital/womb/nW = new
nW.Insert(M)
/datum/reagent/fermi/BEsmaller_hypo/on_mob_life(mob/living/carbon/M)
var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
if(!B)
return..()
if(!M.dna.features["has_breasts"])//Fast fix for those who don't want it.
B.cached_size = B.cached_size - 0.1
B.update()
else if(B.cached_size > (sizeConv[M.dna.features["breasts_size"]]+0.1))
B.cached_size = B.cached_size - 0.05
B.update()
else if(B.cached_size < (sizeConv[M.dna.features["breasts_size"]])+0.1)
B.cached_size = B.cached_size + 0.05
B.update()
..()
////////////////////////////////////////////////////////////////////////////////////////////////////
// PENIS ENLARGE
///////////////////////////////////////////////////////////////////////////////////////////////////
//See breast explanation, it's the same but with taliwhackers
//instead of slower movement and attacks, it slows you and increases the total blood you need in your system.
//Since someone else made this in the time it took me to PR it, I merged them.
/datum/reagent/fermi/penis_enlarger // Due to popular demand...!
name = "Incubus draft"
id = "penis_enlarger"
description = "A volatile collodial mixture derived from various masculine solutions that encourages a larger gentleman's package via a potent testosterone mix, formula derived from a collaboration from Fermichem and Doctor Ronald Hyatt, who is well known for his phallus palace." //The toxic masculinity thing is a joke because I thought it would be funny to include it in the reagents, but I don't think many would find it funny? dumb
color = "#888888" // This is greyish..?
taste_description = "chinese dragon powder"
overdose_threshold = 17 //ODing makes you male and removes female genitals
metabolization_rate = 0.5
ImpureChem = "PEsmaller" //If you make an inpure chem, it stalls growth
InverseChemVal = 0.35
InverseChem = "PEsmaller" //At really impure vols, it just becomes 100% inverse and shrinks instead.
can_synth = FALSE
/datum/reagent/fermi/penis_enlarger/on_mob_add(mob/living/carbon/M)
. = ..()
if(!ishuman(M)) //Just monkeying around.
if(volume >= 15) //to prevent monkey penis farms
var/turf/T = get_turf(M)
var/obj/item/organ/genital/penis/P = new /obj/item/organ/genital/penis(T)
var/list/seen = viewers(8, T)
for(var/mob/S in seen)
to_chat(S, "<span class='warning'>A penis suddenly flies out of the [M]!</b></span>")
var/T2 = get_random_station_turf()
M.adjustBruteLoss(25)
M.Knockdown(50)
M.Stun(50)
P.throw_at(T2, 8, 1)
M.reagents.remove_reagent(id, volume)
return
var/mob/living/carbon/human/H = M
H.genital_override = TRUE
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
if(!P)
H.emergent_genital_call()
return
P.prev_length = P.length
P.cached_length = P.length
/datum/reagent/fermi/penis_enlarger/on_mob_life(mob/living/carbon/M) //Increases penis size, 5u = +1 inch.
if(!ishuman(M))
return
var/mob/living/carbon/human/H = M
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
if(!P)//They do have a preponderance for escapism, or so I've heard.
//If they have Acute hepatic pharmacokinesis, then route processing though liver.
if(HAS_TRAIT(M, TRAIT_PHARMA))
var/obj/item/organ/liver/L = M.getorganslot("liver")
if(L)
L.swelling+= 0.05
return..()
else
M.adjustToxLoss(1)
return..()
//otherwise proceed as normal
var/obj/item/organ/genital/penis/nP = new
nP.Insert(M)
if(nP)
nP.length = 1
to_chat(M, "<span class='warning'>Your groin feels warm, as you feel a newly forming bulge down below.</b></span>")
nP.cached_length = 1
nP.prev_length = 1
M.reagents.remove_reagent(id, 5)
P = nP
P.cached_length = P.cached_length + 0.1
if (P.cached_length >= 20.5 && P.cached_length < 21)
if(H.w_uniform || H.wear_suit)
var/target = M.get_bodypart(BODY_ZONE_CHEST)
to_chat(M, "<span class='warning'>Your cock begin to strain against your clothes tightly!</b></span>")
M.apply_damage(2.5, BRUTE, target)
P.update()
..()
/datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders.
//Acute hepatic pharmacokinesis.
if(HAS_TRAIT(M, TRAIT_PHARMA))
var/obj/item/organ/liver/L = M.getorganslot("liver")
L.swelling+= 0.05
return..()
var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
var/obj/item/organ/genital/vagina/V = M.getorganslot("vagina")
var/obj/item/organ/genital/womb/W = M.getorganslot("womb")
if(M.gender == FEMALE)
M.gender = MALE
M.visible_message("<span class='boldnotice'>[M] suddenly looks more masculine!</span>", "<span class='boldwarning'>You suddenly feel more masculine!</span>")
if(B)
B.cached_size = B.cached_size - 0.05
B.update()
if(V)
V.Remove(M)
if(W)
W.Remove(M)
if(!T)
var/obj/item/organ/genital/testicles/nT = new
nT.Insert(M)
T = nT
..()
/datum/reagent/fermi/PEsmaller // Due to cozmo's request...!
name = "Chastity draft"
id = "PEsmaller"
description = "A volatile collodial mixture derived from various masculine solutions that encourages a smaller gentleman's package via a potent testosterone mix, formula derived from a collaboration from Fermichem and Doctor Ronald Hyatt, who is well known for his phallus palace."
color = "#888888" // This is greyish..?
taste_description = "chinese dragon powder"
metabolization_rate = 0.5
can_synth = FALSE
/datum/reagent/fermi/PEsmaller/on_mob_life(mob/living/carbon/M)
var/mob/living/carbon/human/H = M
var/obj/item/organ/genital/penis/P = H.getorganslot("penis")
if(!P)
//Acute hepatic pharmacokinesis.
if(HAS_TRAIT(M, TRAIT_PHARMA))
var/obj/item/organ/liver/L = M.getorganslot("liver")
L.swelling-= 0.05
return..()
//otherwise proceed as normal
return..()
P.cached_length = P.cached_length - 0.1
P.update()
..()
/datum/reagent/fermi/PEsmaller_hypo
name = "Rectify draft"
id = "PEsmaller_hypo"
color = "#888888" // This is greyish..?
taste_description = "chinese dragon powder"
description = "A medicine used to treat organomegaly in a patient's penis."
metabolization_rate = 0.5
can_synth = TRUE
/datum/reagent/fermi/PEsmaller_hypo/on_mob_add(mob/living/carbon/M)
. = ..()
if(!M.getorganslot("testicles"))
if(M.dna.features["has_balls"])
var/obj/item/organ/genital/testicles/nT = new
nT.Insert(M)
/datum/reagent/fermi/PEsmaller_hypo/on_mob_life(mob/living/carbon/M)
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
if(!P)
return ..()
if(!M.dna.features["has_cock"])//Fast fix for those who don't want it.
P.cached_length = P.cached_length - 0.2
P.update()
else if(P.cached_length > (M.dna.features["cock_length"]+0.1))
P.cached_length = P.cached_length - 0.1
P.update()
else if(P.cached_length < (M.dna.features["cock_length"]+0.1))
P.cached_length = P.cached_length + 0.1
P.update()
..()
@@ -0,0 +1,462 @@
//Fermichem!!
//Fun chems for all the family
/datum/reagent/fermi
name = "Fermi" //This should never exist, but it does so that it can exist in the case of errors..
id = "fermi"
taste_description = "affection and love!"
can_synth = FALSE
//This should process fermichems to find out how pure they are and what effect to do.
/datum/reagent/fermi/on_mob_add(mob/living/carbon/M, amount)
. = ..()
if(!M)
return
if(purity < 0)
CRASH("Purity below 0 for chem: [id], Please let Fermis Know!")
if (purity == 1 || DoNotSplit == TRUE)
log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [id]")
return
else if (InverseChemVal > purity)//Turns all of a added reagent into the inverse chem
M.reagents.remove_reagent(id, amount, FALSE)
M.reagents.add_reagent(InverseChem, amount, FALSE, other_purity = 1)
log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [InverseChem]")
return
else
var/impureVol = amount * (1 - purity) //turns impure ratio into impure chem
M.reagents.remove_reagent(id, (impureVol), FALSE)
M.reagents.add_reagent(ImpureChem, impureVol, FALSE, other_purity = 1)
log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume - impureVol]u of [id]")
log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [ImpureChem]")
return
//When merging two fermichems, see above
/datum/reagent/fermi/on_merge(data, amount, mob/living/carbon/M, purity)//basically on_mob_add but for merging
. = ..()
if(!ishuman(M))
return
if (purity < 0)
CRASH("Purity below 0 for chem: [id], Please let Fermis Know!")
if (purity == 1 || DoNotSplit == TRUE)
log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [id] in themselves")
return
else if (InverseChemVal > purity)
M.reagents.remove_reagent(id, amount, FALSE)
M.reagents.add_reagent(InverseChem, amount, FALSE, other_purity = 1)
for(var/datum/reagent/fermi/R in M.reagents.reagent_list)
if(R.name == "")
R.name = name//Negative effects are hidden
log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [InverseChem]")
return
else
var/impureVol = amount * (1 - purity)
M.reagents.remove_reagent(id, impureVol, FALSE)
M.reagents.add_reagent(ImpureChem, impureVol, FALSE, other_purity = 1)
for(var/datum/reagent/fermi/R in M.reagents.reagent_list)
if(R.name == "")
R.name = name//Negative effects are hidden
log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume - impureVol]u of [id]")
log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [ImpureChem]")
return
////////////////////////////////////////////////////////////////////////////////////////////////////
// HATIMUIM
///////////////////////////////////////////////////////////////////////////////////////////////////
//Adds a heat upon your head, and tips their hat
//Also has a speech alteration effect when the hat is there
//Increase armour; 1 armour per 10u
//but if you OD it becomes negative.
/datum/reagent/fermi/hatmium //for hatterhat
name = "Hat growth serium"
id = "hatmium"
description = "A strange substance that draws in a hat from the hat dimention."
color = "#7c311a" // rgb: , 0, 255
taste_description = "like jerky, whiskey and an off aftertaste of a crypt."
metabolization_rate = 0.2
overdose_threshold = 25
DoNotSplit = TRUE
pH = 4
can_synth = TRUE
/datum/reagent/fermi/hatmium/on_mob_add(mob/living/carbon/human/M)
. = ..()
if(M.head)
var/obj/item/W = M.head
if(istype(W, /obj/item/clothing/head/hattip))
qdel(W)
else
M.dropItemToGround(W, TRUE)
var/hat = new /obj/item/clothing/head/hattip()
M.equip_to_slot(hat, SLOT_HEAD, 1, 1)
/datum/reagent/fermi/hatmium/on_mob_life(mob/living/carbon/human/M)
if(!istype(M.head, /obj/item/clothing/head/hattip))
return ..()
var/hatArmor = 0
if(!overdosed)
hatArmor = (purity/10)
else
hatArmor = - (purity/10)
if(hatArmor > 90)
return ..()
var/obj/item/W = M.head
W.armor = W.armor.modifyAllRatings(hatArmor)
..()
////////////////////////////////////////////////////////////////////////////////////////////////////
// FURRANIUM
///////////////////////////////////////////////////////////////////////////////////////////////////
//OwO whats this?
//Makes you nya and awoo
//At a certain amount of time in your system it gives you a fluffy tongue, if pure enough, it's permanent.
/datum/reagent/fermi/furranium
name = "Furranium"
id = "furranium"
description = "OwO whats this?"
color = "#f9b9bc" // rgb: , 0, 255
taste_description = "dewicious degenyewacy"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
InverseChemVal = 0
var/obj/item/organ/tongue/nT
DoNotSplit = TRUE
pH = 5
var/obj/item/organ/tongue/T
can_synth = TRUE
/datum/reagent/fermi/furranium/reaction_mob(mob/living/carbon/human/M, method=INJECT, reac_volume)
if(method == INJECT)
var/turf/T = get_turf(M)
M.adjustOxyLoss(15)
M.Knockdown(50)
M.Stun(50)
M.emote("cough")
var/obj/item/toy/plush/P = pick(subtypesof(/obj/item/toy/plush))
new P(T)
to_chat(M, "<span class='warning'>You feel a lump form in your throat, as you suddenly cough up what seems to be a hairball?</b></span>")
var/list/seen = viewers(8, T)
for(var/mob/S in seen)
to_chat(S, "<span class='warning'>[M] suddenly coughs up a [P.name]!</b></span>")
var/T2 = get_random_station_turf()
P.throw_at(T2, 8, 1)
..()
/datum/reagent/fermi/furranium/on_mob_life(mob/living/carbon/M)
switch(current_cycle)
if(1 to 9)
if(prob(20))
to_chat(M, "<span class='notice'>Your tongue feels... fluffy</span>")
if(10 to 15)
if(prob(10))
to_chat(M, "You find yourself unable to supress the desire to meow!")
M.emote("nya")
if(prob(10))
to_chat(M, "You find yourself unable to supress the desire to howl!")
M.emote("awoo")
if(prob(20))
var/list/seen = viewers(5, get_turf(M))//Sound and sight checkers
for(var/victim in seen)
if((istype(victim, /mob/living/simple_animal/pet/)) || (victim == M) || (!isliving(victim)))
seen = seen - victim
if(LAZYLEN(seen))
to_chat(M, "You notice [pick(seen)]'s bulge [pick("OwO!", "uwu!")]")
if(16)
T = M.getorganslot(ORGAN_SLOT_TONGUE)
var/obj/item/organ/tongue/nT = new /obj/item/organ/tongue/fluffy
T.Remove(M)
nT.Insert(M)
T.moveToNullspace()//To valhalla
to_chat(M, "<span class='big warning'>Your tongue feels... weally fwuffy!!</span>")
if(17 to INFINITY)
if(prob(5))
to_chat(M, "You find yourself unable to supress the desire to meow!")
M.emote("nya")
if(prob(5))
to_chat(M, "You find yourself unable to supress the desire to howl!")
M.emote("awoo")
if(prob(5))
var/list/seen = viewers(5, get_turf(M))//Sound and sight checkers
for(var/victim in seen)
if((istype(victim, /mob/living/simple_animal/pet/)) || (victim == M) || (!isliving(victim)))
seen = seen - victim
if(LAZYLEN(seen))
to_chat(M, "You notice [pick(seen)]'s bulge [pick("OwO!", "uwu!")]")
..()
/datum/reagent/fermi/furranium/on_mob_delete(mob/living/carbon/M)
if(purity < 1)//Only permanent if you're a good chemist.
nT = M.getorganslot(ORGAN_SLOT_TONGUE)
nT.Remove(M)
qdel(nT)
T.Insert(M)
to_chat(M, "<span class='notice'>You feel your tongue.... unfluffify...?</span>")
M.say("Pleh!")
else
log_game("FERMICHEM: [M] ckey: [M.key]'s tongue has been made permanent")
///////////////////////////////////////////////////////////////////////////////////////////////
//Nanite removal
//Writen by Trilby!! Embellsished a little by me.
/datum/reagent/fermi/nanite_b_gone
name = "Naninte bane"
id = "nanite_b_gone"
description = "A stablised EMP that is highly volatile, shocking small nano machines that will kill them off at a rapid rate in a patient's system."
color = "#708f8f"
overdose_threshold = 15
ImpureChem = "nanite_b_goneTox" //If you make an inpure chem, it stalls growth
InverseChemVal = 0.25
InverseChem = "nanite_b_goneTox" //At really impure vols, it just becomes 100% inverse
taste_description = "what can only be described as licking a battery."
pH = 9
can_synth = FALSE
/datum/reagent/fermi/nanite_b_gone/on_mob_life(mob/living/carbon/C)
//var/component/nanites/N = M.GetComponent(/datum/component/nanites)
GET_COMPONENT_FROM(N, /datum/component/nanites, C)
if(isnull(N))
return ..()
N.nanite_volume = -purity//0.5 seems to be the default to me, so it'll neuter them.
..()
/datum/reagent/fermi/nanite_b_gone/overdose_process(mob/living/carbon/C)
//var/component/nanites/N = M.GetComponent(/datum/component/nanites)
GET_COMPONENT_FROM(N, /datum/component/nanites, C)
if(prob(5))
to_chat(C, "<span class='warning'>The residual voltage from the nanites causes you to seize up!</b></span>")
C.electrocute_act(10, (get_turf(C)), 1, FALSE, FALSE, FALSE, TRUE)
if(prob(10))
//empulse((get_turf(C)), 3, 2)//So the nanites randomize
var/atom/T = C
T.emp_act(EMP_HEAVY)
to_chat(C, "<span class='warning'>The nanites short circuit within your system!</b></span>")
if(isnull(N))
return ..()
N.nanite_volume = -2
..()
/datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume)
O.emp_act(EMP_HEAVY)
/datum/reagent/fermi/nanite_b_goneTox
name = "Naninte bain"
id = "nanite_b_goneTox"
description = "Poorly made, and shocks you!"
metabolization_rate = 1
//Increases shock events.
/datum/reagent/fermi/nanite_b_goneTox/on_mob_life(mob/living/carbon/C)//Damages the taker if their purity is low. Extended use of impure chemicals will make the original die. (thus can't be spammed unless you've very good)
if(prob(15))
to_chat(C, "<span class='warning'>The residual voltage in your system causes you to seize up!</b></span>")
C.electrocute_act(10, (get_turf(C)), 1, FALSE, FALSE, FALSE, TRUE)
if(prob(50))
var/atom/T = C
T.emp_act(EMP_HEAVY)
to_chat(C, "<span class='warning'>You feel your hair stand on end as you glow brightly for a moment!</b></span>")
..()
///////////////////////////////////////////////////////////////////////////////////////////////
// MISC FERMICHEM CHEMS FOR SPECIFIC INTERACTIONS ONLY
///////////////////////////////////////////////////////////////////////////////////////////////
/datum/reagent/fermi/fermiAcid
name = "Acid vapour"
id = "fermiAcid"
description = "Someone didn't do like an otter, and add acid to water."
taste_description = "acid burns, ow"
color = "#FFFFFF"
pH = 0
can_synth = FALSE
/datum/reagent/fermi/fermiAcid/reaction_mob(mob/living/carbon/C, method)
var/target = C.get_bodypart(BODY_ZONE_CHEST)
var/acidstr
if(!C.reagents.pH || C.reagents.pH >5)
acidstr = 3
else
acidstr = ((5-C.reagents.pH)*2) //runtime - null.pH ?
C.adjustFireLoss(acidstr/2, 0)
if((method==VAPOR) && (!C.wear_mask))
if(prob(20))
to_chat(C, "<span class='warning'>You can feel your lungs burning!</b></span>")
var/obj/item/organ/lungs/L = C.getorganslot(ORGAN_SLOT_LUNGS)
L.adjustLungLoss(acidstr*2, C)
C.apply_damage(acidstr/5, BURN, target)
C.acid_act(acidstr, volume)
..()
/datum/reagent/fermi/fermiAcid/reaction_obj(obj/O, reac_volume)
if(ismob(O.loc)) //handled in human acid_act()
return
if((holder.pH > 5) || (volume < 0.1)) //Shouldn't happen, but just in case
return
reac_volume = round(volume,0.1)
var/acidstr = (5-holder.pH)*2 //(max is 10)
O.acid_act(acidstr, volume)
..()
/datum/reagent/fermi/fermiAcid/reaction_turf(turf/T, reac_volume)
if (!istype(T))
return
reac_volume = round(volume,0.1)
var/acidstr = (5-holder.pH)
T.acid_act(acidstr, volume)
..()
/datum/reagent/fermi/fermiTest
name = "Fermis Test Reagent"
id = "fermiTest"
description = "You should be really careful with this...! Also, how did you get this?"
addProc = TRUE
can_synth = FALSE
/datum/reagent/fermi/fermiTest/on_new(datum/reagents/holder)
..()
if(LAZYLEN(holder.reagent_list) == 1)
return
else
holder.remove_reagent("fermiTest", volume)//Avoiding recurrsion
var/location = get_turf(holder.my_atom)
if(purity < 0.34 || purity == 1)
var/datum/effect_system/foam_spread/s = new()
s.set_up(volume*2, location, holder)
s.start()
if((purity < 0.67 && purity >= 0.34)|| purity == 1)
var/datum/effect_system/smoke_spread/chem/s = new()
s.set_up(holder, volume*2, location)
s.start()
if(purity >= 0.67)
for (var/datum/reagent/reagent in holder.reagent_list)
if (istype(reagent, /datum/reagent/fermi))
var/datum/chemical_reaction/fermi/Ferm = GLOB.chemical_reagents_list[reagent.id]
Ferm.FermiExplode(src, holder.my_atom, holder, holder.total_volume, holder.chem_temp, holder.pH)
else
var/datum/chemical_reaction/Ferm = GLOB.chemical_reagents_list[reagent.id]
Ferm.on_reaction(holder, reagent.volume)
for(var/mob/M in viewers(8, location))
to_chat(M, "<span class='danger'>The solution reacts dramatically, with a meow!</span>")
playsound(get_turf(M), 'modular_citadel/sound/voice/merowr.ogg', 50, 1)
holder.clear_reagents()
/datum/reagent/fermi/fermiTox
name = "FermiTox"
id = "fermiTox"
description = "You should be really careful with this...! Also, how did you get this? You shouldn't have this!"
data = "merge"
color = "FFFFFF"
can_synth = FALSE
//I'm concerned this is too weak, but I also don't want deathmixes.
/datum/reagent/fermi/fermiTox/on_mob_life(mob/living/carbon/C, method)
if(C.dna && istype(C.dna.species, /datum/species/jelly))
C.adjustToxLoss(-2)
else
C.adjustToxLoss(2)
..()
/datum/reagent/fermi/acidic_buffer
name = "Acidic buffer"
id = "acidic_buffer"
description = "This reagent will consume itself and move the pH of a beaker towards acidity when added to another."
color = "#fbc314"
pH = 0
can_synth = TRUE
//Consumes self on addition and shifts pH
/datum/reagent/fermi/acidic_buffer/on_new(datapH)
data = datapH
if(LAZYLEN(holder.reagent_list) == 1)
return
holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume))
var/list/seen = viewers(5, get_turf(holder))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The beaker fizzes as the pH changes!</b></span>")
playsound(get_turf(holder.my_atom), 'sound/FermiChem/bufferadd.ogg', 50, 1)
holder.remove_reagent(id, volume, ignore_pH = TRUE)
..()
/datum/reagent/fermi/basic_buffer
name = "Basic buffer"
id = "basic_buffer"
description = "This reagent will consume itself and move the pH of a beaker towards alkalinity when added to another."
color = "#3853a4"
pH = 14
can_synth = TRUE
/datum/reagent/fermi/basic_buffer/on_new(datapH)
data = datapH
if(LAZYLEN(holder.reagent_list) == 1)
return
holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume))
var/list/seen = viewers(5, get_turf(holder))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The beaker froths as the pH changes!</b></span>")
playsound(get_turf(holder.my_atom), 'sound/FermiChem/bufferadd.ogg', 50, 1)
holder.remove_reagent(id, volume, ignore_pH = TRUE)
..()
//Turns you into a cute catto while it's in your system.
//If you manage to gamble perfectly, makes you have cat ears after you transform back. But really, you shouldn't end up with that with how random it is.
/datum/reagent/fermi/secretcatchem //Should I hide this from code divers? A secret cit chem?
name = "secretcatchem" //an attempt at hiding it
id = "secretcatchem"
description = "An illegal and hidden chem that turns people into cats. It's said that it's so rare and unstable that having it means you've been blessed."
taste_description = "hairballs and cream"
color = "#ffc224"
var/catshift = FALSE
var/mob/living/simple_animal/pet/cat/custom_cat/catto = null
can_synth = FALSE
/datum/reagent/fermi/secretcatchem/New()
name = "Catbalti[pick("a","u","e","y")]m [pick("apex", "prime", "meow")]"//rename
/datum/reagent/fermi/secretcatchem/on_mob_add(mob/living/carbon/human/H)
. = ..()
if(purity >= 0.8)//ONLY if purity is high, and given the stuff is random. It's very unlikely to get this to 1. It already requires felind too, so no new functionality there.
//exception(al) handler:
H.dna.features["ears"] = "Cat"
H.dna.features["mam_ears"] = "Cat"
H.verb_say = "mewls"
catshift = TRUE
playsound(get_turf(H), 'modular_citadel/sound/voice/merowr.ogg', 50, 1, -1)
to_chat(H, "<span class='notice'>You suddenly turn into a cat!</span>")
catto = new(get_turf(H.loc))
H.mind.transfer_to(catto)
catto.name = H.name
catto.desc = "A cute catto! They remind you of [H] somehow."
catto.color = "#[H.dna.features["mcolor"]]"
catto.pseudo_death = TRUE
H.forceMove(catto)
log_game("FERMICHEM: [H] ckey: [H.key] has been made into a cute catto.")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "cats")
//Just to deal with rascally ghosts
//ADD_TRAIT(catto, TRAIT_NODEATH, "catto")//doesn't work
//catto.health = 1000 //To simulate fake death, while preventing ghosts escaping.
/datum/reagent/fermi/secretcatchem/on_mob_life(mob/living/carbon/H)
if(catto.health <= 0) //So the dead can't ghost
if(prob(10))
to_chat(H, "<span class='notice'>You feel your body start to slowly shift back from it's dead form.</span>")
else if(prob(5))
playsound(get_turf(catto), 'modular_citadel/sound/voice/merowr.ogg', 50, 1, -1)
catto.say("lets out a meowrowr!*")
..()
/datum/reagent/fermi/secretcatchem/on_mob_delete(mob/living/carbon/H)
var/words = "Your body shifts back to normal."
H.forceMove(catto.loc)
catto.mind.transfer_to(H)
if(catshift == TRUE)
words += " ...But wait, are those cat ears?"
H.say("*wag")//force update sprites.
to_chat(H, "<span class='notice'>[words]</span>")
qdel(catto)
log_game("FERMICHEM: [H] ckey: [H.key] has returned to normal")
@@ -0,0 +1,95 @@
/datum/reagent/fermi/yamerol
name = "Yamerol"
id = "yamerol"
description = "For when you've trouble speaking or breathing, just yell YAMEROL! A chem that helps soothe any congestion problems and at high concentrations restores damaged lungs and tongues!"
taste_description = "a weird, syrupy flavour, yamero"
color = "#68e83a"
pH = 8.6
overdose_threshold = 35
ImpureChem = "yamerol_tox"
InverseChemVal = 0.4
InverseChem = "yamerol_tox"
can_synth = TRUE
/datum/reagent/fermi/yamerol/on_mob_life(mob/living/carbon/C)
var/obj/item/organ/tongue/T = C.getorganslot(ORGAN_SLOT_TONGUE)
var/obj/item/organ/lungs/L = C.getorganslot(ORGAN_SLOT_LUNGS)
if(T)
T.adjustTongueLoss(C, -2)//Fix the inputs me!
if(L)
L.adjustLungLoss(-5, C)
C.adjustOxyLoss(-2)
else
C.adjustOxyLoss(-10)
if(T)
if(T.name == "fluffy tongue")
var/obj/item/organ/tongue/nT
if(C.dna && C.dna.species && C.dna.species.mutanttongue)
nT = new C.dna.species.mutanttongue()
else
nT = new()
T.Remove(C)
qdel(T)
nT.Insert(C)
to_chat(C, "<span class='notice'>You feel your tongue.... unfluffify...?</span>")
holder.remove_reagent(src.id, "10")
..()
/datum/reagent/fermi/yamerol/overdose_process(mob/living/carbon/C)
var/obj/item/organ/tongue/oT = C.getorganslot(ORGAN_SLOT_TONGUE)
if(current_cycle == 1)
to_chat(C, "<span class='notice'>You feel the Yamerol sooth your tongue and lungs.</span>")
if(current_cycle > 10)
if(!C.getorganslot(ORGAN_SLOT_TONGUE))
var/obj/item/organ/tongue/T
if(C.dna && C.dna.species && C.dna.species.mutanttongue)
T = new C.dna.species.mutanttongue()
else
T = new()
T.Insert(C)
to_chat(C, "<span class='notice'>You feel your tongue reform in your mouth.</span>")
holder.remove_reagent(src.id, "10")
else
if((oT.name == "fluffy tongue") && (purity == 1))
var/obj/item/organ/tongue/T
if(C.dna && C.dna.species && C.dna.species.mutanttongue)
T = new C.dna.species.mutanttongue()
else
T = new()
oT.Remove(C)
qdel(oT)
T.Insert(C)
to_chat(C, "<span class='notice'>You feel your tongue.... unfluffify...?</span>")
holder.remove_reagent(src.id, "10")
if(!C.getorganslot(ORGAN_SLOT_LUNGS))
var/obj/item/organ/lungs/L = new()
L.Insert(C)
to_chat(C, "<span class='notice'>You feel your lungs reform in your chest.</span>")
holder.remove_reagent(src.id, "10")
C.adjustOxyLoss(-3)
..()
/datum/reagent/fermi/yamerol_tox
name = "Yamerol"
id = "yamerol_tox"
description = "For when you've trouble speaking or breathing, just yell YAMEROL! A chem that helps soothe any congestion problems and at high concentrations restores damaged lungs and tongues!"
taste_description = "a weird, syrupy flavour, yamero"
color = "#68e83a"
pH = 8.6
/datum/reagent/fermi/yamerol_tox/on_mob_life(mob/living/carbon/C)
var/obj/item/organ/tongue/T = C.getorganslot(ORGAN_SLOT_TONGUE)
var/obj/item/organ/lungs/L = C.getorganslot(ORGAN_SLOT_LUNGS)
if(T)
T.adjustTongueLoss(C, 1)
if(L)
L.adjustLungLoss(4, C)
C.adjustOxyLoss(3)
else
C.adjustOxyLoss(10)
..()
@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
"""
Created on Fri May 17 05:12:17 2019
@author: Fermi
"""
import numpy
import matplotlib as mpl
import matplotlib.pyplot as plt
@@ -0,0 +1,541 @@
/datum/chemical_reaction/fermi
mix_sound = 'sound/effects/bubbles.ogg'
//Called for every reaction step
/datum/chemical_reaction/fermi/proc/FermiCreate(holder)
return
//Called when reaction STOP_PROCESSING
/datum/chemical_reaction/fermi/proc/FermiFinish(datum/reagents/holder)
return
//Called when temperature is above a certain threshold, or if purity is too low.
/datum/chemical_reaction/fermi/proc/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH, Exploding = FALSE)
if (Exploding == TRUE)
return
if(!pH)//Dunno how things got here without a pH, but just in case
pH = 7
var/ImpureTot = 0
var/turf/T = get_turf(my_atom)
if(temp>500)//if hot, start a fire
switch(temp)
if (500 to 750)
for(var/turf/turf in range(1,T))
new /obj/effect/hotspot(turf)
if (751 to 1100)
for(var/turf/turf in range(2,T))
new /obj/effect/hotspot(turf)
if (1101 to 1500) //If you're crafty
for(var/turf/turf in range(3,T))
new /obj/effect/hotspot(turf)
if (1501 to 2500) //requested
for(var/turf/turf in range(4,T))
new /obj/effect/hotspot(turf)
if (2501 to 5000)
for(var/turf/turf in range(5,T))
new /obj/effect/hotspot(turf)
if (5001 to INFINITY)
for(var/turf/turf in range(6,T))
new /obj/effect/hotspot(turf)
message_admins("Fermi explosion at [T], with a temperature of [temp], pH of [pH], Impurity tot of [ImpureTot].")
log_game("Fermi explosion at [T], with a temperature of [temp], pH of [pH], Impurity tot of [ImpureTot].")
var/datum/reagents/R = new/datum/reagents(3000)//Hey, just in case.
var/datum/effect_system/smoke_spread/chem/s = new()
R.my_atom = my_atom //Give the gas a fingerprint
for (var/datum/reagent/reagent in my_atom.reagents.reagent_list) //make gas for reagents, has to be done this way, otherwise it never stops Exploding
R.add_reagent(reagent.id, reagent.volume/3) //Seems fine? I think I fixed the infinite explosion bug.
if (reagent.purity < 0.6)
ImpureTot = (ImpureTot + (1-reagent.purity)) / 2
if(pH < 4) //if acidic, make acid spray
R.add_reagent("fermiAcid", (volume/3))
if(R.reagent_list)
s.set_up(R, (volume/5), my_atom)
s.start()
if (pH > 10) //if alkaline, small explosion.
var/datum/effect_system/reagents_explosion/e = new()
e.set_up(round((volume/30)*(pH-9)), T, 0, 0)
e.start()
if(!ImpureTot == 0) //If impure, v.small emp (0.6 or less)
ImpureTot *= volume
var/empVol = CLAMP (volume/10, 0, 15)
empulse(T, empVol, ImpureTot/10, 1)
my_atom.reagents.clear_reagents() //just in case
return
/datum/chemical_reaction/fermi/eigenstate
name = "Eigenstasium"
id = "eigenstate"
results = list("eigenstate" = 0.1)
required_reagents = list("bluespace" = 0.1, "stable_plasma" = 0.1, "sugar" = 0.1)
mix_message = "the reaction zaps suddenly!"
//FermiChem vars:
OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions
OptimalTempMax = 600 // Upper end for above
ExplodeTemp = 650 //Temperature at which reaction explodes
OptimalpHMin = 7 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase)
OptimalpHMax = 9 // Higest value for above
ReactpHLim = 5 // How far out pH wil react, giving impurity place (Exponential phase)
CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst)
CurveSharpT = 1.5 // How sharp the temperature exponential curve is (to the power of value)
CurveSharppH = 3 // How sharp the pH exponential curve is (to the power of value)
ThermicConstant = 10 //Temperature change per 1u produced
HIonRelease = -0.02 //pH change per 1u reaction
RateUpLim = 3 //Optimal/max rate possible if all conditions are perfect
FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics
FermiExplode = FALSE //If the chemical explodes in a special way
PurityMin = 0.4 //The minimum purity something has to be above, otherwise it explodes.
/datum/chemical_reaction/fermi/eigenstate/FermiFinish(datum/reagents/holder, var/atom/my_atom)//Strange how this doesn't work but the other does.
if(!locate(/datum/reagent/fermi/eigenstate) in my_atom.reagents.reagent_list)
return
var/turf/open/location = get_turf(my_atom)
var/datum/reagent/fermi/eigenstate/E = locate(/datum/reagent/fermi/eigenstate) in my_atom.reagents.reagent_list
if(location)
E.location_created = location
E.data.["location_created"] = location
//serum
/datum/chemical_reaction/fermi/SDGF
name = "Synthetic-derived growth factor"
id = "SDGF"
results = list("SDGF" = 0.3)
required_reagents = list("stable_plasma" = 0.15, "clonexadone" = 0.15, "uranium" = 0.15, "synthflesh" = 0.15)
mix_message = "the reaction gives off a blorble!"
required_temp = 1
//FermiChem vars:
OptimalTempMin = 600 // Lower area of bell curve for determining heat based rate reactions
OptimalTempMax = 630 // Upper end for above
ExplodeTemp = 635 // Temperature at which reaction explodes
OptimalpHMin = 3 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase)
OptimalpHMax = 3.5 // Higest value for above
ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase)
CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst)
CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value)
CurveSharppH = 4 // How sharp the pH exponential curve is (to the power of value)
ThermicConstant = -10 // Temperature change per 1u produced
HIonRelease = 0.02 // pH change per 1u reaction (inverse for some reason)
RateUpLim = 1 // Optimal/max rate possible if all conditions are perfect
FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics
FermiExplode = TRUE // If the chemical explodes in a special way
PurityMin = 0.2
/datum/chemical_reaction/fermi/SDGF/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH)//Spawns an angery teratoma!
var/turf/T = get_turf(my_atom)
var/mob/living/simple_animal/slime/S = new(T,"green")
S.damage_coeff = list(BRUTE = 0.9 , BURN = 2, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
S.name = "Living teratoma"
S.real_name = "Living teratoma"
S.rabid = 1//Make them an angery boi
S.color = "#810010"
my_atom.reagents.clear_reagents()
var/list/seen = viewers(8, get_turf(my_atom))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The cells clump up into a horrifying tumour!</span>")
/datum/chemical_reaction/fermi/breast_enlarger
name = "Sucubus milk"
id = "breast_enlarger"
results = list("breast_enlarger" = 0.8)
required_reagents = list("salglu_solution" = 0.1, "milk" = 0.1, "synthflesh" = 0.2, "silicon" = 0.3, "aphro" = 0.3)
mix_message = "the reaction gives off a mist of milk."
//FermiChem vars:
OptimalTempMin = 200
OptimalTempMax = 800
ExplodeTemp = 900
OptimalpHMin = 6
OptimalpHMax = 10
ReactpHLim = 3
CatalystFact = 0
CurveSharpT = 2
CurveSharppH = 1
ThermicConstant = 1
HIonRelease = -0.1
RateUpLim = 5
FermiChem = TRUE
FermiExplode = TRUE
PurityMin = 0.1
/datum/chemical_reaction/fermi/breast_enlarger/FermiFinish(datum/reagents/holder, var/atom/my_atom)
var/datum/reagent/fermi/breast_enlarger/BE = locate(/datum/reagent/fermi/breast_enlarger) in my_atom.reagents.reagent_list
var/cached_volume = BE.volume
if(BE.purity < 0.35)
holder.remove_reagent(src.id, cached_volume)
holder.add_reagent("BEsmaller", cached_volume)
/datum/chemical_reaction/fermi/breast_enlarger/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH)
var/obj/item/organ/genital/breasts/B = new /obj/item/organ/genital/breasts(get_turf(my_atom))
var/list/seen = viewers(8, get_turf(my_atom))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The reaction suddenly condenses, creating a pair of breasts!</b></span>")
var/datum/reagent/fermi/breast_enlarger/BE = locate(/datum/reagent/fermi/breast_enlarger) in my_atom.reagents.reagent_list
B.size = ((BE.volume * BE.purity) / 10) //half as effective.
my_atom.reagents.clear_reagents()
/datum/chemical_reaction/fermi/penis_enlarger
name = "Incubus draft"
id = "penis_enlarger"
results = list("penis_enlarger" = 0.8)
required_reagents = list("blood" = 0.5, "synthflesh" = 0.2, "carbon" = 0.2, "aphro" = 0.2, "salglu_solution" = 0.1,)
mix_message = "the reaction gives off a spicy mist."
//FermiChem vars:
OptimalTempMin = 200
OptimalTempMax = 800
ExplodeTemp = 900
OptimalpHMin = 2
OptimalpHMax = 6
ReactpHLim = 3
CatalystFact = 0
CurveSharpT = 2
CurveSharppH = 1
ThermicConstant = 1
HIonRelease = 0.1
RateUpLim = 5
FermiChem = TRUE
FermiExplode = TRUE
PurityMin = 0.1
/datum/chemical_reaction/fermi/penis_enlarger/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH)
var/obj/item/organ/genital/penis/P = new /obj/item/organ/genital/penis(get_turf(my_atom))
var/list/seen = viewers(8, get_turf(my_atom))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The reaction suddenly condenses, creating a penis!</b></span>")
var/datum/reagent/fermi/penis_enlarger/PE = locate(/datum/reagent/fermi/penis_enlarger) in my_atom.reagents.reagent_list
P.length = ((PE.volume * PE.purity) / 10)//half as effective.
my_atom.reagents.clear_reagents()
/datum/chemical_reaction/fermi/penis_enlarger/FermiFinish(datum/reagents/holder, var/atom/my_atom)
var/datum/reagent/fermi/penis_enlarger/PE = locate(/datum/reagent/fermi/penis_enlarger) in my_atom.reagents.reagent_list
var/cached_volume = PE.volume
if(PE.purity < 0.35)
holder.remove_reagent(src.id, cached_volume)
holder.add_reagent("PEsmaller", cached_volume)
/datum/chemical_reaction/fermi/astral
name = "Astrogen"
id = "astral"
results = list("astral" = 0.5)
required_reagents = list("eigenstate" = 0.1, "plasma" = 0.3, "synaptizine" = 0.1, "aluminium" = 0.5)
//FermiChem vars:
OptimalTempMin = 700
OptimalTempMax = 800
ExplodeTemp = 1150
OptimalpHMin = 10
OptimalpHMax = 13
ReactpHLim = 2
CatalystFact = 0
CurveSharpT = 1
CurveSharppH = 1
ThermicConstant = 25
HIonRelease = 0.02
RateUpLim = 15
FermiChem = TRUE
FermiExplode = TRUE
PurityMin = 0.25
/datum/chemical_reaction/fermi/enthrall/ //check this
name = "MKUltra"
id = "enthrall"
results = list("enthrall" = 0.5)
//required_reagents = list("iron" = 1, "iodine" = 1) Test vars
//required_reagents = list("cocoa" = 0.1, "astral" = 0.1, "mindbreaker" = 0.1, "psicodine" = 0.1, "happiness" = 0.1)
required_reagents = list("cocoa" = 0.1, "bluespace" = 0.1, "mindbreaker" = 0.1, "psicodine" = 0.1, "happiness" = 0.1) //TEMPORARY UNTIL HEADMINS GIVE THE OKAY FOR MK USE.
required_catalysts = list("blood" = 1)
mix_message = "the reaction gives off a burgundy plume of smoke!"
//FermiChem vars:
OptimalTempMin = 780
OptimalTempMax = 820
ExplodeTemp = 840
OptimalpHMin = 12
OptimalpHMax = 13
ReactpHLim = 2
//CatalystFact = 0
CurveSharpT = 0.5
CurveSharppH = 4
ThermicConstant = 15
HIonRelease = 0.1
RateUpLim = 1
FermiChem = TRUE
FermiExplode = TRUE
PurityMin = 0.2
/datum/chemical_reaction/fermi/enthrall/FermiFinish(datum/reagents/holder, var/atom/my_atom)
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in my_atom.reagents.reagent_list
var/datum/reagent/fermi/enthrall/E = locate(/datum/reagent/fermi/enthrall) in my_atom.reagents.reagent_list
if(!B)
return
if(!B.data)
var/list/seen = viewers(5, get_turf(my_atom))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The reaction splutters and fails to react properly.</span>") //Just in case
E.purity = 0
if (B.data.["gender"] == "female")
E.data.["creatorGender"] = "Mistress"
E.creatorGender = "Mistress"
else
E.data.["creatorGender"] = "Master"
E.creatorGender = "Master"
E.data["creatorName"] = B.data.["real_name"]
E.creatorName = B.data.["real_name"]
E.data.["creatorID"] = B.data.["ckey"]
E.creatorID = B.data.["ckey"]
//So slimes can play too.
/datum/chemical_reaction/fermi/enthrall/slime
required_catalysts = list("slimejelly" = 1)
/datum/chemical_reaction/fermi/enthrall/slime/FermiFinish(datum/reagents/holder, var/atom/my_atom)
var/datum/reagent/toxin/slimejelly/B = locate(/datum/reagent/toxin/slimejelly) in my_atom.reagents.reagent_list//The one line change.
var/datum/reagent/fermi/enthrall/E = locate(/datum/reagent/fermi/enthrall) in my_atom.reagents.reagent_list
if(!B.data)
var/list/seen = viewers(5, get_turf(my_atom))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The reaction splutters and fails to react.</span>") //Just in case
E.purity = 0
if (B.data.["gender"] == "female")
E.data.["creatorGender"] = "Mistress"
E.creatorGender = "Mistress"
else
E.data.["creatorGender"] = "Master"
E.creatorGender = "Master"
E.data["creatorName"] = B.data.["real_name"]
E.creatorName = B.data.["real_name"]
E.data.["creatorID"] = B.data.["ckey"]
E.creatorID = B.data.["ckey"]
/datum/chemical_reaction/fermi/enthrall/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH)
var/turf/T = get_turf(my_atom)
var/datum/reagents/R = new/datum/reagents(1000)
var/datum/effect_system/smoke_spread/chem/s = new()
R.add_reagent("enthrallExplo", volume)
s.set_up(R, volume/2, T)
s.start()
my_atom.reagents.clear_reagents()
/datum/chemical_reaction/fermi/hatmium // done
name = "Hat growth serum"
id = "hatmium"
results = list("hatmium" = 0.5)
required_reagents = list("ethanol" = 0.1, "nutriment" = 0.3, "cooking_oil" = 0.2, "iron" = 0.1, "gold" = 0.3)
//mix_message = ""
//FermiChem vars:
OptimalTempMin = 500
OptimalTempMax = 700
ExplodeTemp = 750
OptimalpHMin = 2
OptimalpHMax = 5
ReactpHLim = 3
//CatalystFact = 0 //To do 1
CurveSharpT = 8
CurveSharppH = 0.5
ThermicConstant = -2
HIonRelease = -0.1
RateUpLim = 2
FermiChem = TRUE
FermiExplode = TRUE
PurityMin = 0.5
/datum/chemical_reaction/fermi/hatmium/FermiExplode(src, var/atom/my_atom, volume, temp, pH)
var/obj/item/clothing/head/hattip/hat = new /obj/item/clothing/head/hattip(get_turf(my_atom))
hat.animate_atom_living()
var/list/seen = viewers(8, get_turf(my_atom))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The makes an off sounding pop, as a hat suddenly climbs out of the beaker!</b></span>")
my_atom.reagents.clear_reagents()
/datum/chemical_reaction/fermi/furranium
name = "Furranium"
id = "furranium"
results = list("furranium" = 0.5)
required_reagents = list("aphro" = 0.1, "moonsugar" = 0.1, "silver" = 0.2, "salglu_solution" = 0.1)
mix_message = "You think you can hear a howl come from the beaker."
//FermiChem vars:
OptimalTempMin = 350
OptimalTempMax = 600
ExplodeTemp = 700
OptimalpHMin = 8
OptimalpHMax = 10
ReactpHLim = 2
//CatalystFact = 0 //To do 1
CurveSharpT = 2
CurveSharppH = 0.5
ThermicConstant = -10
HIonRelease = -0.1
RateUpLim = 2
FermiChem = TRUE
PurityMin = 0.3
//FOR INSTANT REACTIONS - DO NOT MULTIPLY LIMIT BY 10.
//There's a weird rounding error or something ugh.
//Nano-b-gone
/datum/chemical_reaction/fermi/nanite_b_gone//done test
name = "Naninte bain"
id = "nanite_b_gone"
results = list("nanite_b_gone" = 4)
required_reagents = list("synthflesh" = 1, "uranium" = 1, "iron" = 1, "salglu_solution" = 1)
mix_message = "the reaction gurgles, encapsulating the reagents in flesh before the emp can be set off."
required_temp = 450//To force fermireactions before EMP.
//FermiChem vars:
OptimalTempMin = 500
OptimalTempMax = 600
ExplodeTemp = 700
OptimalpHMin = 6
OptimalpHMax = 6.25
ReactpHLim = 3
//CatalystFact = 0 //To do 1
CurveSharpT = 0
CurveSharppH = 1
ThermicConstant = 5
HIonRelease = 0.01
RateUpLim = 1
FermiChem = TRUE
/datum/chemical_reaction/fermi/acidic_buffer//done test
name = "Acetic acid buffer"
id = "acidic_buffer"
results = list("acidic_buffer" = 2) //acetic acid
required_reagents = list("salglu_solution" = 0.2, "ethanol" = 0.6, "oxygen" = 0.6, "water" = 0.6)
//FermiChem vars:
OptimalTempMin = 250
OptimalTempMax = 500
ExplodeTemp = 9999 //check to see overflow doesn't happen!
OptimalpHMin = 2
OptimalpHMax = 6
ReactpHLim = 0
//CatalystFact = 0 //To do 1
CurveSharpT = 4
CurveSharppH = 0
ThermicConstant = 0
HIonRelease = -0.01
RateUpLim = 20
FermiChem = TRUE
/datum/chemical_reaction/fermi/acidic_buffer/FermiFinish(datum/reagents/holder, var/atom/my_atom) //might need this
if(!locate(/datum/reagent/fermi/acidic_buffer) in my_atom.reagents.reagent_list)
return
var/datum/reagent/fermi/acidic_buffer/Fa = locate(/datum/reagent/fermi/acidic_buffer) in my_atom.reagents.reagent_list
Fa.data = 0.1//setting it to 0 means byond thinks it's not there.
/datum/chemical_reaction/fermi/basic_buffer//done test
name = "Ethyl Ethanoate buffer"
id = "basic_buffer"
results = list("basic_buffer" = 1.5)
required_reagents = list("acidic_buffer" = 0.5, "ethanol" = 0.5, "water" = 0.5)
required_catalysts = list("sacid" = 1) //vagely acetic
//FermiChem vars:x
OptimalTempMin = 250
OptimalTempMax = 500
ExplodeTemp = 9999 //check to see overflow doesn't happen!
OptimalpHMin = 5
OptimalpHMax = 12
ReactpHLim = 0
//CatalystFact = 0 //To do 1
CurveSharpT = 4
CurveSharppH = 0
ThermicConstant = 0
HIonRelease = 0.01
RateUpLim = 15
FermiChem = TRUE
/datum/chemical_reaction/fermi/basic_buffer/FermiFinish(datum/reagents/holder, var/atom/my_atom) //might need this
if(!locate(/datum/reagent/fermi/basic_buffer) in my_atom.reagents.reagent_list)
return
var/datum/reagent/fermi/basic_buffer/Fb = locate(/datum/reagent/fermi/basic_buffer) in my_atom.reagents.reagent_list
Fb.data = 14
//secretcatchemcode, shh!! Of couse I hide it amongst cats. Though, I moved it with your requests.
//I'm not trying to be sneaky, I'm trying to keep it a secret!
//I don't know how to do hidden chems like Aurora
//ChemReactionVars:
/datum/chemical_reaction/fermi/secretcatchem //DONE
name = "secretcatchem"
id = "secretcatchem"
results = list("secretcatchem" = 0.5)
required_reagents = list("stable_plasma" = 0.1, "sugar" = 0.1, "cream" = 0.1, "clonexadone" = 0.1)//Yes this will make a plushie if you don't lucky guess. It'll eat all your reagents too.
required_catalysts = list("SDGF" = 1)
required_temp = 600
mix_message = "the reaction gives off a meow!"
mix_sound = "modular_citadel/sound/voice/merowr.ogg"
//FermiChem vars:
OptimalTempMin = 650
OptimalpHMin = 0
ReactpHLim = 2
CurveSharpT = 0
CurveSharppH = 0
ThermicConstant = 0
HIonRelease = 0
RateUpLim = 0.1
FermiChem = TRUE
FermiExplode = FALSE
PurityMin = 0.2
/datum/chemical_reaction/fermi/secretcatchem/New()
//rand doesn't seem to work with n^-e
OptimalTempMin += rand(-100, 100)
OptimalTempMax = (OptimalTempMin+rand(20, 200))
ExplodeTemp = (OptimalTempMax+rand(20, 200))
OptimalpHMin += rand(1, 10)
OptimalpHMax = (OptimalpHMin + rand(1, 5))
ReactpHLim += rand(-1.5, 2.5)
CurveSharpT += (rand(1, 500)/100)
CurveSharppH += (rand(1, 500)/100)
ThermicConstant += rand(-20, 20)
HIonRelease += (rand(-25, 25)/100)
RateUpLim += (rand(1, 1000)/100)
PurityMin += (rand(-1, 1)/10)
var/additions = list("aluminium", "silver", "gold", "plasma", "silicon", "uranium", "milk")
required_reagents[pick(additions)] = rand(0.1, 0.5)//weird
/datum/chemical_reaction/fermi/secretcatchem/FermiFinish(datum/reagents/holder, var/atom/my_atom)
SSblackbox.record_feedback("tally", "catgirlium")//log
/datum/chemical_reaction/fermi/secretcatchem/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH)
var/mob/living/simple_animal/pet/cat/custom_cat/catto = new(get_turf(my_atom))
var/list/seen = viewers(8, get_turf(my_atom))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The reaction suddenly gives out a meow, condensing into a chemcat!</b></span>")//meow!
playsound(get_turf(my_atom), 'modular_citadel/sound/voice/merowr.ogg', 50, 1, -1)
catto.name = "Chemcat"
catto.desc = "A cute chem cat, created by a lot of compicated and confusing chemistry!"
catto.color = "#770000"
my_atom.reagents.remove_all(5)
/datum/chemical_reaction/fermi/yamerol//done test
name = "Yamerol"
id = "yamerol"
results = list("yamerol" = 1.5)
required_reagents = list("perfluorodecalin" = 0.5, "salbutamol" = 0.5, "water" = 0.5)
//FermiChem vars:
OptimalTempMin = 300
OptimalTempMax = 500
ExplodeTemp = 800 //check to see overflow doesn't happen!
OptimalpHMin = 6.8
OptimalpHMax = 7.2
ReactpHLim = 4
//CatalystFact = 0 //To do 1
CurveSharpT = 5
CurveSharppH = 0.5
ThermicConstant = -15
HIonRelease = 0.1
RateUpLim = 2
FermiChem = TRUE
@@ -0,0 +1,69 @@
//Fermiclothes!
//Clothes made from FermiChem
/obj/item/clothing/head/hattip //I wonder if anyone else has played cryptworlds
name = "Sythetic hat"
icon = 'icons/obj/clothing/hats.dmi'
icon_state = "cowboy"
desc = "A sythesized hat, you can't seem to take it off. And tips their hat."
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
//item_flags = NODROP //Tips their hat!
/obj/item/clothing/head/hattip/attack_hand(mob/user)
if(iscarbon(user))
var/mob/living/carbon/C = user
if(is_ninja(C))
to_chat(C, "<span class='notice'>Using your superior ninja reflexes, you take the hat off before tipping.</span>")
return ..()
if(src == C.head)
C.emote("me",1,"tips their hat.",TRUE)
return
else
user.emote("me",1,"admires such a spiffy hat.",TRUE)
return ..()
/obj/item/clothing/head/hattip/MouseDrop(atom/over_object)
//You sure do love tipping your hat.
if(usr)
var/mob/living/carbon/C = usr
if(is_ninja(C))
to_chat(C, "<span class='notice'>Using your superior ninja reflexes, you take the hat off before tipping.</span>")
return ..()
if(src == C.head)
C.emote("me",1,"tips their hat.",TRUE)
return
..()
/obj/item/clothing/head/hattip/equipped(mob/M, slot)
. = ..()
if (slot == SLOT_HEAD)
RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
else
UnregisterSignal(M, COMSIG_MOB_SAY)
/obj/item/clothing/head/hattip/dropped(mob/M)
. = ..()
UnregisterSignal(M, COMSIG_MOB_SAY)
/obj/item/clothing/head/hattip/proc/handle_speech(datum/source, mob/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
var/mob/living/carbon/C = get_wearer()//user
var/obj/item/organ/tongue/T = C.getorganslot(ORGAN_SLOT_TONGUE)
if (T.name == "fluffy tongue")
if(prob(0.01))
message += "\" and tips their hat. \"swpy's sappin' my chem dispwencer uwu!!"
else
message += "\" and tips their hat. \"[pick("weehaw!", "bwoy howdy.", "dawn tuutin'.", "weww don't that beat aww.", "whoooowee, wouwd ya wook at that!", "whoooowee! makin' bwacon!", "cweam gwavy!", "yippekeeyah-heeyapeeah-kwayoh!", "mwove 'em uut!", "gwiddy up!")]"
speech_args[SPEECH_MESSAGE] = trim(message)
return
if(prob(0.01))
message += "\" and tips their hat. \"Spy's sappin' my chem dispenser!"//How did I not think of this earlier
message_admins("I really appreciate all the hard work you put into adminning citadel, I hope you're all having a good day and I hope this hidden and rare message_admins brightens up your day.")
else
message += "\" and tips their hat. \"[pick("Yeehaw!", "Boy howdy.", "Darn tootin'.", "Well don't that beat all.", "Whoooowee, would ya look at that!", "Whoooowee! Makin' bacon!", "Cream Gravy!", "Yippekeeyah-heeyapeeah-kayoh!", "Move 'em out!", "Giddy up!")]"
speech_args[SPEECH_MESSAGE] = trim(message)
/obj/item/clothing/head/hattip/proc/get_wearer()
return loc
@@ -0,0 +1,147 @@
/obj/item/fermichem/pHbooklet
name = "pH indicator booklet"
desc = "A booklet containing paper soaked in universal indicator."
icon_state = "pHbooklet"
icon = 'modular_citadel/icons/obj/FermiChem.dmi'
item_flags = NOBLUDGEON
var/numberOfPages = 50
resistance_flags = FLAMMABLE
w_class = WEIGHT_CLASS_TINY
//A little janky with pockets
/obj/item/fermichem/pHbooklet/attack_hand(mob/user)
if(user.get_held_index_of_item(src))//Does this check pockets too..?
if(numberOfPages == 50)
icon_state = "pHbookletOpen"
if(numberOfPages >= 1)
var/obj/item/fermichem/pHpaper/P = new /obj/item/fermichem/pHpaper
P.add_fingerprint(user)
P.forceMove(user.loc)
user.put_in_active_hand(P)
to_chat(user, "<span class='notice'>You take [P] out of \the [src].</span>")
numberOfPages--
playsound(user.loc, 'sound/items/poster_ripped.ogg', 50, 1)
add_fingerprint(user)
if(numberOfPages == 0)
icon_state = "pHbookletEmpty"
return
else
to_chat(user, "<span class='warning'>[src] is empty!</span>")
add_fingerprint(user)
return
. = ..()
if(. & COMPONENT_NO_INTERACT)
return
var/I = user.get_active_held_item()
if(!I)
user.put_in_active_hand(src)
/obj/item/fermichem/pHbooklet/MouseDrop()
var/mob/living/user = usr
if(numberOfPages >= 1)
var/obj/item/fermichem/pHpaper/P = new /obj/item/fermichem/pHpaper
P.add_fingerprint(user)
P.forceMove(user)
user.put_in_active_hand(P)
to_chat(user, "<span class='notice'>You take [P] out of \the [src].</span>")
numberOfPages--
playsound(user.loc, 'sound/items/poster_ripped.ogg', 50, 1)
add_fingerprint(user)
if(numberOfPages == 0)
icon_state = "pHbookletEmpty"
return
else
to_chat(user, "<span class='warning'>[src] is empty!</span>")
add_fingerprint(user)
return
..()
/obj/item/fermichem/pHpaper
name = "pH indicator strip"
desc = "A piece of paper that will change colour depending on the pH of a solution."
icon_state = "pHpaper"
icon = 'modular_citadel/icons/obj/FermiChem.dmi'
item_flags = NOBLUDGEON
color = "#f5c352"
var/used = FALSE
resistance_flags = FLAMMABLE
w_class = WEIGHT_CLASS_TINY
/obj/item/fermichem/pHpaper/afterattack(obj/item/reagent_containers/cont, mob/user, proximity)
if(!istype(cont))
return
if(used == TRUE)
to_chat(user, "<span class='warning'>[user] has already been used!</span>")
return
if(!LAZYLEN(cont.reagents.reagent_list))
return
switch(round(cont.reagents.pH, 1))
if(14 to INFINITY)
color = "#462c83"
if(13 to 14)
color = "#63459b"
if(12 to 13)
color = "#5a51a2"
if(11 to 12)
color = "#3853a4"
if(10 to 11)
color = "#3f93cf"
if(9 to 10)
color = "#0bb9b7"
if(8 to 9)
color = "#23b36e"
if(7 to 8)
color = "#3aa651"
if(6 to 7)
color = "#4cb849"
if(5 to 6)
color = "#b5d335"
if(4 to 5)
color = "#f7ec1e"
if(3 to 4)
color = "#fbc314"
if(2 to 3)
color = "#f26724"
if(1 to 2)
color = "#ef1d26"
if(-INFINITY to 1)
color = "#c6040c"
desc += " The paper looks to be around a pH of [round(cont.reagents.pH, 1)]"
used = TRUE
/obj/item/fermichem/pHmeter
name = "Chemistry Analyser"
desc = "A a electrode attached to a small circuit box that will tell you the pH of a solution. The screen currently displays nothing."
icon_state = "pHmeter"
icon = 'modular_citadel/icons/obj/FermiChem.dmi'
resistance_flags = FLAMMABLE
w_class = WEIGHT_CLASS_TINY
var/scanmode = 1
/obj/item/fermichem/pHmeter/attack_self(mob/user)
if(!scanmode)
to_chat(user, "<span class='notice'>You switch the chemical analyzer to give a detailed report.</span>")
scanmode = 1
else
to_chat(user, "<span class='notice'>You switch the chemical analyzer to give a reduced report.</span>")
scanmode = 0
/obj/item/fermichem/pHmeter/afterattack(atom/A, mob/user, proximity)
. = ..()
if(!istype(A, /obj/item/reagent_containers))
return
var/obj/item/reagent_containers/cont = A
if(LAZYLEN(cont.reagents.reagent_list) == null)
return
var/out_message
to_chat(user, "<i>The chemistry meter beeps and displays:</i>")
out_message += "<span class='notice'><b>Total volume: [round(cont.volume, 0.01)] Total pH: [round(cont.reagents.pH, 0.1)]\n"
if(cont.reagents.fermiIsReacting)
out_message += "<span class='warning'>A reaction appears to be occuring currently.<span class='notice'>\n"
out_message += "Chemicals found in the beaker:</b>\n"
for(var/datum/reagent/R in cont.reagents.reagent_list)
out_message += "<b>[R.volume]u of [R.name]</b>, <b>Purity:</b> [R.purity], [(scanmode?"[(R.overdose_threshold?"<b>Overdose:</b> [R.overdose_threshold]u, ":"")][(R.addiction_threshold?"<b>Addiction:</b> [R.addiction_threshold]u, ":"")]<b>Base pH:</b> [R.pH].":".")]\n"
if(scanmode)
out_message += "<b>Analysis:</b> [R.description]\n"
to_chat(user, "[out_message]</span>")
desc = "An electrode attached to a small circuit box that will analyse a beaker. It can be toggled to give a reduced or extended report. The screen currently displays [round(cont.reagents.pH, 0.1)]."
@@ -50,6 +50,9 @@
/obj/item/hypospray/mkii/tricord
start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/tricord
/obj/item/hypospray/mkii/enlarge
spawnwithvial = FALSE
/obj/item/hypospray/mkii/CMO
name = "hypospray mk.II deluxe"
allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small, /obj/item/reagent_containers/glass/bottle/vial/large)
@@ -14,7 +14,8 @@
"green hypovial" = "hypovial-a",
"orange hypovial" = "hypovial-k",
"purple hypovial" = "hypovial-p",
"black hypovial" = "hypovial-t"
"black hypovial" = "hypovial-t",
"pink hypovial" = "hypovial-pink"
)
always_reskinnable = TRUE
@@ -136,6 +137,16 @@
icon_state = "hypovial"
comes_with = list("tricordrazine" = 30)
/obj/item/reagent_containers/glass/bottle/vial/small/preloaded/breastreduction
name = "pink hypovial (breast treatment)"
icon_state = "hypovial-pink"
comes_with = list("BEsmaller_hypo" = 30)
/obj/item/reagent_containers/glass/bottle/vial/small/preloaded/penisreduction
name = "pink hypovial (penis treatment)"
icon_state = "hypovial-pink"
comes_with = list("PEsmaller_hypo" = 30)
/obj/item/reagent_containers/glass/bottle/vial/large/preloaded/CMO
name = "deluxe hypovial"
icon_state = "hypoviallarge-cmos"
@@ -8,6 +8,7 @@
data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null)
reagent_state = LIQUID
color = "#FFFFFF" // rgb: 255, 255, 255
can_synth = FALSE
nutriment_factor = 0.5 * REAGENTS_METABOLISM
/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume)
@@ -19,7 +20,6 @@
var/obj/effect/decal/cleanable/semen/S = locate() in T
if(!S)
S = new(T)
S.reagents.add_reagent("semen", reac_volume)
if(data["blood_DNA"])
S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
@@ -50,6 +50,7 @@
data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null)
reagent_state = LIQUID
color = "#AAAAAA77"
can_synth = FALSE
nutriment_factor = 0.5 * REAGENTS_METABOLISM
/obj/effect/decal/cleanable/femcum
@@ -82,7 +83,6 @@
var/obj/effect/decal/cleanable/femcum/S = locate() in T
if(!S)
S = new(T)
S.reagents.add_reagent("femcum", reac_volume)
if(data["blood_DNA"])
S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
@@ -47,7 +47,7 @@
var/tmp/next_process = 0 // Waiting for this SSbellies times_fired to process again.
var/tmp/list/items_preserved = list() // Stuff that wont digest so we shouldn't process it again.
var/tmp/next_emote = 0 // When we're supposed to print our next emote, as a belly controller tick #
var/tmp/recent_sound = FALSE // Prevent audio spam
var/tmp/recent_sound // Prevent audio spam
var/tmp/last_hearcheck = 0
var/tmp/list/hearing_mobs
@@ -167,12 +167,13 @@
to_chat(owner,"<span class='notice'>[thing] slides into your [lowertext(name)].</span>")
//Sound w/ antispam flag setting
if(is_wet && !recent_sound)
for(var/mob/M in get_hearers_in_view(2, get_turf(owner)))
if(M.client && (M.client.prefs.cit_toggles & EATING_NOISES))
var/sound/devourments = GLOB.vore_sounds[vore_sound]
playsound(get_turf(owner),devourments,50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
recent_sound = TRUE
if(is_wet && (world.time > recent_sound))
var/turf/source = get_turf(owner)
var/sound/eating = GLOB.vore_sounds[vore_sound]
for(var/mob/living/M in get_hearers_in_view(3, source))
if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
SEND_SOUND(M, eating)
recent_sound = (world.time + 20 SECONDS)
//Messages if it's a mob
if(isliving(thing))
@@ -187,7 +188,7 @@
var/atom/destination = drop_location()
//Don't bother if we don't have contents
if(!contents.len)
return 0
return FALSE
var/count = 0
for(var/thing in contents)
@@ -206,10 +207,10 @@
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "emptyprey", /datum/mood_event/emptyprey)
AM.forceMove(destination) // Move the belly contents into the same location as belly's owner.
count++
for(var/mob/M in get_hearers_in_view(2, get_turf(owner)))
for(var/mob/living/M in get_hearers_in_view(2, get_turf(owner)))
if(M.client && (M.client.prefs.cit_toggles & EATING_NOISES))
var/sound/releasement = GLOB.release_sounds[release_sound]
playsound(get_turf(owner),releasement,50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
SEND_SOUND(M, releasement)
//Clean up our own business
items_preserved.Cut()
@@ -233,10 +234,10 @@
M.forceMove(drop_location()) // Move the belly contents into the same location as belly's owner.
items_preserved -= M
if(!silent)
for(var/mob/H in get_hearers_in_view(2, get_turf(owner)))
for(var/mob/living/H in get_hearers_in_view(2, get_turf(owner)))
if(H.client && (H.client.prefs.cit_toggles & EATING_NOISES))
var/sound/releasement = GLOB.release_sounds[release_sound]
playsound(get_turf(owner),releasement,50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
SEND_SOUND(H, releasement)
if(istype(M,/mob/living))
var/mob/living/ML = M
@@ -285,10 +286,6 @@
SEND_SIGNAL(prey, COMSIG_CLEAR_MOOD_EVENT, "emptyprey", /datum/mood_event/emptyprey)
prey.forceMove(src)
var/sound/preyloop = sound('sound/vore/prey/loop.ogg', repeat = TRUE)
if(is_wet)
prey.playsound_local(loc,preyloop,70,0, channel = CHANNEL_PREYLOOP)
owner.updateVRPanel()
@@ -317,10 +314,12 @@
M.cure_blind("belly_[REF(src)]")
target.nom_mob(content, target.owner)
if(!silent)
for(var/mob/M in get_hearers_in_view(5, get_turf(owner)))
if(M.client && (M.client.prefs.cit_toggles & EATING_NOISES))
var/sound/devourments = GLOB.vore_sounds[vore_sound]
playsound(get_turf(owner),devourments,50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
var/turf/source = get_turf(owner)
var/sound/eating = GLOB.vore_sounds[vore_sound]
for(var/mob/living/M in get_hearers_in_view(3, source))
if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
SEND_SOUND(M, eating)
owner.updateVRPanel()
for(var/mob/living/M in contents)
M.updateVRPanel()
@@ -524,22 +523,25 @@
struggle_outer_message = "<span class='alert'>" + struggle_outer_message + "</span>"
struggle_user_message = "<span class='alert'>" + struggle_user_message + "</span>"
var/turf/source = get_turf(owner)
var/sound/struggle_snuggle = sound(get_sfx("struggle_sound"))
var/sound/struggle_rustle = sound(get_sfx("rustle"))
if(is_wet)
for(var/mob/M in get_hearers_in_view(2, get_turf(owner)))
if(M.client && (M.client.prefs.cit_toggles & EATING_NOISES))
playsound(get_turf(owner),"struggle_sound",35,0,-5,1,ignore_walls = FALSE,channel=CHANNEL_PRED)
R.stop_sound_channel(CHANNEL_PRED)
var/sound/prey_struggle = sound(get_sfx("prey_struggle"))
R.playsound_local(get_turf(R),prey_struggle,45,0)
for(var/mob/living/M in get_hearers_in_view(3, source))
if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
SEND_SOUND(M, struggle_snuggle)
else
for(var/mob/M in get_hearers_in_view(2, get_turf(owner)))
if(M.client && (M.client.prefs.cit_toggles & EATING_NOISES))
playsound(get_turf(owner),"rustle",35,0,-5,1,ignore_walls = FALSE,channel=CHANNEL_PRED)
for(var/mob/living/M in get_hearers_in_view(3, source))
if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
SEND_SOUND(M, struggle_rustle)
for(var/mob/M in get_hearers_in_view(3, get_turf(owner)))
var/list/watching = hearers(3, owner)
for(var/mob/living/M in watching)
if(M.client && (M.client.prefs.cit_toggles & EATING_NOISES)) //Might as well censor the normies here too.
M.show_message(struggle_outer_message, 1) // visible
to_chat(R,struggle_user_message)
if(escapable) //If the stomach has escapable enabled.
@@ -26,10 +26,13 @@
if(isbelly(M.loc))
if(world.time > M.next_preyloop)
if(is_wet)
if(!M.client)
continue
M.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case
var/sound/preyloop = sound('sound/vore/prey/loop.ogg', repeat = TRUE)
M.playsound_local(get_turf(src),preyloop,80,0, channel = CHANNEL_PREYLOOP)
M.next_preyloop = world.time + 52 SECONDS
if(M.client.prefs.cit_toggles & DIGESTION_NOISES)
var/sound/preyloop = sound('sound/vore/prey/loop.ogg', repeat = TRUE)
M.playsound_local(get_turf(src),preyloop, 80,0, channel = CHANNEL_PREYLOOP)
M.next_preyloop = (world.time + 52 SECONDS)
/////////////////////////// Exit Early ////////////////////////////
@@ -63,12 +66,12 @@
if(prob(25))
if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
for(var/mob/H in get_hearers_in_view(3, source))
for(var/mob/living/H in get_hearers_in_view(3, source))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
for(var/mob/living/H in hearing_mobs)
if(!isbelly(H.loc))
H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
else if(H in contents)
@@ -100,12 +103,12 @@
owner.nutrition += 400 // so eating dead mobs gives you *something*.
if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
for(var/mob/H in get_hearers_in_view(3, source))
for(var/mob/living/H in get_hearers_in_view(3, source))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
for(var/mob/living/H in hearing_mobs)
if(!isbelly(H.loc))
H.playsound_local(source, null, 45, falloff = 0, S = pred_death)
else if(H in contents)
@@ -135,12 +138,12 @@
if(prob(25))
if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
for(var/mob/H in get_hearers_in_view(3, source))
for(var/mob/living/H in get_hearers_in_view(3, source))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
for(var/mob/living/H in hearing_mobs)
if(!isbelly(H.loc))
H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
else if(H in contents)
@@ -159,12 +162,12 @@
if(prob(35))
if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
for(var/mob/H in get_hearers_in_view(3, source))
for(var/mob/living/H in get_hearers_in_view(3, source))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
for(var/mob/living/H in hearing_mobs)
if(!isbelly(H.loc))
H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
else if(H in contents)
@@ -179,12 +182,12 @@
if(prob(10))//Less often than gurgles. People might leave this on forever.
if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
for(var/mob/H in get_hearers_in_view(3, source))
for(var/mob/living/H in get_hearers_in_view(3, source))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
for(var/mob/living/H in hearing_mobs)
if(!isbelly(H.loc))
H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
else if(H in contents)
@@ -221,12 +224,12 @@
if(prob(55)) //if you're hearing this, you're a vore ho anyway.
if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
for(var/mob/H in get_hearers_in_view(3, source))
for(var/mob/living/H in get_hearers_in_view(3, source))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
for(var/mob/living/H in hearing_mobs)
if(!isbelly(H.loc))
H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
else if(H in contents)
@@ -254,12 +257,12 @@
M.visible_message("<span class='notice'>You watch as [owner]'s guts loudly rumble as it finishes off a meal.</span>")
if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
for(var/mob/H in get_hearers_in_view(3, source))
for(var/mob/living/H in get_hearers_in_view(3, source))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
for(var/mob/living/H in hearing_mobs)
if(!isbelly(H.loc))
H.playsound_local(source, null, 45, falloff = 0, S = pred_death)
else if(H in contents)
@@ -60,18 +60,6 @@
B.can_taste = 1
return TRUE
/*
// Hide vore organs in contents
//
/datum/proc/view_variables_filter_contents(list/L)
return 0
/mob/living/view_variables_filter_contents(list/L)
. = ..()
var/len_before = L.len
L -= vore_organs
. += len_before - L.len*/
// Handle being clicked, perhaps with something to devour
//
@@ -121,21 +109,12 @@
/mob/living/proc/feed_grabbed_to_self(var/mob/living/user, var/mob/living/prey)
var/belly = user.vore_selected
return perform_the_nom(user, prey, user, belly)
/*
/mob/living/proc/eat_held_mob(var/mob/living/user, var/mob/living/prey, var/mob/living/pred)
var/belly
if(user != pred)
belly = input("Choose Belly") in pred.vore_organs
else
belly = pred.vore_selected
return perform_the_nom(user, prey, pred, belly)*/
/mob/living/proc/feed_self_to_grabbed(var/mob/living/user, var/mob/living/pred)
var/belly = input("Choose Belly") in pred.vore_organs
return perform_the_nom(user, user, pred, belly)
/mob/living/proc/feed_grabbed_to_other(var/mob/living/user, var/mob/living/prey, var/mob/living/pred)
// return//disabled until I can make that toggle work
var/belly = input("Choose Belly") in pred.vore_organs
return perform_the_nom(user, prey, pred, belly)
@@ -182,9 +161,13 @@
// If we got this far, nom successful! Announce it!
user.visible_message(success_msg)
for(var/mob/M in get_hearers_in_view(5, get_turf(user)))
// incredibly contentious eating noises time
var/turf/source = get_turf(user)
var/sound/eating = GLOB.vore_sounds[belly.vore_sound]
for(var/mob/living/M in get_hearers_in_view(3, source))
if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
playsound(get_turf(user),"[belly.vore_sound]",50,0,-5,0,ignore_walls = FALSE,channel=CHANNEL_PRED)
SEND_SOUND(M, eating)
// Actually shove prey into the belly.
belly.nom_mob(prey, user)
@@ -214,41 +197,7 @@
//
//End vore code.
/*
//Handle case: /obj/item/holder
if(/obj/item/holder/micro)
var/obj/item/holder/H = I
if(!isliving(user)) return 0 // Return 0 to continue upper procs
var/mob/living/attacker = user // Typecast to living
if (is_vore_predator(src))
for (var/mob/living/M in H.contents)
attacker.eat_held_mob(attacker, M, src)
return 1 //Return 1 to exit upper procs
else
log_attack("[attacker] attempted to feed [H.contents] to [src] ([src.type]) but it failed.")
// I just can't imagine this not being complained about
//Handle case: /obj/item/radio/beacon
if(/obj/item/radio/beacon)
var/confirm = alert(user, "[src == user ? "Eat the beacon?" : "Feed the beacon to [src]?"]", "Confirmation", "Yes!", "Cancel")
if(confirm == "Yes!")
var/bellychoice = input("Which belly?","Select A Belly") in src.vore_organs
var/datum/belly/B = src.vore_organs[bellychoice]
src.visible_message("<span class='warning'>[user] is trying to stuff a beacon into [src]'s [bellychoice]!</span>","<span class='warning'>[user] is trying to stuff a beacon into you!</span>")
if(do_after(user,30,src))
user.drop_item()
I.loc = src
B.internal_contents += I
src.visible_message("<span class='warning'>[src] is fed the beacon!</span>","You're fed the beacon!")
playsound(get_turf(src), B.vore_sound,50,0,-6,0)
return 1
else
return 1 //You don't get to hit someone 'later'
return 0
*/
//
// Our custom resist catches for /mob/living
@@ -272,7 +221,7 @@
if(isbelly(loc))
src.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case
var/sound/preyloop = sound('sound/vore/prey/loop.ogg', repeat = TRUE)
src.playsound_local(get_turf(src),preyloop,80,0, channel = CHANNEL_PREYLOOP)
SEND_SOUND(src, preyloop)
else
to_chat(src, "<span class='alert'>You aren't inside anything, you clod.</span>")
@@ -57,7 +57,7 @@
/datum/vore_look/proc/gen_vui(var/mob/living/user)
var/dat
dat += "Remember to toggle the vore mode, it's to the left of your combat toggle. Open mouth means you're voracious!<br>"
dat += "Remember that your prey is blind, use audible mode subtle messages to communicate to them with posts!<br>"
dat += "Remember that the prey is blind, use audible mode subtle messages to communicate to them with posts!<br>"
dat += "<HR>"
var/atom/userloc = user.loc
if (isbelly(userloc))
@@ -554,7 +554,7 @@
if(href_list["b_releasesoundtest"])
var/sound/releasetest = GLOB.release_sounds[selected.release_sound]
if(releasetest)
user << releasetest
SEND_SOUND(user, releasetest)
if(href_list["b_sound"])
var/choice = input(user,"Currently set to [selected.vore_sound]","Select Sound") as null|anything in GLOB.vore_sounds
@@ -567,7 +567,7 @@
if(href_list["b_soundtest"])
var/sound/voretest = GLOB.vore_sounds[selected.vore_sound]
if(voretest)
user << voretest
SEND_SOUND(user, voretest)
if(href_list["b_tastes"])
selected.can_taste = !selected.can_taste