Merge remote-tracking branch 'origin/master' into donator_grouping
This commit is contained in:
@@ -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 host’s 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
|
||||
|
||||
Reference in New Issue
Block a user