mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 02:34:00 +00:00
DNA2 Bug Fixes - Part 2
We discovered that most of the problems were were having was because of BYOND passing lists (e.g. SE and UI) by-ref instead of the assumed by-val. This commit adds dna.Clone() and (UI|SE).Copy() where needed. These should be used where DNA or SE/UI lists are COPIED, otherwise changes made in the reference will affect the real strand. This change also messes with the gene activation logic.
This commit is contained in:
@@ -39,12 +39,14 @@
|
|||||||
|
|
||||||
//Save original dna for when the disease is cured.
|
//Save original dna for when the disease is cured.
|
||||||
src.original_dna["name"] = affected_mob.real_name
|
src.original_dna["name"] = affected_mob.real_name
|
||||||
src.original_dna["UI"] = affected_mob.dna.UI
|
src.original_dna["UI"] = affected_mob.dna.UI.Copy()
|
||||||
src.original_dna["SE"] = affected_mob.dna.SE
|
src.original_dna["SE"] = affected_mob.dna.SE.Copy()
|
||||||
|
|
||||||
affected_mob << "\red You don't feel like yourself.."
|
affected_mob << "\red You don't feel like yourself.."
|
||||||
affected_mob.UpdateAppearance(strain_data["UI"])
|
var/list/newUI=strain_data["UI"]
|
||||||
affected_mob.dna.SE = strain_data["SE"]
|
var/list/newSE=strain_data["SE"]
|
||||||
|
affected_mob.UpdateAppearance(newUI.Copy())
|
||||||
|
affected_mob.dna.SE = newSE.Copy()
|
||||||
affected_mob.dna.UpdateSE()
|
affected_mob.dna.UpdateSE()
|
||||||
affected_mob.real_name = strain_data["name"]
|
affected_mob.real_name = strain_data["name"]
|
||||||
domutcheck(affected_mob)
|
domutcheck(affected_mob)
|
||||||
@@ -56,8 +58,10 @@
|
|||||||
|
|
||||||
/datum/disease/dnaspread/Del()
|
/datum/disease/dnaspread/Del()
|
||||||
if ((original_dna["name"]) && (original_dna["UI"]) && (original_dna["SE"]))
|
if ((original_dna["name"]) && (original_dna["UI"]) && (original_dna["SE"]))
|
||||||
affected_mob.UpdateAppearance(original_dna["UI"])
|
var/list/newUI=original_dna["UI"]
|
||||||
affected_mob.dna.SE = original_dna["SE"]
|
var/list/newSE=original_dna["SE"]
|
||||||
|
affected_mob.UpdateAppearance(newUI.Copy())
|
||||||
|
affected_mob.dna.SE = newSE.Copy()
|
||||||
affected_mob.dna.UpdateSE()
|
affected_mob.dna.UpdateSE()
|
||||||
affected_mob.real_name = original_dna["name"]
|
affected_mob.real_name = original_dna["name"]
|
||||||
|
|
||||||
|
|||||||
@@ -16,17 +16,6 @@
|
|||||||
#define DNA_HARDER_BOUNDS list(1,3049,3050,4095)
|
#define DNA_HARDER_BOUNDS list(1,3049,3050,4095)
|
||||||
#define DNA_HARD_BOUNDS list(1,3490,3500,4095)
|
#define DNA_HARD_BOUNDS list(1,3490,3500,4095)
|
||||||
|
|
||||||
// Defines which values mean "on" or "off".
|
|
||||||
// This is to make some of the more OP superpowers a larger PITA to activate,
|
|
||||||
// and to tell our new DNA datum which values to set in order to turn something
|
|
||||||
// on or off.
|
|
||||||
var/global/list/dna_activity_bounds[STRUCDNASIZE]
|
|
||||||
|
|
||||||
// Used to determine what each block means (admin hax and species stuff on /vg/, mostly)
|
|
||||||
var/global/list/assigned_blocks[STRUCDNASIZE]
|
|
||||||
|
|
||||||
var/global/list/datum/dna/gene/dna_genes[0]
|
|
||||||
|
|
||||||
// UI Indices (can change to mutblock style, if desired)
|
// UI Indices (can change to mutblock style, if desired)
|
||||||
#define DNA_UI_HAIR_R 1
|
#define DNA_UI_HAIR_R 1
|
||||||
#define DNA_UI_HAIR_G 2
|
#define DNA_UI_HAIR_G 2
|
||||||
@@ -43,6 +32,22 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
|||||||
#define DNA_UI_HAIR_STYLE 13
|
#define DNA_UI_HAIR_STYLE 13
|
||||||
#define DNA_UI_LENGTH 13 // Update this when you add something, or you WILL break shit.
|
#define DNA_UI_LENGTH 13 // Update this when you add something, or you WILL break shit.
|
||||||
|
|
||||||
|
#define DNA_SE_LENGTH 27
|
||||||
|
// For later:
|
||||||
|
//#define DNA_SE_LENGTH 50 // Was STRUCDNASIZE, size 27. 15 new blocks added = 42, plus room to grow.
|
||||||
|
|
||||||
|
|
||||||
|
// Defines which values mean "on" or "off".
|
||||||
|
// This is to make some of the more OP superpowers a larger PITA to activate,
|
||||||
|
// and to tell our new DNA datum which values to set in order to turn something
|
||||||
|
// on or off.
|
||||||
|
var/global/list/dna_activity_bounds[DNA_SE_LENGTH]
|
||||||
|
|
||||||
|
// Used to determine what each block means (admin hax and species stuff on /vg/, mostly)
|
||||||
|
var/global/list/assigned_blocks[DNA_SE_LENGTH]
|
||||||
|
|
||||||
|
var/global/list/datum/dna/gene/dna_genes[0]
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
// GENE DEFINES
|
// GENE DEFINES
|
||||||
/////////////////
|
/////////////////
|
||||||
@@ -64,7 +69,7 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
|||||||
|
|
||||||
// Okay to read, but you're an idiot if you do.
|
// Okay to read, but you're an idiot if you do.
|
||||||
// BLOCK = VALUE
|
// BLOCK = VALUE
|
||||||
var/list/SE[STRUCDNASIZE]
|
var/list/SE[DNA_SE_LENGTH]
|
||||||
var/list/UI[DNA_UI_LENGTH]
|
var/list/UI[DNA_UI_LENGTH]
|
||||||
|
|
||||||
// From old dna.
|
// From old dna.
|
||||||
@@ -84,7 +89,7 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
|||||||
new_dna.mutantrace=mutantrace
|
new_dna.mutantrace=mutantrace
|
||||||
new_dna.real_name=real_name
|
new_dna.real_name=real_name
|
||||||
new_dna.species=species
|
new_dna.species=species
|
||||||
for(var/b=1;b<=STRUCDNASIZE;b++)
|
for(var/b=1;b<=DNA_SE_LENGTH;b++)
|
||||||
new_dna.SE[b]=SE[b]
|
new_dna.SE[b]=SE[b]
|
||||||
if(b<=DNA_UI_LENGTH)
|
if(b<=DNA_UI_LENGTH)
|
||||||
new_dna.UI[b]=UI[b]
|
new_dna.UI[b]=UI[b]
|
||||||
@@ -224,13 +229,12 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
|||||||
|
|
||||||
// "Zeroes out" all of the blocks.
|
// "Zeroes out" all of the blocks.
|
||||||
/datum/dna/proc/ResetSE()
|
/datum/dna/proc/ResetSE()
|
||||||
for(var/i = 1, i <= STRUCDNASIZE, i++)
|
for(var/i = 1, i <= DNA_SE_LENGTH, i++)
|
||||||
SetSEValue(i,rand(1,1024),1)
|
SetSEValue(i,rand(1,1024),1)
|
||||||
UpdateSE()
|
UpdateSE()
|
||||||
|
|
||||||
// Set a DNA SE block's raw value.
|
// Set a DNA SE block's raw value.
|
||||||
/datum/dna/proc/SetSEValue(var/block,var/value,var/defer=0)
|
/datum/dna/proc/SetSEValue(var/block,var/value,var/defer=0)
|
||||||
//testing("SetSEBlock([block],[value],[defer]): [value] -> [nval]")
|
|
||||||
if (block<=0) return
|
if (block<=0) return
|
||||||
ASSERT(value>=0)
|
ASSERT(value>=0)
|
||||||
ASSERT(value<=4095)
|
ASSERT(value<=4095)
|
||||||
@@ -335,7 +339,7 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
|||||||
if(UI.len != DNA_UI_LENGTH)
|
if(UI.len != DNA_UI_LENGTH)
|
||||||
ResetUIFrom(character)
|
ResetUIFrom(character)
|
||||||
|
|
||||||
if(length(struc_enzymes)!= 3*STRUCDNASIZE)
|
if(length(struc_enzymes)!= 3*DNA_SE_LENGTH)
|
||||||
ResetSE()
|
ResetSE()
|
||||||
|
|
||||||
if(length(unique_enzymes) != 32)
|
if(length(unique_enzymes) != 32)
|
||||||
@@ -343,7 +347,7 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
|||||||
else
|
else
|
||||||
if(length(uni_identity) != 3*DNA_UI_LENGTH)
|
if(length(uni_identity) != 3*DNA_UI_LENGTH)
|
||||||
uni_identity = "00600200A00E0110148FC01300B0095BD7FD3F4"
|
uni_identity = "00600200A00E0110148FC01300B0095BD7FD3F4"
|
||||||
if(length(struc_enzymes)!= 3*STRUCDNASIZE)
|
if(length(struc_enzymes)!= 3*DNA_SE_LENGTH)
|
||||||
struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6"
|
struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6"
|
||||||
|
|
||||||
// BACK-COMPAT!
|
// BACK-COMPAT!
|
||||||
@@ -355,4 +359,3 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
|||||||
|
|
||||||
unique_enzymes = md5(character.real_name)
|
unique_enzymes = md5(character.real_name)
|
||||||
reg_dna[unique_enzymes] = character.real_name
|
reg_dna[unique_enzymes] = character.real_name
|
||||||
|
|
||||||
|
|||||||
@@ -23,336 +23,21 @@
|
|||||||
|
|
||||||
// Prior state
|
// Prior state
|
||||||
var/gene_prior_status = (gene.type in M.active_genes)
|
var/gene_prior_status = (gene.type in M.active_genes)
|
||||||
|
var/changed = gene_active != gene_prior_status || (gene.flags & GENE_ALWAYS_ACTIVATE)
|
||||||
|
|
||||||
if((gene_active && !gene_prior_status) || (gene.flags & GENE_ALWAYS_ACTIVATE))
|
// If gene state has changed:
|
||||||
//testing("[gene.name] activated!")
|
if(changed)
|
||||||
gene.activate(M,connected,flags)
|
// Gene active (or ALWAYS ACTIVATE)
|
||||||
if(M)
|
if(gene_active || (gene.flags & GENE_ALWAYS_ACTIVATE))
|
||||||
if(!(gene.flags & GENE_ALWAYS_ACTIVATE))
|
testing("[gene.name] activated!")
|
||||||
|
gene.activate(M,connected,flags)
|
||||||
|
if(M)
|
||||||
M.active_genes |= gene.type
|
M.active_genes |= gene.type
|
||||||
M.update_icon=1
|
M.update_icon = 1
|
||||||
else if(!gene_active && gene_prior_status)
|
// If Gene is NOT active:
|
||||||
//testing("[gene.name] deactivated!")
|
|
||||||
gene.deactivate(M,connected,flags)
|
|
||||||
if(M)
|
|
||||||
M.active_genes -= gene.type
|
|
||||||
M.update_icon = 1
|
|
||||||
//else
|
|
||||||
// testing("[M] - Failed to activate [gene.name] - [gene_active?"+":"-"]active, [gene_prior_status?"+":"-"]prior")
|
|
||||||
|
|
||||||
|
|
||||||
// PROC CONTINUES BELOW AFTER COMMENTED CODE.
|
|
||||||
|
|
||||||
/* Old, inflexibile
|
|
||||||
/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
|
|
||||||
|
|
||||||
if(PLANT in old_mutations)
|
|
||||||
M.mutations.Add(PLANT)
|
|
||||||
if(SKELETON in old_mutations)
|
|
||||||
M.mutations.Add(SKELETON)
|
|
||||||
if(FAT in old_mutations)
|
|
||||||
M.mutations.Add(FAT)
|
|
||||||
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(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(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(forced || probinj(45,inj) || (mRegen in old_mutations))
|
|
||||||
M << "\blue You feel better"
|
|
||||||
M.mutations.Add(mRegen)
|
|
||||||
if(M.dna.GetSEState(INCREASERUNBLOCK))
|
|
||||||
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(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(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
|
|
||||||
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"
|
|
||||||
if(M.dna.GetSEState(HALLUCINATIONBLOCK))
|
|
||||||
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(forced || probinj(45,inj) || (mFingerprints in old_mutations))
|
|
||||||
M.mutations.Add(mFingerprints)
|
|
||||||
M << "\blue Your fingers feel numb"
|
|
||||||
if(M.dna.GetSEState(SHOCKIMMUNITYBLOCK))
|
|
||||||
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(forced || probinj(45,inj) || (mSmallsize in old_mutations))
|
|
||||||
M << "\blue Your skin feels rubbery"
|
|
||||||
M.mutations.Add(mSmallsize)
|
|
||||||
M.pass_flags |= 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (M.dna.GetSEState(HULKBLOCK))
|
|
||||||
if(forced || probinj(5,inj) || (HULK in old_mutations))
|
|
||||||
M << "\blue Your muscles hurt."
|
|
||||||
M.mutations.Add(HULK)
|
|
||||||
if (M.dna.GetSEState(HEADACHEBLOCK))
|
|
||||||
M.disabilities |= EPILEPSY
|
|
||||||
M << "\red You get a headache."
|
|
||||||
if (M.dna.GetSEState(FAKEBLOCK))
|
|
||||||
M << "\red You feel strange."
|
|
||||||
if (prob(95))
|
|
||||||
if(prob(50))
|
|
||||||
randmutb(M)
|
|
||||||
else
|
else
|
||||||
randmuti(M)
|
testing("[gene.name] deactivated!")
|
||||||
else
|
gene.deactivate(M,connected,flags)
|
||||||
randmutg(M)
|
if(M)
|
||||||
if (M.dna.GetSEState(COUGHBLOCK))
|
M.active_genes -= gene.type
|
||||||
M.disabilities |= COUGHING
|
M.update_icon = 1
|
||||||
M << "\red You start coughing."
|
|
||||||
if (M.dna.GetSEState(CLUMSYBLOCK))
|
|
||||||
M << "\red You feel lightheaded."
|
|
||||||
M.mutations.Add(CLUMSY)
|
|
||||||
if (M.dna.GetSEState(TWITCHBLOCK))
|
|
||||||
M.disabilities |= TOURETTES
|
|
||||||
M << "\red You twitch."
|
|
||||||
if (M.dna.GetSEState(XRAYBLOCK))
|
|
||||||
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
|
|
||||||
// M.see_invisible = 2
|
|
||||||
M.mutations.Add(XRAY)
|
|
||||||
if (M.dna.GetSEState(NERVOUSBLOCK))
|
|
||||||
M.disabilities |= NERVOUS
|
|
||||||
M << "\red You feel nervous."
|
|
||||||
if (M.dna.GetSEState(FIREBLOCK))
|
|
||||||
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)
|
|
||||||
if (M.dna.GetSEState(BLINDBLOCK))
|
|
||||||
M.sdisabilities |= BLIND
|
|
||||||
M << "\red You can't seem to see anything."
|
|
||||||
if (M.dna.GetSEState(TELEBLOCK))
|
|
||||||
if(forced || probinj(15,inj) || (TK in old_mutations))
|
|
||||||
M << "\blue You feel smarter."
|
|
||||||
M.mutations.Add(TK)
|
|
||||||
if (M.dna.GetSEState(DEAFBLOCK))
|
|
||||||
M.sdisabilities |= DEAF
|
|
||||||
M.ear_deaf = 1
|
|
||||||
M << "\red Its kinda quiet.."
|
|
||||||
if (M.dna.GetSEState(GLASSESBLOCK))
|
|
||||||
M.disabilities |= NEARSIGHTED
|
|
||||||
M << "Your eyes feel weird..."
|
|
||||||
|
|
||||||
/* If you want the new mutations to work, UNCOMMENT THIS.
|
|
||||||
if(istype(M, /mob/living/carbon))
|
|
||||||
for (var/datum/mutations/mut in global_mutations)
|
|
||||||
mut.check_mutation(M)
|
|
||||||
*/
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////// Monkey Block
|
|
||||||
if (M.dna.GetSEState(MONKEYBLOCK) && istype(M, /mob/living/carbon/human))
|
|
||||||
// human > monkey
|
|
||||||
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
|
|
||||||
|
|
||||||
if (!M.dna.GetSEState(MONKEYBLOCK) && !istype(M, /mob/living/carbon/human))
|
|
||||||
// monkey > human,
|
|
||||||
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
|
|
||||||
//////////////////////////////////////////////////////////// Monkey Block
|
|
||||||
if(M)
|
|
||||||
M.update_icon = 1 //queue a full icon update at next life() call
|
|
||||||
return null
|
|
||||||
/////////////////////////// DNA MISC-PROCS
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
/proc/randmuti(var/mob/living/M)
|
/proc/randmuti(var/mob/living/M)
|
||||||
if(!M) return
|
if(!M) return
|
||||||
M.dna.check_integrity()
|
M.dna.check_integrity()
|
||||||
M.dna.SetUIValue(rand(1,UNIDNASIZE),rand(1,4095))
|
M.dna.SetUIValue(rand(1,DNA_UI_LENGTH),rand(1,4095))
|
||||||
|
|
||||||
// Scramble UI or SE.
|
// Scramble UI or SE.
|
||||||
/proc/scramble(var/UI, var/mob/M, var/prob)
|
/proc/scramble(var/UI, var/mob/M, var/prob)
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
M.UpdateAppearance()
|
M.UpdateAppearance()
|
||||||
|
|
||||||
else
|
else
|
||||||
for(var/i = 1, i <= STRUCDNASIZE-1, i++)
|
for(var/i = 1, i <= DNA_SE_LENGTH-1, i++)
|
||||||
if(prob(prob))
|
if(prob(prob))
|
||||||
M.dna.SetSEValue(i,rand(1,4095),1)
|
M.dna.SetSEValue(i,rand(1,4095),1)
|
||||||
M.dna.UpdateSE()
|
M.dna.UpdateSE()
|
||||||
|
|||||||
@@ -19,17 +19,18 @@
|
|||||||
|
|
||||||
/datum/dna2/record/proc/GetData()
|
/datum/dna2/record/proc/GetData()
|
||||||
var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0)
|
var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0)
|
||||||
ser["ue"] = (types & DNA2_BUF_UE) == DNA2_BUF_UE
|
if(dna)
|
||||||
if(types & DNA2_BUF_SE)
|
ser["ue"] = (types & DNA2_BUF_UE) == DNA2_BUF_UE
|
||||||
ser["data"] = dna.SE
|
if(types & DNA2_BUF_SE)
|
||||||
else
|
ser["data"] = dna.SE
|
||||||
ser["data"] = dna.UI
|
else
|
||||||
ser["owner"] = src.dna.real_name
|
ser["data"] = dna.UI
|
||||||
ser["label"] = name
|
ser["owner"] = src.dna.real_name
|
||||||
if(types & DNA2_BUF_UI)
|
ser["label"] = name
|
||||||
ser["type"] = "ui"
|
if(types & DNA2_BUF_UI)
|
||||||
else
|
ser["type"] = "ui"
|
||||||
ser["type"] = "se"
|
else
|
||||||
|
ser["type"] = "se"
|
||||||
return ser
|
return ser
|
||||||
|
|
||||||
/////////////////////////// DNA MACHINES
|
/////////////////////////// DNA MACHINES
|
||||||
@@ -311,6 +312,8 @@
|
|||||||
|
|
||||||
/obj/machinery/computer/scan_consolenew/New()
|
/obj/machinery/computer/scan_consolenew/New()
|
||||||
..()
|
..()
|
||||||
|
for(var/i=0;i<3;i++)
|
||||||
|
buffers[i+1]=new /datum/dna2/record
|
||||||
spawn(5)
|
spawn(5)
|
||||||
for(dir in list(NORTH,EAST,SOUTH,WEST))
|
for(dir in list(NORTH,EAST,SOUTH,WEST))
|
||||||
connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
|
connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
|
||||||
@@ -400,8 +403,8 @@
|
|||||||
data["disk"] = diskData
|
data["disk"] = diskData
|
||||||
|
|
||||||
var/list/new_buffers = list()
|
var/list/new_buffers = list()
|
||||||
for(var/datum/dna2/record/buf in buffers)
|
for(var/datum/dna2/record/buf in src.buffers)
|
||||||
new_buffers.Add(buf.GetData())
|
new_buffers += list(buf.GetData())
|
||||||
data["buffers"]=new_buffers
|
data["buffers"]=new_buffers
|
||||||
|
|
||||||
data["radiationIntensity"] = radiation_intensity
|
data["radiationIntensity"] = radiation_intensity
|
||||||
@@ -635,7 +638,7 @@
|
|||||||
if (href_list["selectSEBlock"] && href_list["selectSESubblock"]) // This chunk of code updates selected block / sub-block based on click (se stands for strutural enzymes)
|
if (href_list["selectSEBlock"] && href_list["selectSESubblock"]) // This chunk of code updates selected block / sub-block based on click (se stands for strutural enzymes)
|
||||||
var/select_block = text2num(href_list["selectSEBlock"])
|
var/select_block = text2num(href_list["selectSEBlock"])
|
||||||
var/select_subblock = text2num(href_list["selectSESubblock"])
|
var/select_subblock = text2num(href_list["selectSESubblock"])
|
||||||
if ((select_block <= STRUCDNASIZE) && (select_block >= 1))
|
if ((select_block <= DNA_SE_LENGTH) && (select_block >= 1))
|
||||||
src.selected_se_block = select_block
|
src.selected_se_block = select_block
|
||||||
if ((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
|
if ((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
|
||||||
src.selected_se_subblock = select_subblock
|
src.selected_se_subblock = select_subblock
|
||||||
@@ -663,9 +666,9 @@
|
|||||||
var/real_SE_block=selected_se_block
|
var/real_SE_block=selected_se_block
|
||||||
block = miniscramble(block, src.radiation_intensity, src.radiation_duration)
|
block = miniscramble(block, src.radiation_intensity, src.radiation_duration)
|
||||||
if(prob(20))
|
if(prob(20))
|
||||||
if (src.selected_se_block > 1 && src.selected_se_block < STRUCDNASIZE/2)
|
if (src.selected_se_block > 1 && src.selected_se_block < DNA_SE_LENGTH/2)
|
||||||
real_SE_block++
|
real_SE_block++
|
||||||
else if (src.selected_se_block > STRUCDNASIZE/2 && src.selected_se_block < STRUCDNASIZE)
|
else if (src.selected_se_block > DNA_SE_LENGTH/2 && src.selected_se_block < DNA_SE_LENGTH)
|
||||||
real_SE_block--
|
real_SE_block--
|
||||||
|
|
||||||
//testing("Irradiated SE block [real_SE_block]:[src.selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!")
|
//testing("Irradiated SE block [real_SE_block]:[src.selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!")
|
||||||
@@ -730,7 +733,9 @@
|
|||||||
if(src.connected.occupant && src.connected.occupant.dna)
|
if(src.connected.occupant && src.connected.occupant.dna)
|
||||||
var/datum/dna2/record/databuf=new
|
var/datum/dna2/record/databuf=new
|
||||||
databuf.types = DNA2_BUF_UE
|
databuf.types = DNA2_BUF_UE
|
||||||
databuf.dna = src.connected.occupant.dna
|
databuf.dna = src.connected.occupant.dna.Clone()
|
||||||
|
if(ishuman(connected.occupant))
|
||||||
|
databuf.dna.real_name=connected.occupant.name
|
||||||
databuf.name = "Unique Identifier"
|
databuf.name = "Unique Identifier"
|
||||||
src.buffers[bufferId] = databuf
|
src.buffers[bufferId] = databuf
|
||||||
return 1
|
return 1
|
||||||
@@ -739,7 +744,9 @@
|
|||||||
if(src.connected.occupant && src.connected.occupant.dna)
|
if(src.connected.occupant && src.connected.occupant.dna)
|
||||||
var/datum/dna2/record/databuf=new
|
var/datum/dna2/record/databuf=new
|
||||||
databuf.types = DNA2_BUF_UI|DNA2_BUF_UE
|
databuf.types = DNA2_BUF_UI|DNA2_BUF_UE
|
||||||
databuf.dna = src.connected.occupant.dna
|
databuf.dna = src.connected.occupant.dna.Clone()
|
||||||
|
if(ishuman(connected.occupant))
|
||||||
|
databuf.dna.real_name=connected.occupant.name
|
||||||
databuf.name = "Unique Identifier + Unique Enzymes"
|
databuf.name = "Unique Identifier + Unique Enzymes"
|
||||||
src.buffers[bufferId] = databuf
|
src.buffers[bufferId] = databuf
|
||||||
return 1
|
return 1
|
||||||
@@ -748,19 +755,21 @@
|
|||||||
if(src.connected.occupant && src.connected.occupant.dna)
|
if(src.connected.occupant && src.connected.occupant.dna)
|
||||||
var/datum/dna2/record/databuf=new
|
var/datum/dna2/record/databuf=new
|
||||||
databuf.types = DNA2_BUF_SE
|
databuf.types = DNA2_BUF_SE
|
||||||
databuf.dna = src.connected.occupant.dna
|
databuf.dna = src.connected.occupant.dna.Clone()
|
||||||
|
if(ishuman(connected.occupant))
|
||||||
|
databuf.dna.real_name=connected.occupant.name
|
||||||
databuf.name = "Structural Enzymes"
|
databuf.name = "Structural Enzymes"
|
||||||
src.buffers[bufferId] = databuf
|
src.buffers[bufferId] = databuf
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if (bufferOption == "clear")
|
if (bufferOption == "clear")
|
||||||
src.buffers[bufferId]=null
|
src.buffers[bufferId]=new /datum/dna2/record()
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if (bufferOption == "changeLabel")
|
if (bufferOption == "changeLabel")
|
||||||
var/datum/dna2/record/buf = src.buffers[bufferId]
|
var/datum/dna2/record/buf = src.buffers[bufferId]
|
||||||
buf.name = buf.name ? src.buffers[bufferId]["label"] : "New Label"
|
var/text = sanitize(input(usr, "New Label:", "Edit Label", buf.name) as text|null)
|
||||||
buf.name = sanitize(input("New Label:", "Edit Label", buf.name))
|
buf.name = text
|
||||||
src.buffers[bufferId] = buf
|
src.buffers[bufferId] = buf
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
@@ -784,7 +793,7 @@
|
|||||||
if ((buf.types & DNA2_BUF_UE))
|
if ((buf.types & DNA2_BUF_UE))
|
||||||
src.connected.occupant.real_name = buf.dna.real_name
|
src.connected.occupant.real_name = buf.dna.real_name
|
||||||
src.connected.occupant.name = buf.dna.real_name
|
src.connected.occupant.name = buf.dna.real_name
|
||||||
src.connected.occupant.UpdateAppearance(buf.dna.UI)
|
src.connected.occupant.UpdateAppearance(buf.dna.UI.Copy())
|
||||||
else if (buf.types & DNA2_BUF_SE)
|
else if (buf.types & DNA2_BUF_SE)
|
||||||
src.connected.occupant.dna.SE = buf.dna.SE
|
src.connected.occupant.dna.SE = buf.dna.SE
|
||||||
src.connected.occupant.dna.UpdateSE()
|
src.connected.occupant.dna.UpdateSE()
|
||||||
@@ -800,7 +809,12 @@
|
|||||||
var/datum/dna2/record/buf = src.buffers[bufferId]
|
var/datum/dna2/record/buf = src.buffers[bufferId]
|
||||||
if(href_list["createBlockInjector"])
|
if(href_list["createBlockInjector"])
|
||||||
waiting_for_user_input=1
|
waiting_for_user_input=1
|
||||||
var/blk = input(usr,"Select Block","Block") in all_dna_blocks(buf.GetData())
|
var/list/selectedbuf
|
||||||
|
if(buf.types & DNA2_BUF_SE)
|
||||||
|
selectedbuf=buf.dna.SE
|
||||||
|
else
|
||||||
|
selectedbuf=buf.dna.UI
|
||||||
|
var/blk = input(usr,"Select Block","Block") in all_dna_blocks(selectedbuf)
|
||||||
success = setInjectorBlock(I,blk,buf)
|
success = setInjectorBlock(I,blk,buf)
|
||||||
else
|
else
|
||||||
I.buf = buf
|
I.buf = buf
|
||||||
|
|||||||
@@ -36,6 +36,8 @@
|
|||||||
M.sdisabilities|=sdisability
|
M.sdisabilities|=sdisability
|
||||||
if(activation_message)
|
if(activation_message)
|
||||||
M << "\red [activation_message]"
|
M << "\red [activation_message]"
|
||||||
|
else
|
||||||
|
testing("[name] has no activation message.")
|
||||||
|
|
||||||
/datum/dna/gene/disability/deactivate(var/mob/M, var/connected, var/flags)
|
/datum/dna/gene/disability/deactivate(var/mob/M, var/connected, var/flags)
|
||||||
if(mutation && (mutation in M.mutations))
|
if(mutation && (mutation in M.mutations))
|
||||||
@@ -46,6 +48,8 @@
|
|||||||
M.sdisabilities &= ~sdisability
|
M.sdisabilities &= ~sdisability
|
||||||
if(deactivation_message)
|
if(deactivation_message)
|
||||||
M << "\red [deactivation_message]"
|
M << "\red [deactivation_message]"
|
||||||
|
else
|
||||||
|
testing("[name] has no deactivation message.")
|
||||||
|
|
||||||
// Note: Doesn't seem to do squat, at the moment.
|
// Note: Doesn't seem to do squat, at the moment.
|
||||||
/datum/dna/gene/disability/hallucinate
|
/datum/dna/gene/disability/hallucinate
|
||||||
|
|||||||
@@ -23,6 +23,12 @@
|
|||||||
// Any of a number of GENE_ flags.
|
// Any of a number of GENE_ flags.
|
||||||
var/flags=0
|
var/flags=0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the gene active in this mob's DNA?
|
||||||
|
*/
|
||||||
|
/datum/dna/gene/proc/is_active(var/mob/M)
|
||||||
|
return M.active_genes && type in M.active_genes
|
||||||
|
|
||||||
// Return 1 if we can activate.
|
// Return 1 if we can activate.
|
||||||
// HANDLE MUTCHK_FORCED HERE!
|
// HANDLE MUTCHK_FORCED HERE!
|
||||||
/datum/dna/gene/proc/can_activate(var/mob/M, var/flags)
|
/datum/dna/gene/proc/can_activate(var/mob/M, var/flags)
|
||||||
@@ -32,11 +38,43 @@
|
|||||||
/datum/dna/gene/proc/activate(var/mob/M, var/connected, var/flags)
|
/datum/dna/gene/proc/activate(var/mob/M, var/connected, var/flags)
|
||||||
return
|
return
|
||||||
|
|
||||||
// Called when the gene deactivates. Undo your magic here.
|
/**
|
||||||
// Only called when the block is deactivated.
|
* 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, var/flags)
|
/datum/dna/gene/proc/deactivate(var/mob/M, var/connected, var/flags)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
// This section inspired by goone's bioEffects.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called in each life() tick.
|
||||||
|
*/
|
||||||
|
/datum/dna/gene/proc/OnMobLife(var/mob/M)
|
||||||
|
return
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the mob dies
|
||||||
|
*/
|
||||||
|
/datum/dna/gene/proc/OnMobDeath(var/mob/M)
|
||||||
|
return
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the mob says shit
|
||||||
|
*/
|
||||||
|
/datum/dna/gene/proc/OnSay(var/mob/M, var/message)
|
||||||
|
return message
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after the mob runs update_icons.
|
||||||
|
*
|
||||||
|
* @params M The subject.
|
||||||
|
* @params g Gender (m or f)
|
||||||
|
* @params fat Fat? (0 or 1)
|
||||||
|
*/
|
||||||
|
/datum/dna/gene/proc/OnDrawUnderlays(var/mob/M, var/g, var/fat)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// BASIC GENES
|
// BASIC GENES
|
||||||
@@ -66,14 +104,10 @@
|
|||||||
var/list/deactivation_messages=list()
|
var/list/deactivation_messages=list()
|
||||||
|
|
||||||
/datum/dna/gene/basic/can_activate(var/mob/M,var/flags)
|
/datum/dna/gene/basic/can_activate(var/mob/M,var/flags)
|
||||||
if(mutation==0)
|
if(flags & MUTCHK_FORCED)
|
||||||
return 0
|
|
||||||
|
|
||||||
// Probability check
|
|
||||||
if(flags & MUTCHK_FORCED || probinj(activation_prob,(flags&MUTCHK_FORCED)))
|
|
||||||
return 1
|
return 1
|
||||||
|
// Probability check
|
||||||
return 0
|
return probinj(activation_prob,(flags&MUTCHK_FORCED))
|
||||||
|
|
||||||
/datum/dna/gene/basic/activate(var/mob/M)
|
/datum/dna/gene/basic/activate(var/mob/M)
|
||||||
M.mutations.Add(mutation)
|
M.mutations.Add(mutation)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
/datum/dna/gene/monkey/activate(var/mob/living/M, var/connected, var/flags)
|
/datum/dna/gene/monkey/activate(var/mob/living/M, var/connected, var/flags)
|
||||||
if(!istype(M,/mob/living/carbon/human))
|
if(!istype(M,/mob/living/carbon/human))
|
||||||
|
//testing("Cannot monkey-ify [M], type is [M.type].")
|
||||||
return
|
return
|
||||||
var/mob/living/carbon/human/H = M
|
var/mob/living/carbon/human/H = M
|
||||||
H.monkeyizing = 1
|
H.monkeyizing = 1
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
|
|
||||||
if(M)
|
if(M)
|
||||||
if (M.dna)
|
if (M.dna)
|
||||||
O.dna = M.dna
|
O.dna = M.dna.Clone()
|
||||||
M.dna = null
|
M.dna = null
|
||||||
|
|
||||||
if (M.suiciding)
|
if (M.suiciding)
|
||||||
@@ -86,6 +87,7 @@
|
|||||||
|
|
||||||
/datum/dna/gene/monkey/deactivate(var/mob/living/M, var/connected, var/flags)
|
/datum/dna/gene/monkey/deactivate(var/mob/living/M, var/connected, var/flags)
|
||||||
if(!istype(M,/mob/living/carbon/monkey))
|
if(!istype(M,/mob/living/carbon/monkey))
|
||||||
|
//testing("Cannot humanize [M], type is [M.type].")
|
||||||
return
|
return
|
||||||
var/mob/living/carbon/monkey/Mo = M
|
var/mob/living/carbon/monkey/Mo = M
|
||||||
Mo.monkeyizing = 1
|
Mo.monkeyizing = 1
|
||||||
@@ -119,7 +121,7 @@
|
|||||||
|
|
||||||
if (M)
|
if (M)
|
||||||
if (M.dna)
|
if (M.dna)
|
||||||
O.dna = M.dna
|
O.dna = M.dna.Clone()
|
||||||
M.dna = null
|
M.dna = null
|
||||||
|
|
||||||
if (M.suiciding)
|
if (M.suiciding)
|
||||||
|
|||||||
@@ -72,12 +72,17 @@
|
|||||||
block=COLDBLOCK
|
block=COLDBLOCK
|
||||||
|
|
||||||
can_activate(var/mob/M,var/flags)
|
can_activate(var/mob/M,var/flags)
|
||||||
|
if(flags & MUTCHK_FORCED)
|
||||||
|
return !(/datum/dna/gene/basic/cold_resist in M.active_genes)
|
||||||
// Probability check
|
// Probability check
|
||||||
var/_prob = 15
|
var/_prob = 15
|
||||||
if(COLD_RESISTANCE in M.mutations)
|
if(COLD_RESISTANCE in M.mutations)
|
||||||
_prob=5
|
_prob=5
|
||||||
if(probinj(_prob,(flags&MUTCHK_FORCED)))
|
if(probinj(_prob,(flags&MUTCHK_FORCED)))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
OnDrawUnderlays(var/mob/M,var/g,var/fat)
|
||||||
|
return "cold[fat]_s"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/datum/dna/gene/basic/cold_resist
|
/datum/dna/gene/basic/cold_resist
|
||||||
@@ -89,7 +94,9 @@
|
|||||||
block=FIREBLOCK
|
block=FIREBLOCK
|
||||||
|
|
||||||
can_activate(var/mob/M,var/flags)
|
can_activate(var/mob/M,var/flags)
|
||||||
|
if(flags & MUTCHK_FORCED)
|
||||||
|
return 1
|
||||||
|
// return !(/datum/dna/gene/basic/heat_resist in M.active_genes)
|
||||||
// Probability check
|
// Probability check
|
||||||
var/_prob=30
|
var/_prob=30
|
||||||
//if(mHeatres in M.mutations)
|
//if(mHeatres in M.mutations)
|
||||||
@@ -97,6 +104,9 @@
|
|||||||
if(probinj(_prob,(flags&MUTCHK_FORCED)))
|
if(probinj(_prob,(flags&MUTCHK_FORCED)))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
OnDrawUnderlays(var/mob/M,var/g,var/fat)
|
||||||
|
return "fire[fat]_s"
|
||||||
|
|
||||||
/datum/dna/gene/basic/noprints
|
/datum/dna/gene/basic/noprints
|
||||||
name="No Prints"
|
name="No Prints"
|
||||||
activation_messages=list("Your fingers feel numb.")
|
activation_messages=list("Your fingers feel numb.")
|
||||||
@@ -149,6 +159,22 @@
|
|||||||
return 0
|
return 0
|
||||||
return ..(M,flags)
|
return ..(M,flags)
|
||||||
|
|
||||||
|
OnDrawUnderlays(var/mob/M,var/g,var/fat)
|
||||||
|
if(fat)
|
||||||
|
return "hulk_[fat]_s"
|
||||||
|
else
|
||||||
|
return "hulk_[g]_s"
|
||||||
|
return 0
|
||||||
|
|
||||||
|
OnMobLife(var/mob/living/carbon/human/M)
|
||||||
|
if(!istype(M)) return
|
||||||
|
if(M.health <= 25)
|
||||||
|
M.mutations.Remove(HULK)
|
||||||
|
M.update_mutations() //update our mutation overlays
|
||||||
|
M << "\red You suddenly feel very weak."
|
||||||
|
M.Weaken(3)
|
||||||
|
M.emote("collapse")
|
||||||
|
|
||||||
/datum/dna/gene/basic/xray
|
/datum/dna/gene/basic/xray
|
||||||
name="X-Ray Vision"
|
name="X-Ray Vision"
|
||||||
activation_messages=list("The walls suddenly disappear.")
|
activation_messages=list("The walls suddenly disappear.")
|
||||||
@@ -164,4 +190,7 @@
|
|||||||
activation_prob=15
|
activation_prob=15
|
||||||
|
|
||||||
New()
|
New()
|
||||||
block=TELEBLOCK
|
block=TELEBLOCK
|
||||||
|
|
||||||
|
OnDrawUnderlays(var/mob/M,var/g,var/fat)
|
||||||
|
return "telekinesishead[fat]_s"
|
||||||
@@ -184,7 +184,7 @@
|
|||||||
changeling.chem_charges -= 5
|
changeling.chem_charges -= 5
|
||||||
src.visible_message("<span class='warning'>[src] transforms!</span>")
|
src.visible_message("<span class='warning'>[src] transforms!</span>")
|
||||||
changeling.geneticdamage = 30
|
changeling.geneticdamage = 30
|
||||||
src.dna = chosen_dna
|
src.dna = chosen_dna.Clone()
|
||||||
src.real_name = chosen_dna.real_name
|
src.real_name = chosen_dna.real_name
|
||||||
src.flavor_text = ""
|
src.flavor_text = ""
|
||||||
src.UpdateAppearance()
|
src.UpdateAppearance()
|
||||||
@@ -236,7 +236,7 @@
|
|||||||
del(animation)
|
del(animation)
|
||||||
|
|
||||||
var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey(src)
|
var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey(src)
|
||||||
O.dna = C.dna
|
O.dna = C.dna.Clone()
|
||||||
C.dna = null
|
C.dna = null
|
||||||
|
|
||||||
for(var/obj/item/W in C)
|
for(var/obj/item/W in C)
|
||||||
@@ -289,7 +289,7 @@
|
|||||||
changeling.chem_charges--
|
changeling.chem_charges--
|
||||||
C.remove_changeling_powers()
|
C.remove_changeling_powers()
|
||||||
C.visible_message("<span class='warning'>[C] transforms!</span>")
|
C.visible_message("<span class='warning'>[C] transforms!</span>")
|
||||||
C.dna = chosen_dna
|
C.dna = chosen_dna.Clone()
|
||||||
|
|
||||||
var/list/implants = list()
|
var/list/implants = list()
|
||||||
for (var/obj/item/weapon/implant/I in C) //Still preserving implants
|
for (var/obj/item/weapon/implant/I in C) //Still preserving implants
|
||||||
@@ -322,7 +322,7 @@
|
|||||||
O.gender = FEMALE
|
O.gender = FEMALE
|
||||||
else
|
else
|
||||||
O.gender = MALE
|
O.gender = MALE
|
||||||
O.dna = C.dna
|
O.dna = C.dna.Clone()
|
||||||
C.dna = null
|
C.dna = null
|
||||||
O.real_name = chosen_dna.real_name
|
O.real_name = chosen_dna.real_name
|
||||||
|
|
||||||
@@ -721,7 +721,7 @@ var/list/datum/dna/hivemind_bank = list()
|
|||||||
src << "<span class='warning'>Our sting appears ineffective against its DNA.</span>"
|
src << "<span class='warning'>Our sting appears ineffective against its DNA.</span>"
|
||||||
return 0
|
return 0
|
||||||
T.visible_message("<span class='warning'>[T] transforms!</span>")
|
T.visible_message("<span class='warning'>[T] transforms!</span>")
|
||||||
T.dna = chosen_dna
|
T.dna = chosen_dna.Clone()
|
||||||
T.real_name = chosen_dna.real_name
|
T.real_name = chosen_dna.real_name
|
||||||
T.UpdateAppearance()
|
T.UpdateAppearance()
|
||||||
domutcheck(T, null)
|
domutcheck(T, null)
|
||||||
|
|||||||
@@ -163,8 +163,8 @@
|
|||||||
continue
|
continue
|
||||||
var/datum/disease/dnaspread/D = new
|
var/datum/disease/dnaspread/D = new
|
||||||
D.strain_data["name"] = H.real_name
|
D.strain_data["name"] = H.real_name
|
||||||
D.strain_data["UI"] = H.dna.UI
|
D.strain_data["UI"] = H.dna.uni_identity
|
||||||
D.strain_data["SE"] = H.dna.SE
|
D.strain_data["SE"] = H.dna.struc_enzymes
|
||||||
D.carrier = 1
|
D.carrier = 1
|
||||||
D.holder = H
|
D.holder = H
|
||||||
D.affected_mob = H
|
D.affected_mob = H
|
||||||
@@ -233,10 +233,10 @@
|
|||||||
if (prob(25))
|
if (prob(25))
|
||||||
if (prob(75))
|
if (prob(75))
|
||||||
randmutb(H)
|
randmutb(H)
|
||||||
domutcheck(H,null,1)
|
domutcheck(H,null,MUTCHK_FORCED)
|
||||||
else
|
else
|
||||||
randmutg(H)
|
randmutg(H)
|
||||||
domutcheck(H,null,1)
|
domutcheck(H,null,MUTCHK_FORCED)
|
||||||
for(var/mob/living/carbon/monkey/M in living_mob_list)
|
for(var/mob/living/carbon/monkey/M in living_mob_list)
|
||||||
var/turf/T = get_turf(M)
|
var/turf/T = get_turf(M)
|
||||||
if(!T)
|
if(!T)
|
||||||
|
|||||||
@@ -60,10 +60,10 @@
|
|||||||
Initialize()
|
Initialize()
|
||||||
buf.types=DNA2_BUF_SE
|
buf.types=DNA2_BUF_SE
|
||||||
var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4)
|
var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4)
|
||||||
for(var/i=new_SE.len;i<=STRUCDNASIZE;i++)
|
for(var/i=new_SE.len;i<=DNA_SE_LENGTH;i++)
|
||||||
new_SE += rand(1,1024)
|
new_SE += rand(1,1024)
|
||||||
buf.dna.SE=new_SE
|
buf.dna.SE=new_SE
|
||||||
buf.dna.SetSEValue(MONKEYBLOCK,0xFFF)
|
buf.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF)
|
||||||
|
|
||||||
|
|
||||||
//Find a dead mob with a brain and client.
|
//Find a dead mob with a brain and client.
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
if (!(NOCLONE in M.mutations)) // prevents drained people from having their DNA changed
|
if (!(NOCLONE in M.mutations)) // prevents drained people from having their DNA changed
|
||||||
if (buf.types & DNA2_BUF_UI)
|
if (buf.types & DNA2_BUF_UI)
|
||||||
if (!block) //isolated block?
|
if (!block) //isolated block?
|
||||||
M.UpdateAppearance(buf.dna)
|
M.UpdateAppearance(buf.dna.UI.Copy())
|
||||||
if (buf.types & DNA2_BUF_UE) //unique enzymes? yes
|
if (buf.types & DNA2_BUF_UE) //unique enzymes? yes
|
||||||
M.real_name = buf.dna.real_name
|
M.real_name = buf.dna.real_name
|
||||||
M.name = buf.dna.real_name
|
M.name = buf.dna.real_name
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
uses--
|
uses--
|
||||||
if (buf.types & DNA2_BUF_SE)
|
if (buf.types & DNA2_BUF_SE)
|
||||||
if (!block) //isolated block?
|
if (!block) //isolated block?
|
||||||
M.dna.SE = buf.dna.SE
|
M.dna.SE = buf.dna.SE.Copy()
|
||||||
M.dna.UpdateSE()
|
M.dna.UpdateSE()
|
||||||
else
|
else
|
||||||
M.dna.SetSEValue(block,src.GetValue())
|
M.dna.SetSEValue(block,src.GetValue())
|
||||||
|
|||||||
@@ -119,6 +119,25 @@ var/global/floorIsLava = 0
|
|||||||
else
|
else
|
||||||
body += "<A href='?src=\ref[src];makeanimal=\ref[M]'>Animalize</A> | "
|
body += "<A href='?src=\ref[src];makeanimal=\ref[M]'>Animalize</A> | "
|
||||||
|
|
||||||
|
// DNA2 - Admin Hax
|
||||||
|
if(iscarbon(M))
|
||||||
|
body += "<br><br>"
|
||||||
|
body += "<b>DNA Blocks:</b><br><table border='0'><tr><th> </th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th>"
|
||||||
|
var/bname
|
||||||
|
for(var/block=1;block<=DNA_SE_LENGTH;block++)
|
||||||
|
if(((block-1)%5)==0)
|
||||||
|
body += "</tr><tr><th>[block-1]</th>"
|
||||||
|
bname = assigned_blocks[block]
|
||||||
|
body += "<td>"
|
||||||
|
if(bname)
|
||||||
|
var/bstate=M.dna.GetSEState(block)
|
||||||
|
var/bcolor="[(bstate)?"#006600":"#ff0000"]"
|
||||||
|
body += "<A href='?src=\ref[src];togmutate=\ref[M];block=[block]' style='color:[bcolor];'>[bname]</A><sub>[block]</sub>"
|
||||||
|
else
|
||||||
|
body += "[block]"
|
||||||
|
body+="</td>"
|
||||||
|
body += "</tr></table>"
|
||||||
|
|
||||||
body += {"<br><br>
|
body += {"<br><br>
|
||||||
<b>Rudimentary transformation:</b><font size=2><br>These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.</font><br>
|
<b>Rudimentary transformation:</b><font size=2><br>These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.</font><br>
|
||||||
<A href='?src=\ref[src];simplemake=observer;mob=\ref[M]'>Observer</A> |
|
<A href='?src=\ref[src];simplemake=observer;mob=\ref[M]'>Observer</A> |
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
|||||||
if(istype(M, /mob/living/carbon/human))
|
if(istype(M, /mob/living/carbon/human))
|
||||||
log_admin("[key_name(src)] has made [M.key] a changeling.")
|
log_admin("[key_name(src)] has made [M.key] a changeling.")
|
||||||
spawn(10)
|
spawn(10)
|
||||||
M.absorbed_dna[M.real_name] = M.dna
|
M.absorbed_dna[M.real_name] = M.dna.Clone()
|
||||||
M.make_changeling()
|
M.make_changeling()
|
||||||
if(M.mind)
|
if(M.mind)
|
||||||
M.mind.special_role = "Changeling"
|
M.mind.special_role = "Changeling"
|
||||||
@@ -986,3 +986,19 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
|||||||
usr << list2text(dead_mob_list,",")
|
usr << list2text(dead_mob_list,",")
|
||||||
if("Clients")
|
if("Clients")
|
||||||
usr << list2text(clients,",")
|
usr << list2text(clients,",")
|
||||||
|
|
||||||
|
// DNA2 - Admin Hax
|
||||||
|
/client/proc/cmd_admin_toggle_block(var/mob/M,var/block)
|
||||||
|
if(!ticker)
|
||||||
|
alert("Wait until the game starts")
|
||||||
|
return
|
||||||
|
if(istype(M, /mob/living/carbon))
|
||||||
|
M.dna.SetSEState(block,!M.dna.GetSEState(block))
|
||||||
|
domutcheck(M,null,MUTCHK_FORCED)
|
||||||
|
M.update_mutations()
|
||||||
|
var/state="[M.dna.GetSEState(block)?"on":"off"]"
|
||||||
|
var/blockname=assigned_blocks[block]
|
||||||
|
message_admins("[key_name_admin(src)] has toggled [M.key]'s [blockname] block [state]!")
|
||||||
|
log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!")
|
||||||
|
else
|
||||||
|
alert("Invalid mob")
|
||||||
|
|||||||
@@ -447,9 +447,13 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
|||||||
if(record_found)//Pull up their name from database records if they did have a mind.
|
if(record_found)//Pull up their name from database records if they did have a mind.
|
||||||
new_character.dna = new()//Let's first give them a new DNA.
|
new_character.dna = new()//Let's first give them a new DNA.
|
||||||
new_character.dna.unique_enzymes = record_found.fields["b_dna"]//Enzymes are based on real name but we'll use the record for conformity.
|
new_character.dna.unique_enzymes = record_found.fields["b_dna"]//Enzymes are based on real name but we'll use the record for conformity.
|
||||||
new_character.dna.SE = record_found.fields["enzymes"]//This is the default of enzymes so I think it's safe to go with.
|
|
||||||
|
// I HATE BYOND. HATE. HATE. - N3X
|
||||||
|
var/list/newSE= record_found.fields["enzymes"]
|
||||||
|
var/list/newUI = record_found.fields["identity"]
|
||||||
|
new_character.dna.SE = newSE.Copy() //This is the default of enzymes so I think it's safe to go with.
|
||||||
new_character.dna.UpdateSE()
|
new_character.dna.UpdateSE()
|
||||||
new_character.UpdateAppearance(record_found.fields["identity"])//Now we configure their appearance based on their unique identity, same as with a DNA machine or somesuch.
|
new_character.UpdateAppearance(newUI.Copy())//Now we configure their appearance based on their unique identity, same as with a DNA machine or somesuch.
|
||||||
else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile.
|
else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile.
|
||||||
new_character.dna.ready_dna(new_character)
|
new_character.dna.ready_dna(new_character)
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
continue
|
continue
|
||||||
var/datum/disease/dnaspread/D = new
|
var/datum/disease/dnaspread/D = new
|
||||||
D.strain_data["name"] = H.real_name
|
D.strain_data["name"] = H.real_name
|
||||||
D.strain_data["UI"] = H.dna.UI
|
D.strain_data["UI"] = H.dna.UI.Copy()
|
||||||
D.strain_data["SE"] = H.dna.SE
|
D.strain_data["SE"] = H.dna.SE.Copy()
|
||||||
D.carrier = 1
|
D.carrier = 1
|
||||||
D.holder = H
|
D.holder = H
|
||||||
D.affected_mob = H
|
D.affected_mob = H
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
brainmob = new(src)
|
brainmob = new(src)
|
||||||
brainmob.name = H.real_name
|
brainmob.name = H.real_name
|
||||||
brainmob.real_name = H.real_name
|
brainmob.real_name = H.real_name
|
||||||
brainmob.dna = H.dna
|
brainmob.dna = H.dna.Clone()
|
||||||
brainmob.timeofhostdeath = H.timeofdeath
|
brainmob.timeofhostdeath = H.timeofdeath
|
||||||
if(H.mind)
|
if(H.mind)
|
||||||
H.mind.transfer_to(brainmob)
|
H.mind.transfer_to(brainmob)
|
||||||
|
|||||||
@@ -366,8 +366,18 @@ proc/get_damage_icon_part(damage_state, body_part)
|
|||||||
var/add_image = 0
|
var/add_image = 0
|
||||||
var/g = "m"
|
var/g = "m"
|
||||||
if(gender == FEMALE) g = "f"
|
if(gender == FEMALE) g = "f"
|
||||||
|
// DNA2 - Drawing underlays.
|
||||||
|
for(var/datum/dna/gene/gene in dna_genes)
|
||||||
|
if(!gene.block)
|
||||||
|
continue
|
||||||
|
if(gene.is_active(src))
|
||||||
|
var/underlay=gene.OnDrawUnderlays(src,g,fat)
|
||||||
|
if(underlay)
|
||||||
|
standing.underlays += underlay
|
||||||
|
add_image = 1
|
||||||
for(var/mut in mutations)
|
for(var/mut in mutations)
|
||||||
switch(mut)
|
switch(mut)
|
||||||
|
/*
|
||||||
if(HULK)
|
if(HULK)
|
||||||
if(fat)
|
if(fat)
|
||||||
standing.underlays += "hulk_[fat]_s"
|
standing.underlays += "hulk_[fat]_s"
|
||||||
@@ -380,6 +390,7 @@ proc/get_damage_icon_part(damage_state, body_part)
|
|||||||
if(TK)
|
if(TK)
|
||||||
standing.underlays += "telekinesishead[fat]_s"
|
standing.underlays += "telekinesishead[fat]_s"
|
||||||
add_image = 1
|
add_image = 1
|
||||||
|
*/
|
||||||
if(LASER)
|
if(LASER)
|
||||||
standing.overlays += "lasereyes_s"
|
standing.overlays += "lasereyes_s"
|
||||||
add_image = 1
|
add_image = 1
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
M.real_name = src.real_name
|
M.real_name = src.real_name
|
||||||
|
|
||||||
if(src.dna)
|
if(src.dna)
|
||||||
M.dna = src.dna
|
M.dna = src.dna.Clone()
|
||||||
|
|
||||||
if(mind)
|
if(mind)
|
||||||
mind.transfer_to(M)
|
mind.transfer_to(M)
|
||||||
|
|||||||
@@ -29,10 +29,9 @@
|
|||||||
|
|
||||||
O = new species.primitive(loc)
|
O = new species.primitive(loc)
|
||||||
|
|
||||||
O.dna = dna
|
O.dna = dna.Clone()
|
||||||
//O.dna.uni_identity = "000000000000000000DC00000660004DA0A0E00"
|
|
||||||
//O.dna.struc_enzymes = "[copytext(O.dna.struc_enzymes,1,1+3*(STRUCDNASIZE-1))]BB8"
|
|
||||||
O.dna.SetSEState(MONKEYBLOCK,1)
|
O.dna.SetSEState(MONKEYBLOCK,1)
|
||||||
|
O.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF)
|
||||||
O.loc = loc
|
O.loc = loc
|
||||||
O.viruses = viruses
|
O.viruses = viruses
|
||||||
O.a_intent = "hurt"
|
O.a_intent = "hurt"
|
||||||
@@ -166,7 +165,7 @@
|
|||||||
mind.transfer_to(O)
|
mind.transfer_to(O)
|
||||||
if(O.mind.assigned_role == "Cyborg")
|
if(O.mind.assigned_role == "Cyborg")
|
||||||
O.mind.original = O
|
O.mind.original = O
|
||||||
else if(mind.special_role)
|
else if(mind&&mind.special_role)
|
||||||
O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite")
|
O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite")
|
||||||
else
|
else
|
||||||
O.key = key
|
O.key = key
|
||||||
|
|||||||
@@ -903,7 +903,7 @@ obj/item/weapon/organ/head/proc/transfer_identity(var/mob/living/carbon/human/H)
|
|||||||
brainmob = new(src)
|
brainmob = new(src)
|
||||||
brainmob.name = H.real_name
|
brainmob.name = H.real_name
|
||||||
brainmob.real_name = H.real_name
|
brainmob.real_name = H.real_name
|
||||||
brainmob.dna = H.dna
|
brainmob.dna = H.dna.Clone()
|
||||||
if(H.mind)
|
if(H.mind)
|
||||||
H.mind.transfer_to(brainmob)
|
H.mind.transfer_to(brainmob)
|
||||||
brainmob.container = src
|
brainmob.container = src
|
||||||
|
|||||||
Reference in New Issue
Block a user