+65
-31
@@ -2,32 +2,57 @@
|
||||
|
||||
#define CHECK_DNA_AND_SPECIES(C) if((!(C.dna)) || (!(C.dna.species))) return
|
||||
|
||||
//Defines copying names of mutations in all cases, make sure to change this if you change mutation's name
|
||||
#define HULK "Hulk"
|
||||
#define XRAY "X Ray Vision"
|
||||
#define COLDRES "Cold Resistance"
|
||||
#define TK "Telekinesis"
|
||||
#define NERVOUS "Nervousness"
|
||||
#define EPILEPSY "Epilepsy"
|
||||
#define MUTATE "Unstable DNA"
|
||||
#define COUGH "Cough"
|
||||
#define DWARFISM "Dwarfism"
|
||||
#define CLOWNMUT "Clumsiness"
|
||||
#define TOURETTES "Tourettes Syndrome"
|
||||
#define DEAFMUT "Deafness"
|
||||
#define BLINDMUT "Blindness"
|
||||
#define RACEMUT "Monkified"
|
||||
#define BADSIGHT "Near Sightness"
|
||||
#define LASEREYES "Laser Eyes"
|
||||
#define CHAMELEON "Chameleon"
|
||||
#define WACKY "Wacky"
|
||||
#define MUT_MUTE "Mute"
|
||||
#define SMILE "Smile"
|
||||
#define STONER "Stoner"
|
||||
#define UNINTELLIGIBLE "Unintelligible"
|
||||
#define SWEDISH "Swedish"
|
||||
#define CHAV "Chav"
|
||||
#define ELVIS "Elvis"
|
||||
//Defines copying names of mutations in all cases, make sure to change this if you change mutation's type
|
||||
#define HULK /datum/mutation/human/hulk
|
||||
#define XRAY /datum/mutation/human/thermal/x_ray
|
||||
#define SPACEMUT /datum/mutation/human/space_adaptation
|
||||
#define TK /datum/mutation/human/telekinesis
|
||||
#define NERVOUS /datum/mutation/human/nervousness
|
||||
#define EPILEPSY /datum/mutation/human/epilepsy
|
||||
#define MUTATE /datum/mutation/human/bad_dna
|
||||
#define COUGH /datum/mutation/human/cough
|
||||
#define DWARFISM /datum/mutation/human/dwarfism
|
||||
#define GIGANTISM /datum/mutation/human/gigantism
|
||||
#define CLOWNMUT /datum/mutation/human/clumsy
|
||||
#define TOURETTES /datum/mutation/human/tourettes
|
||||
#define DEAFMUT /datum/mutation/human/deaf
|
||||
#define BLINDMUT /datum/mutation/human/blind
|
||||
#define RACEMUT /datum/mutation/human/race
|
||||
#define BADSIGHT /datum/mutation/human/nearsight
|
||||
#define LASEREYES /datum/mutation/human/laser_eyes
|
||||
#define CHAMELEON /datum/mutation/human/chameleon
|
||||
#define WACKY /datum/mutation/human/wacky
|
||||
#define MUT_MUTE /datum/mutation/human/mute
|
||||
#define SMILE /datum/mutation/human/smile
|
||||
#define STONER /datum/mutation/human/stoner
|
||||
#define UNINTELLIGIBLE /datum/mutation/human/unintelligible
|
||||
#define SWEDISH /datum/mutation/human/swedish
|
||||
#define CHAV /datum/mutation/human/chav
|
||||
#define ELVIS /datum/mutation/human/elvis
|
||||
#define RADIOACTIVE /datum/mutation/human/radioactive
|
||||
#define GLOWY /datum/mutation/human/glow
|
||||
#define ANTIGLOWY /datum/mutation/human/glow/anti
|
||||
#define TELEPATHY /datum/mutation/human/telepathy
|
||||
#define FIREBREATH /datum/mutation/human/firebreath
|
||||
#define VOID /datum/mutation/human/void
|
||||
#define TONGUESPIKE /datum/mutation/human/tongue_spike
|
||||
#define TONGUESPIKECHEM /datum/mutation/human/tongue_spike/chem
|
||||
#define STRONG /datum/mutation/human/strong
|
||||
#define STIMMED /datum/mutation/human/stimmed
|
||||
#define FIRESWEAT /datum/mutation/human/fire
|
||||
#define THERMAL /datum/mutation/human/thermal
|
||||
#define ANTENNA /datum/mutation/human/antenna
|
||||
#define PARANOIA /datum/mutation/human/paranoia
|
||||
#define MINDREAD /datum/mutation/human/mindreader
|
||||
#define INSULATED /datum/mutation/human/insulated
|
||||
#define SHOCKTOUCH /datum/mutation/human/shock
|
||||
#define OLFACTION /datum/mutation/human/olfaction
|
||||
#define ACIDFLESH /datum/mutation/human/acidflesh
|
||||
#define BADBLINK /datum/mutation/human/badblink
|
||||
#define SPASTIC /datum/mutation/human/spastic
|
||||
#define GELADIKINESIS /datum/mutation/human/geladikinesis
|
||||
#define CRYOKINESIS /datum/mutation/human/cryokinesis
|
||||
#define SPIDER_WEB /datum/mutation/human/webbing
|
||||
|
||||
#define UI_CHANGED "ui changed"
|
||||
#define UE_CHANGED "ue changed"
|
||||
@@ -39,10 +64,12 @@
|
||||
//Types of usual mutations
|
||||
#define POSITIVE 1
|
||||
#define NEGATIVE 2
|
||||
#define MINOR_NEGATIVE 3
|
||||
#define MINOR_NEGATIVE 4
|
||||
|
||||
//Mutations that cant be taken from genetics and are not in SE
|
||||
#define NON_SCANNABLE -1
|
||||
//Mutation classes. Normal being on them, extra being additional mutations with instability and other being stuff you dont want people to fuck with like wizard mutate
|
||||
#define MUT_NORMAL 1
|
||||
#define MUT_EXTRA 2
|
||||
#define MUT_OTHER 3
|
||||
|
||||
//DNA - Because fuck you and your magic numbers being all over the codebase.
|
||||
#define DNA_BLOCK_SIZE 3
|
||||
@@ -63,7 +90,8 @@
|
||||
#define DNA_MUTANTMARKING_BLOCK 13
|
||||
#define DNA_TAUR_BLOCK 14
|
||||
|
||||
#define DNA_STRUC_ENZYMES_BLOCKS 18
|
||||
#define DNA_SEQUENCE_LENGTH 4
|
||||
#define DNA_MUTATION_BLOCKS 8
|
||||
#define DNA_UNIQUE_ENZYMES_LEN 32
|
||||
|
||||
//Transformation proc stuff
|
||||
@@ -141,7 +169,13 @@
|
||||
#define STANDARD_ORGAN_HEALING (1/(15 MINUTES / (2 SECONDS)))
|
||||
#define STANDARD_ORGAN_DECAY (1/(15 MINUTES / (2 SECONDS))) //designed to fail organs when left to decay for ~15 minutes. 2 SECOND is SSmobs tickrate.
|
||||
|
||||
|
||||
//used for the can_chromosome var on mutations
|
||||
#define CHROMOSOME_NEVER 0
|
||||
#define CHROMOSOME_NONE 1
|
||||
#define CHROMOSOME_USED 2
|
||||
|
||||
#define G_MALE 1
|
||||
#define G_FEMALE 2
|
||||
#define G_PLURAL 3
|
||||
#define G_NEUTER 4
|
||||
#define G_NEUTER 4
|
||||
@@ -118,3 +118,4 @@
|
||||
|
||||
#define STATUS_EFFECT_RAINBOWPROTECTION /datum/status_effect/rainbow_protection //Invulnerable and pacifistic
|
||||
#define STATUS_EFFECT_SLIMESKIN /datum/status_effect/slimeskin //Increased armor
|
||||
#define STATUS_EFFECT_DNA_MELT /datum/status_effect/dna_melt //usually does something horrible to you when you hit 100 genetic instability
|
||||
|
||||
@@ -195,6 +195,8 @@
|
||||
#define TRAIT_AUTO_CATCH_ITEM "auto_catch_item"
|
||||
#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman.
|
||||
#define TRAIT_FREESPRINT "free_sprinting"
|
||||
#define TRAIT_XRAY_VISION "xray_vision"
|
||||
#define TRAIT_THERMAL_VISION "thermal_vision"
|
||||
#define TRAIT_NO_TELEPORT "no-teleport" //you just can't
|
||||
#define TRAIT_NO_INTERNALS "no-internals"
|
||||
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
//////////////////////////////////////////////////////////
|
||||
//A bunch of helpers to make genetics less of a headache//
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
#define GET_INITIALIZED_MUTATION(A) GLOB.all_mutations[A]
|
||||
#define GET_GENE_STRING(A, B) (B.mutation_index[A])
|
||||
#define GET_SEQUENCE(A) (GLOB.full_sequences[A])
|
||||
|
||||
#define GET_MUTATION_STABILIZER(A) ((A.stabilizer_coeff < 0) ? 1 : A.stabilizer_coeff)
|
||||
#define GET_MUTATION_SYNCHRONIZER(A) ((A.synchronizer_coeff < 0) ? 1 : A.synchronizer_coeff)
|
||||
#define GET_MUTATION_POWER(A) ((A.power_coeff < 0) ? 1 : A.power_coeff)
|
||||
#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff)
|
||||
@@ -21,8 +21,11 @@ GLOBAL_LIST(op_se_blocks)
|
||||
GLOBAL_VAR(NULLED_SE)
|
||||
GLOBAL_VAR(NULLED_UI)
|
||||
|
||||
GLOBAL_LIST_EMPTY(global_mutations) // list of hidden mutation things
|
||||
GLOBAL_LIST_EMPTY(all_mutations)
|
||||
GLOBAL_LIST_EMPTY(full_sequences)
|
||||
|
||||
GLOBAL_LIST_EMPTY(bad_mutations)
|
||||
GLOBAL_LIST_EMPTY(good_mutations)
|
||||
GLOBAL_LIST_EMPTY(not_good_mutations)
|
||||
GLOBAL_LIST_EMPTY(not_good_mutations)
|
||||
|
||||
GLOBAL_LIST_EMPTY(mutation_recipes)
|
||||
@@ -16,7 +16,7 @@ SUBSYSTEM_DEF(atoms)
|
||||
|
||||
/datum/controller/subsystem/atoms/Initialize(timeofday)
|
||||
GLOB.fire_overlay.appearance_flags = RESET_COLOR
|
||||
setupGenetics() //to set the mutations' place in structural enzymes, so monkey.initialize() knows where to put the monkey mutation.
|
||||
setupGenetics() //to set the mutations' sequence.
|
||||
initialized = INITIALIZATION_INNEW_MAPLOAD
|
||||
InitializeAtoms()
|
||||
return ..()
|
||||
@@ -108,16 +108,19 @@ SUBSYSTEM_DEF(atoms)
|
||||
BadInitializeCalls = SSatoms.BadInitializeCalls
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/setupGenetics()
|
||||
var/list/avnums = new /list(DNA_STRUC_ENZYMES_BLOCKS)
|
||||
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
|
||||
avnums[i] = i
|
||||
CHECK_TICK
|
||||
|
||||
for(var/A in subtypesof(/datum/mutation/human))
|
||||
var/datum/mutation/human/B = new A()
|
||||
if(B.dna_block == NON_SCANNABLE)
|
||||
var/list/mutations = subtypesof(/datum/mutation/human)
|
||||
shuffle_inplace(mutations)
|
||||
for(var/A in subtypesof(/datum/generecipe))
|
||||
var/datum/generecipe/GR = A
|
||||
GLOB.mutation_recipes[initial(GR.required)] = initial(GR.result)
|
||||
for(var/i in 1 to LAZYLEN(mutations))
|
||||
var/path = mutations[i] //byond gets pissy when we do it in one line
|
||||
var/datum/mutation/human/B = new path ()
|
||||
B.alias = "Mutation #[i]"
|
||||
GLOB.all_mutations[B.type] = B
|
||||
GLOB.full_sequences[B.type] = generate_gene_sequence(B.blocks)
|
||||
if(B.locked)
|
||||
continue
|
||||
B.dna_block = pick_n_take(avnums)
|
||||
if(B.quality == POSITIVE)
|
||||
GLOB.good_mutations |= B
|
||||
else if(B.quality == NEGATIVE)
|
||||
|
||||
@@ -287,7 +287,6 @@
|
||||
G.fields["gender"] = "Other"
|
||||
L.fields["blood_type"] = H.dna.blood_type
|
||||
L.fields["b_dna"] = H.dna.unique_enzymes
|
||||
L.fields["enzymes"] = H.dna.struc_enzymes
|
||||
L.fields["identity"] = H.dna.uni_identity
|
||||
L.fields["species"] = H.dna.species.type
|
||||
L.fields["features"] = H.dna.features
|
||||
|
||||
@@ -61,12 +61,12 @@ Bonus
|
||||
symptom_delay_max = 60
|
||||
if(A.properties["resistance"] >= 8) //mutate twice
|
||||
power = 2
|
||||
possible_mutations = (GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT]
|
||||
possible_mutations = (GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.all_mutations[RACEMUT]
|
||||
var/mob/living/carbon/M = A.affected_mob
|
||||
if(M)
|
||||
if(!M.has_dna())
|
||||
return
|
||||
archived_dna = M.dna.struc_enzymes
|
||||
archived_dna = M.dna.mutation_index
|
||||
|
||||
// Give them back their old DNA when cured.
|
||||
/datum/symptom/genetic_mutation/End(datum/disease/advance/A)
|
||||
@@ -77,5 +77,5 @@ Bonus
|
||||
if(M && archived_dna)
|
||||
if(!M.has_dna())
|
||||
return
|
||||
M.dna.struc_enzymes = archived_dna
|
||||
M.dna.mutation_index = archived_dna
|
||||
M.domutcheck()
|
||||
|
||||
+242
-58
@@ -2,7 +2,6 @@
|
||||
/////////////////////////// DNA DATUM
|
||||
/datum/dna
|
||||
var/unique_enzymes
|
||||
var/struc_enzymes
|
||||
var/uni_identity
|
||||
var/blood_type
|
||||
var/datum/species/species = new /datum/species/human //The type of mutant race the player is if applicable (i.e. potato-man)
|
||||
@@ -11,10 +10,13 @@
|
||||
var/nameless = FALSE
|
||||
var/custom_species //siiiiigh I guess this is important
|
||||
var/list/mutations = list() //All mutations are from now on here
|
||||
var/list/temporary_mutations = list() //Timers for temporary mutations
|
||||
var/list/temporary_mutations = list() //Temporary changes to the UE
|
||||
var/list/previous = list() //For temporary name/ui/ue/blood_type modifications
|
||||
var/mob/living/holder
|
||||
var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875
|
||||
var/mutation_index[DNA_MUTATION_BLOCKS] //List of which mutations this carbon has and its assigned block
|
||||
var/stability = 100
|
||||
var/scrambled = FALSE //Did we take something like mutagen? In that case we cant get our genes scanned to instantly cheese all the powers.
|
||||
|
||||
/datum/dna/New(mob/living/new_holder)
|
||||
if(istype(new_holder))
|
||||
@@ -42,8 +44,8 @@
|
||||
destination.dna.unique_enzymes = unique_enzymes
|
||||
destination.dna.uni_identity = uni_identity
|
||||
destination.dna.blood_type = blood_type
|
||||
destination.dna.features = features.Copy()
|
||||
destination.set_species(species.type, icon_update=0)
|
||||
destination.dna.features = features.Copy()
|
||||
destination.dna.real_name = real_name
|
||||
destination.dna.nameless = nameless
|
||||
destination.dna.custom_species = custom_species
|
||||
@@ -52,13 +54,13 @@
|
||||
var/mob/living/carbon/human/H = destination
|
||||
H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA
|
||||
if(transfer_SE)
|
||||
destination.dna.struc_enzymes = struc_enzymes
|
||||
destination.dna.mutation_index = mutation_index
|
||||
|
||||
SEND_SIGNAL(destination, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, src, transfer_SE)
|
||||
|
||||
/datum/dna/proc/copy_dna(datum/dna/new_dna)
|
||||
new_dna.unique_enzymes = unique_enzymes
|
||||
new_dna.struc_enzymes = struc_enzymes
|
||||
new_dna.mutation_index = mutation_index
|
||||
new_dna.uni_identity = uni_identity
|
||||
new_dna.blood_type = blood_type
|
||||
new_dna.features = features.Copy()
|
||||
@@ -68,26 +70,32 @@
|
||||
new_dna.custom_species = custom_species
|
||||
new_dna.mutations = mutations.Copy()
|
||||
|
||||
/datum/dna/proc/add_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
HM.on_acquiring(holder)
|
||||
//See mutation.dm for what 'class' does. 'time' is time till it removes itself in decimals. 0 for no timer
|
||||
/datum/dna/proc/add_mutation(mutation, class = MUT_OTHER, time)
|
||||
var/mutation_type = mutation
|
||||
if(istype(mutation, /datum/mutation/human))
|
||||
var/datum/mutation/human/HM = mutation
|
||||
mutation_type = HM.type
|
||||
if(get_mutation(mutation_type))
|
||||
return
|
||||
return force_give(new mutation_type (class, time, copymut = mutation))
|
||||
|
||||
/datum/dna/proc/remove_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
HM.on_losing(holder)
|
||||
/datum/dna/proc/remove_mutation(mutation_type)
|
||||
return force_lose(get_mutation(mutation_type))
|
||||
|
||||
/datum/dna/proc/check_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
return mutations.Find(HM)
|
||||
/datum/dna/proc/check_mutation(mutation_type)
|
||||
return get_mutation(mutation_type)
|
||||
|
||||
/datum/dna/proc/remove_all_mutations()
|
||||
remove_mutation_group(mutations)
|
||||
/datum/dna/proc/remove_all_mutations(list/classes = list(MUT_NORMAL, MUT_EXTRA, MUT_OTHER), mutadone = FALSE)
|
||||
remove_mutation_group(mutations, classes, mutadone)
|
||||
scrambled = FALSE
|
||||
|
||||
/datum/dna/proc/remove_mutation_group(list/group)
|
||||
/datum/dna/proc/remove_mutation_group(list/group, list/classes = list(MUT_NORMAL, MUT_EXTRA, MUT_OTHER), mutadone = FALSE)
|
||||
if(!group)
|
||||
return
|
||||
for(var/datum/mutation/human/HM in group)
|
||||
HM.force_lose(holder)
|
||||
if((HM.class in classes) && !(HM.mutadone_proof && mutadone))
|
||||
force_lose(HM)
|
||||
|
||||
/datum/dna/proc/generate_uni_identity()
|
||||
. = ""
|
||||
@@ -137,19 +145,49 @@
|
||||
. += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters)
|
||||
return .
|
||||
|
||||
/datum/dna/proc/generate_struc_enzymes()
|
||||
var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS)
|
||||
var/result = ""
|
||||
for(var/datum/mutation/human/A in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations)
|
||||
if(A.name == RACEMUT && ismonkey(holder))
|
||||
sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE)
|
||||
mutations |= A
|
||||
else
|
||||
sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6"))
|
||||
/datum/dna/proc/generate_dna_blocks()
|
||||
var/bonus
|
||||
if(species && species.inert_mutation)
|
||||
bonus = GET_INITIALIZED_MUTATION(species.inert_mutation)
|
||||
var/list/mutations_temp = GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations + bonus
|
||||
if(!LAZYLEN(mutations_temp))
|
||||
return
|
||||
mutation_index.Cut()
|
||||
shuffle_inplace(mutations_temp)
|
||||
if(ismonkey(holder))
|
||||
mutations |= new RACEMUT(MUT_NORMAL)
|
||||
mutation_index[RACEMUT] = GET_SEQUENCE(RACEMUT)
|
||||
else
|
||||
mutation_index[RACEMUT] = create_sequence(RACEMUT, FALSE)
|
||||
for(var/i in 2 to DNA_MUTATION_BLOCKS)
|
||||
var/datum/mutation/human/M = mutations_temp[i]
|
||||
mutation_index[M.type] = create_sequence(M.type, FALSE,M.difficulty)
|
||||
shuffle_inplace(mutation_index)
|
||||
|
||||
for(var/B in sorting)
|
||||
result += B
|
||||
return result
|
||||
//Used to generate original gene sequences for every mutation
|
||||
/proc/generate_gene_sequence(length=4)
|
||||
var/static/list/active_sequences = list("AT","TA","GC","CG")
|
||||
var/sequence
|
||||
for(var/i in 1 to length*DNA_SEQUENCE_LENGTH)
|
||||
sequence += pick(active_sequences)
|
||||
return sequence
|
||||
|
||||
//Used to create a chipped gene sequence
|
||||
/proc/create_sequence(mutation, active, difficulty)
|
||||
if(!difficulty)
|
||||
var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(mutation) //leaves the possibility to change difficulty mid-round
|
||||
if(!A)
|
||||
return
|
||||
difficulty = A.difficulty
|
||||
difficulty += rand(-2,4)
|
||||
var/sequence = GET_SEQUENCE(mutation)
|
||||
if(active)
|
||||
return sequence
|
||||
while(difficulty)
|
||||
var/randnum = rand(1, length(sequence))
|
||||
sequence = copytext(sequence, 1, randnum) + "X" + copytext(sequence, randnum+1, length(sequence)+1)
|
||||
difficulty--
|
||||
return sequence
|
||||
|
||||
/datum/dna/proc/generate_unique_enzymes()
|
||||
. = ""
|
||||
@@ -202,12 +240,57 @@
|
||||
if(DNA_TAUR_BLOCK)
|
||||
construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len)
|
||||
|
||||
//Please use add_mutation or activate_mutation instead
|
||||
/datum/dna/proc/force_give(datum/mutation/human/HM)
|
||||
if(holder && HM)
|
||||
if(HM.class == MUT_NORMAL)
|
||||
set_se(1, HM)
|
||||
. = HM.on_acquiring(holder)
|
||||
if(.)
|
||||
qdel(HM)
|
||||
update_instability()
|
||||
|
||||
//Use remove_mutation instead
|
||||
/datum/dna/proc/force_lose(datum/mutation/human/HM)
|
||||
if(holder && (HM in mutations))
|
||||
set_se(0, HM)
|
||||
. = HM.on_losing(holder)
|
||||
update_instability(FALSE)
|
||||
return
|
||||
|
||||
/datum/dna/proc/is_same_as(datum/dna/D)
|
||||
if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name && nameless == D.nameless && custom_species == D.custom_species)
|
||||
if(uni_identity == D.uni_identity && mutation_index == D.mutation_index && real_name == D.real_name && nameless == D.nameless && custom_species == D.custom_species)
|
||||
if(species.type == D.species.type && features == D.features && blood_type == D.blood_type)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/dna/proc/update_instability(alert=TRUE)
|
||||
stability = 100
|
||||
for(var/datum/mutation/human/M in mutations)
|
||||
if(M.class == MUT_EXTRA)
|
||||
stability -= M.instability * GET_MUTATION_STABILIZER(M)
|
||||
if(holder)
|
||||
var/message
|
||||
if(alert)
|
||||
switch(stability)
|
||||
if(70 to 90)
|
||||
message = "<span class='warning'>You shiver.</span>"
|
||||
if(60 to 69)
|
||||
message = "<span class='warning'>You feel cold.</span>"
|
||||
if(40 to 59)
|
||||
message = "<span class='warning'>You feel sick.</span>"
|
||||
if(20 to 39)
|
||||
message = "<span class='warning'>It feels like your skin is moving.</span>"
|
||||
if(1 to 19)
|
||||
message = "<span class='warning'>You can feel your cells burning.</span>"
|
||||
if(-INFINITY to 0)
|
||||
message = "<span class='boldwarning'>You can feel your DNA exploding, we need to do something fast!</span>"
|
||||
if(stability <= 0)
|
||||
holder.apply_status_effect(STATUS_EFFECT_DNA_MELT)
|
||||
if(message)
|
||||
to_chat(holder, message)
|
||||
|
||||
|
||||
//used to update dna UI, UE, and dna.real_name.
|
||||
/datum/dna/proc/update_dna_identity()
|
||||
uni_identity = generate_uni_identity()
|
||||
@@ -218,7 +301,7 @@
|
||||
blood_type = newblood_type
|
||||
unique_enzymes = generate_unique_enzymes()
|
||||
uni_identity = generate_uni_identity()
|
||||
struc_enzymes = generate_struc_enzymes()
|
||||
generate_dna_blocks()
|
||||
features = random_features(species?.id)
|
||||
|
||||
|
||||
@@ -233,10 +316,10 @@
|
||||
/datum/dna/stored/check_mutation(mutation_name)
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_all_mutations()
|
||||
/datum/dna/stored/remove_all_mutations(list/classes = list(MUT_NORMAL, MUT_EXTRA, MUT_OTHER), mutadone = FALSE)
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_mutation_group(list/group)
|
||||
/datum/dna/stored/remove_mutation_group(list/group, list/classes = list(MUT_NORMAL, MUT_EXTRA, MUT_OTHER), mutadone = FALSE)
|
||||
return
|
||||
|
||||
/////////////////////////// DNA MOB-PROCS //////////////////////
|
||||
@@ -271,6 +354,7 @@
|
||||
if(icon_update)
|
||||
update_body()
|
||||
update_hair()
|
||||
update_body_parts()
|
||||
update_mutations_overlay()// no lizard with human hulk overlay please.
|
||||
|
||||
|
||||
@@ -281,7 +365,7 @@
|
||||
return dna
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures)
|
||||
/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures)
|
||||
|
||||
if(newfeatures)
|
||||
dna.features = newfeatures
|
||||
@@ -302,8 +386,8 @@
|
||||
dna.uni_identity = ui
|
||||
updateappearance(icon_update=0)
|
||||
|
||||
if(se)
|
||||
dna.struc_enzymes = se
|
||||
if(LAZYLEN(mutation_index))
|
||||
dna.mutation_index = mutation_index.Copy()
|
||||
domutcheck()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_HUMAN_HARDSET_DNA, ui, se, newreal_name, newblood_type, mrace, newfeatures)
|
||||
@@ -357,19 +441,63 @@
|
||||
/mob/proc/domutcheck()
|
||||
return
|
||||
|
||||
/mob/living/carbon/domutcheck(force_powers=0) //Set force_powers to 1 to bypass the power chance
|
||||
/mob/living/carbon/domutcheck()
|
||||
if(!has_dna())
|
||||
return
|
||||
|
||||
for(var/datum/mutation/human/A in GLOB.good_mutations | GLOB.bad_mutations | GLOB.not_good_mutations)
|
||||
if(ismob(A.check_block(src, force_powers)))
|
||||
for(var/mutation in dna.mutation_index)
|
||||
if(ismob(dna.check_block(mutation)))
|
||||
return //we got monkeyized/humanized, this mob will be deleted, no need to continue.
|
||||
|
||||
update_mutations_overlay()
|
||||
|
||||
/datum/dna/proc/check_block(mutation)
|
||||
var/datum/mutation/human/HM = get_mutation(mutation)
|
||||
if(check_block_string(mutation))
|
||||
if(!HM)
|
||||
. = add_mutation(mutation, MUT_NORMAL)
|
||||
return
|
||||
return force_lose(HM)
|
||||
|
||||
//Return the active mutation of a type if there is one
|
||||
/datum/dna/proc/get_mutation(A)
|
||||
for(var/datum/mutation/human/HM in mutations)
|
||||
if(HM.type == A)
|
||||
return HM
|
||||
|
||||
/datum/dna/proc/check_block_string(mutation)
|
||||
if((LAZYLEN(mutation_index) > DNA_MUTATION_BLOCKS) || !(mutation in mutation_index))
|
||||
return 0
|
||||
return is_gene_active(mutation)
|
||||
|
||||
/datum/dna/proc/is_gene_active(mutation)
|
||||
return (mutation_index[mutation] == GET_SEQUENCE(mutation))
|
||||
|
||||
/datum/dna/proc/set_se(on=TRUE, datum/mutation/human/HM)
|
||||
if(!HM || !(HM.type in mutation_index) || (LAZYLEN(mutation_index) < DNA_MUTATION_BLOCKS))
|
||||
return
|
||||
. = TRUE
|
||||
if(on)
|
||||
mutation_index[HM.type] = GET_SEQUENCE(HM.type)
|
||||
else if(GET_SEQUENCE(HM.type) == mutation_index[HM.type])
|
||||
mutation_index[HM.type] = create_sequence(HM.type, FALSE, HM.difficulty)
|
||||
|
||||
/datum/dna/proc/activate_mutation(mutation) //note that this returns a boolean and not a new mob
|
||||
if(!mutation)
|
||||
return FALSE
|
||||
var/mutation_type = mutation
|
||||
if(istype(mutation, /datum/mutation/human))
|
||||
var/datum/mutation/human/M = mutation
|
||||
mutation_type = M.type
|
||||
if(!mutation_in_sequence(mutation_type)) //cant activate what we dont have, use add_mutation
|
||||
return FALSE
|
||||
add_mutation(mutation, MUT_NORMAL)
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS //////////////////////////////
|
||||
|
||||
/proc/getleftblocks(input,blocknumber,blocksize)
|
||||
if(blocknumber > 1)
|
||||
return copytext_char(input,1,((blocksize*blocknumber)-(blocksize-1)))
|
||||
@@ -386,29 +514,47 @@
|
||||
return 0
|
||||
return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize)
|
||||
|
||||
/datum/dna/proc/mutation_in_sequence(mutation)
|
||||
if(!mutation)
|
||||
return
|
||||
if(istype(mutation, /datum/mutation/human))
|
||||
var/datum/mutation/human/HM = mutation
|
||||
if(HM.type in mutation_index)
|
||||
return TRUE
|
||||
else if(mutation in mutation_index)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/proc/randmut(list/candidates, difficulty = 2)
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/num = pick(candidates)
|
||||
. = num.force_give(src)
|
||||
var/mutation = pick(candidates)
|
||||
. = dna.add_mutation(mutation)
|
||||
|
||||
/mob/living/carbon/proc/randmutb()
|
||||
/mob/living/carbon/proc/easy_randmut(quality = POSITIVE + NEGATIVE + MINOR_NEGATIVE, scrambled = TRUE, sequence = TRUE, exclude_monkey = TRUE)
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick((GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT])
|
||||
. = HM.force_give(src)
|
||||
var/list/mutations = list()
|
||||
if(quality & POSITIVE)
|
||||
mutations += GLOB.good_mutations
|
||||
if(quality & NEGATIVE)
|
||||
mutations += GLOB.bad_mutations
|
||||
if(quality & MINOR_NEGATIVE)
|
||||
mutations += GLOB.not_good_mutations
|
||||
var/list/possible = list()
|
||||
for(var/datum/mutation/human/A in mutations)
|
||||
if((!sequence || dna.mutation_in_sequence(A.type)) && !dna.get_mutation(A.type))
|
||||
possible += A.type
|
||||
if(exclude_monkey)
|
||||
possible.Remove(RACEMUT)
|
||||
if(LAZYLEN(possible))
|
||||
var/mutation = pick(possible)
|
||||
. = dna.activate_mutation(mutation)
|
||||
if(scrambled)
|
||||
var/datum/mutation/human/HM = dna.get_mutation(mutation)
|
||||
if(HM)
|
||||
HM.scrambled = TRUE
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/proc/randmutg()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick(GLOB.good_mutations)
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmutvg()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick((GLOB.good_mutations) - GLOB.mutations_list[HULK] - GLOB.mutations_list[DWARFISM])
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmuti()
|
||||
if(!has_dna())
|
||||
@@ -431,9 +577,9 @@
|
||||
if(!M.has_dna())
|
||||
return 0
|
||||
if(se)
|
||||
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
|
||||
for(var/i=1, i<=DNA_MUTATION_BLOCKS, i++)
|
||||
if(prob(probability))
|
||||
M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters))
|
||||
M.dna.generate_dna_blocks()
|
||||
M.domutcheck()
|
||||
if(ui)
|
||||
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
|
||||
@@ -460,3 +606,41 @@
|
||||
return value
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS
|
||||
|
||||
/mob/living/carbon/human/proc/something_horrible()
|
||||
if(!has_dna()) //shouldn't ever happen anyway so it's just in really weird cases
|
||||
return
|
||||
if(dna.stability > 0)
|
||||
return
|
||||
var/instability = -dna.stability
|
||||
dna.remove_all_mutations()
|
||||
dna.stability = 100
|
||||
if(prob(max(70-instability,0)))
|
||||
switch(rand(0,3)) //not complete and utter death
|
||||
if(0)
|
||||
monkeyize()
|
||||
if(1)
|
||||
gain_trauma(/datum/brain_trauma/severe/paralysis)
|
||||
if(2)
|
||||
corgize()
|
||||
if(3)
|
||||
to_chat(src, "<span class='notice'>Oh, we actually feel quite alright!</span>")
|
||||
else
|
||||
switch(rand(0,3))
|
||||
if(0)
|
||||
gib()
|
||||
if(1)
|
||||
dust()
|
||||
|
||||
if(2)
|
||||
death()
|
||||
petrify(INFINITY)
|
||||
if(3)
|
||||
if(prob(90))
|
||||
var/obj/item/bodypart/BP = get_bodypart(pick(BODY_ZONE_CHEST,BODY_ZONE_HEAD))
|
||||
if(BP)
|
||||
BP.dismember()
|
||||
else
|
||||
gib()
|
||||
else
|
||||
set_species(/datum/species/dullahan)
|
||||
|
||||
+96
-40
@@ -1,58 +1,55 @@
|
||||
GLOBAL_LIST_EMPTY(mutations_list)
|
||||
|
||||
/datum/mutation
|
||||
|
||||
var/name
|
||||
|
||||
/datum/mutation/New()
|
||||
GLOB.mutations_list[name] = src
|
||||
|
||||
/datum/mutation/human
|
||||
var/dna_block
|
||||
name = "mutation"
|
||||
var/desc = "A mutation."
|
||||
var/locked
|
||||
var/quality
|
||||
var/get_chance = 100
|
||||
var/lowest_value = 256 * 8
|
||||
var/text_gain_indication = ""
|
||||
var/text_lose_indication = ""
|
||||
var/list/mutable_appearance/visual_indicators = list()
|
||||
var/obj/effect/proc_holder/spell/power
|
||||
var/layer_used = MUTATIONS_LAYER //which mutation layer to use
|
||||
var/list/species_allowed = list() //to restrict mutation to only certain species
|
||||
var/health_req //minimum health required to acquire the mutation
|
||||
var/limb_req //required limbs to acquire this mutation
|
||||
var/time_coeff = 1 //coefficient for timed mutations
|
||||
var/datum/dna/dna
|
||||
var/mob/living/carbon/human/owner
|
||||
var/instability = 0 //instability the holder gets when the mutation is not native
|
||||
var/blocks = 4 //Amount of those big blocks with gene sequences
|
||||
var/difficulty = 8 //Amount of missing sequences. Sometimes it removes an entire pair for 2 points
|
||||
var/timed = FALSE //Boolean to easily check if we're going to self destruct
|
||||
var/alias //'Mutation #49', decided every round to get some form of distinction between undiscovered mutations
|
||||
var/scrambled = FALSE //Wheter we can read it if it's active. To avoid cheesing with mutagen
|
||||
var/class //Decides player accesibility, sorta
|
||||
//MUT_NORMAL - A mutation that can be activated and deactived by completing a sequence
|
||||
//MUT_EXTRA - A mutation that is in the mutations tab, and can be given and taken away through though the DNA console. Has a 0 before it's name in the mutation section of the dna console
|
||||
//MUT_OTHER Cannot be interacted with by players through normal means. I.E. wizards mutate
|
||||
|
||||
/datum/mutation/human/proc/force_give(mob/living/carbon/human/owner)
|
||||
set_block(owner)
|
||||
. = on_acquiring(owner)
|
||||
var/can_chromosome = CHROMOSOME_NONE //can we take chromosomes? 0: CHROMOSOME_NEVER never, 1:CHROMOSOME_NONE yeah, 2: CHROMOSOME_USED no, already have one
|
||||
var/chromosome_name //purely cosmetic
|
||||
var/modified = FALSE //ugly but we really don't want chromosomes and on_acquiring to overlap and apply double the powers
|
||||
var/mutadone_proof = FALSE
|
||||
|
||||
/datum/mutation/human/proc/force_lose(mob/living/carbon/human/owner)
|
||||
set_block(owner, 0)
|
||||
. = on_losing(owner)
|
||||
//Chromosome stuff - set to -1 to prevent people from changing it. Example: It'd be a waste to decrease cooldown on mutism
|
||||
var/stabilizer_coeff = 1 //genetic stability coeff
|
||||
var/synchronizer_coeff = -1 //makes the mutation hurt the user less
|
||||
var/power_coeff = -1 //boosts mutation strength
|
||||
var/energy_coeff = -1 //lowers mutation cooldown
|
||||
|
||||
/datum/mutation/human/proc/set_se(se_string, on = 1)
|
||||
if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
|
||||
return
|
||||
var/before = copytext_char(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1)
|
||||
var/injection = num2hex(on ? rand(lowest_value, (256 * 16) - 1) : rand(0, lowest_value - 1), DNA_BLOCK_SIZE)
|
||||
var/after = copytext_char(se_string, (dna_block * DNA_BLOCK_SIZE) + 1, 0)
|
||||
return before + injection + after
|
||||
|
||||
/datum/mutation/human/proc/set_block(mob/living/carbon/owner, on = 1)
|
||||
if(owner && owner.has_dna())
|
||||
owner.dna.struc_enzymes = set_se(owner.dna.struc_enzymes, on)
|
||||
|
||||
/datum/mutation/human/proc/check_block_string(se_string)
|
||||
if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
|
||||
return 0
|
||||
if(hex2num(getblock(se_string, dna_block)) >= lowest_value)
|
||||
return 1
|
||||
|
||||
/datum/mutation/human/proc/check_block(mob/living/carbon/human/owner, force_powers=0)
|
||||
if(check_block_string(owner.dna.struc_enzymes))
|
||||
if(prob(get_chance)||force_powers)
|
||||
. = on_acquiring(owner)
|
||||
else
|
||||
. = on_losing(owner)
|
||||
/datum/mutation/human/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
. = ..()
|
||||
class = class_
|
||||
if(timer)
|
||||
addtimer(CALLBACK(src, .proc/remove), timer)
|
||||
timed = TRUE
|
||||
if(copymut && istype(copymut, /datum/mutation/human))
|
||||
copy_mutation(copymut)
|
||||
|
||||
/datum/mutation/human/proc/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(!owner || !istype(owner) || owner.stat == DEAD || (src in owner.dna.mutations))
|
||||
@@ -63,7 +60,8 @@ GLOBAL_LIST_EMPTY(mutations_list)
|
||||
return TRUE
|
||||
if(limb_req && !owner.get_bodypart(limb_req))
|
||||
return TRUE
|
||||
owner.dna.mutations.Add(src)
|
||||
dna = owner.dna
|
||||
dna.mutations += src
|
||||
if(text_gain_indication)
|
||||
to_chat(owner, text_gain_indication)
|
||||
if(visual_indicators.len)
|
||||
@@ -75,6 +73,10 @@ GLOBAL_LIST_EMPTY(mutations_list)
|
||||
owner.overlays_standing[layer_used] = mut_overlay
|
||||
owner.apply_overlay(layer_used)
|
||||
|
||||
grant_spell(owner)
|
||||
if(!modified)
|
||||
addtimer(CALLBACK(src, .proc/modify, 5)) //gonna want children calling ..() to run first
|
||||
|
||||
/datum/mutation/human/proc/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return
|
||||
|
||||
@@ -102,26 +104,80 @@ GLOBAL_LIST_EMPTY(mutations_list)
|
||||
mut_overlay.Remove(get_visual_indicator(owner))
|
||||
owner.overlays_standing[layer_used] = mut_overlay
|
||||
owner.apply_overlay(layer_used)
|
||||
if(power)
|
||||
owner.RemoveSpell(power)
|
||||
qdel(src)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/mutation/human/proc/say_mod(message)
|
||||
if(message)
|
||||
return message
|
||||
|
||||
/datum/mutation/human/proc/get_spans()
|
||||
return list()
|
||||
|
||||
/mob/living/carbon/proc/update_mutations_overlay()
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/update_mutations_overlay()
|
||||
for(var/datum/mutation/human/CM in dna.mutations)
|
||||
if(CM.species_allowed.len && !CM.species_allowed.Find(dna.species.id))
|
||||
CM.force_lose(src) //shouldn't have that mutation at all
|
||||
dna.force_lose(CM) //shouldn't have that mutation at all
|
||||
continue
|
||||
if(CM.visual_indicators.len)
|
||||
var/list/mut_overlay = list()
|
||||
if(overlays_standing[CM.layer_used])
|
||||
mut_overlay = overlays_standing[CM.layer_used]
|
||||
var/mutable_appearance/V = CM.get_visual_indicator(src)
|
||||
var/mutable_appearance/V = CM.get_visual_indicator()
|
||||
if(!mut_overlay.Find(V)) //either we lack the visual indicator or we have the wrong one
|
||||
remove_overlay(CM.layer_used)
|
||||
for(var/mutable_appearance/MA in CM.visual_indicators)
|
||||
for(var/mutable_appearance/MA in CM.visual_indicators[CM.type])
|
||||
mut_overlay.Remove(MA)
|
||||
mut_overlay |= V
|
||||
overlays_standing[CM.layer_used] = mut_overlay
|
||||
apply_overlay(CM.layer_used)
|
||||
|
||||
|
||||
/datum/mutation/human/proc/modify() //called when a genome is applied so we can properly update some stats without having to remove and reapply the mutation from someone
|
||||
if(modified || !power || !owner)
|
||||
return
|
||||
power.charge_max *= GET_MUTATION_ENERGY(src)
|
||||
power.charge_counter *= GET_MUTATION_ENERGY(src)
|
||||
modified = TRUE
|
||||
|
||||
/datum/mutation/human/proc/copy_mutation(datum/mutation/human/HM)
|
||||
if(!HM)
|
||||
return
|
||||
chromosome_name = HM.chromosome_name
|
||||
stabilizer_coeff = HM.stabilizer_coeff
|
||||
synchronizer_coeff = HM.synchronizer_coeff
|
||||
power_coeff = HM.power_coeff
|
||||
energy_coeff = HM.energy_coeff
|
||||
mutadone_proof = HM.mutadone_proof
|
||||
can_chromosome = HM.can_chromosome
|
||||
|
||||
/datum/mutation/human/proc/remove_chromosome()
|
||||
stabilizer_coeff = initial(stabilizer_coeff)
|
||||
synchronizer_coeff = initial(synchronizer_coeff)
|
||||
power_coeff = initial(power_coeff)
|
||||
energy_coeff = initial(energy_coeff)
|
||||
mutadone_proof = initial(mutadone_proof)
|
||||
can_chromosome = initial(can_chromosome)
|
||||
chromosome_name = null
|
||||
|
||||
/datum/mutation/human/proc/remove()
|
||||
if(dna)
|
||||
dna.force_lose(src)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/mutation/human/proc/grant_spell(mob/living/carbon/human/owner)
|
||||
if(!ispath(power) || !owner)
|
||||
return FALSE
|
||||
|
||||
power = new power()
|
||||
power.action_background_icon_state = "bg_tech_blue_on"
|
||||
power.panel = "Genetic"
|
||||
owner.AddSpell(power)
|
||||
return TRUE
|
||||
@@ -0,0 +1,503 @@
|
||||
/datum/mutation/human/telepathy
|
||||
name = "Telepathy"
|
||||
desc = "A rare mutation that allows the user to telepathically communicate to others."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You can hear your own voice echoing in your mind!</span>"
|
||||
text_lose_indication = "<span class='notice'>You don't hear your mind echo anymore.</span>"
|
||||
difficulty = 12
|
||||
power = /obj/effect/proc_holder/spell/targeted/telepathy/genetic
|
||||
instability = 10
|
||||
energy_coeff = 1
|
||||
|
||||
/datum/mutation/human/telepathy/on_acquiring(mob/living/carbon/human/owner)
|
||||
. = ..()
|
||||
|
||||
/datum/mutation/human/telepathy/on_losing(mob/living/carbon/human/owner)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/telepathy/genetic
|
||||
magic_check = FALSE
|
||||
|
||||
/datum/mutation/human/firebreath
|
||||
name = "Fire Breath"
|
||||
desc = "An ancient mutation that gives lizards breath of fire."
|
||||
quality = POSITIVE
|
||||
difficulty = 12
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>Your throat is burning!</span>"
|
||||
text_lose_indication = "<span class='notice'>Your throat is cooling down.</span>"
|
||||
power = /obj/effect/proc_holder/spell/aimed/firebreath
|
||||
instability = 30
|
||||
energy_coeff = 1
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/firebreath/modify()
|
||||
if(power)
|
||||
var/obj/effect/proc_holder/spell/aimed/firebreath/S = power
|
||||
S.strength = 4 + GET_MUTATION_POWER(src)
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/firebreath
|
||||
name = "Fire Breath"
|
||||
desc = "You can breathe fire at a target."
|
||||
school = "evocation"
|
||||
charge_max = 1200
|
||||
clothes_req = FALSE
|
||||
range = 20
|
||||
base_icon_state = "fireball"
|
||||
action_icon_state = "fireball0"
|
||||
sound = 'sound/magic/demon_dies.ogg' //horrifying lizard noises
|
||||
active_msg = "You built up heat in your mouth."
|
||||
deactive_msg = "You swallow the flame."
|
||||
var/strength = 4
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/firebreath/before_cast(list/targets)
|
||||
. = ..()
|
||||
if(iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
if(C.is_mouth_covered())
|
||||
C.adjust_fire_stacks(2)
|
||||
C.IgniteMob()
|
||||
to_chat(C,"<span class='warning'>Something in front of your mouth caught fire!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/firebreath/cast(list/targets, mob/living/user)
|
||||
var/turf/T = user.loc
|
||||
if(!isturf(T))
|
||||
return FALSE
|
||||
firecone(T,user.dir,strength)
|
||||
remove_ranged_ability()
|
||||
charge_counter = 0
|
||||
start_recharge()
|
||||
on_deactivation(user)
|
||||
|
||||
/proc/firecone(loc,dir,length)
|
||||
var/addsides = FALSE
|
||||
var/list/turf/recentturf = list(loc)
|
||||
for (var/i = 0;i < length;i++)
|
||||
var/list/turf/h = list()
|
||||
for (var/turf/g in recentturf)
|
||||
var/frontturf = get_step(g,dir)
|
||||
if (addsides)
|
||||
var/rightturf = get_step(frontturf,turn(dir,90))
|
||||
var/leftturf = get_step(frontturf,turn(dir,270))
|
||||
if (!(rightturf in h))
|
||||
h += rightturf
|
||||
if (!(leftturf in h))
|
||||
h += leftturf
|
||||
if (!(frontturf in h))
|
||||
h += frontturf
|
||||
for (var/turf/j in h)
|
||||
if (j.blocks_air)
|
||||
h -= j
|
||||
continue
|
||||
for (var/obj/o in j)
|
||||
if (o.CanAtmosPass == ATMOS_PASS_PROC ? !o.CanAtmosPass(loc) : !o.CanAtmosPass)
|
||||
h -= j
|
||||
continue
|
||||
for (var/turf/l in h)
|
||||
new /obj/effect/hotspot(l)
|
||||
l.hotspot_expose(700,50,1)
|
||||
sleep(1)
|
||||
recentturf = h
|
||||
addsides = !addsides
|
||||
|
||||
/datum/mutation/human/void
|
||||
name = "Void Magnet"
|
||||
desc = "A rare genome that attracts odd forces not usually observed."
|
||||
quality = MINOR_NEGATIVE //upsides and downsides
|
||||
text_gain_indication = "<span class='notice'>You feel a heavy, dull force just beyond the walls watching you.</span>"
|
||||
instability = 30
|
||||
power = /obj/effect/proc_holder/spell/self/void
|
||||
energy_coeff = 1
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/datum/mutation/human/void/on_life(mob/living/carbon/human/owner)
|
||||
if(!isturf(owner.loc))
|
||||
return
|
||||
if(prob((0.5+((100-dna.stability)/20))) * GET_MUTATION_SYNCHRONIZER(src)) //very rare, but enough to annoy you hopefully. +0.5 probability for every 10 points lost in stability
|
||||
new /obj/effect/immortality_talisman/void(get_turf(owner), owner)
|
||||
|
||||
/obj/effect/proc_holder/spell/self/void
|
||||
name = "Convoke Void" //magic the gathering joke here
|
||||
desc = "A rare genome that attracts odd forces not usually observed. May sometimes pull you in randomly."
|
||||
school = "evocation"
|
||||
clothes_req = FALSE
|
||||
charge_max = 600
|
||||
invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!"
|
||||
invocation_type = "shout"
|
||||
action_icon_state = "void_magnet"
|
||||
var/in_use = FALSE //so it doesnt cast while you are already deep innit
|
||||
|
||||
/obj/effect/proc_holder/spell/self/void/can_cast(mob/user = usr)
|
||||
. = ..()
|
||||
if(!isturf(user.loc))
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/self/void/cast(mob/user = usr)
|
||||
. = ..()
|
||||
new /obj/effect/immortality_talisman/void(get_turf(user), user)
|
||||
|
||||
/datum/mutation/human/shock
|
||||
name = "Shock Touch"
|
||||
desc = "The affected can channel excess electricity through their hands without shocking themselves, allowing them to shock others."
|
||||
quality = POSITIVE
|
||||
locked = TRUE
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>You feel power flow through your hands.</span>"
|
||||
text_lose_indication = "<span class='notice'>The energy in your hands subsides.</span>"
|
||||
power = /obj/effect/proc_holder/spell/targeted/touch/shock
|
||||
instability = 30
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/shock
|
||||
name = "Shock Touch"
|
||||
desc = "Channel electricity to your hand to shock people with."
|
||||
drawmessage = "You channel electricity into your hand."
|
||||
dropmessage = "You let the electricity from your hand dissipate."
|
||||
hand_path = /obj/item/melee/touch_attack/shock
|
||||
charge_max = 400
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "zap"
|
||||
|
||||
/obj/item/melee/touch_attack/shock
|
||||
name = "\improper shock touch"
|
||||
desc = "This is kind of like when you rub your feet on a shag rug so you can zap your friends, only a lot less safe."
|
||||
catchphrase = null
|
||||
on_use_sound = 'sound/weapons/zapbang.ogg'
|
||||
icon_state = "zapper"
|
||||
item_state = "zapper"
|
||||
|
||||
/obj/item/melee/touch_attack/shock/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(!proximity || !isliving(target))
|
||||
return
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
if(C.electrocute_act(15, user, 1, stun = 0))//doesnt stun. never let this stun
|
||||
C.dropItemToGround(C.get_active_held_item())
|
||||
C.dropItemToGround(C.get_inactive_held_item())
|
||||
C.confused += 10
|
||||
C.visible_message("<span class='danger'>[user] electrocutes [target]!</span>","<span class='userdanger'>[user] electrocutes you!</span>")
|
||||
return ..()
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] fails to electrocute [target]!</span>")
|
||||
return ..()
|
||||
else if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
L.electrocute_act(15, user, 1, stun = 0)
|
||||
L.visible_message("<span class='danger'>[user] electrocutes [target]!</span>","<span class='userdanger'>[user] electrocutes you!</span>")
|
||||
return ..()
|
||||
else
|
||||
to_chat(user,"<span class='warning'>The electricity doesn't seem to affect [target]...</span>")
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/mutation/human/olfaction
|
||||
name = "Transcendent Olfaction"
|
||||
desc = "Your sense of smell is comparable to that of a canine."
|
||||
quality = POSITIVE
|
||||
difficulty = 12
|
||||
text_gain_indication = "<span class='notice'>Smells begin to make more sense...</span>"
|
||||
text_lose_indication = "<span class='notice'>Your sense of smell goes back to normal.</span>"
|
||||
power = /obj/effect/proc_holder/spell/targeted/olfaction
|
||||
instability = 30
|
||||
synchronizer_coeff = 1
|
||||
var/reek = 200
|
||||
|
||||
/datum/mutation/human/olfaction/modify()
|
||||
if(power)
|
||||
var/obj/effect/proc_holder/spell/targeted/olfaction/S = power
|
||||
S.sensitivity = GET_MUTATION_SYNCHRONIZER(src)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/olfaction
|
||||
name = "Remember the Scent"
|
||||
desc = "Get a scent off of the item you're currently holding to track it. With an empty hand, you'll track the scent you've remembered."
|
||||
charge_max = 100
|
||||
clothes_req = FALSE
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
action_icon_state = "nose"
|
||||
var/mob/living/carbon/tracking_target
|
||||
var/list/mob/living/carbon/possible = list()
|
||||
var/sensitivity = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/olfaction/cast(list/targets, mob/living/user = usr)
|
||||
//can we sniff? is there miasma in the air?
|
||||
var/datum/gas_mixture/air = user.loc.return_air()
|
||||
var/list/cached_gases = air.gases
|
||||
|
||||
if(cached_gases[/datum/gas/miasma])
|
||||
user.adjust_disgust(sensitivity * 45)
|
||||
to_chat(user, "<span class='warning'>With your overly sensitive nose, you get a whiff of stench and feel sick! Try moving to a cleaner area!</span>")
|
||||
return
|
||||
|
||||
var/atom/sniffed = user.get_active_held_item()
|
||||
if(sniffed)
|
||||
var/old_target = tracking_target
|
||||
possible = list()
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
if(md5(H.dna.uni_identity) in sniffed.fingerprints)
|
||||
possible |= H
|
||||
if(!length(possible))
|
||||
to_chat(user,"<span class='warning'>Despite your best efforts, there are no scents to be found on [sniffed]...</span>")
|
||||
return
|
||||
tracking_target = input(user, "Choose a scent to remember.", "Scent Tracking") as null|anything in sortNames(possible)
|
||||
if(!tracking_target)
|
||||
if(!old_target)
|
||||
to_chat(user,"<span class='warning'>You decide against remembering any scents. Instead, you notice your own nose in your peripheral vision. This goes on to remind you of that one time you started breathing manually and couldn't stop. What an awful day that was.</span>")
|
||||
return
|
||||
tracking_target = old_target
|
||||
on_the_trail(user)
|
||||
return
|
||||
to_chat(user,"<span class='notice'>You pick up the scent of [tracking_target]. The hunt begins.</span>")
|
||||
on_the_trail(user)
|
||||
return
|
||||
|
||||
if(!tracking_target)
|
||||
to_chat(user,"<span class='warning'>You're not holding anything to smell, and you haven't smelled anything you can track. You smell your skin instead; it's kinda salty.</span>")
|
||||
return
|
||||
|
||||
on_the_trail(user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/olfaction/proc/on_the_trail(mob/living/user)
|
||||
if(!tracking_target)
|
||||
to_chat(user,"<span class='warning'>You're not tracking a scent, but the game thought you were. Something's gone wrong! Report this as a bug.</span>")
|
||||
return
|
||||
if(tracking_target == user)
|
||||
to_chat(user,"<span class='warning'>You smell out the trail to yourself. Yep, it's you.</span>")
|
||||
return
|
||||
if(usr.z < tracking_target.z)
|
||||
to_chat(user,"<span class='warning'>The trail leads... way up above you? Huh. They must be really, really far away.</span>")
|
||||
return
|
||||
else if(usr.z > tracking_target.z)
|
||||
to_chat(user,"<span class='warning'>The trail leads... way down below you? Huh. They must be really, really far away.</span>")
|
||||
return
|
||||
var/direction_text = "[dir2text(get_dir(usr, tracking_target))]"
|
||||
if(direction_text)
|
||||
to_chat(user,"<span class='notice'>You consider [tracking_target]'s scent. The trail leads <b>[direction_text].</b></span>")
|
||||
|
||||
|
||||
/datum/mutation/human/self_amputation
|
||||
name = "Autotomy"
|
||||
desc = "Allows a creature to voluntary discard a random appendage."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your joints feel loose.</span>"
|
||||
instability = 30
|
||||
power = /obj/effect/proc_holder/spell/self/self_amputation
|
||||
|
||||
energy_coeff = 1
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/self/self_amputation
|
||||
name = "Drop a limb"
|
||||
desc = "Concentrate to make a random limb pop right off your body."
|
||||
clothes_req = FALSE
|
||||
human_req = FALSE
|
||||
charge_max = 100
|
||||
action_icon_state = "autotomy"
|
||||
|
||||
/obj/effect/proc_holder/spell/self/self_amputation/cast(list/targets, mob/user = usr)
|
||||
if(!iscarbon(user))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = user
|
||||
if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
|
||||
return
|
||||
|
||||
var/list/parts = list()
|
||||
for(var/X in C.bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
if(BP.body_part != HEAD && BP.body_part != CHEST)
|
||||
if(BP.dismemberable)
|
||||
parts += BP
|
||||
if(!parts.len)
|
||||
to_chat(usr, "<span class='notice'>You can't shed any more limbs!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/bodypart/BP = pick(parts)
|
||||
BP.dismember()
|
||||
|
||||
//spider webs
|
||||
/datum/mutation/human/webbing
|
||||
name = "Webbing Production"
|
||||
desc = "Allows the user to lay webbing, and travel through it."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your skin feels webby.</span>"
|
||||
instability = 15
|
||||
power = /obj/effect/proc_holder/spell/self/lay_genetic_web
|
||||
|
||||
/obj/effect/proc_holder/spell/self/lay_genetic_web
|
||||
name = "Lay Web"
|
||||
desc = "Drops a web. Only you will be able to traverse your web easily, making it pretty good for keeping you safe."
|
||||
clothes_req = FALSE
|
||||
human_req = FALSE
|
||||
charge_max = 4 SECONDS //the same time to lay a web
|
||||
action_icon = 'icons/mob/actions/actions_genetic.dmi'
|
||||
action_icon_state = "lay_web"
|
||||
|
||||
/obj/effect/proc_holder/spell/self/lay_genetic_web/cast(list/targets, mob/user = usr)
|
||||
var/failed = FALSE
|
||||
if(!isturf(user.loc))
|
||||
to_chat(user, "<span class='warning'>You can't lay webs here!</span>")
|
||||
failed = TRUE
|
||||
var/turf/T = get_turf(user)
|
||||
var/obj/structure/spider/stickyweb/genetic/W = locate() in T
|
||||
if(W)
|
||||
to_chat(user, "<span class='warning'>There's already a web here!</span>")
|
||||
failed = TRUE
|
||||
if(failed)
|
||||
revert_cast(user)
|
||||
return FALSE
|
||||
|
||||
user.visible_message("<span class='notice'>[user] begins to secrete a sticky substance.</span>","<span class='notice'>You begin to lay a web.</span>")
|
||||
if(!do_after(user, 4 SECONDS, target = T))
|
||||
to_chat(user, "<span class='warning'>Your web spinning was interrupted!</span>")
|
||||
return
|
||||
else
|
||||
new /obj/structure/spider/stickyweb/genetic(T, user)
|
||||
|
||||
|
||||
/datum/mutation/human/tongue_spike
|
||||
name = "Tongue Spike"
|
||||
desc = "Allows a creature to voluntary shoot their tongue out as a deadly weapon."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your feel like you can throw your voice.</span>"
|
||||
instability = 15
|
||||
power = /obj/effect/proc_holder/spell/self/tongue_spike
|
||||
|
||||
energy_coeff = 1
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/self/tongue_spike
|
||||
name = "Launch spike"
|
||||
desc = "Shoot your tongue out in the direction you're facing, embedding it and dealing damage until they remove it."
|
||||
clothes_req = FALSE
|
||||
human_req = TRUE
|
||||
charge_max = 100
|
||||
action_icon = 'icons/mob/actions/actions_genetic.dmi'
|
||||
action_icon_state = "spike"
|
||||
var/spike_path = /obj/item/hardened_spike
|
||||
|
||||
/obj/effect/proc_holder/spell/self/tongue_spike/cast(list/targets, mob/user = usr)
|
||||
if(!iscarbon(user))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = user
|
||||
if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
|
||||
return
|
||||
var/obj/item/organ/tongue/tongue
|
||||
for(var/org in C.internal_organs)
|
||||
if(istype(org, /obj/item/organ/tongue))
|
||||
tongue = org
|
||||
break
|
||||
|
||||
if(!tongue)
|
||||
to_chat(C, "<span class='notice'>You don't have a tongue to shoot!</span>")
|
||||
return
|
||||
|
||||
tongue.Remove(C, special = TRUE)
|
||||
var/obj/item/hardened_spike/spike = new spike_path(get_turf(C), C)
|
||||
tongue.forceMove(spike)
|
||||
spike.throw_at(get_edge_target_turf(C,C.dir), 14, 4, C)
|
||||
|
||||
/obj/item/hardened_spike
|
||||
name = "biomass spike"
|
||||
desc = "Hardened biomass, shaped into a spike. Very pointy!"
|
||||
icon_state = "tonguespike"
|
||||
force = 2
|
||||
throwforce = 15 //15 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = i didnt do the math
|
||||
throw_speed = 4
|
||||
embedding = list("embedded_pain_multiplier" = 4, "embed_chance" = 100, "embedded_fall_chance" = 0)
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
sharpness = IS_SHARP
|
||||
var/mob/living/carbon/human/fired_by
|
||||
|
||||
/obj/item/hardened_spike/Initialize(mapload, firedby)
|
||||
. = ..()
|
||||
fired_by = firedby
|
||||
addtimer(CALLBACK(src, .proc/checkembedded), 5 SECONDS)
|
||||
|
||||
/obj/item/hardened_spike/proc/checkembedded()
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/embedtest = loc
|
||||
for(var/l in embedtest.bodyparts)
|
||||
var/obj/item/bodypart/limb = l
|
||||
if(src in limb.embedded_objects)
|
||||
return limb
|
||||
unembedded()
|
||||
|
||||
/obj/item/hardened_spike/unembedded()
|
||||
var/turf/T = get_turf(src)
|
||||
visible_message("<span class='warning'>[src] cracks and twists, changing shape!</span>")
|
||||
for(var/i in contents)
|
||||
var/obj/o = i
|
||||
o.forceMove(T)
|
||||
qdel(src)
|
||||
|
||||
/datum/mutation/human/tongue_spike/chem
|
||||
name = "Chem Spike"
|
||||
desc = "Allows a creature to voluntary shoot their tongue out as biomass, allowing a long range transfer of chemicals."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your feel like you can really connect with people by throwing your voice.</span>"
|
||||
instability = 15
|
||||
locked = TRUE
|
||||
power = /obj/effect/proc_holder/spell/self/tongue_spike/chem
|
||||
energy_coeff = 1
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/self/tongue_spike/chem
|
||||
name = "Launch chem spike"
|
||||
desc = "Shoot your tongue out in the direction you're facing, embedding it for a very small amount of damage. While the other person has the spike embedded, you can transfer your chemicals to them."
|
||||
action_icon_state = "spikechem"
|
||||
spike_path = /obj/item/hardened_spike/chem
|
||||
|
||||
/obj/item/hardened_spike/chem
|
||||
name = "chem spike"
|
||||
desc = "Hardened biomass, shaped into... something."
|
||||
icon_state = "tonguespikechem"
|
||||
throwforce = 2 //2 + 2 (WEIGHT_CLASS_SMALL) * 0 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = i didnt do the math again but very low or smthin
|
||||
embedding = list("embedded_pain_multiplier" = 0, "embed_chance" = 100, "embedded_fall_chance" = 0, "embedded_pain_chance" = 0, "embedded_ignore_throwspeed_threshold" = TRUE) //never hurts once it's in you
|
||||
var/been_places = FALSE
|
||||
var/datum/action/innate/send_chems/chems
|
||||
|
||||
/obj/item/hardened_spike/chem/embedded(mob/living/carbon/human/embedded_mob)
|
||||
if(been_places)
|
||||
return
|
||||
been_places = TRUE
|
||||
chems = new
|
||||
chems.transfered = embedded_mob
|
||||
chems.spikey = src
|
||||
to_chat(fired_by, "<span class='notice'>Link established! Use the \"Transfer Chemicals\" ability to send your chemicals to the linked target!</span>")
|
||||
chems.Grant(fired_by)
|
||||
|
||||
/obj/item/hardened_spike/chem/unembedded()
|
||||
to_chat(fired_by, "<span class='warning'>Link lost!</span>")
|
||||
QDEL_NULL(chems)
|
||||
..()
|
||||
|
||||
/datum/action/innate/send_chems
|
||||
icon_icon = 'icons/mob/actions/actions_genetic.dmi'
|
||||
background_icon_state = "bg_spell"
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
button_icon_state = "spikechemswap"
|
||||
name = "Transfer Chemicals"
|
||||
desc = "Send all of your reagents into whomever the chem spike is embedded in. One use."
|
||||
var/obj/item/hardened_spike/chem/spikey
|
||||
var/mob/living/carbon/human/transfered
|
||||
|
||||
/datum/action/innate/send_chems/Activate()
|
||||
if(!ishuman(transfered) || !ishuman(owner))
|
||||
return
|
||||
var/mob/living/carbon/human/transferer = owner
|
||||
|
||||
to_chat(transfered, "<span class='warning'>You feel a tiny prick!</span>")
|
||||
transferer.reagents.trans_to(transfered, transferer.reagents.total_volume, 1, 1, 0)
|
||||
|
||||
var/obj/item/bodypart/L = spikey.checkembedded()
|
||||
|
||||
L.embedded_objects -= spikey
|
||||
//this is where it would deal damage, if it transfers chems it removes itself so no damage
|
||||
spikey.forceMove(get_turf(L))
|
||||
transfered.visible_message("<span class='notice'>[spikey] falls out of [transfered]!</span>")
|
||||
if(!transfered.has_embedded_objects())
|
||||
transfered.clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(transfered, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
spikey.unembedded()
|
||||
@@ -0,0 +1,108 @@
|
||||
/datum/mutation/human/antenna
|
||||
name = "Antenna"
|
||||
desc = "The affected person sprouts an antenna. This is known to allow them to access common radio channels passively."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You feel an antenna sprout from your forehead.</span>"
|
||||
text_lose_indication = "<span class='notice'>Your antenna shrinks back down.</span>"
|
||||
instability = 5
|
||||
difficulty = 8
|
||||
var/obj/item/implant/radio/antenna/linked_radio
|
||||
|
||||
/obj/item/implant/radio/antenna
|
||||
name = "internal antenna organ"
|
||||
desc = "The internal organ part of the antenna. Science has not yet given it a good name."
|
||||
icon = 'icons/obj/radio.dmi'//maybe make a unique sprite later. not important
|
||||
icon_state = "walkietalkie"
|
||||
|
||||
/obj/item/implant/radio/antenna/Initialize(mapload)
|
||||
..()
|
||||
if (radio)
|
||||
radio.name = "internal antenna"
|
||||
|
||||
/datum/mutation/human/antenna/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
linked_radio = new(owner)
|
||||
linked_radio.implant(owner, null, TRUE, TRUE)
|
||||
|
||||
/datum/mutation/human/antenna/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
if(linked_radio)
|
||||
linked_radio.Destroy()
|
||||
|
||||
/datum/mutation/human/antenna/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "antenna", -FRONT_MUTATIONS_LAYER+1))//-MUTATIONS_LAYER+1
|
||||
|
||||
/datum/mutation/human/antenna/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[type][1]
|
||||
|
||||
/datum/mutation/human/mindreader
|
||||
name = "Mind Reader"
|
||||
desc = "The affected person can look into the recent memories of others."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You hear distant voices at the corners of your mind.</span>"
|
||||
text_lose_indication = "<span class='notice'>The distant voices fade.</span>"
|
||||
power = /obj/effect/proc_holder/spell/targeted/mindread
|
||||
instability = 40
|
||||
difficulty = 8
|
||||
locked = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/mindread
|
||||
name = "Mindread"
|
||||
desc = "Read the target's mind."
|
||||
charge_max = 300
|
||||
range = 7
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "mindread"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/mindread/cast(list/targets, mob/living/carbon/human/user = usr)
|
||||
for(var/mob/living/M in targets)
|
||||
if(usr.anti_magic_check(FALSE, FALSE, TRUE, 0) || M.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
to_chat(usr, "<span class='warning'>As you reach out with your mind, you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
|
||||
return
|
||||
if(M.stat == DEAD)
|
||||
to_chat(user, "<span class='boldnotice'>[M] is dead!</span>")
|
||||
return
|
||||
if(M.mind)
|
||||
to_chat(user, "<span class='boldnotice'>You plunge into [M]'s mind...</span>")
|
||||
if(prob(20))
|
||||
to_chat(M, "<span class='danger'>You feel something foreign enter your mind.</span>")//chance to alert the read-ee
|
||||
var/list/recent_speech = list()
|
||||
var/list/say_log = list()
|
||||
var/log_source = M.logging
|
||||
for(var/log_type in log_source)//this whole loop puts the read-ee's say logs into say_log in an easy to access way
|
||||
var/nlog_type = text2num(log_type)
|
||||
if(nlog_type & LOG_SAY)
|
||||
var/list/reversed = log_source[log_type]
|
||||
if(islist(reversed))
|
||||
say_log = reverseRange(reversed.Copy())
|
||||
break
|
||||
if(LAZYLEN(say_log))
|
||||
for(var/spoken_memory in say_log)
|
||||
if(recent_speech.len >= 3)//up to 3 random lines of speech, favoring more recent speech
|
||||
break
|
||||
if(prob(50))
|
||||
recent_speech[spoken_memory] = say_log[spoken_memory]
|
||||
if(recent_speech.len)
|
||||
to_chat(user, "<span class='boldnotice'>You catch some drifting memories of their past conversations...</span>")
|
||||
for(var/spoken_memory in recent_speech)
|
||||
to_chat(user, "<span class='notice'>[recent_speech[spoken_memory]]</span>")
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
to_chat(user, "<span class='boldnotice'>You find that their intent is to [H.a_intent]...</span>")
|
||||
var/datum/dna/the_dna = H.has_dna()
|
||||
if(the_dna)
|
||||
to_chat(user, "<span class='boldnotice'>You uncover that [H.p_their()] true identity is [the_dna.real_name].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't find a mind to read inside of [M]!</span>")
|
||||
|
||||
/datum/mutation/human/mindreader/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "antenna", -FRONT_MUTATIONS_LAYER+1))
|
||||
|
||||
/datum/mutation/human/mindreader/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[type][1]
|
||||
+232
-10
@@ -3,16 +3,19 @@
|
||||
//Epilepsy gives a very small chance to have a seizure every life tick, knocking you unconscious.
|
||||
/datum/mutation/human/epilepsy
|
||||
name = "Epilepsy"
|
||||
desc = "A genetic defect that sporadically causes seizures."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You get a headache.</span>"
|
||||
synchronizer_coeff = 1
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/epilepsy/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(1) && owner.stat == CONSCIOUS)
|
||||
if(prob(1 * GET_MUTATION_SYNCHRONIZER(src)) && owner.stat == CONSCIOUS)
|
||||
owner.visible_message("<span class='danger'>[owner] starts having a seizure!</span>", "<span class='userdanger'>You have a seizure!</span>")
|
||||
owner.Unconscious(200)
|
||||
owner.Jitter(1000)
|
||||
owner.Unconscious(200 * GET_MUTATION_POWER(src))
|
||||
owner.Jitter(1000 * GET_MUTATION_POWER(src))
|
||||
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "epilepsy", /datum/mood_event/epilepsy)
|
||||
addtimer(CALLBACK(src, .proc/jitter_less, owner), 90)
|
||||
addtimer(CALLBACK(src, .proc/jitter_less), 90)
|
||||
|
||||
/datum/mutation/human/epilepsy/proc/jitter_less(mob/living/carbon/human/owner)
|
||||
if(owner)
|
||||
@@ -22,19 +25,23 @@
|
||||
//Unstable DNA induces random mutations!
|
||||
/datum/mutation/human/bad_dna
|
||||
name = "Unstable DNA"
|
||||
desc = "Strange mutation that causes the holder to randomly mutate."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel strange.</span>"
|
||||
locked = TRUE
|
||||
|
||||
/datum/mutation/human/bad_dna/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
to_chat(owner, text_gain_indication)
|
||||
var/mob/new_mob
|
||||
if(prob(95))
|
||||
if(prob(50))
|
||||
new_mob = owner.randmutb()
|
||||
new_mob = owner.easy_randmut(NEGATIVE + MINOR_NEGATIVE)
|
||||
else
|
||||
new_mob = owner.randmuti()
|
||||
else
|
||||
new_mob = owner.randmutg()
|
||||
new_mob = owner.easy_randmut(POSITIVE)
|
||||
if(new_mob && ismob(new_mob))
|
||||
owner = new_mob
|
||||
. = owner
|
||||
@@ -44,21 +51,31 @@
|
||||
//Cough gives you a chronic cough that causes you to drop items.
|
||||
/datum/mutation/human/cough
|
||||
name = "Cough"
|
||||
desc = "A chronic cough."
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You start coughing.</span>"
|
||||
synchronizer_coeff = 1
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/cough/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(5) && owner.stat == CONSCIOUS)
|
||||
if(prob(5 * GET_MUTATION_SYNCHRONIZER(src)) && owner.stat == CONSCIOUS)
|
||||
owner.drop_all_held_items()
|
||||
owner.emote("cough")
|
||||
|
||||
if(GET_MUTATION_POWER(src) > 1)
|
||||
var/cough_range = GET_MUTATION_POWER(src) * 4
|
||||
var/turf/target = get_ranged_target_turf(owner, turn(owner.dir, 180), cough_range)
|
||||
owner.throw_at(target, cough_range, GET_MUTATION_POWER(src))
|
||||
|
||||
|
||||
//Dwarfism shrinks your body and lets you pass tables.
|
||||
/datum/mutation/human/dwarfism
|
||||
name = "Dwarfism"
|
||||
desc = "A mutation believed to be the cause of dwarfism."
|
||||
quality = POSITIVE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
difficulty = 16
|
||||
instability = 5
|
||||
locked = TRUE // Default intert species for now, so locked from regular pool.
|
||||
|
||||
/datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
@@ -78,6 +95,7 @@
|
||||
//Clumsiness has a very large amount of small drawbacks depending on item.
|
||||
/datum/mutation/human/clumsy
|
||||
name = "Clumsiness"
|
||||
desc = "A genome that inhibits certain brain functions, causing the holder to appear clumsy. Honk"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel lightheaded.</span>"
|
||||
|
||||
@@ -95,11 +113,13 @@
|
||||
//Tourettes causes you to randomly stand in place and shout.
|
||||
/datum/mutation/human/tourettes
|
||||
name = "Tourette's Syndrome"
|
||||
desc = "A chronic twitch that forces the user to use colorful language."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You twitch.</span>"
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/datum/mutation/human/tourettes/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(10) && owner.stat == CONSCIOUS && !owner.IsStun())
|
||||
if(prob(10 * GET_MUTATION_SYNCHRONIZER(src)) && owner.stat == CONSCIOUS && !owner.IsStun())
|
||||
owner.Stun(200)
|
||||
switch(rand(1, 3))
|
||||
if(1)
|
||||
@@ -117,6 +137,7 @@
|
||||
//Deafness makes you deaf.
|
||||
/datum/mutation/human/deaf
|
||||
name = "Deafness"
|
||||
desc = "The holder of this genome is completely deaf."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to hear anything.</span>"
|
||||
|
||||
@@ -134,8 +155,10 @@
|
||||
//Monified turns you into a monkey.
|
||||
/datum/mutation/human/race
|
||||
name = "Monkified"
|
||||
desc = "A strange genome, believing to be what differentiates monkeys from humans."
|
||||
quality = NEGATIVE
|
||||
time_coeff = 2
|
||||
locked = TRUE //Species specific, keep out of actual gene pool
|
||||
|
||||
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
@@ -145,3 +168,202 @@
|
||||
/datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner)
|
||||
if(owner && istype(owner) && owner.stat != DEAD && (owner.dna.mutations.Remove(src)))
|
||||
. = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
|
||||
|
||||
|
||||
/datum/mutation/human/glow
|
||||
name = "Glowy"
|
||||
desc = "You permanently emit a light with a random color and intensity."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your skin begins to glow softly.</span>"
|
||||
instability = 5
|
||||
var/obj/effect/dummy/luminescent_glow/glowth //shamelessly copied from luminescents
|
||||
var/glow = 1.5
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/glow/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
glowth = new(owner)
|
||||
glowth.set_light(glow, glow, dna.features["mcolor"])
|
||||
|
||||
/datum/mutation/human/glow/modify(mob/living/carbon/human/owner)
|
||||
if(glowth)
|
||||
glowth.set_light(glow + GET_MUTATION_POWER(src) , glow + GET_MUTATION_POWER(src), dna.features["mcolor"])
|
||||
|
||||
/datum/mutation/human/glow/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
qdel(glowth)
|
||||
|
||||
/datum/mutation/human/strong
|
||||
name = "Strength"
|
||||
desc = "The user's muscles slightly expand."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You feel strong.</span>"
|
||||
difficulty = 16
|
||||
|
||||
/datum/mutation/human/fire
|
||||
name = "Fiery Sweat"
|
||||
desc = "The user's skin will randomly combust, but is generally alot more resilient to burning."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='warning'>You feel hot.</span>"
|
||||
text_lose_indication = "<span class'notice'>You feel a lot cooler.</span>"
|
||||
difficulty = 14
|
||||
synchronizer_coeff = 1
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/fire/on_life(mob/living/carbon/human/owner)
|
||||
if(prob((1+(100-dna.stability)/10)) * GET_MUTATION_SYNCHRONIZER(src))
|
||||
owner.adjust_fire_stacks(2 * GET_MUTATION_POWER(src))
|
||||
owner.IgniteMob()
|
||||
|
||||
/datum/mutation/human/fire/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.physiology.burn_mod *= 0.5
|
||||
|
||||
/datum/mutation/human/fire/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.physiology.burn_mod *= 2
|
||||
|
||||
/datum/mutation/human/insulated
|
||||
name = "Insulated"
|
||||
desc = "The affected person does not conduct electricity."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your fingertips go numb.</span>"
|
||||
text_lose_indication = "<span class='notice'>Your fingertips regain feeling.</span>"
|
||||
difficulty = 16
|
||||
instability = 25
|
||||
|
||||
/datum/mutation/human/insulated/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "genetics")
|
||||
|
||||
/datum/mutation/human/insulated/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "genetics")
|
||||
|
||||
|
||||
/datum/mutation/human/glow/anti
|
||||
name = "Anti-Glow"
|
||||
desc = "Your skin seems to attract and absorb nearby light creating 'darkness' around you."
|
||||
text_gain_indication = "<span class='notice'>Your light around you seems to disappear.</span>"
|
||||
glow = -3.5 //Slightly stronger, since negating light tends to be harder than making it.
|
||||
locked = TRUE
|
||||
|
||||
/datum/mutation/human/stimmed
|
||||
name = "Stimmed"
|
||||
desc = "The user's chemical balance is more robust."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You feel stimmed.</span>"
|
||||
difficulty = 16
|
||||
|
||||
/datum/mutation/human/paranoia
|
||||
name = "Paranoia"
|
||||
desc = "Subject is easily terrified, and may suffer from hallucinations."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel screams echo through your mind...</span>"
|
||||
text_lose_indication = "<span class'notice'>The screaming in your mind fades.</span>"
|
||||
|
||||
/datum/mutation/human/paranoia/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(5) && owner.stat == CONSCIOUS)
|
||||
owner.emote("scream")
|
||||
owner.jitteriness = min(max(0, owner.jitteriness + 5), 30)
|
||||
if(prob(25))
|
||||
to_chat(owner,"<span class='warning'>You feel someone creeping in on you...</span>")
|
||||
owner.hallucination += 20
|
||||
|
||||
|
||||
/datum/mutation/human/badblink
|
||||
name = "Spatial Instability"
|
||||
desc = "The victim of the mutation has a very weak link to spatial reality, and may be displaced. Often causes extreme nausea."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='warning'>The space around you twists sickeningly.</span>"
|
||||
text_lose_indication = "<span class'notice'>The space around you settles back to normal.</span>"
|
||||
difficulty = 18//high so it's hard to unlock and abuse
|
||||
instability = 10
|
||||
synchronizer_coeff = 1
|
||||
energy_coeff = 1
|
||||
power_coeff = 1
|
||||
var/warpchance = 0
|
||||
|
||||
/datum/mutation/human/badblink/on_life()
|
||||
if (!owner)
|
||||
return
|
||||
if(prob(warpchance))
|
||||
var/warpmessage = pick(
|
||||
"<span class='warning'>With a sickening 720-degree twist of [owner.p_their()] back, [owner] vanishes into thin air.</span>",
|
||||
"<span class='warning'>[owner] does some sort of strange backflip into another dimension. It looks pretty painful.</span>",
|
||||
"<span class='warning'>[owner] does a jump to the left, a step to the right, and warps out of reality.</span>",
|
||||
"<span class='warning'>[owner]'s torso starts folding inside out until it vanishes from reality, taking [owner] with it.</span>",
|
||||
"<span class='warning'>One moment, you see [owner]. The next, [owner] is gone.</span>")
|
||||
owner.visible_message(warpmessage, "<span class='userdanger'>You feel a wave of nausea as you fall through reality!</span>")
|
||||
var/warpdistance = rand(10,15) * GET_MUTATION_POWER(src)
|
||||
do_teleport(owner, get_turf(owner), warpdistance, channel = TELEPORT_CHANNEL_FREE)
|
||||
owner.adjust_disgust(GET_MUTATION_SYNCHRONIZER(src) * (warpchance * warpdistance))
|
||||
warpchance = 0
|
||||
owner.visible_message("<span class='danger'>[owner] appears out of nowhere!</span>")
|
||||
else
|
||||
warpchance += 0.25 * GET_MUTATION_ENERGY(src)
|
||||
|
||||
/datum/mutation/human/acidflesh
|
||||
name = "Acidic Flesh"
|
||||
desc = "Subject has acidic chemicals building up underneath the skin. This is often lethal."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='userdanger'>A horrible burning sensation envelops you as your flesh turns to acid!</span>"
|
||||
text_lose_indication = "<span class'notice'>A feeling of relief fills you as your flesh goes back to normal.</span>"
|
||||
difficulty = 18//high so it's hard to unlock and use on others
|
||||
var/msgcooldown = 0
|
||||
|
||||
/datum/mutation/human/acidflesh/on_life()
|
||||
if(prob(25))
|
||||
if(world.time > msgcooldown)
|
||||
to_chat(owner, "<span class='danger'>Your acid flesh bubbles...</span>")
|
||||
msgcooldown = world.time + 200
|
||||
if(prob(15))
|
||||
owner.acid_act(rand(30,50), 10)
|
||||
owner.visible_message("<span class='warning'>[owner]'s skin bubbles and pops.</span>", "<span class='userdanger'>Your bubbling flesh pops! It burns!</span>")
|
||||
playsound(owner,'sound/weapons/sear.ogg', 50, TRUE)
|
||||
|
||||
/datum/mutation/human/gigantism
|
||||
name = "Gigantism"//negative version of dwarfism
|
||||
desc = "The cells within the subject spread out to cover more area, making the subject appear larger."
|
||||
quality = MINOR_NEGATIVE
|
||||
difficulty = 12
|
||||
|
||||
/datum/mutation/human/gigantism/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.resize = 1.25
|
||||
owner.update_transform()
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly grows!</span>", "<span class='notice'>Everything around you seems to shrink..</span>")
|
||||
|
||||
/datum/mutation/human/gigantism/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.resize = 0.8
|
||||
owner.update_transform()
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly shrinks!</span>", "<span class='notice'>Everything around you seems to grow..</span>")
|
||||
|
||||
/datum/mutation/human/spastic
|
||||
name = "Spastic"
|
||||
desc = "Subject suffers from muscle spasms."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='warning'>You flinch.</span>"
|
||||
text_lose_indication = "<span class'notice'>Your flinching subsides.</span>"
|
||||
difficulty = 16
|
||||
|
||||
/datum/mutation/human/spastic/on_acquiring()
|
||||
if(..())
|
||||
return
|
||||
if (owner)
|
||||
owner.apply_status_effect(STATUS_EFFECT_SPASMS)
|
||||
|
||||
/datum/mutation/human/spastic/on_losing()
|
||||
if(..())
|
||||
return
|
||||
if (owner)
|
||||
owner.remove_status_effect(STATUS_EFFECT_SPASMS)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//Chameleon causes the owner to slowly become transparent when not moving.
|
||||
/datum/mutation/human/chameleon
|
||||
name = "Chameleon"
|
||||
desc = "A genome that causes the holder's skin to become transparent over time."
|
||||
quality = POSITIVE
|
||||
get_chance = 20
|
||||
lowest_value = 256 * 12
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>You feel one with your surroundings.</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel oddly exposed.</span>"
|
||||
time_coeff = 5
|
||||
instability = 25
|
||||
|
||||
/datum/mutation/human/chameleon/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/datum/mutation/human/geladikinesis
|
||||
name = "Geladikinesis"
|
||||
desc = "Allows the user to concentrate moisture and sub-zero forces into snow."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your hand feels cold.</span>"
|
||||
instability = 10
|
||||
difficulty = 10
|
||||
synchronizer_coeff = 1
|
||||
power = /obj/effect/proc_holder/spell/targeted/conjure_item/snow
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/conjure_item/snow
|
||||
name = "Create Snow"
|
||||
desc = "Concentrates cryokinetic forces to create snow, useful for snow-like construction."
|
||||
item_type = /obj/item/stack/sheet/mineral/snow
|
||||
charge_max = 50
|
||||
action_icon_state = "snow"
|
||||
delete_old = FALSE
|
||||
|
||||
|
||||
/datum/mutation/human/cryokinesis
|
||||
name = "Cryokinesis"
|
||||
desc = "Draws negative energy from the sub-zero void to freeze surrounding temperatures at subject's will."
|
||||
quality = POSITIVE //upsides and downsides
|
||||
text_gain_indication = "<span class='notice'>Your hand feels cold.</span>"
|
||||
instability = 20
|
||||
difficulty = 12
|
||||
synchronizer_coeff = 1
|
||||
power = /obj/effect/proc_holder/spell/aimed/cryo
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/cryo
|
||||
name = "Cryobeam"
|
||||
desc = "This power fires a frozen bolt at a target."
|
||||
charge_max = 150
|
||||
cooldown_min = 150
|
||||
clothes_req = FALSE
|
||||
range = 3
|
||||
projectile_type = /obj/item/projectile/temp/cryo
|
||||
base_icon_state = "icebeam"
|
||||
action_icon_state = "icebeam"
|
||||
active_msg = "You focus your cryokinesis!"
|
||||
deactive_msg = "You relax."
|
||||
active = FALSE
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
//Cold Resistance gives your entire body an orange halo, and makes you immune to the effects of vacuum and cold.
|
||||
/datum/mutation/human/cold_resistance
|
||||
name = "Cold Resistance"
|
||||
quality = POSITIVE
|
||||
get_chance = 25
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>Your body feels warm!</span>"
|
||||
time_coeff = 5
|
||||
|
||||
/datum/mutation/human/cold_resistance/New()
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "fire", -MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/cold_resistance/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
ADD_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
// ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
// REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner)
|
||||
if(owner.getFireLoss())
|
||||
if(prob(1))
|
||||
owner.heal_bodypart_damage(0,1) //Is this really needed?
|
||||
@@ -0,0 +1,32 @@
|
||||
/datum/generecipe
|
||||
var/required = "" //it hurts so bad but initial is not compatible with lists
|
||||
var/result = null
|
||||
|
||||
/proc/get_mixed_mutation(mutation1, mutation2)
|
||||
if(!mutation1 || !mutation2)
|
||||
return FALSE
|
||||
if(mutation1 == mutation2) //this could otherwise be bad
|
||||
return FALSE
|
||||
for(var/A in GLOB.mutation_recipes)
|
||||
if(findtext(A, "[mutation1]") && findtext(A, "[mutation2]"))
|
||||
return GLOB.mutation_recipes[A]
|
||||
|
||||
/datum/generecipe/x_ray
|
||||
required = "/datum/mutation/human/thermal; /datum/mutation/human/radioactive"
|
||||
result = /datum/mutation/human/thermal/x_ray
|
||||
|
||||
/datum/generecipe/shock
|
||||
required = "/datum/mutation/human/insulated; /datum/mutation/human/radioactive"
|
||||
result = SHOCKTOUCH
|
||||
|
||||
/datum/generecipe/mindread
|
||||
required = "/datum/mutation/human/antenna; /datum/mutation/human/paranoia"
|
||||
result = MINDREAD
|
||||
|
||||
/datum/generecipe/antiglow
|
||||
required = "/datum/mutation/human/glow; /datum/mutation/human/void"
|
||||
result = ANTIGLOWY
|
||||
|
||||
/datum/generecipe/tonguechem
|
||||
required = "/datum/mutation/human/tongue_spike; /datum/mutation/human/stimmed"
|
||||
result = TONGUESPIKECHEM
|
||||
@@ -1,12 +1,14 @@
|
||||
//Hulk turns your skin green, and allows you to punch through walls.
|
||||
/datum/mutation/human/hulk
|
||||
name = "Hulk"
|
||||
desc = "A poorly understood genome that causes the holder's muscles to expand, inhibit speech and gives the person a bad skin condition."
|
||||
quality = POSITIVE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
locked = TRUE
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>Your muscles hurt!</span>"
|
||||
species_allowed = list("fly") //no skeleton/lizard hulk
|
||||
species_allowed = list("human") //no skeleton/lizard hulk
|
||||
health_req = 25
|
||||
instability = 40
|
||||
|
||||
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
@@ -18,7 +20,7 @@
|
||||
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "hulk", /datum/mood_event/hulk)
|
||||
RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||
|
||||
/datum/mutation/human/hulk/on_attack_hand(mob/living/carbon/human/owner, atom/target, proximity)
|
||||
/datum/mutation/human/hulk/on_attack_hand(mob/living/carbon/human/owner,atom/target, proximity)
|
||||
if(proximity) //no telekinetic hulk attack
|
||||
return target.attack_hulk(owner)
|
||||
|
||||
@@ -32,7 +34,7 @@
|
||||
return
|
||||
REMOVE_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK)
|
||||
REMOVE_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK)
|
||||
ADD_TRAIT(owner, TRAIT_CHUNKYFINGERS, TRAIT_HULK)
|
||||
REMOVE_TRAIT(owner, TRAIT_CHUNKYFINGERS, TRAIT_HULK)
|
||||
owner.update_body_parts()
|
||||
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "hulk")
|
||||
UnregisterSignal(owner, COMSIG_MOB_SAY)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/mutation/human/radioactive
|
||||
name = "Radioactivity"
|
||||
desc = "A volatile mutation that causes the host to sent out deadly beta radiation. This affects both the hosts and their surroundings."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='warning'>You can feel it in your bones!</span>"
|
||||
time_coeff = 5
|
||||
instability = 5
|
||||
difficulty = 8
|
||||
|
||||
/datum/mutation/human/radioactive/on_life(mob/living/carbon/human/owner)
|
||||
radiation_pulse(owner, 20)
|
||||
|
||||
/datum/mutation/human/radioactive/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "radiation", -MUTATIONS_LAYER))
|
||||
|
||||
/datum/mutation/human/radioactive/get_visual_indicator()
|
||||
return visual_indicators[type][1]
|
||||
@@ -1,6 +1,7 @@
|
||||
//Nearsightedness restricts your vision by several tiles.
|
||||
/datum/mutation/human/nearsight
|
||||
name = "Near Sightness"
|
||||
desc = "The holder of this mutation has poor eyesight."
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't see very well.</span>"
|
||||
|
||||
@@ -18,6 +19,7 @@
|
||||
//Blind makes you blind. Who knew?
|
||||
/datum/mutation/human/blind
|
||||
name = "Blindness"
|
||||
desc = "Renders the subject completely blind."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to see anything.</span>"
|
||||
|
||||
@@ -32,43 +34,58 @@
|
||||
owner.cure_blind(GENETIC_MUTATION)
|
||||
|
||||
|
||||
//X-ray Vision lets you see through walls.
|
||||
/datum/mutation/human/x_ray
|
||||
name = "X Ray Vision"
|
||||
///Thermal Vision lets you see mobs through walls
|
||||
/datum/mutation/human/thermal
|
||||
name = "Thermal Vision"
|
||||
desc = "The user of this genome can visually percieve the unique human thermal signature."
|
||||
quality = POSITIVE
|
||||
get_chance = 25
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>The walls suddenly disappear!</span>"
|
||||
difficulty = 18
|
||||
text_gain_indication = "<span class='notice'>You can see the heat rising off of your skin...</span>"
|
||||
time_coeff = 2
|
||||
instability = 25
|
||||
var/visionflag = TRAIT_THERMAL_VISION
|
||||
|
||||
/datum/mutation/human/x_ray/on_acquiring(mob/living/carbon/human/owner)
|
||||
/datum/mutation/human/thermal/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
|
||||
ADD_TRAIT(owner, visionflag, GENETIC_MUTATION)
|
||||
owner.update_sight()
|
||||
|
||||
/datum/mutation/human/x_ray/on_losing(mob/living/carbon/human/owner)
|
||||
/datum/mutation/human/thermal/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
REMOVE_TRAIT(owner, visionflag, GENETIC_MUTATION)
|
||||
owner.update_sight()
|
||||
|
||||
///X-ray Vision lets you see through walls.
|
||||
/datum/mutation/human/thermal/x_ray
|
||||
name = "X Ray Vision"
|
||||
desc = "A strange genome that allows the user to see between the spaces of walls." //actual x-ray would mean you'd constantly be blasting rads, wich might be fun for later //hmb
|
||||
text_gain_indication = "<span class='notice'>The walls suddenly disappear!</span>"
|
||||
instability = 35
|
||||
locked = TRUE
|
||||
visionflag = TRAIT_XRAY_VISION
|
||||
|
||||
|
||||
//Laser Eyes lets you shoot lasers from your eyes!
|
||||
/datum/mutation/human/laser_eyes
|
||||
name = "Laser Eyes"
|
||||
desc = "Reflects concentrated light back from the eyes."
|
||||
quality = POSITIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
locked = TRUE
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>You feel pressure building up behind your eyes.</span>"
|
||||
layer_used = FRONT_MUTATIONS_LAYER
|
||||
limb_req = BODY_ZONE_HEAD
|
||||
|
||||
/datum/mutation/human/laser_eyes/New()
|
||||
/datum/mutation/human/laser_eyes/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "lasereyes", -FRONT_MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/laser_eyes/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
/datum/mutation/human/laser_eyes/get_visual_indicator()
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target, mouseparams)
|
||||
/datum/mutation/human/laser_eyes/on_ranged_attack(atom/target, mouseparams)
|
||||
if(owner.a_intent == INTENT_HARM)
|
||||
owner.LaserEyes(target, mouseparams)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//Cold Resistance gives your entire body an orange halo, and makes you immune to the effects of vacuum and cold.
|
||||
/datum/mutation/human/space_adaptation
|
||||
name = "Space Adaptation"
|
||||
desc = "A strange mutation that renders the host immune to the vacuum if space. Will still need an oxygen supply."
|
||||
quality = POSITIVE
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>Your body feels warm!</span>"
|
||||
time_coeff = 5
|
||||
instability = 30
|
||||
|
||||
/datum/mutation/human/space_adaptation/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "fire", -MUTATIONS_LAYER))
|
||||
|
||||
/datum/mutation/human/space_adaptation/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[type][1]
|
||||
|
||||
/datum/mutation/human/space_adaptation/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
ADD_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance")
|
||||
|
||||
/datum/mutation/human/space_adaptation/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance")
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
/datum/mutation/human/nervousness
|
||||
name = "Nervousness"
|
||||
desc = "Causes the holder to stutter."
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel nervous.</span>"
|
||||
|
||||
@@ -13,6 +14,7 @@
|
||||
|
||||
/datum/mutation/human/wacky
|
||||
name = "Wacky"
|
||||
desc = "<span class='sans'>Unknown.</span>"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='sans'>You feel an off sensation in your voicebox.</span>"
|
||||
text_lose_indication = "<span class='notice'>The off sensation passes.</span>"
|
||||
@@ -34,6 +36,7 @@
|
||||
|
||||
/datum/mutation/human/mute
|
||||
name = "Mute"
|
||||
desc = "Completely inhibits the vocal section of the brain."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel unable to express yourself at all.</span>"
|
||||
text_lose_indication = "<span class='danger'>You feel able to speak freely again.</span>"
|
||||
@@ -53,8 +56,8 @@
|
||||
|
||||
/datum/mutation/human/smile
|
||||
name = "Smile"
|
||||
desc = "Causes the user to be in constant mania."
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel so happy. Nothing can be wrong with anything. :)</span>"
|
||||
text_lose_indication = "<span class='notice'>Everything is terrible again. :(</span>"
|
||||
|
||||
@@ -95,7 +98,6 @@
|
||||
message = replacetext(message," ugly "," beautiful ")
|
||||
message = replacetext(message," douchbag "," nice guy ")
|
||||
message = replacetext(message," whore "," lady ")
|
||||
message = replacetext(message," gamer "," intellectual ")
|
||||
message = replacetext(message," nerd "," smarty pants ")
|
||||
message = replacetext(message," moron "," fun person ")
|
||||
message = replacetext(message," IT'S LOOSE "," EVERYTHING IS FINE ")
|
||||
@@ -121,8 +123,8 @@
|
||||
|
||||
/datum/mutation/human/unintelligible
|
||||
name = "Unintelligible"
|
||||
desc = "Partially inhibits the vocal center of the brain, severely distorting speech."
|
||||
quality = NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to form any coherent thoughts!</span>"
|
||||
text_lose_indication = "<span class='danger'>Your mind feels more clear.</span>"
|
||||
|
||||
@@ -141,8 +143,9 @@
|
||||
|
||||
/datum/mutation/human/swedish
|
||||
name = "Swedish"
|
||||
desc = "A horrible mutation originating from the distant past. Thought to be eradicated after the incident in 2037."
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>You feel Swedish, however that works.</span>"
|
||||
text_lose_indication = "<span class='notice'>The feeling of Swedishness passes.</span>"
|
||||
|
||||
@@ -173,8 +176,8 @@
|
||||
|
||||
/datum/mutation/human/chav
|
||||
name = "Chav"
|
||||
desc = "Unknown"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>Ye feel like a reet prat like, innit?</span>"
|
||||
text_lose_indication = "<span class='notice'>You no longer feel like being rude and sassy.</span>"
|
||||
|
||||
@@ -220,12 +223,13 @@
|
||||
|
||||
/datum/mutation/human/elvis
|
||||
name = "Elvis"
|
||||
desc = "A terrifying mutation named after its 'patient-zero'."
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>You feel pretty good, honeydoll.</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel a little less conversation would be great.</span>"
|
||||
|
||||
/datum/mutation/human/elvis/on_life(mob/living/carbon/human/owner)
|
||||
/datum/mutation/human/elvis/on_life()
|
||||
switch(pick(1,2))
|
||||
if(1)
|
||||
if(prob(15))
|
||||
@@ -266,8 +270,9 @@
|
||||
|
||||
/datum/mutation/human/stoner
|
||||
name = "Stoner"
|
||||
desc = "A common mutation that severely decreases intelligence."
|
||||
quality = NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>You feel...totally chill, man!</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel like you have a better sense of time.</span>"
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
//Telekinesis lets you interact with objects from range, and gives you a light blue halo around your head.
|
||||
/datum/mutation/human/telekinesis
|
||||
name = "Telekinesis"
|
||||
desc = "A strange mutation that allows the holder to interact with objects through thought."
|
||||
quality = POSITIVE
|
||||
get_chance = 20
|
||||
lowest_value = 256 * 12
|
||||
difficulty = 18
|
||||
text_gain_indication = "<span class='notice'>You feel smarter!</span>"
|
||||
limb_req = BODY_ZONE_HEAD
|
||||
instability = 30
|
||||
|
||||
/datum/mutation/human/telekinesis/New()
|
||||
/datum/mutation/human/telekinesis/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "telekinesishead", -MUTATIONS_LAYER)
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "telekinesishead", -MUTATIONS_LAYER))
|
||||
|
||||
/datum/mutation/human/telekinesis/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
return visual_indicators[type][1]
|
||||
|
||||
/datum/mutation/human/telekinesis/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
|
||||
target.attack_tk(owner)
|
||||
target.attack_tk(owner)
|
||||
@@ -801,3 +801,26 @@ datum/status_effect/pacify
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK)
|
||||
owner.throw_item(pick(targets))
|
||||
|
||||
/datum/status_effect/dna_melt
|
||||
id = "dna_melt"
|
||||
duration = 600
|
||||
status_type = STATUS_EFFECT_REPLACE
|
||||
alert_type = /obj/screen/alert/status_effect/dna_melt
|
||||
var/kill_either_way = FALSE //no amount of removing mutations is gonna save you now
|
||||
|
||||
/datum/status_effect/dna_melt/on_creation(mob/living/new_owner, set_duration, updating_canmove)
|
||||
. = ..()
|
||||
to_chat(new_owner, "<span class='boldwarning'>My body can't handle the mutations! I need to get my mutations removed fast!</span>")
|
||||
|
||||
/datum/status_effect/dna_melt/on_remove()
|
||||
if(!ishuman(owner))
|
||||
owner.gib() //fuck you in particular
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.something_horrible(kill_either_way)
|
||||
|
||||
/obj/screen/alert/status_effect/dna_melt
|
||||
name = "Genetic Breakdown"
|
||||
desc = "I don't feel so good. Your body can't handle the mutations! You have one minute to remove your mutations, or you will be met with a horrible fate."
|
||||
icon_state = "dna_melt"
|
||||
@@ -77,6 +77,8 @@
|
||||
name = "cloning data disk"
|
||||
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
|
||||
var/list/fields = list()
|
||||
var/list/mutations = list()
|
||||
var/max_mutations = 6
|
||||
var/read_only = 0 //Well,it's still a floppy disk
|
||||
|
||||
//Disk stuff.
|
||||
@@ -129,7 +131,7 @@
|
||||
return examine(user)
|
||||
|
||||
//Start growing a human clone in the pod!
|
||||
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions, list/quirks)
|
||||
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks)
|
||||
if(panel_open)
|
||||
return FALSE
|
||||
if(mess || attempting)
|
||||
@@ -165,8 +167,9 @@
|
||||
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
|
||||
|
||||
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
|
||||
H.randmutb() //100% bad mutation. Can be cured with mutadone.
|
||||
H.hardset_dna(ui, mutation_index, H.real_name, null, mrace, features)
|
||||
|
||||
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) //100% bad mutation. Can be cured with mutadone.
|
||||
|
||||
H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
|
||||
occupant = H
|
||||
|
||||
@@ -485,7 +485,7 @@
|
||||
R.fields["id"] = copytext_char(md5(mob_occupant.real_name), 2, 6)
|
||||
R.fields["UE"] = dna.unique_enzymes
|
||||
R.fields["UI"] = dna.uni_identity
|
||||
R.fields["SE"] = dna.struc_enzymes
|
||||
R.fields["SE"] = dna.mutation_index
|
||||
R.fields["blood_type"] = dna.blood_type
|
||||
R.fields["features"] = dna.features
|
||||
R.fields["factions"] = mob_occupant.faction
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#define INJECTOR_TIMEOUT 100
|
||||
#define REJUVENATORS_INJECT 15
|
||||
#define REJUVENATORS_MAX 90
|
||||
#define NUMBER_OF_BUFFERS 3
|
||||
#define SCRAMBLE_TIMEOUT 600
|
||||
#define JOKER_TIMEOUT 12000 //20 minutes
|
||||
#define JOKER_UPGRADE 1800
|
||||
|
||||
#define RADIATION_STRENGTH_MAX 15
|
||||
#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has a more range
|
||||
#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has more range
|
||||
|
||||
#define RADIATION_DURATION_MAX 30
|
||||
#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate
|
||||
|
||||
|
||||
#define RADIATION_IRRADIATION_MULTIPLIER 1 //multiplier for how much radiation a test subject receives
|
||||
|
||||
#define SCANNER_ACTION_SE 1
|
||||
@@ -23,22 +25,44 @@
|
||||
icon_keyboard = "med_key"
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/computer/scan_consolenew
|
||||
var/radduration = 2
|
||||
var/radstrength = 1
|
||||
|
||||
var/list/buffer[NUMBER_OF_BUFFERS]
|
||||
|
||||
var/injectorready = 0 //world timer cooldown var
|
||||
var/current_screen = "mainmenu"
|
||||
var/obj/machinery/dna_scannernew/connected = null
|
||||
var/obj/item/disk/data/diskette = null
|
||||
var/list/delayed_action = null
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 400
|
||||
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
var/datum/techweb/stored_research
|
||||
var/max_storage = 6
|
||||
var/combine
|
||||
var/radduration = 2
|
||||
var/radstrength = 1
|
||||
var/max_chromosomes = 6
|
||||
|
||||
///Amount of mutations we can store
|
||||
var/list/buffer[NUMBER_OF_BUFFERS]
|
||||
///mutations we have stored
|
||||
var/list/stored_mutations = list()
|
||||
///chromosomes we have stored
|
||||
var/list/stored_chromosomes = list()
|
||||
///combinations of injectors for the 'injector selection'. format is list("Elsa" = list(Cryokinesis, Geladikinesis), "The Hulk" = list(Hulk, Gigantism), etc) Glowy and the gang being an initialized datum
|
||||
var/list/injector_selection = list()
|
||||
///max amount of selections you can make
|
||||
var/max_injector_selections = 2
|
||||
///hard-cap on the advanced dna injector
|
||||
var/max_injector_mutations = 10
|
||||
///the max instability of the advanced injector.
|
||||
var/max_injector_instability = 50
|
||||
|
||||
var/injectorready = 0 //world timer cooldown var
|
||||
var/jokerready = 0
|
||||
var/scrambleready = 0
|
||||
var/current_screen = "mainmenu"
|
||||
var/current_mutation //what block are we inspecting? only used when screen = "info"
|
||||
var/current_storage //what storage block are we looking at?
|
||||
var/obj/machinery/dna_scannernew/connected = null
|
||||
var/obj/item/disk/data/diskette = null
|
||||
var/list/delayed_action = null
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
|
||||
if (istype(I, /obj/item/disk/data)) //INSERT SOME DISKETTES
|
||||
if (!src.diskette)
|
||||
@@ -48,6 +72,28 @@
|
||||
to_chat(user, "<span class='notice'>You insert [I].</span>")
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
if (istype(I, /obj/item/chromosome))
|
||||
if(LAZYLEN(stored_chromosomes) < max_chromosomes)
|
||||
I.forceMove(src)
|
||||
stored_chromosomes += I
|
||||
to_chat(user, "<span class='notice'>You insert [I].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You cannot store any more chromosomes!</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/dnainjector/activator))
|
||||
var/obj/item/dnainjector/activator/A = I
|
||||
if(A.used)
|
||||
to_chat(user,"<span class='notice'>Recycled [I].</span>")
|
||||
if(A.research)
|
||||
var/c_typepath = generate_chromosome()
|
||||
var/obj/item/chromosome/CM = new c_typepath (drop_location())
|
||||
to_chat(user,"<span class='notice'>Recycled [I].</span>")
|
||||
if((LAZYLEN(stored_chromosomes) < max_chromosomes) && prob(60))
|
||||
CM.forceMove(src)
|
||||
stored_chromosomes += CM
|
||||
to_chat(user,"<span class='notice'>[capitalize(CM.name)] added to storage.</span>")
|
||||
qdel(I)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -58,12 +104,26 @@
|
||||
if(!isnull(connected))
|
||||
break
|
||||
injectorready = world.time + INJECTOR_TIMEOUT
|
||||
scrambleready = world.time + SCRAMBLE_TIMEOUT
|
||||
jokerready = world.time + JOKER_TIMEOUT
|
||||
|
||||
stored_research = SSresearch.science_tech
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/examine(mob/user)
|
||||
. = ..()
|
||||
if(jokerready < world.time)
|
||||
. += "<span class='notice'>JOKER algorithm available.</span>"
|
||||
else
|
||||
. += "<span class='notice'>JOKER algorithm available in about [round(0.00166666667 * (jokerready - world.time))] minutes."
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, last_change)
|
||||
. = ..()
|
||||
if(!user)
|
||||
return
|
||||
var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window
|
||||
if(user.client)
|
||||
var/datum/asset/simple/assets = get_asset_datum(/datum/asset/simple/genetics)
|
||||
assets.send(user.client)
|
||||
if(!(in_range(src, user) || hasSiliconAccessInArea(user)))
|
||||
popup.close()
|
||||
return
|
||||
@@ -88,8 +148,6 @@
|
||||
occupant_status += "</div></div>"
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Health:</div><div class='progressBar'><div style='width: [viable_occupant.health]%;' class='progressFill good'></div></div><div class='statusValue'>[viable_occupant.health] %</div></div>"
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Radiation Level:</div><div class='progressBar'><div style='width: [viable_occupant.radiation/(RAD_MOB_SAFE/100)]%;' class='progressFill bad'></div></div><div class='statusValue'>[viable_occupant.radiation/(RAD_MOB_SAFE/100)] %</div></div>"
|
||||
var/rejuvenators = viable_occupant.reagents.get_reagent_amount(/datum/reagent/medicine/potass_iodide)
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Rejuvenators:</div><div class='progressBar'><div style='width: [round((rejuvenators / REJUVENATORS_MAX) * 100)]%;' class='progressFill highlight'></div></div><div class='statusValue'>[rejuvenators] units</div></div>"
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Unique Enzymes :</div><div class='statusValue'><span class='highlight'>[viable_occupant.dna.unique_enzymes]</span></div></div>"
|
||||
occupant_status += "<div class='line'><div class='statusLabel'>Last Operation:</div><div class='statusValue'>[last_change ? last_change : "----"]</div></div>"
|
||||
else
|
||||
@@ -147,28 +205,61 @@
|
||||
buttons += "<a href='?src=[REF(src)];task=togglelock;'>[connected.locked ? "Unlock" : "Lock"] Scanner</a>"
|
||||
else
|
||||
buttons += "<span class='linkOff'>Open Scanner</span> <span class='linkOff'>Lock Scanner</span>"
|
||||
if(viable_occupant)
|
||||
buttons += "<a href='?src=[REF(src)];task=rejuv'>Inject Rejuvenators</a>"
|
||||
if(viable_occupant && (scrambleready < world.time))
|
||||
buttons += "<a href='?src=[REF(src)];task=scramble'>Scramble DNA</a>"
|
||||
else
|
||||
buttons += "<span class='linkOff'>Inject Rejuvenators</span>"
|
||||
buttons += "<span class='linkOff'>Scramble DNA</span>"
|
||||
if(diskette)
|
||||
buttons += "<a href='?src=[REF(src)];task=ejectdisk'>Eject Disk</a>"
|
||||
buttons += "<a href='?src=[REF(src)];task=screen;text=disk;'>Disk</a>"
|
||||
else
|
||||
buttons += "<span class='linkOff'>Eject Disk</span>"
|
||||
if(current_screen == "buffer")
|
||||
buttons += "<a href='?src=[REF(src)];task=screen;text=mainmenu;'>Radiation Emitter Menu</a>"
|
||||
buttons += "<span class='linkOff'>Disk</span>"
|
||||
if(current_screen == "mutations")
|
||||
buttons += "<span class='linkOff'>Mutations</span>"
|
||||
else
|
||||
buttons += "<a href='?src=[REF(src)];task=screen;text=buffer;'>Buffer Menu</a>"
|
||||
|
||||
buttons += "<a href='?src=[REF(src)];task=screen;text=mutations;'>Mutations</a>"
|
||||
if((current_screen == "mainmenu") || !current_screen)
|
||||
buttons += "<span class='linkOff'>Genetic Sequencer</span>"
|
||||
else
|
||||
buttons += "<a href='?src=[REF(src)];task=screen;text=mainmenu;'>Genetic Sequencer</a>"
|
||||
if(current_screen == "ui")
|
||||
buttons += "<span class='linkOff'>Unique Identifiers</span>"
|
||||
else
|
||||
buttons += "<a href='?src=[REF(src)];task=screen;text=ui;'>Unique Identifiers</a>"
|
||||
if(current_screen == "advinjector")
|
||||
buttons += "<span class='linkOff'>Adv. Injectors</span>"
|
||||
else
|
||||
buttons += "<a href='?src=[REF(src)];task=screen;text=advinjector;'>Adv. Injectors</a>"
|
||||
switch(current_screen)
|
||||
if("working")
|
||||
temp_html += status
|
||||
temp_html += "<h1>System Busy</h1>"
|
||||
temp_html += "Working ... Please wait ([DisplayTimeText(radduration*10)])"
|
||||
if("buffer")
|
||||
if("ui")
|
||||
temp_html += status
|
||||
temp_html += buttons
|
||||
temp_html += "<h1>Buffer Menu</h1>"
|
||||
temp_html += "<h1>Unique Identifiers</h1>"
|
||||
temp_html += "<a href='?src=[REF(src)];task=setstrength;num=[radstrength-1];'>--</a> <a href='?src=[REF(src)];task=setstrength;'>Output Level</a> <a href='?src=[REF(src)];task=setstrength;num=[radstrength+1];'>++</a>"
|
||||
temp_html += "<br><a href='?src=[REF(src)];task=setduration;num=[radduration-1];'>--</a> <a href='?src=[REF(src)];task=setduration;'>Pulse Duration</a> <a href='?src=[REF(src)];task=setduration;num=[radduration+1];'>++</a>"
|
||||
temp_html += "<h3>Irradiate Subject</h3>"
|
||||
temp_html += "<div class='line'><div class='statusLabel'>Unique Identifier:</div><div class='statusValue'><div class='clearBoth'>"
|
||||
var/max_line_len = 7*DNA_BLOCK_SIZE
|
||||
if(viable_occupant)
|
||||
temp_html += "<div class='dnaBlockNumber'>1</div>"
|
||||
var/char = ""
|
||||
var/ui_text = viable_occupant.dna.uni_identity
|
||||
var/len_byte = length(ui_text)
|
||||
var/char_it = 0
|
||||
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
|
||||
char_it++
|
||||
char = ui_text[byte_it]
|
||||
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulseui;num=[char_it];'>[char]</a>"
|
||||
if((char_it % max_line_len) == 0)
|
||||
temp_html += "</div><div class='clearBoth'>"
|
||||
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
|
||||
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
|
||||
else
|
||||
temp_html += "---------"
|
||||
temp_html += "</div></div><br><h1>Buffer Menu</h1>"
|
||||
|
||||
if(istype(buffer))
|
||||
for(var/i=1, i<=buffer.len, i++)
|
||||
@@ -188,7 +279,6 @@
|
||||
temp_html += "<span class='linkOff'>Save to Disk</span>"
|
||||
else
|
||||
var/ui = buffer_slot["UI"]
|
||||
var/se = buffer_slot["SE"]
|
||||
var/ue = buffer_slot["UE"]
|
||||
var/name = buffer_slot["name"]
|
||||
var/label = buffer_slot["label"]
|
||||
@@ -234,19 +324,6 @@
|
||||
temp_html += "<a href='?src=[REF(src)];task=injector;num=[i];text=mixed'>UI+UE Injector</a>"
|
||||
else
|
||||
temp_html += "<span class='linkOff'>UI+UE Injector</span>"
|
||||
if(se)
|
||||
temp_html += "<br>\tSE: [se] "
|
||||
if(viable_occupant)
|
||||
temp_html += "<a href='?src=[REF(src)];task=transferbuffer;num=[i];text=se'>Occupant</a>"
|
||||
else
|
||||
temp_html += "<span class='linkOff'>Occupant</span>"
|
||||
temp_html += "<a href='?src=[REF(src)];task=setdelayed;num=[i];delayaction=[SCANNER_ACTION_SE]'>Occupant:Delayed</a>"
|
||||
if(injectorready < world.time )
|
||||
temp_html += "<a href='?src=[REF(src)];task=injector;num=[i];text=se'>Injector</a>"
|
||||
else
|
||||
temp_html += "<span class='linkOff'>Injector</span>"
|
||||
else
|
||||
temp_html += "<br>\tSE: No Data"
|
||||
if(viable_occupant)
|
||||
temp_html += "<br><a href='?src=[REF(src)];task=setbuffer;num=[i];'>Save to Buffer</a>"
|
||||
else
|
||||
@@ -260,58 +337,225 @@
|
||||
temp_html += "<a href='?src=[REF(src)];task=savedisk;num=[i];'>Save to Disk</a>"
|
||||
else
|
||||
temp_html += "<span class='linkOff'>Save to Disk</span>"
|
||||
if("disk")
|
||||
temp_html += status
|
||||
temp_html += buttons
|
||||
if(diskette)
|
||||
temp_html += "<h3>[diskette.name]</h3><br>"
|
||||
temp_html += "<a href='?src=[REF(src)];task=ejectdisk'>Eject Disk</a><br>"
|
||||
if(LAZYLEN(diskette.mutations))
|
||||
temp_html += "<table>"
|
||||
for(var/datum/mutation/human/A in diskette.mutations)
|
||||
temp_html += "<tr><td><span class='linkOff'>[A.name]</span></td>"
|
||||
temp_html += "<td><a href='?src=[REF(src)];task=deletediskmut;num=[diskette.mutations.Find(A)];'>Delete</a></td>"
|
||||
if(LAZYLEN(stored_mutations) < max_storage)
|
||||
temp_html += "<td><a href='?src=[REF(src)];task=importdiskmut;num=[diskette.mutations.Find(A)];'>Import</a></td>"
|
||||
else
|
||||
temp_html += "<td><td><span class='linkOff'>Import</span></td>"
|
||||
temp_html += "</tr>"
|
||||
temp_html += "</table>"
|
||||
else
|
||||
temp_html += "<br>Load diskette to start ----------"
|
||||
if("info")
|
||||
if(LAZYLEN(stored_mutations))
|
||||
if(LAZYLEN(stored_mutations) >= current_storage)
|
||||
var/datum/mutation/human/HM = stored_mutations[current_storage]
|
||||
if(HM)
|
||||
temp_html += display_sequence(HM.type, current_storage)
|
||||
else
|
||||
current_screen = "mainmenu"
|
||||
if("mutations")
|
||||
temp_html += status
|
||||
temp_html += buttons
|
||||
temp_html += "<h3>Mutation Storage:<br></h3>"
|
||||
temp_html += "<table>"
|
||||
for(var/datum/mutation/human/HM in stored_mutations)
|
||||
var/i = stored_mutations.Find(HM)
|
||||
temp_html += "<tr><td><a href='?src=[REF(src)];task=inspectstorage;num=[i]'>[HM.name]</a></td>"
|
||||
temp_html += "<td><a href='?src=[REF(src)];task=exportdiskmut;path=[HM.type]'>Export</a></td>"
|
||||
temp_html += "<td><a href='?src=[REF(src)];task=deletemut;num=[i]'>Delete</a></td>"
|
||||
if(combine == HM.type)
|
||||
temp_html += "<td><span class='linkOff'>Combine</span></td></tr>"
|
||||
else
|
||||
temp_html += "<td><a href='?src=[REF(src)];task=combine;num=[i]'>Combine</a></td></tr>"
|
||||
temp_html += "</table><br>"
|
||||
temp_html += "<h3>Chromosome Storage:<br></h3>"
|
||||
temp_html += "<table>"
|
||||
for(var/i in 1 to stored_chromosomes.len)
|
||||
var/obj/item/chromosome/CM = stored_chromosomes[i]
|
||||
temp_html += "<td><a href='?src=[REF(src)];task=ejectchromosome;num=[i]'>[CM.name]</a></td><br>"
|
||||
temp_html += "</table>"
|
||||
if("advinjector")
|
||||
temp_html += status
|
||||
temp_html += buttons
|
||||
temp_html += "<div class='line'><div class='statusLabel'><b>Advanced Injectors:</b></div></div><br>"
|
||||
temp_html += "<div class='statusLine'><a href='?src=[REF(src)];task=add_advinjector;'>New Selection</a></div>"
|
||||
for(var/A in injector_selection)
|
||||
temp_html += "<div class='statusDisplay'><b>[A]</b>"
|
||||
var/list/true_selection = injector_selection[A]
|
||||
temp_html += "<br>"
|
||||
for(var/B in true_selection)
|
||||
var/datum/mutation/human/HM = B
|
||||
var/mutcolor
|
||||
switch(HM.quality)
|
||||
if(POSITIVE)
|
||||
mutcolor = "good"
|
||||
if(MINOR_NEGATIVE)
|
||||
mutcolor = "average"
|
||||
if(NEGATIVE)
|
||||
mutcolor = "bad"
|
||||
temp_html += "<div class='statusLine'><span class='[mutcolor]'>[HM.name] </span>"
|
||||
temp_html += "<a href='?src=[REF(src)];task=remove_from_advinjector;injector=[A];path=[HM.type];'>Remove</a></div>"
|
||||
if (injectorready < world.time)
|
||||
temp_html += "<div class='statusLine'> <a href='?src=[REF(src)];task=advinjector;injector=[A];'>Print Advanced Injector</a>"
|
||||
else
|
||||
temp_html += "<div class='statusLine'> <span class='linkOff'>Print Advanced Injector</span>"
|
||||
temp_html += "<a href='?src=[REF(src)];task=remove_advinjector;injector=[A];'>Remove Injector</a></div>"
|
||||
temp_html += "<br></div>"
|
||||
else
|
||||
temp_html += status
|
||||
temp_html += buttons
|
||||
temp_html += "<h1>Radiation Emitter Menu</h1>"
|
||||
|
||||
temp_html += "<a href='?src=[REF(src)];task=setstrength;num=[radstrength-1];'>--</a> <a href='?src=[REF(src)];task=setstrength;'>Output Level</a> <a href='?src=[REF(src)];task=setstrength;num=[radstrength+1];'>++</a>"
|
||||
temp_html += "<br><a href='?src=[REF(src)];task=setduration;num=[radduration-1];'>--</a> <a href='?src=[REF(src)];task=setduration;'>Pulse Duration</a> <a href='?src=[REF(src)];task=setduration;num=[radduration+1];'>++</a>"
|
||||
|
||||
temp_html += "<h3>Irradiate Subject</h3>"
|
||||
temp_html += "<div class='line'><div class='statusLabel'>Unique Identifier:</div><div class='statusValue'><div class='clearBoth'>"
|
||||
|
||||
var/max_line_len = 7*DNA_BLOCK_SIZE
|
||||
temp_html += "<div class='line'><div class='statusLabel'>Genetic Sequence:</div><br>"
|
||||
if(viable_occupant)
|
||||
temp_html += "<div class='dnaBlockNumber'>1</div>"
|
||||
var/char = ""
|
||||
var/ui_text = viable_occupant.dna.uni_identity
|
||||
var/len_byte = length(ui_text)
|
||||
var/char_it = 0
|
||||
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
|
||||
char_it++
|
||||
char = ui_text[byte_it]
|
||||
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulseui;num=[char_it];'>[char]</a>"
|
||||
if((char_it % max_line_len) == 0)
|
||||
temp_html += "</div><div class='clearBoth'>"
|
||||
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
|
||||
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
|
||||
if(viable_occupant)
|
||||
for(var/A in get_mutation_list())
|
||||
temp_html += display_inactive_sequence(A)
|
||||
temp_html += "<br>"
|
||||
else
|
||||
temp_html += "----"
|
||||
if(viable_occupant && (current_mutation in get_mutation_list(viable_occupant)))
|
||||
temp_html += display_sequence(current_mutation)
|
||||
temp_html += "</div><br>"
|
||||
else
|
||||
temp_html += "----"
|
||||
temp_html += "</div></div></div><br>"
|
||||
|
||||
temp_html += "<br><div class='line'><div class='statusLabel'>Structural Enzymes:</div><div class='statusValue'><div class='clearBoth'>"
|
||||
if(viable_occupant)
|
||||
temp_html += "<div class='dnaBlockNumber'>1</div>"
|
||||
var/char = ""
|
||||
var/se_text = viable_occupant.dna.struc_enzymes
|
||||
var/len_byte = length(se_text)
|
||||
var/char_it = 0
|
||||
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
|
||||
char_it++
|
||||
char = se_text[byte_it]
|
||||
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulsese;num=[char_it];'>[char]</a>"
|
||||
if((char_it % max_line_len) == 0)
|
||||
temp_html += "</div><div class='clearBoth'>"
|
||||
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
|
||||
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
|
||||
else
|
||||
temp_html += "----"
|
||||
temp_html += "</div></div></div>"
|
||||
temp_html += "----------"
|
||||
|
||||
popup.set_content(temp_html.Join())
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/proc/display_inactive_sequence(mutation)
|
||||
var/temp_html = ""
|
||||
var/class = "unselected"
|
||||
var/mob/living/carbon/viable_occupant = get_viable_occupant()
|
||||
if(!viable_occupant)
|
||||
return
|
||||
|
||||
var/location = viable_occupant.dna.mutation_index.Find(mutation) //We do this because we dont want people using sysexp or similair tools to just read the mutations.
|
||||
|
||||
if(!location) //Do this only when needed, dont make a list with mutations for every iteration if you dont need to
|
||||
var/list/mutations = get_mutation_list(TRUE)
|
||||
if(mutation in mutations)
|
||||
location = mutations.Find(mutation)
|
||||
if(mutation == current_mutation)
|
||||
class = "selected"
|
||||
if(location > DNA_MUTATION_BLOCKS)
|
||||
temp_html += "<a class='clean' href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_extra.gif' width = '65' alt='Extra Mutation'></a>"
|
||||
else if(mutation in stored_research.discovered_mutations)
|
||||
temp_html += "<a class='clean' href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_discovered.gif' width = '65' alt='Discovered Mutation'></a>"
|
||||
else
|
||||
temp_html += "<a class='clean' clean href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_undiscovered.gif' width = '65' alt=Undiscovered Mutation'></a>"
|
||||
return temp_html
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/proc/display_sequence(mutation, storage_slot) //Storage slot is for when viewing from the stored mutations
|
||||
var/temp_html = ""
|
||||
if(!mutation)
|
||||
temp_html += "ERR-"
|
||||
return
|
||||
var/mut_name = "Unknown gene"
|
||||
var/mut_desc = "No information available."
|
||||
var/alias
|
||||
var/discovered = FALSE
|
||||
var/active = FALSE
|
||||
var/scrambled = FALSE
|
||||
var/instability
|
||||
var/mob/living/carbon/viable_occupant = get_viable_occupant()
|
||||
var/datum/mutation/human/HM = get_valid_mutation(mutation)
|
||||
|
||||
if(viable_occupant)
|
||||
var/datum/mutation/human/M = viable_occupant.dna.get_mutation(mutation)
|
||||
if(M)
|
||||
scrambled = M.scrambled
|
||||
active = TRUE
|
||||
var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(mutation)
|
||||
alias = A.alias
|
||||
if(active && !scrambled)
|
||||
discover(mutation)
|
||||
if(stored_research && (mutation in stored_research.discovered_mutations))
|
||||
mut_name = A.name
|
||||
mut_desc = A.desc
|
||||
discovered = TRUE
|
||||
instability = A.instability
|
||||
var/extra
|
||||
if(viable_occupant && !(storage_slot || viable_occupant.dna.mutation_in_sequence(mutation)))
|
||||
extra = TRUE
|
||||
|
||||
if(discovered && !scrambled)
|
||||
var/mutcolor
|
||||
switch(A.quality)
|
||||
if(POSITIVE)
|
||||
mutcolor = "good"
|
||||
if(MINOR_NEGATIVE)
|
||||
mutcolor = "average"
|
||||
if(NEGATIVE)
|
||||
mutcolor = "bad"
|
||||
if(HM)
|
||||
instability *= GET_MUTATION_STABILIZER(HM)
|
||||
temp_html += "<div class='statusDisplay'><div class='statusLine'><span class='[mutcolor]'><b>[mut_name]</b></span><small> ([alias])</small><br>"
|
||||
temp_html += "<div class='statusLine'>Instability : [round(instability)]</span><br>"
|
||||
else
|
||||
temp_html += "<div class='statusDisplay'><div class='statusLine'><b>[alias]</b><br>"
|
||||
temp_html += "<div class='statusLine'>[mut_desc]<br></div>"
|
||||
if(active && !storage_slot)
|
||||
if(HM?.can_chromosome && (HM in viable_occupant.dna.mutations))
|
||||
var/i = viable_occupant.dna.mutations.Find(HM)
|
||||
var/chromosome_name = "<a href='?src=[REF(src)];task=applychromosome;path=[mutation];num=[i];'>----</a>"
|
||||
if(HM.chromosome_name)
|
||||
chromosome_name = HM.chromosome_name
|
||||
temp_html += "<div class='statusLine'>Chromosome status: [chromosome_name]<br></div>"
|
||||
temp_html += "<div class='statusLine'>Sequence:<br><br></div>"
|
||||
if(!scrambled)
|
||||
for(var/block in 1 to A.blocks)
|
||||
var/whole_sequence = get_valid_gene_string(mutation)
|
||||
var/sequence = copytext(whole_sequence, 1+(block-1)*(DNA_SEQUENCE_LENGTH*2),(DNA_SEQUENCE_LENGTH*2*block+1))
|
||||
temp_html += "<div class='statusLine'><table class='statusDisplay'><tr>"
|
||||
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
|
||||
var/num = 1+(i-1)*2
|
||||
var/genenum = num+(DNA_SEQUENCE_LENGTH*2*(block-1))
|
||||
temp_html += "<td><div class='statusLine'><span class='dnaBlockNumber'><a href='?src=[REF(src)];task=pulsegene;num=[genenum];path=[mutation];'>[sequence[num]]</span></a></div></td>"
|
||||
temp_html += "</tr><tr>"
|
||||
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
|
||||
temp_html += "<td><div class='statusLine'>|</div></td>"
|
||||
temp_html += "</tr><tr>"
|
||||
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
|
||||
var/num = i*2
|
||||
var/genenum = num+(DNA_SEQUENCE_LENGTH*2*(block-1))
|
||||
temp_html += "<td><div class='statusLine'><span class='dnaBlockNumber'><a href='?src=[REF(src)];task=pulsegene;num=[genenum];path=[mutation];'>[sequence[num]]</span></a></div></td>"
|
||||
temp_html += "</tr></table></div>"
|
||||
temp_html += "<br><br><br><br><br>"
|
||||
else
|
||||
temp_html = "<div class='statusLine'>Sequence unreadable due to unpredictable mutation.</div>"
|
||||
if((active || storage_slot) && (injectorready < world.time) && !scrambled)
|
||||
temp_html += "<a href='?src=[REF(src)];task=activator;path=[mutation];slot=[storage_slot];'>Print Activator</a>"
|
||||
temp_html += "<a href='?src=[REF(src)];task=mutator;path=[mutation];slot;=[storage_slot];'>Print Mutator</a>"
|
||||
else
|
||||
temp_html += "<span class='linkOff'>Print Activator</span>"
|
||||
temp_html += "<span class='linkOff'>Print Mutator</span>"
|
||||
temp_html += "<br><div class='statusLine'>"
|
||||
if(storage_slot)
|
||||
temp_html += "<a href='?src=[REF(src)];task=deletemut;num=[storage_slot];'>Delete</a>"
|
||||
if((LAZYLEN(stored_mutations) < max_storage) && diskette && !diskette.read_only)
|
||||
temp_html += "<a href='?src=[REF(src)];task=exportdiskmut;path=[mutation];'>Export</a>"
|
||||
else
|
||||
temp_html += "<span class='linkOff'>Export</span>"
|
||||
temp_html += "<a href='?src=[REF(src)];task=screen;text=mutations;'>Back</a>"
|
||||
else if(active && !scrambled)
|
||||
temp_html += "<a href='?src=[REF(src)];task=savemut;path=[mutation];'>Store</a>"
|
||||
temp_html += "<a href='?src=[REF(src)];task=expand_advinjector;path=[mutation];'>Adv. Injector</a>"
|
||||
if(extra || scrambled)
|
||||
temp_html += "<a href='?src=[REF(src)];task=nullify;'>Nullify</a>"
|
||||
else
|
||||
temp_html += "<span class='linkOff'>Nullify</span>"
|
||||
temp_html += "</div></div>"
|
||||
return temp_html
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
|
||||
if(..())
|
||||
@@ -350,13 +594,15 @@
|
||||
radstrength = WRAP(num, 1, RADIATION_STRENGTH_MAX+1)
|
||||
if("screen")
|
||||
current_screen = href_list["text"]
|
||||
if("rejuv")
|
||||
if(viable_occupant && viable_occupant.reagents)
|
||||
var/potassiodide_amount = viable_occupant.reagents.get_reagent_amount(/datum/reagent/medicine/potass_iodide)
|
||||
var/can_add = max(min(REJUVENATORS_MAX - potassiodide_amount, REJUVENATORS_INJECT), 0)
|
||||
viable_occupant.reagents.add_reagent(/datum/reagent/medicine/potass_iodide, can_add)
|
||||
if("scramble")
|
||||
if(viable_occupant && (scrambleready < world.time))
|
||||
viable_occupant.dna.remove_all_mutations(list(MUT_NORMAL, MUT_EXTRA))
|
||||
viable_occupant.dna.generate_dna_blocks()
|
||||
scrambleready = world.time + SCRAMBLE_TIMEOUT
|
||||
to_chat(usr,"<span class'notice'>DNA scrambled.</span>")
|
||||
viable_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER*50/(connected.damage_coeff ** 2)
|
||||
if("setbufferlabel")
|
||||
var/text = sanitize(input(usr, "Input a new label:", "Input an Text", null) as text|null)
|
||||
var/text = sanitize(input(usr, "Input a new label:", "Input a Text", null) as text|null)
|
||||
if(num && text)
|
||||
num = CLAMP(num, 1, NUMBER_OF_BUFFERS)
|
||||
var/list/buffer_slot = buffer[num]
|
||||
@@ -368,7 +614,6 @@
|
||||
buffer[num] = list(
|
||||
"label"="Buffer[num]:[viable_occupant.real_name]",
|
||||
"UI"=viable_occupant.dna.uni_identity,
|
||||
"SE"=viable_occupant.dna.struc_enzymes,
|
||||
"UE"=viable_occupant.dna.unique_enzymes,
|
||||
"name"=viable_occupant.real_name,
|
||||
"blood_type"=viable_occupant.dna.blood_type
|
||||
@@ -382,8 +627,6 @@
|
||||
if("transferbuffer")
|
||||
if(num && viable_occupant)
|
||||
switch(href_list["text"]) //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
|
||||
if("se")
|
||||
apply_buffer(SCANNER_ACTION_SE,num)
|
||||
if("ui")
|
||||
apply_buffer(SCANNER_ACTION_UI,num)
|
||||
if("ue")
|
||||
@@ -397,28 +640,6 @@
|
||||
if(istype(buffer_slot))
|
||||
var/obj/item/dnainjector/timed/I
|
||||
switch(href_list["text"])
|
||||
if("se")
|
||||
if(buffer_slot["SE"])
|
||||
I = new /obj/item/dnainjector/timed(loc)
|
||||
var/powers = 0
|
||||
for(var/datum/mutation/human/HM in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations)
|
||||
if(HM.check_block_string(buffer_slot["SE"]))
|
||||
I.add_mutations.Add(HM)
|
||||
if(HM in GLOB.good_mutations)
|
||||
powers += 1
|
||||
if(HM in GLOB.bad_mutations + GLOB.not_good_mutations)
|
||||
powers -= 1 //To prevent just unlocking everything to get all powers to a syringe for max tech
|
||||
else
|
||||
I.remove_mutations.Add(HM)
|
||||
var/time_coeff
|
||||
for(var/datum/mutation/human/HM in I.add_mutations)
|
||||
if(!time_coeff)
|
||||
time_coeff = HM.time_coeff
|
||||
continue
|
||||
time_coeff = min(time_coeff,HM.time_coeff)
|
||||
if(connected)
|
||||
I.duration = I.duration * time_coeff * connected.damage_coeff
|
||||
I.damage_coeff = connected.damage_coeff
|
||||
if("ui")
|
||||
if(buffer_slot["UI"])
|
||||
I = new /obj/item/dnainjector/timed(loc)
|
||||
@@ -457,7 +678,7 @@
|
||||
if("setdelayed")
|
||||
if(num)
|
||||
delayed_action = list("action"=text2num(href_list["delayaction"]),"buffer"=num)
|
||||
if("pulseui","pulsese")
|
||||
if("pulseui")
|
||||
if(num && viable_occupant && connected)
|
||||
radduration = WRAP(radduration, 1, RADIATION_DURATION_MAX+1)
|
||||
radstrength = WRAP(radstrength, 1, RADIATION_STRENGTH_MAX+1)
|
||||
@@ -469,7 +690,7 @@
|
||||
ui_interact(usr)
|
||||
|
||||
sleep(radduration*10)
|
||||
current_screen = "mainmenu"
|
||||
current_screen = "ui"
|
||||
|
||||
if(viable_occupant && connected && connected.occupant==viable_occupant)
|
||||
viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation
|
||||
@@ -478,7 +699,7 @@
|
||||
var/len = length_char(viable_occupant.dna.uni_identity)
|
||||
num = WRAP(num, 1, len+1)
|
||||
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2
|
||||
//Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
|
||||
//Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
|
||||
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
|
||||
var/subblock = num - block*DNA_BLOCK_SIZE
|
||||
last_change = "UI #[block]-[subblock]; "
|
||||
@@ -490,35 +711,229 @@
|
||||
|
||||
viable_occupant.dna.uni_identity = copytext_char(viable_occupant.dna.uni_identity, 1, num) + hex + copytext_char(viable_occupant.dna.uni_identity, num + 1)
|
||||
viable_occupant.updateappearance(mutations_overlay_update=1)
|
||||
if("pulsese")
|
||||
var/len = length(viable_occupant.dna.struc_enzymes)
|
||||
num = WRAP(num, 1, len+1)
|
||||
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len)
|
||||
|
||||
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
|
||||
var/subblock = num - block*DNA_BLOCK_SIZE
|
||||
last_change = "SE #[block]-[subblock]; "
|
||||
|
||||
var/hex = copytext_char(viable_occupant.dna.struc_enzymes, num, num+1)
|
||||
last_change += "[hex]"
|
||||
hex = scramble(hex, radstrength, radduration)
|
||||
last_change += "->[hex]"
|
||||
|
||||
viable_occupant.dna.struc_enzymes = copytext_char(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext_char(viable_occupant.dna.struc_enzymes, num + 1)
|
||||
viable_occupant.domutcheck()
|
||||
else
|
||||
current_screen = "mainmenu"
|
||||
|
||||
if(connected)
|
||||
connected.locked = locked_state
|
||||
if("inspect")
|
||||
if(viable_occupant)
|
||||
var/list/mutations = get_mutation_list(TRUE)
|
||||
if(current_mutation == mutations[num])
|
||||
current_mutation = null
|
||||
else
|
||||
current_mutation = mutations[num]
|
||||
|
||||
if("inspectstorage")
|
||||
current_storage = num
|
||||
current_screen = "info"
|
||||
if("savemut")
|
||||
if(viable_occupant)
|
||||
var/succes
|
||||
if(LAZYLEN(stored_mutations) < max_storage)
|
||||
var/mutation = text2path(href_list["path"])
|
||||
if(ispath(mutation, /datum/mutation/human)) //sanity checks
|
||||
var/datum/mutation/human/HM = viable_occupant.dna.get_mutation(mutation)
|
||||
if(HM)
|
||||
var/datum/mutation/human/A = new HM.type()
|
||||
A.copy_mutation(HM)
|
||||
succes = TRUE
|
||||
stored_mutations += A
|
||||
to_chat(usr,"<span class='notice'>Mutation succesfully stored.</span>")
|
||||
if(!succes) //we can exactly return here
|
||||
to_chat(usr,"<span class='warning'>Mutation storage is full.</span>")
|
||||
if("deletemut")
|
||||
var/datum/mutation/human/HM = stored_mutations[num]
|
||||
if(HM)
|
||||
stored_mutations.Remove(HM)
|
||||
qdel(HM)
|
||||
current_screen = "mutations"
|
||||
if("activator")
|
||||
if(injectorready < world.time)
|
||||
var/mutation = text2path(href_list["path"])
|
||||
if(ispath(mutation, /datum/mutation/human))
|
||||
var/datum/mutation/human/HM = get_valid_mutation(mutation)
|
||||
if(HM)
|
||||
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
|
||||
I.add_mutations += new HM.type (copymut = HM)
|
||||
I.name = "[HM.name] activator"
|
||||
I.research = TRUE
|
||||
if(connected)
|
||||
I.damage_coeff = connected.damage_coeff*4
|
||||
injectorready = world.time + INJECTOR_TIMEOUT * (1 - 0.1 * connected.precision_coeff) //precision_coeff being the matter bin rating
|
||||
else
|
||||
injectorready = world.time + INJECTOR_TIMEOUT
|
||||
if("mutator")
|
||||
if(injectorready < world.time)
|
||||
var/mutation = text2path(href_list["path"])
|
||||
if(ispath(mutation, /datum/mutation/human))
|
||||
var/datum/mutation/human/HM = get_valid_mutation(mutation)
|
||||
if(HM)
|
||||
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
|
||||
I.add_mutations += new HM.type (copymut = HM)
|
||||
I.doitanyway = TRUE
|
||||
I.name = "[HM.name] injector"
|
||||
if(connected)
|
||||
I.damage_coeff = connected.damage_coeff
|
||||
injectorready = world.time + INJECTOR_TIMEOUT * 5 * (1 - 0.1 * connected.precision_coeff)
|
||||
else
|
||||
injectorready = world.time + INJECTOR_TIMEOUT * 5
|
||||
|
||||
if("advinjector")
|
||||
var/selection = href_list["injector"]
|
||||
if(injectorready < world.time)
|
||||
if(injector_selection.Find(selection))
|
||||
var/list/true_selection = injector_selection[selection]
|
||||
if(LAZYLEN(injector_selection))
|
||||
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
|
||||
for(var/A in true_selection)
|
||||
var/datum/mutation/human/HM = A
|
||||
I.add_mutations += new HM.type (copymut = HM)
|
||||
I.doitanyway = TRUE
|
||||
I.name = "Advanced [selection] injector"
|
||||
if(connected)
|
||||
I.damage_coeff = connected.damage_coeff
|
||||
injectorready = world.time + INJECTOR_TIMEOUT * 8 * (1 - 0.1 * connected.precision_coeff)
|
||||
else
|
||||
injectorready = world.time + INJECTOR_TIMEOUT * 8
|
||||
if("nullify")
|
||||
if(viable_occupant)
|
||||
var/datum/mutation/human/A = viable_occupant.dna.get_mutation(current_mutation)
|
||||
if(A && (!viable_occupant.dna.mutation_in_sequence(current_mutation) || A.scrambled))
|
||||
viable_occupant.dna.remove_mutation(current_mutation)
|
||||
current_screen = "mainmenu"
|
||||
current_mutation = null
|
||||
if("pulsegene")
|
||||
if(current_screen != "info")
|
||||
var/path = text2path(href_list["path"])
|
||||
if(viable_occupant && num && (path in viable_occupant.dna.mutation_index))
|
||||
var/list/genes = list("A","T","G","C","X")
|
||||
if(jokerready < world.time)
|
||||
genes += "JOKER"
|
||||
var/sequence = GET_GENE_STRING(path, viable_occupant.dna)
|
||||
var/original = sequence[num]
|
||||
var/new_gene = input("From [original] to-", "New block", original) as null|anything in genes
|
||||
if(!new_gene)
|
||||
new_gene = original
|
||||
if(viable_occupant == get_viable_occupant()) //No cheesing
|
||||
if((new_gene == "JOKER") && (jokerready < world.time))
|
||||
var/true_genes = GET_SEQUENCE(current_mutation)
|
||||
new_gene = true_genes[num]
|
||||
jokerready = world.time + JOKER_TIMEOUT - (JOKER_UPGRADE * (connected.precision_coeff-1))
|
||||
sequence = copytext(sequence, 1, num) + new_gene + copytext(sequence, num+1, length(sequence)+1)
|
||||
viable_occupant.dna.mutation_index[path] = sequence
|
||||
viable_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER/connected.damage_coeff
|
||||
viable_occupant.domutcheck()
|
||||
if("exportdiskmut")
|
||||
if(diskette && !diskette.read_only)
|
||||
var/path = text2path(href_list["path"])
|
||||
if(ispath(path, /datum/mutation/human))
|
||||
var/datum/mutation/human/A = get_valid_mutation(path)
|
||||
if(A && diskette && (LAZYLEN(diskette.mutations) < diskette.max_mutations))
|
||||
var/datum/mutation/human/HM = new A.type()
|
||||
diskette.mutations += HM
|
||||
HM.copy_mutation(A)
|
||||
to_chat(usr, "<span class='notice'>Succesfully written [A.name] to [diskette.name].</span>")
|
||||
if("deletediskmut")
|
||||
if(diskette && !diskette.read_only)
|
||||
if(num && (LAZYLEN(diskette.mutations) >= num))
|
||||
var/datum/mutation/human/A = diskette.mutations[num]
|
||||
diskette.mutations.Remove(A)
|
||||
qdel(A)
|
||||
if("importdiskmut")
|
||||
if(diskette && (LAZYLEN(diskette.mutations) >= num))
|
||||
if(LAZYLEN(stored_mutations) < max_storage)
|
||||
var/datum/mutation/human/A = diskette.mutations[num]
|
||||
var/datum/mutation/human/HM = new A.type()
|
||||
HM.copy_mutation(A)
|
||||
stored_mutations += HM
|
||||
to_chat(usr,"<span class='notice'>Succesfully written [A.name] to storage.")
|
||||
if("combine")
|
||||
if(num && (LAZYLEN(stored_mutations) >= num))
|
||||
if(LAZYLEN(stored_mutations) < max_storage)
|
||||
var/datum/mutation/human/A = stored_mutations[num]
|
||||
var/path = A.type
|
||||
if(combine)
|
||||
var/result_path = get_mixed_mutation(combine, path)
|
||||
if(result_path)
|
||||
stored_mutations += new result_path()
|
||||
to_chat(usr, "<span class='boldnotice'>Succes! New mutation has been added to storage</span>")
|
||||
discover(result_path)
|
||||
combine = null
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Failed. No mutation could be created.</span>")
|
||||
combine = null
|
||||
else
|
||||
combine = path
|
||||
to_chat(usr,"<span class='notice'>Selected [A.name] for combining</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Not enough space to store potential mutation.</span>")
|
||||
if("ejectchromosome")
|
||||
if(LAZYLEN(stored_chromosomes) <= num)
|
||||
var/obj/item/chromosome/CM = stored_chromosomes[num]
|
||||
CM.forceMove(drop_location())
|
||||
adjust_item_drop_location(CM)
|
||||
stored_chromosomes -= CM
|
||||
if("applychromosome")
|
||||
if(viable_occupant && (LAZYLEN(viable_occupant.dna.mutations) <= num))
|
||||
var/datum/mutation/human/HM = viable_occupant.dna.mutations[num]
|
||||
var/list/chromosomes = list()
|
||||
for(var/obj/item/chromosome/CM in stored_chromosomes)
|
||||
if(CM.can_apply(HM))
|
||||
chromosomes += CM
|
||||
if(chromosomes.len)
|
||||
var/obj/item/chromosome/CM = input("Select a chromosome to apply", "Apply Chromosome") as null|anything in sortNames(chromosomes)
|
||||
if(CM)
|
||||
to_chat(usr, "<span class='notice'>You apply [CM] to [HM.name].</span>")
|
||||
stored_chromosomes -= CM
|
||||
CM.apply(HM)
|
||||
if("expand_advinjector")
|
||||
var/mutation = text2path(href_list["path"])
|
||||
var/datum/mutation/human/HM = get_valid_mutation(mutation)
|
||||
if(HM && LAZYLEN(injector_selection))
|
||||
var/which_injector = input(usr, "Select Adv. Injector", "Advanced Injectors") as null|anything in injector_selection
|
||||
if(injector_selection.Find(which_injector))
|
||||
var/list/true_selection = injector_selection[which_injector]
|
||||
var/total_instability
|
||||
for(var/B in true_selection)
|
||||
var/datum/mutation/human/mootacion = B
|
||||
total_instability += mootacion.instability
|
||||
total_instability += HM.instability
|
||||
if((total_instability > max_injector_instability) || (true_selection.len + 1) > max_injector_mutations)
|
||||
to_chat(usr, "<span class='warning'>Adding more mutations would make the advanced injector too unstable!</span>")
|
||||
else
|
||||
true_selection += HM //reminder that this works. because I keep forgetting this works
|
||||
if("remove_from_advinjector")
|
||||
var/mutation = text2path(href_list["path"])
|
||||
var/selection = href_list["injector"]
|
||||
if(injector_selection.Find(selection))
|
||||
var/list/true_selection = injector_selection[selection]
|
||||
for(var/B in true_selection)
|
||||
var/datum/mutation/human/HM = B
|
||||
if(HM.type == mutation)
|
||||
true_selection -= HM
|
||||
break
|
||||
|
||||
if("remove_advinjector")
|
||||
var/selection = href_list["injector"]
|
||||
for(selection in injector_selection)
|
||||
if(selection == selection)
|
||||
injector_selection.Remove(selection)
|
||||
|
||||
if("add_advinjector")
|
||||
if(LAZYLEN(injector_selection) < max_injector_selections)
|
||||
var/new_selection = input(usr, "Enter Adv. Injector name", "Advanced Injectors") as text|null
|
||||
if(new_selection && !(new_selection in injector_selection))
|
||||
injector_selection[new_selection] = list()
|
||||
|
||||
|
||||
ui_interact(usr,last_change)
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd)
|
||||
/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd) //hexadecimal genetics. dont confuse with scramble button
|
||||
var/length = length(input)
|
||||
var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER)
|
||||
if(ran == 0)
|
||||
ran = pick(-1,1) //hacky, statistically should almost never happen. 0-change makes people mad though
|
||||
ran = pick(-1,1) //hacky, statistically should almost never happen. 0-chance makes people mad though
|
||||
else if(ran < 0)
|
||||
ran = round(ran) //negative, so floor it
|
||||
else
|
||||
@@ -547,10 +962,6 @@
|
||||
//Each laser level reduces damage by lvl^2, so no effect on 1 lvl, 4 times less damage on 2 and 9 times less damage on 3
|
||||
//Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
|
||||
switch(action)
|
||||
if(SCANNER_ACTION_SE)
|
||||
if(buffer_slot["SE"])
|
||||
viable_occupant.dna.struc_enzymes = buffer_slot["SE"]
|
||||
viable_occupant.domutcheck()
|
||||
if(SCANNER_ACTION_UI)
|
||||
if(buffer_slot["UI"])
|
||||
viable_occupant.dna.uni_identity = buffer_slot["UI"]
|
||||
@@ -572,15 +983,54 @@
|
||||
viable_occupant.dna.blood_type = buffer_slot["blood_type"]
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/proc/on_scanner_close()
|
||||
if(delayed_action && connected)
|
||||
if(delayed_action && get_viable_occupant())
|
||||
to_chat(connected.occupant, "<span class='notice'>[src] activates!</span>")
|
||||
apply_buffer(delayed_action["action"],delayed_action["buffer"])
|
||||
delayed_action = null //or make it stick + reset button ?
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/proc/get_valid_mutation(mutation)
|
||||
var/mob/living/carbon/C = get_viable_occupant()
|
||||
if(C)
|
||||
var/datum/mutation/human/HM = C.dna.get_mutation(mutation)
|
||||
if(HM)
|
||||
return HM
|
||||
for(var/datum/mutation/human/A in stored_mutations)
|
||||
if(A.type == mutation)
|
||||
return A
|
||||
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/proc/get_mutation_list(include_storage) //Returns a list of the mutation index types and any extra mutations
|
||||
var/mob/living/carbon/viable_occupant = get_viable_occupant()
|
||||
var/list/paths = list()
|
||||
if(viable_occupant)
|
||||
for(var/A in viable_occupant.dna.mutation_index)
|
||||
paths += A
|
||||
for(var/datum/mutation/human/A in viable_occupant.dna.mutations)
|
||||
if(A.class == MUT_EXTRA)
|
||||
paths += A.type
|
||||
if(include_storage)
|
||||
for(var/datum/mutation/human/A in stored_mutations)
|
||||
paths += A.type
|
||||
return paths
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/proc/get_valid_gene_string(mutation)
|
||||
var/mob/living/carbon/C = get_viable_occupant()
|
||||
if(C && (mutation in C.dna.mutation_index))
|
||||
return GET_GENE_STRING(mutation, C.dna)
|
||||
else if(C && (LAZYLEN(C.dna.mutations)))
|
||||
for(var/datum/mutation/human/A in C.dna.mutations)
|
||||
if(A.type == mutation)
|
||||
return GET_SEQUENCE(mutation)
|
||||
for(var/datum/mutation/human/A in stored_mutations)
|
||||
if(A.type == mutation)
|
||||
return GET_SEQUENCE(mutation)
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/proc/discover(mutation)
|
||||
if(stored_research && !(mutation in stored_research.discovered_mutations))
|
||||
stored_research.discovered_mutations += mutation
|
||||
return TRUE
|
||||
/////////////////////////// DNA MACHINES
|
||||
#undef INJECTOR_TIMEOUT
|
||||
#undef REJUVENATORS_INJECT
|
||||
#undef REJUVENATORS_MAX
|
||||
#undef NUMBER_OF_BUFFERS
|
||||
|
||||
#undef RADIATION_STRENGTH_MAX
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
precision_coeff = 0
|
||||
for(var/obj/item/stock_parts/scanning_module/P in component_parts)
|
||||
scan_level += P.rating
|
||||
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
||||
for(var/obj/item/stock_parts/matter_bin/P in component_parts)
|
||||
precision_coeff = P.rating
|
||||
for(var/obj/item/stock_parts/micro_laser/P in component_parts)
|
||||
damage_coeff = P.rating
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
internal_radio = FALSE
|
||||
|
||||
//Start growing a human clone in the pod!
|
||||
/obj/machinery/clonepod/experimental/growclone(ckey, clonename, ui, se, datum/species/mrace, list/features, factions)
|
||||
/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks)
|
||||
if(panel_open)
|
||||
return FALSE
|
||||
if(mess || attempting)
|
||||
@@ -20,15 +20,15 @@
|
||||
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
|
||||
|
||||
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
|
||||
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
|
||||
|
||||
if(efficiency > 2)
|
||||
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
|
||||
H.dna.remove_mutation_group(unclean_mutations)
|
||||
if(efficiency > 5 && prob(20))
|
||||
H.randmutvg()
|
||||
H.easy_randmut(POSITIVE)
|
||||
if(efficiency < 3 && prob(50))
|
||||
var/mob/M = H.randmutb()
|
||||
var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
|
||||
if(ismob(M))
|
||||
H = M
|
||||
|
||||
@@ -42,18 +42,17 @@
|
||||
icon_state = "pod_1"
|
||||
//Get the clone body ready
|
||||
maim_clone(H)
|
||||
ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_MUTE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
|
||||
H.Unconscious(80)
|
||||
|
||||
var/list/candidates = pollCandidatesForMob("Do you want and agree to play as a [clonename]'s defective clone, respect their character and not engage in ERP without permission from the original?", null, null, null, 100, H, POLL_IGNORE_CLONE)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
C.transfer_ckey(H)
|
||||
H.key = C.key
|
||||
|
||||
if(grab_ghost_when == CLONER_FRESH_CLONE)
|
||||
H.grab_ghost()
|
||||
@@ -293,6 +292,7 @@
|
||||
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
else
|
||||
pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.struc_enzymes, clone_species, dna.features, mob_occupant.faction)
|
||||
pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
|
||||
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
|
||||
@@ -283,13 +283,13 @@
|
||||
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_charge()
|
||||
if(equip_ready) //disabled
|
||||
return
|
||||
var/area/A = get_base_area(chassis)
|
||||
var/pow_chan = get_power_channel(A)
|
||||
var/area/A = get_area(chassis)
|
||||
var/pow_chan = get_MUTATION_POWER_channel(A)
|
||||
if(pow_chan)
|
||||
return 1000 //making magic
|
||||
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_power_channel(var/area/A)
|
||||
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_MUTATION_POWER_channel(var/area/A)
|
||||
var/pow_chan
|
||||
if(A)
|
||||
for(var/c in use_channels)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
take_damage(5, BURN, 0, 0)
|
||||
|
||||
/obj/structure/spider/stickyweb
|
||||
var/genetic = FALSE
|
||||
icon_state = "stickyweb1"
|
||||
|
||||
/obj/structure/spider/stickyweb/Initialize()
|
||||
@@ -36,6 +37,8 @@
|
||||
. = ..()
|
||||
|
||||
/obj/structure/spider/stickyweb/CanPass(atom/movable/mover, turf/target)
|
||||
if (genetic)
|
||||
return
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider))
|
||||
return TRUE
|
||||
else if(isliving(mover))
|
||||
@@ -48,6 +51,27 @@
|
||||
return prob(30)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/spider/stickyweb/genetic //for the spider genes in genetics
|
||||
genetic = TRUE
|
||||
var/mob/living/allowed_mob
|
||||
|
||||
/obj/structure/spider/stickyweb/genetic/Initialize(mapload, allowedmob)
|
||||
allowed_mob = allowedmob
|
||||
. = ..()
|
||||
|
||||
/obj/structure/spider/stickyweb/genetic/CanPass(atom/movable/mover, turf/target)
|
||||
. = ..() //this is the normal spider web return aka a spider would make this TRUE
|
||||
if(mover == allowed_mob)
|
||||
return TRUE
|
||||
else if(isliving(mover)) //we change the spider to not be able to go through here
|
||||
if(mover.pulledby == allowed_mob)
|
||||
return TRUE
|
||||
if(prob(50))
|
||||
to_chat(mover, "<span class='danger'>You get stuck in \the [src] for a moment.</span>")
|
||||
return FALSE
|
||||
else if(istype(mover, /obj/item/projectile))
|
||||
return prob(30)
|
||||
|
||||
/obj/structure/spider/eggcluster
|
||||
name = "egg cluster"
|
||||
desc = "They seem to pulse slightly with an inner life."
|
||||
|
||||
@@ -850,3 +850,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
if (HAS_TRAIT(src, TRAIT_NODROP))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/proc/embedded(mob/living/carbon/human/embedded_mob)
|
||||
return
|
||||
|
||||
/obj/item/proc/unembedded()
|
||||
return
|
||||
@@ -0,0 +1,92 @@
|
||||
/obj/item/chromosome
|
||||
name = "blank chromosome"
|
||||
icon = 'icons/obj/chromosomes.dmi'
|
||||
icon_state = ""
|
||||
desc = "A tube holding chromosomic data."
|
||||
force = 0
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
var/stabilizer_coeff = 1 //lower is better, affects genetic stability
|
||||
var/synchronizer_coeff = 1 //lower is better, affects chance to backfire
|
||||
var/power_coeff = 1 //higher is better, affects "strength"
|
||||
var/energy_coeff = 1 //lower is better. affects recharge time
|
||||
|
||||
var/weight = 5
|
||||
|
||||
/obj/item/chromosome/proc/can_apply(datum/mutation/human/HM)
|
||||
if(!HM || !(HM.can_chromosome == CHROMOSOME_NONE))
|
||||
return FALSE
|
||||
if((stabilizer_coeff != 1) && (HM.stabilizer_coeff != -1)) //if the chromosome is 1, we dont change anything. If the mutation is -1, we cant change it. sorry
|
||||
return TRUE
|
||||
if((synchronizer_coeff != 1) && (HM.synchronizer_coeff != -1))
|
||||
return TRUE
|
||||
if((power_coeff != 1) && (HM.power_coeff != -1))
|
||||
return TRUE
|
||||
if((energy_coeff != 1) && (HM.energy_coeff != -1))
|
||||
return TRUE
|
||||
|
||||
/obj/item/chromosome/proc/apply(datum/mutation/human/HM)
|
||||
if(HM.stabilizer_coeff != -1)
|
||||
HM.stabilizer_coeff = stabilizer_coeff
|
||||
if(HM.synchronizer_coeff != -1)
|
||||
HM.synchronizer_coeff = synchronizer_coeff
|
||||
if(HM.power_coeff != -1)
|
||||
HM.power_coeff = power_coeff
|
||||
if(HM.energy_coeff != -1)
|
||||
HM.energy_coeff = energy_coeff
|
||||
HM.can_chromosome = 2
|
||||
HM.chromosome_name = name
|
||||
HM.modify()
|
||||
qdel(src)
|
||||
|
||||
/proc/generate_chromosome()
|
||||
var/static/list/chromosomes
|
||||
if(!chromosomes)
|
||||
chromosomes = list()
|
||||
for(var/A in subtypesof(/obj/item/chromosome))
|
||||
var/obj/item/chromosome/CM = A
|
||||
if(!initial(CM.weight))
|
||||
break
|
||||
chromosomes[A] = initial(CM.weight)
|
||||
return pickweight(chromosomes)
|
||||
|
||||
|
||||
/obj/item/chromosome/stabilizer
|
||||
name = "stabilizer chromosome"
|
||||
desc = "A chromosome that adjusts to the body to reduce genetic damage by 20%."
|
||||
icon_state = "stabilizer"
|
||||
stabilizer_coeff = 0.8
|
||||
weight = 1
|
||||
|
||||
/obj/item/chromosome/synchronizer
|
||||
name = "synchronizer chromosome"
|
||||
desc = "A chromosome that gives the mind more controle over the mutation, reducing knockback and downsides by 50%."
|
||||
icon_state = "synchronizer"
|
||||
synchronizer_coeff = 0.5
|
||||
|
||||
/obj/item/chromosome/power
|
||||
name = "power chromosome"
|
||||
desc = "A power chromosome for boosting certain mutation's power by 50%."
|
||||
icon_state = "power"
|
||||
power_coeff = 1.5
|
||||
|
||||
/obj/item/chromosome/energy
|
||||
name = "energetic chromosome"
|
||||
desc = "A chromosome that reduces cooldown on action based mutations by 50%."
|
||||
icon_state = "energy"
|
||||
energy_coeff = 0.5
|
||||
|
||||
/obj/item/chromosome/reinforcer
|
||||
name = "reinforcement chromosome"
|
||||
desc = "Renders the mutation immune to mutadone."
|
||||
icon_state = "reinforcer"
|
||||
weight = 3
|
||||
|
||||
/obj/item/chromosome/reinforcer/can_apply(datum/mutation/human/HM)
|
||||
if(!HM || !(HM.can_chromosome == CHROMOSOME_NONE))
|
||||
return FALSE
|
||||
return !HM.mutadone_proof
|
||||
|
||||
/obj/item/chromosome/reinforcer/apply(datum/mutation/human/HM)
|
||||
HM.mutadone_proof = TRUE
|
||||
..()
|
||||
@@ -74,7 +74,7 @@
|
||||
build_path = /obj/machinery/dna_scannernew
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/scanning_module = 1,
|
||||
/obj/item/stock_parts/manipulator = 1,
|
||||
/obj/item/stock_parts/matter_bin = 1,
|
||||
/obj/item/stock_parts/micro_laser = 1,
|
||||
/obj/item/stack/sheet/glass = 1,
|
||||
/obj/item/stack/cable_coil = 2)
|
||||
|
||||
@@ -150,7 +150,10 @@ SLIME SCANNER
|
||||
msg += "\n\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>"
|
||||
if(advanced)
|
||||
msg += "\n\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>"
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(advanced && H.has_dna())
|
||||
msg += "\n\t<span class='info'>Genetic Stability: [H.dna.stability]%.</span>"
|
||||
|
||||
to_chat(user, msg)
|
||||
msg = ""
|
||||
@@ -776,3 +779,104 @@ SLIME SCANNER
|
||||
var/response = SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, TRUE)
|
||||
if(!response)
|
||||
to_chat(user, "<span class='info'>No nanites detected in the subject.</span>")
|
||||
|
||||
/obj/item/sequence_scanner
|
||||
name = "genetic sequence scanner"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "gene"
|
||||
item_state = "healthanalyzer"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
desc = "A hand-held scanner for analyzing someones gene sequence on the fly. Hold near a DNA console to update the internal database."
|
||||
flags_1 = CONDUCT_1
|
||||
item_flags = NOBLUDGEON
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
throwforce = 3
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
custom_materials = list(/datum/material/iron=200)
|
||||
var/list/discovered = list() //hit a dna console to update the scanners database
|
||||
var/list/buffer
|
||||
var/ready = TRUE
|
||||
var/cooldown = 200
|
||||
|
||||
/obj/item/sequence_scanner/attack(mob/living/M, mob/living/carbon/human/user)
|
||||
add_fingerprint(user)
|
||||
if (!HAS_TRAIT(M, TRAIT_RADIMMUNE)) //no scanning if its a husk or DNA-less Species
|
||||
user.visible_message("<span class='notice'>[user] analyzes [M]'s genetic sequence.</span>", \
|
||||
"<span class='notice'>You analyze [M]'s genetic sequence.</span>")
|
||||
gene_scan(M, user)
|
||||
|
||||
else
|
||||
user.visible_message("<span class='notice'>[user] failed to analyse [M]'s genetic sequence.</span>", "<span class='warning'>[M] has no readable genetic sequence!</span>")
|
||||
|
||||
/obj/item/sequence_scanner/attack_self(mob/user)
|
||||
display_sequence(user)
|
||||
|
||||
/obj/item/sequence_scanner/attack_self_tk(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/sequence_scanner/afterattack(obj/O, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!istype(O) || !proximity)
|
||||
return
|
||||
|
||||
if(istype(O, /obj/machinery/computer/scan_consolenew))
|
||||
var/obj/machinery/computer/scan_consolenew/C = O
|
||||
if(C.stored_research)
|
||||
to_chat(user, "<span class='notice'>[name] linked to central research database.</span>")
|
||||
discovered = C.stored_research.discovered_mutations
|
||||
else
|
||||
to_chat(user,"<span class='warning'>No database to update from.</span>")
|
||||
|
||||
/obj/item/sequence_scanner/proc/gene_scan(mob/living/carbon/C, mob/living/user)
|
||||
if(!iscarbon(C) || !C.has_dna())
|
||||
return
|
||||
buffer = C.dna.mutation_index
|
||||
to_chat(user, "<span class='notice'>Subject [C.name]'s DNA sequence has been saved to buffer.</span>")
|
||||
if(LAZYLEN(buffer))
|
||||
for(var/A in buffer)
|
||||
to_chat(user, "<span class='notice'>[get_display_name(A)]</span>")
|
||||
|
||||
|
||||
/obj/item/sequence_scanner/proc/display_sequence(mob/living/user)
|
||||
if(!LAZYLEN(buffer) || !ready)
|
||||
return
|
||||
var/list/options = list()
|
||||
for(var/A in buffer)
|
||||
options += get_display_name(A)
|
||||
|
||||
var/answer = input(user, "Analyze Potential", "Sequence Analyzer") as null|anything in sortList(options)
|
||||
if(answer && ready && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
var/sequence
|
||||
for(var/A in buffer) //this physically hurts but i dont know what anything else short of an assoc list
|
||||
if(get_display_name(A) == answer)
|
||||
sequence = buffer[A]
|
||||
break
|
||||
|
||||
if(sequence)
|
||||
var/display
|
||||
for(var/i in 0 to length_char(sequence) / DNA_MUTATION_BLOCKS-1)
|
||||
if(i)
|
||||
display += "-"
|
||||
display += copytext_char(sequence, 1 + i*DNA_MUTATION_BLOCKS, DNA_MUTATION_BLOCKS*(1+i) + 1)
|
||||
|
||||
to_chat(user, "<span class='boldnotice'>[display]</span><br>")
|
||||
|
||||
ready = FALSE
|
||||
icon_state = "[icon_state]_recharging"
|
||||
addtimer(CALLBACK(src, .proc/recharge), cooldown, TIMER_UNIQUE)
|
||||
|
||||
/obj/item/sequence_scanner/proc/recharge()
|
||||
icon_state = initial(icon_state)
|
||||
ready = TRUE
|
||||
|
||||
/obj/item/sequence_scanner/proc/get_display_name(mutation)
|
||||
var/datum/mutation/human/HM = GET_INITIALIZED_MUTATION(mutation)
|
||||
if(!HM)
|
||||
return "ERROR"
|
||||
if(mutation in discovered)
|
||||
return "[HM.name] ([HM.alias])"
|
||||
else
|
||||
return HM.alias
|
||||
@@ -14,33 +14,25 @@
|
||||
var/list/add_mutations = list()
|
||||
var/list/remove_mutations = list()
|
||||
|
||||
var/list/add_mutations_static = list()
|
||||
var/list/remove_mutations_static = list()
|
||||
|
||||
var/used = 0
|
||||
|
||||
/obj/item/dnainjector/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/item/dnainjector/proc/prepare()
|
||||
for(var/mut_key in add_mutations_static)
|
||||
add_mutations.Add(GLOB.mutations_list[mut_key])
|
||||
for(var/mut_key in remove_mutations_static)
|
||||
remove_mutations.Add(GLOB.mutations_list[mut_key])
|
||||
|
||||
/obj/item/dnainjector/proc/inject(mob/living/carbon/M, mob/user)
|
||||
prepare()
|
||||
|
||||
if(M.has_dna() && !HAS_TRAIT(M, TRAIT_RADIMMUNE) && !HAS_TRAIT(M, TRAIT_NOCLONE))
|
||||
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
|
||||
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
|
||||
for(var/datum/mutation/human/HM in remove_mutations)
|
||||
HM.force_lose(M)
|
||||
for(var/datum/mutation/human/HM in add_mutations)
|
||||
if(HM.name == RACEMUT)
|
||||
for(var/HM in remove_mutations)
|
||||
M.dna.remove_mutation(HM)
|
||||
for(var/HM in add_mutations)
|
||||
if(HM == RACEMUT)
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(M)] with the [name] <span class='danger'>(MONKEY)</span>")
|
||||
log_msg += " (MONKEY)"
|
||||
HM.force_give(M)
|
||||
if(M.dna.mutation_in_sequence(HM))
|
||||
M.dna.activate_mutation(HM)
|
||||
else
|
||||
M.dna.add_mutation(HM, MUT_EXTRA)
|
||||
if(fields)
|
||||
if(fields["name"] && fields["UE"] && fields["blood_type"])
|
||||
M.real_name = fields["name"]
|
||||
@@ -90,123 +82,123 @@
|
||||
/obj/item/dnainjector/antihulk
|
||||
name = "\improper DNA injector (Anti-Hulk)"
|
||||
desc = "Cures green skin."
|
||||
remove_mutations_static = list(HULK)
|
||||
remove_mutations = list(HULK)
|
||||
|
||||
/obj/item/dnainjector/hulkmut
|
||||
name = "\improper DNA injector (Hulk)"
|
||||
desc = "This will make you big and strong, but give you a bad skin condition."
|
||||
add_mutations_static = list(HULK)
|
||||
add_mutations = list(HULK)
|
||||
|
||||
/obj/item/dnainjector/xraymut
|
||||
name = "\improper DNA injector (X-ray)"
|
||||
desc = "Finally you can see what the Captain does."
|
||||
add_mutations_static = list(XRAY)
|
||||
add_mutations = list(XRAY)
|
||||
|
||||
/obj/item/dnainjector/antixray
|
||||
name = "\improper DNA injector (Anti-X-ray)"
|
||||
desc = "It will make you see harder."
|
||||
remove_mutations_static = list(XRAY)
|
||||
remove_mutations = list(XRAY)
|
||||
|
||||
/////////////////////////////////////
|
||||
/obj/item/dnainjector/antiglasses
|
||||
name = "\improper DNA injector (Anti-Glasses)"
|
||||
desc = "Toss away those glasses!"
|
||||
remove_mutations_static = list(BADSIGHT)
|
||||
remove_mutations = list(BADSIGHT)
|
||||
|
||||
/obj/item/dnainjector/glassesmut
|
||||
name = "\improper DNA injector (Glasses)"
|
||||
desc = "Will make you need dorkish glasses."
|
||||
add_mutations_static = list(BADSIGHT)
|
||||
add_mutations = list(BADSIGHT)
|
||||
|
||||
/obj/item/dnainjector/epimut
|
||||
name = "\improper DNA injector (Epi.)"
|
||||
desc = "Shake shake shake the room!"
|
||||
add_mutations_static = list(EPILEPSY)
|
||||
add_mutations = list(EPILEPSY)
|
||||
|
||||
/obj/item/dnainjector/antiepi
|
||||
name = "\improper DNA injector (Anti-Epi.)"
|
||||
desc = "Will fix you up from shaking the room."
|
||||
remove_mutations_static = list(EPILEPSY)
|
||||
remove_mutations = list(EPILEPSY)
|
||||
////////////////////////////////////
|
||||
/obj/item/dnainjector/anticough
|
||||
name = "\improper DNA injector (Anti-Cough)"
|
||||
desc = "Will stop that awful noise."
|
||||
remove_mutations_static = list(COUGH)
|
||||
remove_mutations = list(COUGH)
|
||||
|
||||
/obj/item/dnainjector/coughmut
|
||||
name = "\improper DNA injector (Cough)"
|
||||
desc = "Will bring forth a sound of horror from your throat."
|
||||
add_mutations_static = list(COUGH)
|
||||
add_mutations = list(COUGH)
|
||||
|
||||
/obj/item/dnainjector/antidwarf
|
||||
name = "\improper DNA injector (Anti-Dwarfism)"
|
||||
desc = "Helps you grow big and strong."
|
||||
remove_mutations_static = list(DWARFISM)
|
||||
remove_mutations = list(DWARFISM)
|
||||
|
||||
/obj/item/dnainjector/dwarf
|
||||
name = "\improper DNA injector (Dwarfism)"
|
||||
desc = "It's a small world after all."
|
||||
add_mutations_static = list(DWARFISM)
|
||||
add_mutations = list(DWARFISM)
|
||||
|
||||
/obj/item/dnainjector/clumsymut
|
||||
name = "\improper DNA injector (Clumsy)"
|
||||
desc = "Makes clown minions."
|
||||
add_mutations_static = list(CLOWNMUT)
|
||||
add_mutations = list(CLOWNMUT)
|
||||
|
||||
/obj/item/dnainjector/anticlumsy
|
||||
name = "\improper DNA injector (Anti-Clumsy)"
|
||||
desc = "Apply this for Security Clown."
|
||||
remove_mutations_static = list(CLOWNMUT)
|
||||
remove_mutations = list(CLOWNMUT)
|
||||
|
||||
/obj/item/dnainjector/antitour
|
||||
name = "\improper DNA injector (Anti-Tour.)"
|
||||
desc = "Will cure Tourette's."
|
||||
remove_mutations_static = list(TOURETTES)
|
||||
remove_mutations = list(TOURETTES)
|
||||
|
||||
/obj/item/dnainjector/tourmut
|
||||
name = "\improper DNA injector (Tour.)"
|
||||
desc = "Gives you a nasty case of Tourette's."
|
||||
add_mutations_static = list(TOURETTES)
|
||||
add_mutations = list(TOURETTES)
|
||||
|
||||
/obj/item/dnainjector/stuttmut
|
||||
name = "\improper DNA injector (Stutt.)"
|
||||
desc = "Makes you s-s-stuttterrr."
|
||||
add_mutations_static = list(NERVOUS)
|
||||
add_mutations = list(NERVOUS)
|
||||
|
||||
/obj/item/dnainjector/antistutt
|
||||
name = "\improper DNA injector (Anti-Stutt.)"
|
||||
desc = "Fixes that speaking impairment."
|
||||
remove_mutations_static = list(NERVOUS)
|
||||
remove_mutations = list(NERVOUS)
|
||||
|
||||
/obj/item/dnainjector/antifire
|
||||
name = "\improper DNA injector (Anti-Fire)"
|
||||
desc = "Cures fire."
|
||||
remove_mutations_static = list(COLDRES)
|
||||
remove_mutations = list(SPACEMUT)
|
||||
|
||||
/obj/item/dnainjector/firemut
|
||||
name = "\improper DNA injector (Fire)"
|
||||
desc = "Gives you fire."
|
||||
add_mutations_static = list(COLDRES)
|
||||
add_mutations = list(SPACEMUT)
|
||||
|
||||
/obj/item/dnainjector/blindmut
|
||||
name = "\improper DNA injector (Blind)"
|
||||
desc = "Makes you not see anything."
|
||||
add_mutations_static = list(BLINDMUT)
|
||||
add_mutations = list(BLINDMUT)
|
||||
|
||||
/obj/item/dnainjector/antiblind
|
||||
name = "\improper DNA injector (Anti-Blind)"
|
||||
desc = "IT'S A MIRACLE!!!"
|
||||
remove_mutations_static = list(BLINDMUT)
|
||||
remove_mutations = list(BLINDMUT)
|
||||
|
||||
/obj/item/dnainjector/antitele
|
||||
name = "\improper DNA injector (Anti-Tele.)"
|
||||
desc = "Will make you not able to control your mind."
|
||||
remove_mutations_static = list(TK)
|
||||
remove_mutations = list(TK)
|
||||
|
||||
/obj/item/dnainjector/telemut
|
||||
name = "\improper DNA injector (Tele.)"
|
||||
desc = "Super brain man!"
|
||||
add_mutations_static = list(TK)
|
||||
add_mutations = list(TK)
|
||||
|
||||
/obj/item/dnainjector/telemut/darkbundle
|
||||
name = "\improper DNA injector"
|
||||
@@ -215,100 +207,258 @@
|
||||
/obj/item/dnainjector/deafmut
|
||||
name = "\improper DNA injector (Deaf)"
|
||||
desc = "Sorry, what did you say?"
|
||||
add_mutations_static = list(DEAFMUT)
|
||||
add_mutations = list(DEAFMUT)
|
||||
|
||||
/obj/item/dnainjector/antideaf
|
||||
name = "\improper DNA injector (Anti-Deaf)"
|
||||
desc = "Will make you hear once more."
|
||||
remove_mutations_static = list(DEAFMUT)
|
||||
remove_mutations = list(DEAFMUT)
|
||||
|
||||
/obj/item/dnainjector/h2m
|
||||
name = "\improper DNA injector (Human > Monkey)"
|
||||
desc = "Will make you a flea bag."
|
||||
add_mutations_static = list(RACEMUT)
|
||||
add_mutations = list(RACEMUT)
|
||||
|
||||
/obj/item/dnainjector/m2h
|
||||
name = "\improper DNA injector (Monkey > Human)"
|
||||
desc = "Will make you...less hairy."
|
||||
remove_mutations_static = list(RACEMUT)
|
||||
remove_mutations = list(RACEMUT)
|
||||
|
||||
/obj/item/dnainjector/antichameleon
|
||||
name = "\improper DNA injector (Anti-Chameleon)"
|
||||
remove_mutations_static = list(CHAMELEON)
|
||||
remove_mutations = list(CHAMELEON)
|
||||
|
||||
/obj/item/dnainjector/chameleonmut
|
||||
name = "\improper DNA injector (Chameleon)"
|
||||
add_mutations_static = list(CHAMELEON)
|
||||
add_mutations = list(CHAMELEON)
|
||||
|
||||
/obj/item/dnainjector/antiwacky
|
||||
name = "\improper DNA injector (Anti-Wacky)"
|
||||
remove_mutations_static = list(WACKY)
|
||||
remove_mutations = list(WACKY)
|
||||
|
||||
/obj/item/dnainjector/wackymut
|
||||
name = "\improper DNA injector (Wacky)"
|
||||
add_mutations_static = list(WACKY)
|
||||
add_mutations = list(WACKY)
|
||||
|
||||
/obj/item/dnainjector/antimute
|
||||
name = "\improper DNA injector (Anti-Mute)"
|
||||
remove_mutations_static = list(MUT_MUTE)
|
||||
remove_mutations = list(MUT_MUTE)
|
||||
|
||||
/obj/item/dnainjector/mutemut
|
||||
name = "\improper DNA injector (Mute)"
|
||||
add_mutations_static = list(MUT_MUTE)
|
||||
add_mutations = list(MUT_MUTE)
|
||||
|
||||
/obj/item/dnainjector/antismile
|
||||
name = "\improper DNA injector (Anti-Smile)"
|
||||
remove_mutations_static = list(SMILE)
|
||||
remove_mutations = list(SMILE)
|
||||
|
||||
/obj/item/dnainjector/smilemut
|
||||
name = "\improper DNA injector (Smile)"
|
||||
add_mutations_static = list(SMILE)
|
||||
add_mutations = list(SMILE)
|
||||
|
||||
/obj/item/dnainjector/unintelligiblemut
|
||||
name = "\improper DNA injector (Unintelligible)"
|
||||
add_mutations_static = list(UNINTELLIGIBLE)
|
||||
add_mutations = list(UNINTELLIGIBLE)
|
||||
|
||||
/obj/item/dnainjector/antiunintelligible
|
||||
name = "\improper DNA injector (Anti-Unintelligible)"
|
||||
remove_mutations_static = list(UNINTELLIGIBLE)
|
||||
remove_mutations = list(UNINTELLIGIBLE)
|
||||
|
||||
/obj/item/dnainjector/swedishmut
|
||||
name = "\improper DNA injector (Swedish)"
|
||||
add_mutations_static = list(SWEDISH)
|
||||
add_mutations = list(SWEDISH)
|
||||
|
||||
/obj/item/dnainjector/antiswedish
|
||||
name = "\improper DNA injector (Anti-Swedish)"
|
||||
remove_mutations_static = list(SWEDISH)
|
||||
remove_mutations = list(SWEDISH)
|
||||
|
||||
/obj/item/dnainjector/chavmut
|
||||
name = "\improper DNA injector (Chav)"
|
||||
add_mutations_static = list(CHAV)
|
||||
add_mutations = list(CHAV)
|
||||
|
||||
/obj/item/dnainjector/antichav
|
||||
name = "\improper DNA injector (Anti-Chav)"
|
||||
remove_mutations_static = list(CHAV)
|
||||
remove_mutations = list(CHAV)
|
||||
|
||||
/obj/item/dnainjector/elvismut
|
||||
name = "\improper DNA injector (Elvis)"
|
||||
add_mutations_static = list(ELVIS)
|
||||
add_mutations = list(ELVIS)
|
||||
|
||||
/obj/item/dnainjector/antielvis
|
||||
name = "\improper DNA injector (Anti-Elvis)"
|
||||
remove_mutations_static = list(ELVIS)
|
||||
remove_mutations = list(ELVIS)
|
||||
|
||||
/obj/item/dnainjector/lasereyesmut
|
||||
name = "\improper DNA injector (Laser Eyes)"
|
||||
add_mutations_static = list(LASEREYES)
|
||||
add_mutations = list(LASEREYES)
|
||||
|
||||
/obj/item/dnainjector/antilasereyes
|
||||
name = "\improper DNA injector (Anti-Laser Eyes)"
|
||||
remove_mutations_static = list(LASEREYES)
|
||||
remove_mutations = list(LASEREYES)
|
||||
|
||||
/obj/item/dnainjector/void
|
||||
name = "\improper DNA injector (Void)"
|
||||
add_mutations = list(VOID)
|
||||
|
||||
/obj/item/dnainjector/antivoid
|
||||
name = "\improper DNA injector (Anti-Void)"
|
||||
remove_mutations = list(VOID)
|
||||
|
||||
/obj/item/dnainjector/antenna
|
||||
name = "\improper DNA injector (Antenna)"
|
||||
add_mutations = list(ANTENNA)
|
||||
|
||||
/obj/item/dnainjector/antiantenna
|
||||
name = "\improper DNA injector (Anti-Antenna)"
|
||||
remove_mutations = list(ANTENNA)
|
||||
|
||||
/obj/item/dnainjector/paranoia
|
||||
name = "\improper DNA injector (Paranoia)"
|
||||
add_mutations = list(PARANOIA)
|
||||
|
||||
/obj/item/dnainjector/antiparanoia
|
||||
name = "\improper DNA injector (Anti-Paranoia)"
|
||||
remove_mutations = list(PARANOIA)
|
||||
|
||||
/obj/item/dnainjector/mindread
|
||||
name = "\improper DNA injector (Mindread)"
|
||||
add_mutations = list(MINDREAD)
|
||||
|
||||
/obj/item/dnainjector/antimindread
|
||||
name = "\improper DNA injector (Anti-Mindread)"
|
||||
remove_mutations = list(MINDREAD)
|
||||
|
||||
/obj/item/dnainjector/radioactive
|
||||
name = "\improper DNA injector (Radioactive)"
|
||||
add_mutations = list(RADIOACTIVE)
|
||||
|
||||
/obj/item/dnainjector/antiradioactive
|
||||
name = "\improper DNA injector (Anti-Radioactive)"
|
||||
remove_mutations = list(RADIOACTIVE)
|
||||
/obj/item/dnainjector/olfaction
|
||||
name = "\improper DNA injector (Olfaction)"
|
||||
add_mutations = list(OLFACTION)
|
||||
|
||||
/obj/item/dnainjector/antiolfaction
|
||||
name = "\improper DNA injector (Anti-Olfaction)"
|
||||
remove_mutations = list(OLFACTION)
|
||||
|
||||
/obj/item/dnainjector/insulated
|
||||
name = "\improper DNA injector (Insulated)"
|
||||
add_mutations = list(INSULATED)
|
||||
|
||||
/obj/item/dnainjector/antiinsulated
|
||||
name = "\improper DNA injector (Anti-Insulated)"
|
||||
remove_mutations = list(INSULATED)
|
||||
|
||||
/obj/item/dnainjector/shock
|
||||
name = "\improper DNA injector (Shock Touch)"
|
||||
add_mutations = list(SHOCKTOUCH)
|
||||
|
||||
/obj/item/dnainjector/antishock
|
||||
name = "\improper DNA injector (Anti-Shock Touch)"
|
||||
remove_mutations = list(SHOCKTOUCH)
|
||||
|
||||
/obj/item/dnainjector/spacialinstability
|
||||
name = "\improper DNA injector (Spacial Instability)"
|
||||
add_mutations = list(BADBLINK)
|
||||
|
||||
/obj/item/dnainjector/antispacialinstability
|
||||
name = "\improper DNA injector (Anti-Spacial Instability)"
|
||||
remove_mutations = list(BADBLINK)
|
||||
|
||||
/obj/item/dnainjector/acidflesh
|
||||
name = "\improper DNA injector (Acid Flesh)"
|
||||
add_mutations = list(ACIDFLESH)
|
||||
|
||||
/obj/item/dnainjector/antiacidflesh
|
||||
name = "\improper DNA injector (Acid Flesh)"
|
||||
remove_mutations = list(ACIDFLESH)
|
||||
|
||||
/obj/item/dnainjector/gigantism
|
||||
name = "\improper DNA injector (Gigantism)"
|
||||
add_mutations = list(GIGANTISM)
|
||||
|
||||
/obj/item/dnainjector/antigigantism
|
||||
name = "\improper DNA injector (Anti-Gigantism)"
|
||||
remove_mutations = list(GIGANTISM)
|
||||
|
||||
/obj/item/dnainjector/spastic
|
||||
name = "\improper DNA injector (Spastic)"
|
||||
add_mutations = list(SPASTIC)
|
||||
|
||||
/obj/item/dnainjector/antispastic
|
||||
name = "\improper DNA injector (Anti-Spastic)"
|
||||
remove_mutations = list(SPASTIC)
|
||||
|
||||
/obj/item/dnainjector/geladikinesis
|
||||
name = "\improper DNA injector (Geladikinesis)"
|
||||
add_mutations = list(GELADIKINESIS)
|
||||
|
||||
/obj/item/dnainjector/antigeladikinesis
|
||||
name = "\improper DNA injector (Anti-Geladikinesis)"
|
||||
remove_mutations = list(GELADIKINESIS)
|
||||
|
||||
/obj/item/dnainjector/cryokinesis
|
||||
name = "\improper DNA injector (Cryokinesis)"
|
||||
add_mutations = list(CRYOKINESIS)
|
||||
|
||||
/obj/item/dnainjector/anticryokinesis
|
||||
name = "\improper DNA injector (Anti-Cryokinesis)"
|
||||
remove_mutations = list(CRYOKINESIS)
|
||||
|
||||
/obj/item/dnainjector/thermal
|
||||
name = "\improper DNA injector (Thermal Vision)"
|
||||
add_mutations = list(THERMAL)
|
||||
|
||||
/obj/item/dnainjector/antithermal
|
||||
name = "\improper DNA injector (Anti-Thermal Vision)"
|
||||
remove_mutations = list(THERMAL)
|
||||
|
||||
/obj/item/dnainjector/glow
|
||||
name = "\improper DNA injector (Glowy)"
|
||||
add_mutations = list(GLOWY)
|
||||
|
||||
/obj/item/dnainjector/removeglow
|
||||
name = "\improper DNA injector (Anti-Glowy)"
|
||||
remove_mutations = list(GLOWY)
|
||||
|
||||
/obj/item/dnainjector/antiglow
|
||||
name = "\improper DNA injector (Antiglowy)"
|
||||
add_mutations = list(ANTIGLOWY)
|
||||
|
||||
/obj/item/dnainjector/removeantiglow
|
||||
name = "\improper DNA injector (Anti-Antiglowy)"
|
||||
remove_mutations = list(ANTIGLOWY)
|
||||
|
||||
/obj/item/dnainjector/firebreath
|
||||
name = "\improper DNA injector (Firebreath)"
|
||||
add_mutations = list(FIREBREATH)
|
||||
|
||||
/obj/item/dnainjector/antifirebreath
|
||||
name = "\improper DNA injector (Anti-Firebreath)"
|
||||
remove_mutations = list(FIREBREATH)
|
||||
|
||||
/obj/item/dnainjector/tonguespike
|
||||
name = "\improper DNA injector (Tongue Spike)"
|
||||
add_mutations = list(TONGUESPIKE)
|
||||
|
||||
/obj/item/dnainjector/antitonguespike
|
||||
name = "\improper DNA injector (Anti-Tongue Spike)"
|
||||
remove_mutations = list(TONGUESPIKE)
|
||||
|
||||
/obj/item/dnainjector/spiderweb
|
||||
name = "\improper DNA injector (Spider Web)"
|
||||
add_mutations = list(SPIDER_WEB)
|
||||
|
||||
/obj/item/dnainjector/antispiderweb
|
||||
name = "\improper DNA injector (Anti-Spider Web)"
|
||||
remove_mutations = list(SPIDER_WEB)
|
||||
|
||||
/obj/item/dnainjector/timed
|
||||
var/duration = 600
|
||||
|
||||
/obj/item/dnainjector/timed/inject(mob/living/carbon/M, mob/user)
|
||||
prepare()
|
||||
if(M.stat == DEAD) //prevents dead people from having their DNA changed
|
||||
to_chat(user, "<span class='notice'>You can't modify [M]'s DNA while [M.p_theyre()] dead.</span>")
|
||||
return FALSE
|
||||
@@ -317,23 +467,22 @@
|
||||
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
|
||||
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
|
||||
var/endtime = world.time+duration
|
||||
for(var/datum/mutation/human/HM in remove_mutations)
|
||||
if(HM.name == RACEMUT)
|
||||
for(var/mutation in remove_mutations)
|
||||
if(mutation == RACEMUT)
|
||||
if(ishuman(M))
|
||||
continue
|
||||
M = HM.force_lose(M)
|
||||
M = M.dna.remove_mutation(mutation)
|
||||
else
|
||||
HM.force_lose(M)
|
||||
for(var/datum/mutation/human/HM in add_mutations)
|
||||
if((HM in M.dna.mutations) && !(M.dna.temporary_mutations[HM.name]))
|
||||
M.dna.remove_mutation(mutation)
|
||||
for(var/mutation in add_mutations)
|
||||
if(M.dna.get_mutation(mutation))
|
||||
continue //Skip permanent mutations we already have.
|
||||
if(HM.name == RACEMUT && ishuman(M))
|
||||
if(mutation == RACEMUT && ishuman(M))
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(M)] with the [name] <span class='danger'>(MONKEY)</span>")
|
||||
log_msg += " (MONKEY)"
|
||||
M = HM.force_give(M)
|
||||
M = M.dna.add_mutation(mutation, MUT_OTHER, endtime)
|
||||
else
|
||||
HM.force_give(M)
|
||||
M.dna.temporary_mutations[HM.name] = endtime
|
||||
M.dna.add_mutation(mutation, MUT_OTHER, endtime)
|
||||
if(fields)
|
||||
if(fields["name"] && fields["UE"] && fields["blood_type"])
|
||||
if(!M.dna.previous["name"])
|
||||
@@ -361,9 +510,41 @@
|
||||
/obj/item/dnainjector/timed/hulk
|
||||
name = "\improper DNA injector (Hulk)"
|
||||
desc = "This will make you big and strong, but give you a bad skin condition."
|
||||
add_mutations_static = list(HULK)
|
||||
add_mutations = list(HULK)
|
||||
|
||||
/obj/item/dnainjector/timed/h2m
|
||||
name = "\improper DNA injector (Human > Monkey)"
|
||||
desc = "Will make you a flea bag."
|
||||
add_mutations_static = list(RACEMUT)
|
||||
add_mutations = list(RACEMUT)
|
||||
|
||||
/obj/item/dnainjector/activator
|
||||
name = "\improper DNA activator"
|
||||
desc = "Activates the current mutation on injection, if the subject has it."
|
||||
var/doitanyway = FALSE
|
||||
var/research = FALSE //Set to true to get expended and filled injectors for chromosomes
|
||||
var/filled = FALSE
|
||||
|
||||
/obj/item/dnainjector/activator/inject(mob/living/carbon/M, mob/user)
|
||||
if(M.has_dna() && !HAS_TRAIT(M, TRAIT_RADIMMUNE) && !HAS_TRAIT(M,TRAIT_NOCLONE))
|
||||
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
|
||||
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
|
||||
for(var/mutation in add_mutations)
|
||||
var/datum/mutation/human/HM = mutation
|
||||
if(istype(HM, /datum/mutation/human))
|
||||
mutation = HM.type
|
||||
if(!M.dna.activate_mutation(HM))
|
||||
if(!doitanyway)
|
||||
log_msg += "(FAILED)"
|
||||
else
|
||||
M.dna.add_mutation(HM, MUT_EXTRA)
|
||||
name = "expended [name]"
|
||||
else if(research && M.client)
|
||||
filled = TRUE
|
||||
name = "filled [name]"
|
||||
else
|
||||
name = "expended [name]"
|
||||
log_msg += "([mutation])"
|
||||
log_attack("[log_msg] [loc_name(user)]")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
user.dropItemToGround(src, TRUE) //user.drop_item() // "drop item" doesn't seem to exist anymore. New proc is user.dropItemToGround() but it doesn't seem like it's needed now?
|
||||
var/obj/item/bodypart/B = C.get_bodypart("chest") // This was all taken from hitby() in human_defense.dm
|
||||
B.embedded_objects |= src
|
||||
embedded()
|
||||
add_mob_blood(target)//Place blood on the stake
|
||||
loc = C // Put INSIDE the character
|
||||
B.receive_damage(w_class * embedding.embedded_impact_pain_multiplier)
|
||||
|
||||
@@ -13,17 +13,14 @@
|
||||
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
|
||||
if(!istype(H)) // req_human could be done in can_sting stuff.
|
||||
return
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[CHAMELEON]
|
||||
if(HM in H.dna.mutations)
|
||||
HM.force_lose(H)
|
||||
if(H.dna.get_mutation(CHAMELEON))
|
||||
H.dna.remove_mutation(CHAMELEON)
|
||||
else
|
||||
HM.force_give(H)
|
||||
H.dna.add_mutation(CHAMELEON)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user)
|
||||
action.Remove(user)
|
||||
if(user.has_dna())
|
||||
var/mob/living/carbon/C = user
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[CHAMELEON]
|
||||
if(HM in C.dna.mutations)
|
||||
HM.force_lose(C)
|
||||
C.dna.remove_mutation(CHAMELEON)
|
||||
@@ -24,5 +24,5 @@
|
||||
return
|
||||
H.dna.add_mutation(HULK)
|
||||
H.dna.add_mutation(XRAY)
|
||||
H.dna.add_mutation(COLDRES)
|
||||
H.dna.add_mutation(SPACEMUT)
|
||||
H.dna.add_mutation(TK)
|
||||
@@ -94,7 +94,7 @@
|
||||
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
|
||||
user.dna.add_mutation(LASEREYES)
|
||||
user.dna.add_mutation(COLDRES)
|
||||
user.dna.add_mutation(SPACEMUT)
|
||||
user.dna.add_mutation(XRAY)
|
||||
user.set_species(/datum/species/shadow)
|
||||
if("Wealth")
|
||||
|
||||
@@ -703,3 +703,10 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
|
||||
Insert(initial(D.id), I)
|
||||
return ..()
|
||||
|
||||
/datum/asset/simple/genetics
|
||||
assets = list(
|
||||
"dna_discovered.gif" = 'html/dna_discovered.gif',
|
||||
"dna_undiscovered.gif" = 'html/dna_undiscovered.gif',
|
||||
"dna_extra.gif" = 'html/dna_extra.gif'
|
||||
)
|
||||
@@ -59,7 +59,7 @@
|
||||
var/datum/disease/dnaspread/DS = D
|
||||
DS.strain_data["name"] = H.real_name
|
||||
DS.strain_data["UI"] = H.dna.uni_identity
|
||||
DS.strain_data["SE"] = H.dna.struc_enzymes
|
||||
DS.strain_data["SE"] = H.dna.mutation_index
|
||||
else
|
||||
D = new virus_type()
|
||||
else
|
||||
|
||||
@@ -32,4 +32,5 @@
|
||||
backpack = /obj/item/storage/backpack/genetics
|
||||
satchel = /obj/item/storage/backpack/satchel/gen
|
||||
duffelbag = /obj/item/storage/backpack/duffelbag/med
|
||||
l_pocket = /obj/item/sequence_scanner
|
||||
|
||||
|
||||
@@ -463,30 +463,45 @@
|
||||
if(cooldown < world.time)
|
||||
SSblackbox.record_feedback("amount", "immortality_talisman_uses", 1)
|
||||
cooldown = world.time + 600
|
||||
user.visible_message("<span class='danger'>[user] vanishes from reality, leaving a hole in [user.p_their()] place!</span>")
|
||||
var/obj/effect/immortality_talisman/Z = new(get_turf(src.loc))
|
||||
Z.name = "hole in reality"
|
||||
Z.desc = "It's shaped an awful lot like [user.name]."
|
||||
Z.setDir(user.dir)
|
||||
user.forceMove(Z)
|
||||
user.notransform = 1
|
||||
user.status_flags |= GODMODE
|
||||
addtimer(CALLBACK(src, .proc/return_to_reality, user, Z), 100)
|
||||
new /obj/effect/immortality_talisman(get_turf(user), user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is not ready yet!</span>")
|
||||
|
||||
/obj/item/immortality_talisman/proc/return_to_reality(mob/user, obj/effect/immortality_talisman/Z)
|
||||
user.status_flags &= ~GODMODE
|
||||
user.notransform = 0
|
||||
user.forceMove(get_turf(Z))
|
||||
user.visible_message("<span class='danger'>[user] pops back into reality!</span>")
|
||||
Z.can_destroy = TRUE
|
||||
qdel(Z)
|
||||
|
||||
/obj/effect/immortality_talisman
|
||||
name = "hole in reality"
|
||||
desc = "It's shaped an awful lot like a person."
|
||||
icon_state = "blank"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
var/can_destroy = FALSE
|
||||
var/vanish_description = "vanishes from reality"
|
||||
var/can_destroy = TRUE
|
||||
|
||||
/obj/effect/immortality_talisman/Initialize(mapload, mob/new_user)
|
||||
. = ..()
|
||||
if(new_user)
|
||||
vanish(new_user)
|
||||
|
||||
/obj/effect/immortality_talisman/proc/vanish(mob/user)
|
||||
user.visible_message("<span class='danger'>[user] [vanish_description], leaving a hole in [user.p_their()] place!</span>")
|
||||
|
||||
desc = "It's shaped an awful lot like [user.name]."
|
||||
setDir(user.dir)
|
||||
|
||||
user.forceMove(src)
|
||||
user.notransform = TRUE
|
||||
user.status_flags |= GODMODE
|
||||
|
||||
can_destroy = FALSE
|
||||
|
||||
addtimer(CALLBACK(src, .proc/unvanish, user), 10 SECONDS)
|
||||
|
||||
/obj/effect/immortality_talisman/proc/unvanish(mob/user)
|
||||
user.status_flags &= ~GODMODE
|
||||
user.notransform = FALSE
|
||||
user.forceMove(get_turf(src))
|
||||
|
||||
user.visible_message("<span class='danger'>[user] pops back into reality!</span>")
|
||||
can_destroy = TRUE
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/immortality_talisman/attackby()
|
||||
return
|
||||
@@ -503,6 +518,9 @@
|
||||
else
|
||||
. = ..()
|
||||
|
||||
/obj/effect/immortality_talisman/void
|
||||
vanish_description = "is dragged into the void"
|
||||
|
||||
|
||||
//Shared Bag
|
||||
|
||||
|
||||
@@ -632,6 +632,13 @@
|
||||
if(M.name == XRAY)
|
||||
sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
||||
see_in_dark = max(see_in_dark, 8)
|
||||
if(HAS_TRAIT(src, TRAIT_THERMAL_VISION))
|
||||
sight |= (SEE_MOBS)
|
||||
lighting_alpha = min(lighting_alpha, LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_XRAY_VISION))
|
||||
sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
||||
see_in_dark = max(see_in_dark, 8)
|
||||
|
||||
if(see_override)
|
||||
see_invisible = see_override
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
L.embedded_objects |= I
|
||||
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
|
||||
I.forceMove(src)
|
||||
I.embedded()
|
||||
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier)
|
||||
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
|
||||
@@ -316,6 +316,7 @@
|
||||
BP.receive_damage(I.w_class*I.embedding.embedded_fall_pain_multiplier)
|
||||
BP.embedded_objects -= I
|
||||
I.forceMove(drop_location())
|
||||
I.unembedded()
|
||||
visible_message("<span class='danger'>[I] falls out of [name]'s [BP.name]!</span>","<span class='userdanger'>[I] falls out of your [BP.name]!</span>")
|
||||
if(!has_embedded_objects())
|
||||
clear_alert("embeddedobject")
|
||||
|
||||
@@ -69,6 +69,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/siemens_coeff = 1 //base electrocution coefficient
|
||||
var/damage_overlay_type = "human" //what kind of damage overlays (if any) appear on our species when wounded?
|
||||
var/fixed_mut_color = "" //to use MUTCOLOR with a fixed color that's independent of dna.feature["mcolor"]
|
||||
var/inert_mutation = DWARFISM
|
||||
var/list/special_step_sounds //Sounds to override barefeet walkng
|
||||
var/grab_sound //Special sound for grabbing
|
||||
var/datum/outfit/outfit_important_for_life // A path to an outfit that is important for species life e.g. plasmaman outfit
|
||||
@@ -356,6 +357,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
else
|
||||
C.type_of_meat = initial(meat)
|
||||
|
||||
//If their inert mutation is not the same, swap it out
|
||||
if((inert_mutation != new_species.inert_mutation) && LAZYLEN(C.dna.mutation_index) && (inert_mutation in C.dna.mutation_index))
|
||||
C.dna.remove_mutation(inert_mutation)
|
||||
//keep it at the right spot, so we can't have people taking shortcuts
|
||||
var/location = C.dna.mutation_index.Find(inert_mutation)
|
||||
C.dna.mutation_index[location] = new_species.inert_mutation
|
||||
C.dna.mutation_index[new_species.inert_mutation] = create_sequence(new_species.inert_mutation)
|
||||
|
||||
SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src)
|
||||
|
||||
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
|
||||
@@ -1394,7 +1403,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(radiation > RAD_MOB_MUTATE)
|
||||
if(prob(1))
|
||||
to_chat(H, "<span class='danger'>You mutate!</span>")
|
||||
H.randmutb()
|
||||
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
|
||||
H.emote("gasp")
|
||||
H.domutcheck()
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
exotic_bloodtype = "L"
|
||||
disliked_food = GRAIN | DAIRY
|
||||
liked_food = GROSS | MEAT
|
||||
inert_mutation = FIREBREATH
|
||||
|
||||
/datum/species/lizard/after_equip_job(datum/job/J, mob/living/carbon/human/H)
|
||||
H.grant_language(/datum/language/draconic)
|
||||
|
||||
@@ -61,9 +61,9 @@
|
||||
H.DefaultCombatKnockdown(100)
|
||||
H.visible_message("<span class='warning'>[H] writhes in pain as [H.p_their()] vacuoles boil.</span>", "<span class='userdanger'>You writhe in pain as your vacuoles boil!</span>", "<span class='italics'>You hear the crunching of leaves.</span>")
|
||||
if(prob(80))
|
||||
H.randmutb()
|
||||
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
|
||||
else
|
||||
H.randmutg()
|
||||
H.easy_randmut(POSITIVE)
|
||||
H.domutcheck()
|
||||
else
|
||||
H.adjustFireLoss(rand(5,15))
|
||||
|
||||
@@ -427,7 +427,6 @@
|
||||
|
||||
/mob/living/carbon/handle_mutations_and_radiation()
|
||||
if(dna && dna.temporary_mutations.len)
|
||||
var/datum/mutation/human/HM
|
||||
for(var/mut in dna.temporary_mutations)
|
||||
if(dna.temporary_mutations[mut] < world.time)
|
||||
if(mut == UI_CHANGED)
|
||||
@@ -450,9 +449,9 @@
|
||||
dna.previous.Remove("blood_type")
|
||||
dna.temporary_mutations.Remove(mut)
|
||||
continue
|
||||
HM = GLOB.mutations_list[mut]
|
||||
HM.force_lose(src)
|
||||
dna.temporary_mutations.Remove(mut)
|
||||
for(var/datum/mutation/human/HM in dna.mutations)
|
||||
if(HM && HM.timed)
|
||||
dna.remove_mutation(HM.type)
|
||||
|
||||
radiation -= min(radiation, RAD_LOSS_PER_TICK)
|
||||
if(radiation > RAD_MOB_SAFE)
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
if(radiation > RAD_MOB_MUTATE)
|
||||
if(prob(1))
|
||||
to_chat(src, "<span class='danger'>You mutate!</span>")
|
||||
randmutb()
|
||||
easy_randmut(NEGATIVE+MINOR_NEGATIVE)
|
||||
emote("gasp")
|
||||
domutcheck()
|
||||
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
|
||||
|
||||
@@ -49,9 +49,8 @@
|
||||
O.updateappearance(icon_update=0)
|
||||
|
||||
if(tr_flags & TR_KEEPSE)
|
||||
O.dna.struc_enzymes = dna.struc_enzymes
|
||||
var/datum/mutation/human/race/R = GLOB.mutations_list[RACEMUT]
|
||||
O.dna.struc_enzymes = R.set_se(O.dna.struc_enzymes, on=1)//we don't want to keep the race block inactive
|
||||
O.dna.mutation_index = dna.mutation_index
|
||||
O.dna.set_se(1, GET_INITIALIZED_MUTATION(RACEMUT))
|
||||
|
||||
if(suiciding)
|
||||
O.suiciding = suiciding
|
||||
@@ -208,9 +207,8 @@
|
||||
O.name = O.real_name
|
||||
|
||||
if(tr_flags & TR_KEEPSE)
|
||||
O.dna.struc_enzymes = dna.struc_enzymes
|
||||
var/datum/mutation/human/race/R = GLOB.mutations_list[RACEMUT]
|
||||
O.dna.struc_enzymes = R.set_se(O.dna.struc_enzymes, on=0)//we don't want to keep the race block active
|
||||
O.dna.mutation_index = dna.mutation_index
|
||||
O.dna.set_se(0, GET_INITIALIZED_MUTATION(RACEMUT))
|
||||
O.domutcheck()
|
||||
|
||||
if(suiciding)
|
||||
|
||||
@@ -16,3 +16,8 @@
|
||||
/obj/item/projectile/temp/hot
|
||||
name = "heat beam"
|
||||
temperature = 400
|
||||
|
||||
/obj/item/projectile/temp/cryo
|
||||
name = "cryo beam"
|
||||
range = 3
|
||||
temperature = -240 // Single slow shot reduces temp greatly
|
||||
@@ -957,7 +957,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
|
||||
/datum/reagent/medicine/mutadone/on_mob_life(mob/living/carbon/M)
|
||||
M.jitteriness = 0
|
||||
if(M.has_dna())
|
||||
M.dna.remove_all_mutations()
|
||||
M.dna.remove_all_mutations(mutadone = TRUE)
|
||||
if(!QDELETED(M)) //We were a monkey, now a human
|
||||
..()
|
||||
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
if((method==VAPOR && prob(min(33, reac_volume))) || method==INGEST || method==PATCH || method==INJECT)
|
||||
M.randmuti()
|
||||
if(prob(98))
|
||||
M.randmutb()
|
||||
M.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
|
||||
else
|
||||
M.randmutg()
|
||||
M.easy_randmut(POSITIVE)
|
||||
M.updateappearance()
|
||||
M.domutcheck()
|
||||
..()
|
||||
|
||||
@@ -162,6 +162,16 @@
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/datum/design/genescanner
|
||||
name = "Genetic Sequence Analyzer"
|
||||
desc = "A handy hand-held analyzers for quickly determining mutations and collecting the full sequence."
|
||||
id = "genescanner"
|
||||
build_path = /obj/item/sequence_scanner
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 1000, /datum/material/glass = 500)
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/datum/design/healthanalyzer_advanced
|
||||
name = "Advanced Health Analyzer"
|
||||
desc = "A hand-held body scanner able to distinguish vital signs of the subject with high accuracy."
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
var/largest_bomb_value = 0
|
||||
var/organization = "Third-Party" //Organization name, used for display.
|
||||
var/list/last_bitcoins = list() //Current per-second production, used for display only.
|
||||
var/list/discovered_mutations = list() //Mutations discovered by genetics, this way they are shared and cant be destroyed by destroying a single console
|
||||
var/list/tiers = list() //Assoc list, id = number, 1 is available, 2 is all reqs are 1, so on
|
||||
|
||||
/datum/techweb/New()
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
display_name = "Biological Technology"
|
||||
description = "What makes us tick." //the MC, silly!
|
||||
prereq_ids = list("base")
|
||||
design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv", "medspray")
|
||||
design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv", "medspray","genescanner")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
|
||||
/datum/techweb_node/adv_biotech
|
||||
|
||||
@@ -80,11 +80,11 @@
|
||||
school = "conjuration"
|
||||
charge_max = 150
|
||||
cooldown_min = 10
|
||||
var/delete_old = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/conjure_item/cast(list/targets, mob/user = usr)
|
||||
if (item && !QDELETED(item))
|
||||
qdel(item)
|
||||
item = null
|
||||
if (delete_old && item && !QDELETED(item))
|
||||
QDEL_NULL(item)
|
||||
else
|
||||
for(var/mob/living/carbon/C in targets)
|
||||
if(C.dropItemToGround(C.get_active_held_item()))
|
||||
|
||||
@@ -128,6 +128,49 @@
|
||||
invocation_type ="none"
|
||||
..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/mimerope
|
||||
name = "Invisible Rope"
|
||||
desc = "Form an invisible rope to tie people or trip people with."
|
||||
school = "mime"
|
||||
panel = "Mime"
|
||||
invocation_type = "emote"
|
||||
invocation_emote_self = "<span class='notice'>You start fabricate an invisible rope.</span>"
|
||||
charge_max = 700
|
||||
sound = null
|
||||
clothes_req = 0
|
||||
range = -1
|
||||
include_user = 1
|
||||
action_icon_state = "mime"
|
||||
action_background_icon_state = "bg_mime"
|
||||
hand_path = /obj/item/melee/touch_attack/mimerope
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/mimerope/Click()
|
||||
if(usr && usr.mind)
|
||||
if(!usr.mind.miming)
|
||||
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
|
||||
return
|
||||
if (usr.get_active_held_item())
|
||||
to_chat(usr, "<span class='notice'>Your hands must be free to create the invisible rope.</span>")
|
||||
return
|
||||
invocation = "<B>[usr.real_name]</B> is twirling an invisible rope in [usr.p_their()] hands."
|
||||
else
|
||||
invocation_type ="none"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/mimerope/cast(list/targets,mob/user = usr)
|
||||
|
||||
usr.put_in_hands()
|
||||
|
||||
/obj/item/melee/touch_attack/mimerope
|
||||
item_state = ""
|
||||
icon_state = ""
|
||||
name = "mime rope"
|
||||
desc = "An invisible rope."
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/mime
|
||||
name = "mime restraints"
|
||||
desc = "An invisible rope."
|
||||
item_state = ""
|
||||
icon_state = ""
|
||||
|
||||
/obj/item/book/granter/spell/mimery_blockade
|
||||
spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/obj/effect/proc_holder/spell/targeted/touch
|
||||
var/hand_path = /obj/item/melee/touch_attack
|
||||
var/obj/item/melee/touch_attack/attached_hand = null
|
||||
var/drawmessage = "You channel the power of the spell to your hand."
|
||||
var/dropmessage = "You draw the power out of your hand."
|
||||
invocation_type = "none" //you scream on connecting, not summoning
|
||||
include_user = 1
|
||||
range = -1
|
||||
@@ -21,7 +23,7 @@
|
||||
/obj/effect/proc_holder/spell/targeted/touch/cast(list/targets,mob/user = usr)
|
||||
if(!QDELETED(attached_hand))
|
||||
remove_hand(TRUE)
|
||||
to_chat(user, "<span class='notice'>You draw the power out of your hand.</span>")
|
||||
to_chat(user, "<span class='notice'>[dropmessage]</span>")
|
||||
return
|
||||
|
||||
for(var/mob/living/carbon/C in targets)
|
||||
@@ -43,7 +45,7 @@
|
||||
remove_hand(TRUE)
|
||||
to_chat(user, "<span class='warning'>Your hands are full!</span>")
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You channel the power of the spell to your hand.</span>")
|
||||
to_chat(user, "<span class='notice'>[drawmessage]</span>")
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
for(var/obj/item/I in embedded_objects)
|
||||
embedded_objects -= I
|
||||
I.forceMove(src)
|
||||
I.unembedded()
|
||||
if(!C.has_embedded_objects())
|
||||
C.clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
@@ -112,7 +113,7 @@
|
||||
for(var/X in C.dna.mutations) //some mutations require having specific limbs to be kept.
|
||||
var/datum/mutation/human/MT = X
|
||||
if(MT.limb_req && MT.limb_req == body_zone)
|
||||
MT.force_lose(C)
|
||||
C.dna.force_lose(MT)
|
||||
|
||||
for(var/X in C.internal_organs) //internal organs inside the dismembered limb are dropped.
|
||||
var/obj/item/organ/O = X
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
for(var/obj/item/I in L.embedded_objects)
|
||||
L.embedded_objects -= I
|
||||
I.forceMove(T)
|
||||
I.unembedded()
|
||||
|
||||
clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
objects++
|
||||
I.forceMove(get_turf(H))
|
||||
L.embedded_objects -= I
|
||||
I.unembedded()
|
||||
if(!H.has_embedded_objects())
|
||||
H.clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
|
||||
Reference in New Issue
Block a user