diff --git a/baystation12.dme b/baystation12.dme index 5045d693c27..9b1d66b8462 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -204,6 +204,10 @@ #include "code\game\dna\dna2.dm" #include "code\game\dna\dna2_helpers.dm" #include "code\game\dna\dna_modifier.dm" +#include "code\game\dna\genes\disabilities.dm" +#include "code\game\dna\genes\gene.dm" +#include "code\game\dna\genes\monkey.dm" +#include "code\game\dna\genes\powers.dm" #include "code\game\gamemodes\events.dm" #include "code\game\gamemodes\factions.dm" #include "code\game\gamemodes\game_mode.dm" diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 03ed8dd23de..3353f83146e 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -171,12 +171,51 @@ /proc/probinj(var/pr, var/inj) return prob(pr+inj*pr) +// Mutations we simply transfer over without checking. +var/global/ignore_mutations=list(PLANT,SKELETON,FAT,HUSK) + +// Mutations we simply transfer over without checking. +var/global/dna_genes=list(PLANT,SKELETON,FAT,HUSK) + // (Re-)Apply mutations. // TODO: Turn into a /mob proc, change inj to a bitflag for various forms of differing behavior. // M: Mob to mess with // connected: Machine we're in, type unchecked so I doubt it's used beyond monkeying -// inj: 1 for if we're checking this from an injector, screws with manifestation probability calc. -/proc/domutcheck(mob/living/M as mob, connected, inj) +// flags: See below, bitfield. +#define MUTCHK_FORCED 1 +/proc/domutcheck(var/mob/living/M, var/connected, var/flags) + if (!M) return + + M.dna.check_integrity() + + M.disabilities = 0 + M.sdisabilities = 0 + var/old_mutations = M.mutations + M.mutations = list() + M.pass_flags = 0 +// M.see_in_dark = 2 +// M.see_invisible = 0 + + var/forced = (flags & MUTCHK_FORCED) == MUTCHK_FORCED + + for(var/legacy_mut in ignore_mutations) + if(legacy_mut in old_mutations) + M.mutations.Add(legacy_mut) + + for(var/datum/dna/gene/G in dna_genes) + if(G.block) + if(M.dna.GetSEState(G.block)) + if(forced || G.can_activate(M,old_mutations,flags)) + if(!(G.type in M.active_genes)) + G.activate(M, connected) + else + if(G.type in M.active_genes) + G.deactivate(M, connected) + + M.update_icon=1 + +/* Old, inflexibile +/proc/domutcheck(var/mob/living/M, var/connected, var/flags) if (!M) return M.dna.check_integrity() @@ -198,47 +237,62 @@ if(HUSK in old_mutations) M.mutations.Add(HUSK) + var/inj = (flags & MUTCHK_FROM_INJECTOR) == MUTCHK_FROM_INJECTOR + var/forced = (flags & MUTCHK_FORCED) == MUTCHK_FORCED + if(M.dna.GetSEState(NOBREATHBLOCK)) - if(probinj(45,inj) || (mNobreath in old_mutations)) + if(forced || probinj(45,inj) || (mNobreath in old_mutations)) M << "\blue You feel no need to breathe." M.mutations.Add(mNobreath) if(M.dna.GetSEState(REMOTEVIEWBLOCK)) - if(probinj(45,inj) || (mRemote in old_mutations)) + if(forced || probinj(45,inj) || (mRemote in old_mutations)) M << "\blue Your mind expands" M.mutations.Add(mRemote) M.verbs += /mob/living/carbon/human/proc/remoteobserve if(M.dna.GetSEState(REGENERATEBLOCK)) - if(probinj(45,inj) || (mRegen in old_mutations)) + if(forced || probinj(45,inj) || (mRegen in old_mutations)) M << "\blue You feel better" M.mutations.Add(mRegen) if(M.dna.GetSEState(INCREASERUNBLOCK)) - if(probinj(45,inj) || (mRun in old_mutations)) + if(forced || probinj(45,inj) || (mRun in old_mutations)) M << "\blue Your leg muscles pulsate." M.mutations.Add(mRun) if(M.dna.GetSEState(REMOTETALKBLOCK)) - if(probinj(45,inj) || (mRemotetalk in old_mutations)) + if(forced || probinj(45,inj) || (mRemotetalk in old_mutations)) M << "\blue You expand your mind outwards" M.mutations.Add(mRemotetalk) M.verbs += /mob/living/carbon/human/proc/remotesay if(M.dna.GetSEState(MORPHBLOCK)) - if(probinj(45,inj) || (mMorph in old_mutations)) + if(forced || probinj(45,inj) || (mMorph in old_mutations)) M.mutations.Add(mMorph) M << "\blue Your skin feels strange" M.verbs += /mob/living/carbon/human/proc/morph +<<<<<<< HEAD +======= + if(M.dna.GetSEState(COLDBLOCK)) + if(!(COLD_RESISTANCE in old_mutations)) + if(forced || probinj(15,inj) || (mHeatres in old_mutations)) + M.mutations.Add(mHeatres) + M << "\blue Your skin is icy to the touch" + else + if(forced || probinj(5,inj) || (mHeatres in old_mutations)) + M.mutations.Add(mHeatres) + M << "\blue Your skin is icy to the touch" +>>>>>>> b65818e... Start wrapping up the new domutcheck logic if(M.dna.GetSEState(HALLUCINATIONBLOCK)) - if(probinj(45,inj) || (mHallucination in old_mutations)) + if(forced || probinj(45,inj) || (mHallucination in old_mutations)) M.mutations.Add(mHallucination) M << "\red Your mind says 'Hello'" if(M.dna.GetSEState(NOPRINTSBLOCK)) - if(probinj(45,inj) || (mFingerprints in old_mutations)) + if(forced || probinj(45,inj) || (mFingerprints in old_mutations)) M.mutations.Add(mFingerprints) M << "\blue Your fingers feel numb" if(M.dna.GetSEState(SHOCKIMMUNITYBLOCK)) - if(probinj(45,inj) || (mShock in old_mutations)) + if(forced || probinj(45,inj) || (mShock in old_mutations)) M.mutations.Add(mShock) M << "\blue Your skin feels strange" if(M.dna.GetSEState(SMALLSIZEBLOCK)) - if(probinj(45,inj) || (mSmallsize in old_mutations)) + if(forced || probinj(45,inj) || (mSmallsize in old_mutations)) M << "\blue Your skin feels rubbery" M.mutations.Add(mSmallsize) M.pass_flags |= 1 @@ -246,7 +300,7 @@ if (M.dna.GetSEState(HULKBLOCK)) - if(probinj(5,inj) || (HULK in old_mutations)) + if(forced || probinj(5,inj) || (HULK in old_mutations)) M << "\blue Your muscles hurt." M.mutations.Add(HULK) if (M.dna.GetSEState(HEADACHEBLOCK)) @@ -271,7 +325,7 @@ M.disabilities |= TOURETTES M << "\red You twitch." if (M.dna.GetSEState(XRAYBLOCK)) - if(probinj(30,inj) || (XRAY in old_mutations)) + if(forced || probinj(30,inj) || (XRAY in old_mutations)) M << "\blue The walls suddenly disappear." // M.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) // M.see_in_dark = 8 @@ -281,14 +335,25 @@ M.disabilities |= NERVOUS M << "\red You feel nervous." if (M.dna.GetSEState(FIREBLOCK)) +<<<<<<< HEAD if(probinj(30,inj) || (COLD_RESISTANCE in old_mutations)) M << "\blue Your body feels warm." M.mutations.Add(COLD_RESISTANCE) +======= + if(!(mHeatres in old_mutations)) + if(forced || probinj(30,inj) || (COLD_RESISTANCE in old_mutations)) + M << "\blue Your body feels warm." + M.mutations.Add(COLD_RESISTANCE) + else + if(forced || probinj(5,inj) || (COLD_RESISTANCE in old_mutations)) + M << "\blue Your body feels warm." + M.mutations.Add(COLD_RESISTANCE) +>>>>>>> b65818e... Start wrapping up the new domutcheck logic if (M.dna.GetSEState(BLINDBLOCK)) M.sdisabilities |= BLIND M << "\red You can't seem to see anything." if (M.dna.GetSEState(TELEBLOCK)) - if(probinj(15,inj) || (TK in old_mutations)) + if(forced || probinj(15,inj) || (TK in old_mutations)) M << "\blue You feel smarter." M.mutations.Add(TK) if (M.dna.GetSEState(DEAFBLOCK)) @@ -469,4 +534,5 @@ if(M) M.update_icon = 1 //queue a full icon update at next life() call return null -/////////////////////////// DNA MISC-PROCS \ No newline at end of file +/////////////////////////// DNA MISC-PROCS +*/ diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm new file mode 100644 index 00000000000..e25f8eec4a9 --- /dev/null +++ b/code/game/dna/genes/disabilities.dm @@ -0,0 +1,111 @@ +///////////////////// +// DISABILITY GENES +// +// These activate either a mutation, disability, or sdisability. +// +// Gene is always activated. +///////////////////// + + +/datum/dna/gene/disability + name="DISABILITY" + + // Mutation to give (or 0) + var/mutation=0 + + // Disability to give (or 0) + var/disability=0 + + // SDisability to give (or 0) + var/sdisability=0 + + // Activation message + var/activation_message="" + +/datum/dna/gene/disability/can_activate(var/mob/M,var/list/old_mutations,var/flags) + return 1 // Always set! + +/datum/dna/gene/disability/activate(var/mob/living/carbon/M) + if(mutation) + M.mutations.Add(mutation) + if(disability) + M.disabilities|=disability + if(mutation) + M.sdisabilities|=sdisability + M << "\red [activation_message]" + +/datum/dna/gene/disability/hallucinate + name="Hallucinate" + activation_message="Your mind says 'Hello'." + mutation=mHallucination + + initialize() + block=HALLUCINATIONBLOCK + +/datum/dna/gene/disability/epilepsy + name="Epilepsy" + activation_message="You get a headache." + disability=EPILEPSY + + initialize() + block=HEADACHEBLOCK + +/datum/dna/gene/disability/cough + name="Coughing" + activation_message="You start coughing." + disability=COUGHING + + initialize() + block=COUGHBLOCK + +/datum/dna/gene/disability/clumsy + name="Clumsiness" + activation_message="You feel lightheaded." + mutation=CLUMSY + + initialize() + block=CLUMSYBLOCK + +/datum/dna/gene/disability/tourettes + name="Tourettes" + activation_message="You twitch." + disability=TOURETTES + + initialize() + block=TWITCHBLOCK + +/datum/dna/gene/disability/nervousness + name="Nervousness" + activation_message="You feel nervous." + disability=NERVOUS + + initialize() + block=NERVOUSBLOCK + +/datum/dna/gene/disability/blindness + name="Blindness" + activation_message="You can't seem to see anything." + sdisability=BLIND + + initialize() + block=BLINDBLOCK + +/datum/dna/gene/disability/deaf + name="Deafness" + activation_message="It's kinda quiet." + sdisability=DEAF + + initialize() + block=DEAFBLOCK + + activate(var/mob/M) + ..(M) + M.ear_deaf = 1 + +/datum/dna/gene/disability/nearsighted + name="Nearsightedness" + activation_message="Your eyes feel weird..." + disability=NEARSIGHTED + + initialize() + block=GLASSESBLOCK \ No newline at end of file diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm new file mode 100644 index 00000000000..192784559ed --- /dev/null +++ b/code/game/dna/genes/gene.dm @@ -0,0 +1,92 @@ +/** +* Gene Datum +* +* domutcheck was getting pretty hairy. This is the solution. +* +* All genes are stored in a global variable to cut down on memory +* usage. +* +* @author N3X15 +*/ + +/datum/dna/gene + // Display name + var/name="BASE GENE" + + // Probably won't get used but why the fuck not + var/desc="Oh god who knows what this does." + + // Set in initialize()! + // What gene activates this? + var/block=0 + +// Called when the gene is loaded by the game. Do initial setup here. +/datum/dna/gene/proc/initialize() + return + +// Return 1 if we can activate. +/datum/dna/gene/proc/can_activate(var/mob/M,var/list/old_mutations,var/flags) + return 0 + +// Called when the gene activates. Do your magic here. +/datum/dna/gene/proc/activate(var/mob/M, var/connected) + return + +// Called when the gene deactivates. Undo your magic here. +// Only called when the block is deactivated. +/datum/dna/gene/proc/deactivate(var/mob/M, var/connected) + return + + +///////////////////// +// BASIC GENES +// +// These just chuck in a mutation and display a message. +// +// Gene is activated: +// 1. If mutation already exists in mob +// 2. If the probability roll succeeds +// 3. Activation is forced (done in domutcheck) +///////////////////// + + +/datum/dna/gene/basic + name="BASIC GENE" + + // Mutation to give + var/mutation=0 + + // Activation probability + var/activation_prob=45 + + // Possible activation messages + var/list/activation_messages=list() + + // Possible deactivation messages + var/list/deactivation_messages=list() + +/datum/dna/gene/basic/can_activate(var/mob/M,var/list/old_mutations,var/flags) + if(mutation==0) + return 0 + + // Mutation already set? + if(mutation in old_mutations) + return 1 + + // Probability check + if(probinj(activation_prob,(flags&MUTCHK_FORCED))) + return 1 + + return 0 + +/datum/dna/gene/basic/activate(var/mob/M) + M.mutations.Add(mutation) + if(activation_messages.len) + var/msg = pick(activation_messages) + M << "\blue [msg]" + +/datum/dna/gene/basic/deactivate(var/mob/M) + M.mutations.Remove(mutation) + if(deactivation_messages.len) + var/msg = pick(deactivation_messages) + M << "\red [msg]" \ No newline at end of file diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm new file mode 100644 index 00000000000..76364c842f8 --- /dev/null +++ b/code/game/dna/genes/monkey.dm @@ -0,0 +1,166 @@ +/datum/dna/gene/monkey + name="Monkey" + +/datum/dna/gene/monkey/initialize() + block=MONKEYBLOCK + +/datum/dna/gene/monkey/can_activate(var/mob/M,var/list/old_mutations,var/flags) + return istype(M, /mob/living/carbon/human) + +/datum/dna/gene/monkey/activate(var/mob/living/M, var/connected) + var/mob/living/carbon/human/H = M + H.monkeyizing = 1 + var/list/implants = list() //Try to preserve implants. + for(var/obj/item/weapon/implant/W in H) + implants += W + W.loc = null + + if(!connected) + for(var/obj/item/W in (H.contents-implants)) + if (W==H.w_uniform) // will be teared + continue + H.drop_from_inventory(W) + M.monkeyizing = 1 + M.canmove = 0 + M.icon = null + M.invisibility = 101 + var/atom/movable/overlay/animation = new( M.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("h2monkey", animation) + sleep(48) + del(animation) + + + var/mob/living/carbon/monkey/O = null + if(H.species.primitive) + O = new H.species.primitive(src) + else + H.gib() //Trying to change the species of a creature with no primitive var set is messy. + return + + if(M) + if (M.dna) + O.dna = M.dna + M.dna = null + + if (M.suiciding) + O.suiciding = M.suiciding + M.suiciding = null + + + for(var/datum/disease/D in M.viruses) + O.viruses += D + D.affected_mob = O + M.viruses -= D + + + for(var/obj/T in (M.contents-implants)) + del(T) + + O.loc = M.loc + + if(M.mind) + M.mind.transfer_to(O) //transfer our mind to the cute little monkey + + if (connected) //inside dna thing + var/obj/machinery/dna_scannernew/C = connected + O.loc = C + C.occupant = O + connected = null + O.real_name = text("monkey ([])",copytext(md5(M.real_name), 2, 6)) + O.take_overall_damage(M.getBruteLoss() + 40, M.getFireLoss()) + O.adjustToxLoss(M.getToxLoss() + 20) + O.adjustOxyLoss(M.getOxyLoss()) + O.stat = M.stat + O.a_intent = "hurt" + for (var/obj/item/weapon/implant/I in implants) + I.loc = O + I.implanted = O +// O.update_icon = 1 //queue a full icon update at next life() call + del(M) + return + +/datum/dna/gene/monkey/deactivate(var/mob/living/M, var/connected) + var/mob/living/carbon/monkey/Mo = M + Mo.monkeyizing = 1 + var/list/implants = list() //Still preserving implants + for(var/obj/item/weapon/implant/W in Mo) + implants += W + W.loc = null + if(!connected) + for(var/obj/item/W in (Mo.contents-implants)) + Mo.drop_from_inventory(W) + M.monkeyizing = 1 + M.canmove = 0 + M.icon = null + M.invisibility = 101 + var/atom/movable/overlay/animation = new( M.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("monkey2h", animation) + sleep(48) + del(animation) + + var/mob/living/carbon/human/O = new( src ) + if(Mo.greaterform) + O.set_species(Mo.greaterform) + + if (M.dna.GetUIState(DNA_UI_GENDER)) + O.gender = FEMALE + else + O.gender = MALE + + if (M) + if (M.dna) + O.dna = M.dna + M.dna = null + + if (M.suiciding) + O.suiciding = M.suiciding + M.suiciding = null + + for(var/datum/disease/D in M.viruses) + O.viruses += D + D.affected_mob = O + M.viruses -= D + + //for(var/obj/T in M) + // del(T) + + O.loc = M.loc + + if(M.mind) + M.mind.transfer_to(O) //transfer our mind to the human + + if (connected) //inside dna thing + var/obj/machinery/dna_scannernew/C = connected + O.loc = C + C.occupant = O + connected = null + + var/i + while (!i) + var/randomname + if (O.gender == MALE) + randomname = capitalize(pick(first_names_male) + " " + capitalize(pick(last_names))) + else + randomname = capitalize(pick(first_names_female) + " " + capitalize(pick(last_names))) + if (findname(randomname)) + continue + else + O.real_name = randomname + i++ + O.UpdateAppearance() + O.take_overall_damage(M.getBruteLoss(), M.getFireLoss()) + O.adjustToxLoss(M.getToxLoss()) + O.adjustOxyLoss(M.getOxyLoss()) + O.stat = M.stat + for (var/obj/item/weapon/implant/I in implants) + I.loc = O + I.implanted = O +// O.update_icon = 1 //queue a full icon update at next life() call + del(M) + return \ No newline at end of file diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm new file mode 100644 index 00000000000..7b7390f4f5f --- /dev/null +++ b/code/game/dna/genes/powers.dm @@ -0,0 +1,147 @@ +/////////////////////////////////// +// POWERS +/////////////////////////////////// + +/datum/dna/gene/basic/nobreath + name="No Breathing" + activation_messages=list("You feel no need to breathe.") + mutation=mNobreath + + initialize() + block=NOBREATHBLOCK + +/datum/dna/gene/basic/remoteview + name="Remote Viewing" + activation_messages=list("Your mind expands.") + mutation=mRemote + + initialize() + block=REMOTEVIEWBLOCK + + activate(var/mob/M) + ..(M) + M.verbs += /mob/living/carbon/human/proc/remoteobserve + +/datum/dna/gene/basic/regenerate + name="Regenerate" + activation_messages=list("You feel better.") + mutation=mRegen + + initialize() + block=REGENERATEBLOCK + +/datum/dna/gene/basic/increaserun + name="Super Speed" + activation_messages=list("Your leg muscles pulsate.") + mutation=mRun + + initialize() + block=INCREASERUNBLOCK + +/datum/dna/gene/basic/remotetalk + name="Telepathy" + activation_messages=list("You expand your mind outwards.") + mutation=mRemotetalk + + initialize() + block=REMOTETALKBLOCK + + activate(var/mob/M) + ..(M) + M.verbs += /mob/living/carbon/human/proc/remotesay + +/datum/dna/gene/basic/morph + name="Morph" + activation_messages=list("Your skin feels strange.") + mutation=mMorph + + initialize() + block=REMOTETALKBLOCK + + activate(var/mob/M) + ..(M) + M.verbs += /mob/living/carbon/human/proc/morph + + +/datum/dna/gene/basic/cold_resist + name="Cold Resistance" + activation_messages=list("Your body is filled with warmth.") + mutation=COLD_RESISTANCE + + initialize() + block=FIREBLOCK + + can_activate(var/mob/M,var/list/old_mutations,var/flags) + // Mutation already set? + if(mutation in old_mutations) + return 1 + + // Probability check + var/_prob=30 + if(probinj(_prob,(flags&MUTCHK_FORCED))) + return 1 + +/datum/dna/gene/basic/noprints + name="No Prints" + activation_messages=list("Your fingers feel numb.") + mutation=mFingerprints + + initialize() + block=NOPRINTSBLOCK + +/datum/dna/gene/basic/noshock + name="Shock Immunity" + activation_messages=list("Your skin feels strange.") + mutation=mShock + + initialize() + block=SHOCKIMMUNITYBLOCK + +/datum/dna/gene/basic/midget + name="Midget" + activation_messages=list("Your skin feels rubbery.") + mutation=mSmallsize + + initialize() + block=SMALLSIZEBLOCK + + can_activate(var/mob/M,var/list/old_mutations,var/flags) + // Can't be big and small. + if(HULK in old_mutations) + return 0 + return ..(M,old_mutations,flags) + + activate(var/mob/M) + ..(M) + M.pass_flags |= 1 + +/datum/dna/gene/basic/hulk + name="Hulk" + activation_messages=list("Your muscles hurt.") + mutation=HULK + + initialize() + block=HULKBLOCK + + can_activate(var/mob/M,var/list/old_mutations,var/flags) + // Can't be big and small. + if(mSmallsize in old_mutations) + return 0 + return ..(M,old_mutations,flags) + +/datum/dna/gene/basic/xray + name="X-Ray Vision" + activation_messages=list("The walls suddenly disappear.") + mutation=XRAY + + initialize() + block=XRAYBLOCK + +/datum/dna/gene/basic/tk + name="Telekenesis" + activation_messages=list("You feel smarter.") + mutation=TK + activation_prob=15 + + initialize() + block=TELEBLOCK \ No newline at end of file diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index a210143ac06..02569e497e3 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -233,10 +233,10 @@ if (prob(25)) if (prob(75)) randmutb(H) - domutcheck(H,null,1) + domutcheck(H,null,MUTCHK_FORCED) else randmutg(H) - domutcheck(H,null,1) + domutcheck(H,null,MUTCHK_FORCED) for(var/mob/living/carbon/monkey/M in living_mob_list) var/turf/T = get_turf(M) if(!T) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 29c61509112..ff8da9ca1d4 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -222,3 +222,7 @@ var/turf/listed_turf = null //the current turf being examined in the stat panel var/kills=0 + + + var/list/active_genes=list() +