mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Merge branch 'master' of https://github.com/PolarisSS13/Polaris into 12/16/2015_newwizard
This commit is contained in:
217
code/modules/xenobio2/_xeno_setup.dm
Normal file
217
code/modules/xenobio2/_xeno_setup.dm
Normal file
@@ -0,0 +1,217 @@
|
||||
//Important definitions for xenos, traits datum.
|
||||
|
||||
//Definitions for gene grouping.
|
||||
#define GENE_XENO_BIOCHEMISTRY "biochemistry"
|
||||
#define GENE_XENO_HEALTH "health"
|
||||
#define GENE_XENO_RESISTANCES "resistances"
|
||||
#define GENE_XENO_INTERNAL "internal"
|
||||
#define GENE_XENO_COLOR "color"
|
||||
#define GENE_XENO_GLOW "glow"
|
||||
#define GENE_XENO_LEARN "learn"
|
||||
#define GENE_XENO_SPEAK "speak"
|
||||
#define GENE_XENO_SPEED "speed"
|
||||
#define GENE_XENO_SPECIAL "special"
|
||||
|
||||
#define ALL_XENO_GENES list(GENE_XENO_BIOCHEMISTRY, GENE_XENO_HEALTH, GENE_XENO_RESISTANCES, GENE_XENO_INTERNAL, GENE_XENO_COLOR, GENE_XENO_LEARN, GENE_XENO_SPEAK, GENE_XENO_SPEED, GENE_XENO_SPECIAL)
|
||||
|
||||
//Definitions for traits.
|
||||
|
||||
#define TRAIT_XENO_COLOR "color"
|
||||
#define TRAIT_XENO_CHEMISTRY "chems"
|
||||
#define TRAIT_XENO_CHEMVOL "chem_vol"
|
||||
#define TRAIT_XENO_HEALTH "health"
|
||||
#define TRAIT_XENO_HUNGER "hunger"
|
||||
#define TRAIT_XENO_STARVEDAMAGE "starvedamage"
|
||||
#define TRAIT_XENO_EATS "eats"
|
||||
#define TRAIT_XENO_CHROMATIC "chrom"
|
||||
#define TRAIT_XENO_HOSTILE "hostile"
|
||||
#define TRAIT_XENO_BIOLUMESCENT "biolum"
|
||||
#define TRAIT_XENO_BIO_COLOR "biocolor"
|
||||
#define TRAIT_XENO_GLOW_STRENGTH "biostrength"
|
||||
#define TRAIT_XENO_GLOW_RANGE "biorange"
|
||||
#define TRAIT_XENO_TOXIC_CHEMS "tox_chems"
|
||||
#define TRAIT_XENO_NUTRITIONAL_CHEMS "nutr_chems"
|
||||
#define TRAIT_XENO_HEALING_CHEMS "heal_chems"
|
||||
#define TRAIT_XENO_MUTATING_CHEMS "mut_chems"
|
||||
#define TRAIT_XENO_SPEED "speed"
|
||||
#define TRAIT_XENO_COLDRES "cold_resistance"
|
||||
#define TRAIT_XENO_HEATRES "heat_resistance"
|
||||
#define TRAIT_XENO_LEARNCHANCE "learn_chance"
|
||||
#define TRAIT_XENO_CANLEARN "can_learn"
|
||||
#define TRAIT_XENO_SPEAKCHANCE "speak_chance"
|
||||
#define TRAIT_XENO_CANSPEAK "can_speak"
|
||||
#define TRAIT_XENO_STRENGTH "melee_strength"
|
||||
#define TRAIT_XENO_STR_RANGE "melee_range"
|
||||
|
||||
//Maleability defines.
|
||||
#define MAX_MALEABLE 2
|
||||
#define MINOR_MALEABLE 1
|
||||
#define MIN_MALEABLE 0
|
||||
|
||||
var/global/list/xenoChemList = list("mutationtoxin",
|
||||
"psilocybin",
|
||||
"mindbreaker",
|
||||
"impedrezene",
|
||||
"cryptobiolin",
|
||||
"space_drugs",
|
||||
"chloralhydrate",
|
||||
"stoxin",
|
||||
"mutagen",
|
||||
"lexorin",
|
||||
"pacid",
|
||||
"cyanide",
|
||||
"phoron",
|
||||
"plasticide",
|
||||
"amatoxin",
|
||||
"carbon",
|
||||
"radium",
|
||||
"sacid",
|
||||
"sugar",
|
||||
"kelotane",
|
||||
"dermaline",
|
||||
"anti_toxin",
|
||||
"dexalin",
|
||||
"synaptizine",
|
||||
"alkysine",
|
||||
"imidazoline",
|
||||
"peridaxon",
|
||||
"rezadone",
|
||||
"mutationtoxin",
|
||||
"docilitytoxin")
|
||||
|
||||
/datum/xeno/traits
|
||||
var/list/traits = list()
|
||||
var/list/chemlist = list()
|
||||
var/list/chems = list()
|
||||
var/source = "unknown"
|
||||
|
||||
/datum/xeno/traits/proc/set_trait(var/trait, var/newval)
|
||||
traits["[trait]"] = newval
|
||||
return
|
||||
|
||||
/datum/xeno/traits/proc/get_trait(var/trait)
|
||||
var/val = traits["[trait]"]
|
||||
return val
|
||||
|
||||
/datum/xeno/traits/proc/copy_traits(var/datum/xeno/traits/target)
|
||||
target.traits = traits
|
||||
target.chemlist = chemlist
|
||||
target.chems = chems
|
||||
target.source = source
|
||||
|
||||
/datum/xeno/traits/New()
|
||||
..()
|
||||
set_trait(TRAIT_XENO_COLOR, "#CACACA")
|
||||
set_trait(TRAIT_XENO_CHEMVOL, 100)
|
||||
set_trait(TRAIT_XENO_HEALTH, 20)
|
||||
set_trait(TRAIT_XENO_HUNGER, 2)
|
||||
set_trait(TRAIT_XENO_STARVEDAMAGE, 0)
|
||||
set_trait(TRAIT_XENO_EATS, 1)
|
||||
set_trait(TRAIT_XENO_CHROMATIC, 0)
|
||||
set_trait(TRAIT_XENO_HOSTILE, 0)
|
||||
set_trait(TRAIT_XENO_BIOLUMESCENT, 0)
|
||||
set_trait(TRAIT_XENO_BIO_COLOR, "#CACACA")
|
||||
set_trait(TRAIT_XENO_GLOW_STRENGTH, 0)
|
||||
set_trait(TRAIT_XENO_GLOW_RANGE, 0)
|
||||
set_trait(TRAIT_XENO_SPEED, 4)
|
||||
set_trait(TRAIT_XENO_COLDRES, 20)
|
||||
set_trait(TRAIT_XENO_HEATRES, 20)
|
||||
set_trait(TRAIT_XENO_LEARNCHANCE, 100)
|
||||
set_trait(TRAIT_XENO_CANLEARN, 1)
|
||||
set_trait(TRAIT_XENO_SPEAKCHANCE, 1)
|
||||
set_trait(TRAIT_XENO_CANSPEAK, 1)
|
||||
set_trait(TRAIT_XENO_STRENGTH, 0)
|
||||
set_trait(TRAIT_XENO_STR_RANGE, 0)
|
||||
|
||||
/datum/xeno/traits/proc/get_gene(var/genetype)
|
||||
|
||||
if(!genetype) return 0
|
||||
|
||||
var/datum/xeno/genes/G = new()
|
||||
G.genetype = genetype
|
||||
G.values = list()
|
||||
|
||||
switch(genetype)
|
||||
if(GENE_XENO_BIOCHEMISTRY)
|
||||
G.values["[TRAIT_XENO_CHEMVOL]"] = get_trait(TRAIT_XENO_CHEMVOL)
|
||||
G.chems = chems
|
||||
if(GENE_XENO_HEALTH)
|
||||
G.values["[TRAIT_XENO_HEALTH]"] = get_trait(TRAIT_XENO_HEALTH)
|
||||
G.values["[TRAIT_XENO_STRENGTH]"] = get_trait(TRAIT_XENO_STRENGTH)
|
||||
G.values["[TRAIT_XENO_STR_RANGE]"] = get_trait(TRAIT_XENO_STR_RANGE)
|
||||
if(GENE_XENO_RESISTANCES)
|
||||
G.values["[TRAIT_XENO_COLDRES]"] = get_trait(TRAIT_XENO_HEALTH)
|
||||
G.values["[TRAIT_XENO_HEATRES]"] = get_trait(TRAIT_XENO_STRENGTH)
|
||||
if(GENE_XENO_INTERNAL)
|
||||
G.values["[TRAIT_XENO_NUTRITIONAL_CHEMS]"] = get_trait(TRAIT_XENO_NUTRITIONAL_CHEMS)
|
||||
G.values["[TRAIT_XENO_HEALING_CHEMS]"] = get_trait(TRAIT_XENO_HEALING_CHEMS)
|
||||
G.values["[TRAIT_XENO_TOXIC_CHEMS]"] = get_trait(TRAIT_XENO_TOXIC_CHEMS)
|
||||
G.values["[TRAIT_XENO_MUTATING_CHEMS]"] = get_trait(TRAIT_XENO_MUTATING_CHEMS)
|
||||
if(GENE_XENO_COLOR)
|
||||
G.values["[TRAIT_XENO_COLOR]"] = get_trait(TRAIT_XENO_COLOR)
|
||||
G.values["[TRAIT_XENO_BIO_COLOR]"] = get_trait(TRAIT_XENO_BIO_COLOR)
|
||||
if(GENE_XENO_GLOW)
|
||||
G.values["[TRAIT_XENO_BIOLUMESCENT]"] = get_trait(TRAIT_XENO_BIOLUMESCENT)
|
||||
G.values["[TRAIT_XENO_GLOW_RANGE]"] = get_trait(TRAIT_XENO_GLOW_RANGE)
|
||||
G.values["[TRAIT_XENO_GLOW_STRENGTH]"] = get_trait(TRAIT_XENO_GLOW_STRENGTH)
|
||||
if(GENE_XENO_LEARN)
|
||||
G.values["[TRAIT_XENO_LEARNCHANCE]"] = get_trait(TRAIT_XENO_LEARNCHANCE)
|
||||
G.values["[TRAIT_XENO_CANLEARN]"] = get_trait(TRAIT_XENO_CANLEARN)
|
||||
if(GENE_XENO_SPEAK)
|
||||
G.values["[TRAIT_XENO_SPEAKCHANCE]"] = get_trait(TRAIT_XENO_SPEAKCHANCE)
|
||||
G.values["[TRAIT_XENO_CANSPEAK]"] = get_trait(TRAIT_XENO_CANSPEAK)
|
||||
if(GENE_XENO_SPEED)
|
||||
G.values["[TRAIT_XENO_SPEED]"] = get_trait(TRAIT_XENO_SPEED)
|
||||
if(GENE_XENO_SPECIAL)
|
||||
G.values["[TRAIT_XENO_HOSTILE]"] = get_trait(TRAIT_XENO_HOSTILE)
|
||||
G.values["[TRAIT_XENO_CHROMATIC]"] = get_trait(TRAIT_XENO_CHROMATIC)
|
||||
|
||||
return G
|
||||
|
||||
/datum/xeno/traits/proc/apply_gene(var/datum/xeno/genes/genes)
|
||||
if(!genes.genetype) return 0
|
||||
|
||||
switch(genes.genetype)
|
||||
if(GENE_XENO_BIOCHEMISTRY)
|
||||
set_trait(TRAIT_XENO_CHEMVOL, genes.values["[TRAIT_XENO_CHEMVOL]"])
|
||||
for(var/reagent in genes.chems)
|
||||
chems[reagent] = genes[reagent]
|
||||
|
||||
if(GENE_XENO_HEALTH)
|
||||
set_trait(TRAIT_XENO_HEALTH, genes.values["[TRAIT_XENO_HEALTH]"])
|
||||
set_trait(TRAIT_XENO_STRENGTH, genes.values["[TRAIT_XENO_STRENGTH]"])
|
||||
set_trait(TRAIT_XENO_STR_RANGE, genes.values["[TRAIT_XENO_STR_RANGE]"])
|
||||
if(GENE_XENO_RESISTANCES)
|
||||
set_trait(TRAIT_XENO_COLDRES, genes.values["[TRAIT_XENO_COLDRES]"])
|
||||
set_trait(TRAIT_XENO_HEATRES, genes.values["[TRAIT_XENO_HEATRES]"])
|
||||
if(GENE_XENO_INTERNAL)
|
||||
set_trait(TRAIT_XENO_NUTRITIONAL_CHEMS, genes.values["[TRAIT_XENO_NUTRITIONAL_CHEMS]"])
|
||||
set_trait(TRAIT_XENO_HEALING_CHEMS, genes.values["[TRAIT_XENO_HEALING_CHEMS]"])
|
||||
set_trait(TRAIT_XENO_TOXIC_CHEMS, genes.values["[TRAIT_XENO_TOXIC_CHEMS]"])
|
||||
set_trait(TRAIT_XENO_MUTATING_CHEMS, genes.values["[TRAIT_XENO_MUTATING_CHEMS]"])
|
||||
if(GENE_XENO_COLOR)
|
||||
set_trait(TRAIT_XENO_COLOR, genes.values["[TRAIT_XENO_COLOR]"])
|
||||
set_trait(TRAIT_XENO_BIO_COLOR, genes.values["[TRAIT_XENO_BIO_COLOR]"])
|
||||
if(GENE_XENO_GLOW)
|
||||
set_trait(TRAIT_XENO_BIOLUMESCENT, genes.values["[TRAIT_XENO_BIOLUMESCENT]"])
|
||||
set_trait(TRAIT_XENO_GLOW_RANGE, genes.values["[TRAIT_XENO_GLOW_RANGE]"])
|
||||
set_trait(TRAIT_XENO_GLOW_STRENGTH, genes.values["[TRAIT_XENO_GLOW_STRENGTH]"])
|
||||
if(GENE_XENO_LEARN)
|
||||
set_trait(TRAIT_XENO_LEARNCHANCE, genes.values["[TRAIT_XENO_LEARNCHANCE]"])
|
||||
set_trait(TRAIT_XENO_CANLEARN, genes.values["[TRAIT_XENO_CANLEARN]"])
|
||||
if(GENE_XENO_SPEAK)
|
||||
set_trait(TRAIT_XENO_SPEAKCHANCE, genes.values["[TRAIT_XENO_SPEAKCHANCE]"])
|
||||
set_trait(TRAIT_XENO_CANSPEAK, genes.values["[TRAIT_XENO_CANSPEAK]"])
|
||||
if(GENE_XENO_SPEED)
|
||||
set_trait(TRAIT_XENO_SPEED ,genes.values["[TRAIT_XENO_SPEED]"])
|
||||
if(GENE_XENO_SPECIAL)
|
||||
set_trait(TRAIT_XENO_HOSTILE, genes.values["[TRAIT_XENO_HOSTILE]"])
|
||||
set_trait(TRAIT_XENO_CHROMATIC, genes.values["[TRAIT_XENO_CHROMATIC]"])
|
||||
|
||||
/datum/xeno/genes
|
||||
var/genetype //Label for specifying what gene is used.
|
||||
var/list/values //What's going to be put into specific traits
|
||||
var/list/chems
|
||||
|
||||
|
||||
|
||||
44
code/modules/xenobio2/controller.dm
Normal file
44
code/modules/xenobio2/controller.dm
Normal file
@@ -0,0 +1,44 @@
|
||||
//Used to create the gene mask. Shamelessly stolen from the plant controller and cut down.
|
||||
|
||||
/client/proc/show_xenobio_genes()
|
||||
set category = "Debug"
|
||||
set name = "Show Xenobio Genes"
|
||||
set desc = "Prints the round's plant xenobio masks."
|
||||
|
||||
if(!holder) return
|
||||
|
||||
if(!xenobio_controller || !xenobio_controller.gene_tag_masks)
|
||||
usr << "Gene masks not set."
|
||||
return
|
||||
|
||||
for(var/mask in xenobio_controller.gene_tag_masks)
|
||||
usr << "[mask]: [xenobio_controller.gene_tag_masks[mask]]"
|
||||
|
||||
var/global/datum/controller/xenobio/xenobio_controller // Set in New().
|
||||
|
||||
/datum/controller/xenobio
|
||||
|
||||
var/list/gene_tag_masks = list() // Gene obfuscation for delicious trial and error goodness.
|
||||
|
||||
/datum/controller/xenobio/New()
|
||||
if(xenobio_controller && xenobio_controller != src)
|
||||
log_debug("Rebuilding xenobio controller.")
|
||||
qdel(xenobio_controller)
|
||||
xenobio_controller = src
|
||||
setup()
|
||||
|
||||
|
||||
/datum/controller/xenobio/proc/setup()
|
||||
|
||||
var/list/used_masks = list()
|
||||
var/list/xenobio_traits = ALL_XENO_GENES
|
||||
while(xenobio_traits && xenobio_traits.len)
|
||||
var/gene_tag = pick(xenobio_traits)
|
||||
var/gene_mask = "[uppertext(num2hex(rand(0,255)))]"
|
||||
|
||||
while(gene_mask in used_masks)
|
||||
gene_mask = "[uppertext(num2hex(rand(0,255)))]"
|
||||
|
||||
used_masks += gene_mask
|
||||
xenobio_traits -= gene_tag
|
||||
gene_tag_masks[gene_tag] = gene_mask
|
||||
195
code/modules/xenobio2/machinery/core_extractor.dm
Normal file
195
code/modules/xenobio2/machinery/core_extractor.dm
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
Here lives the slime core extractor
|
||||
This machine extracts slime cores at the cost of the slime itself.
|
||||
To create more of these slimes, stick the slime core in the extractor.
|
||||
*/
|
||||
/obj/machinery/slime/extractor
|
||||
name = "Slime extractor"
|
||||
desc = "A machine for cutting up slimes to get to their cores."
|
||||
icon = 'icons/obj/xenoarchaeology.dmi'
|
||||
icon_state = "scanner_0old"
|
||||
density = 1
|
||||
anchored = 1
|
||||
circuit = /obj/item/weapon/circuitboard/slimeextractor
|
||||
var/inuse
|
||||
var/mob/living/simple_animal/xeno/slime/occupant = null
|
||||
var/occupiedcolor = "#22FF22"
|
||||
var/emptycolor = "#FF2222"
|
||||
var/operatingcolor = "#FFFF22"
|
||||
|
||||
|
||||
/obj/machinery/slime/extractor/New()
|
||||
..()
|
||||
update_light_color()
|
||||
circuit = new circuit(src)
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/slime/extractor/attackby(var/obj/item/W, var/mob/user)
|
||||
|
||||
//Let's try to deconstruct first.
|
||||
if(istype(W, /obj/item/weapon/screwdriver) && !inuse)
|
||||
default_deconstruction_screwdriver(user, W)
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/crowbar))
|
||||
default_deconstruction_crowbar(user, W)
|
||||
return
|
||||
|
||||
if(panel_open)
|
||||
user << "<span class='warning'>Close the panel first!</span>"
|
||||
|
||||
var/obj/item/weapon/grab/G = W
|
||||
|
||||
if(!istype(G))
|
||||
return ..()
|
||||
|
||||
if(G.state < 2)
|
||||
user << "<span class='danger'>You need a better grip to do that!</span>"
|
||||
return
|
||||
|
||||
move_into_extractor(user,G.affecting)
|
||||
|
||||
/obj/machinery/slime/extractor/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.restrained())
|
||||
return
|
||||
move_into_extractor(user,target)
|
||||
|
||||
/obj/machinery/slime/extractor/proc/move_into_extractor(var/mob/user,var/mob/living/victim)
|
||||
|
||||
if(src.occupant)
|
||||
user << "<span class='danger'>The core extractor is full, empty it first!</span>"
|
||||
return
|
||||
|
||||
if(inuse)
|
||||
user << "<span class='danger'>The core extractor is locked and running, wait for it to finish.</span>"
|
||||
return
|
||||
|
||||
if(!(istype(victim, /mob/living/simple_animal/xeno/slime)) )
|
||||
user << "<span class='danger'>This is not a suitable subject for the core extractor!</span>"
|
||||
return
|
||||
|
||||
var/mob/living/simple_animal/xeno/slime/S = victim
|
||||
if(S.is_child)
|
||||
user << "<span class='danger'>This subject is not developed enough for the core extractor!</span>"
|
||||
return
|
||||
|
||||
user.visible_message("<span class='danger'>[user] starts to put [victim] into the core extractor!</span>")
|
||||
src.add_fingerprint(user)
|
||||
if(do_after(user, 30) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant)
|
||||
user.visible_message("<span class='danger'>[user] stuffs [victim] into the core extractor!</span>")
|
||||
if(victim.client)
|
||||
victim.client.perspective = EYE_PERSPECTIVE
|
||||
victim.client.eye = src
|
||||
victim.forceMove(src)
|
||||
src.occupant = victim
|
||||
update_light_color()
|
||||
|
||||
/obj/machinery/slime/extractor/proc/update_light_color()
|
||||
if(src.occupant && !(inuse))
|
||||
set_light(2, 2, occupiedcolor)
|
||||
else if(src.occupant)
|
||||
set_light(2, 2, operatingcolor)
|
||||
else
|
||||
set_light(2, 2, emptycolor)
|
||||
|
||||
/obj/machinery/slime/extractor/proc/extract_cores()
|
||||
if(!src.occupant)
|
||||
src.visible_message("\icon[src] [src] pings unhappily.")
|
||||
else if(inuse)
|
||||
return
|
||||
|
||||
inuse = 1
|
||||
update_light_color()
|
||||
spawn(30)
|
||||
icon_state = "scanner_1old"
|
||||
for(var/i=1 to occupant.cores)
|
||||
var/obj/item/xenoproduct/slime/core/C = new(src)
|
||||
C.traits = new()
|
||||
occupant.traitdat.copy_traits(C.traits)
|
||||
|
||||
C.nameVar = occupant.nameVar
|
||||
|
||||
C.create_reagents(C.traits.traits[TRAIT_XENO_CHEMVOL])
|
||||
for(var/reagent in occupant.traitdat.chems)
|
||||
C.reagents.add_reagent(reagent, occupant.traitdat.chems[reagent])
|
||||
|
||||
C.color = C.traits.traits[TRAIT_XENO_COLOR]
|
||||
if(occupant.traitdat.get_trait(TRAIT_XENO_BIOLUMESCENT))
|
||||
C.set_light(occupant.traitdat.get_trait(TRAIT_XENO_GLOW_STRENGTH),occupant.traitdat.get_trait(TRAIT_XENO_GLOW_RANGE), occupant.traitdat.get_trait(TRAIT_XENO_BIO_COLOR))
|
||||
|
||||
spawn(30)
|
||||
icon_state = "scanner_0old"
|
||||
qdel(occupant)
|
||||
occupant = null //If qdel's being slow or acting up, let's make sure we can't make more cores from this one.
|
||||
inuse = 0
|
||||
eject_contents()
|
||||
update_light_color()
|
||||
src.updateUsrDialog()
|
||||
|
||||
/obj/machinery/slime/extractor/proc/eject_slime()
|
||||
if(occupant)
|
||||
occupant.forceMove(loc)
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/slime/extractor/proc/eject_core()
|
||||
for(var/obj/thing in (contents - component_parts - circuit))
|
||||
thing.forceMove(loc)
|
||||
|
||||
/obj/machinery/slime/extractor/proc/eject_contents()
|
||||
eject_core()
|
||||
eject_slime()
|
||||
|
||||
//Here lies the UI
|
||||
/obj/machinery/slime/extractor/attack_hand(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/slime/extractor/interact(mob/user as mob)
|
||||
var/dat = ""
|
||||
if(!inuse)
|
||||
dat = {"
|
||||
<b>Slime held:</b><br>
|
||||
[occupant]<br>
|
||||
"}
|
||||
if (occupant && !(stat & (NOPOWER|BROKEN)))
|
||||
dat += "<A href='?src=\ref[src];action=extract'>Start the core extraction.</a><BR>"
|
||||
if(occupant)
|
||||
dat += "<A href='?src=\ref[src];action=eject'>Eject the slime</a><BR>"
|
||||
else
|
||||
dat += "Please wait..."
|
||||
var/datum/browser/popup = new(user, "Slime Extractor", "Slime Extractor", src)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/slime/extractor/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
switch(href_list["action"])
|
||||
if ("extract")
|
||||
extract_cores()
|
||||
if("eject")
|
||||
eject_slime()
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
//Circuit board below,
|
||||
/obj/item/weapon/circuitboard/slimeextractor
|
||||
name = T_BOARD("Slime extractor")
|
||||
build_path = "/obj/machinery/slime/extractor"
|
||||
board_type = "machine"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_BIO = 3)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/manipulator = 2,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 1,
|
||||
/obj/item/weapon/stock_parts/micro_laser = 2
|
||||
)
|
||||
|
||||
430
code/modules/xenobio2/machinery/gene_manipulators.dm
Normal file
430
code/modules/xenobio2/machinery/gene_manipulators.dm
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
This file contains:
|
||||
|
||||
Xenobiological disk:
|
||||
Holds traits that can be taken from cores and transplanted into slimes.
|
||||
|
||||
Biological Product Destructive Analyzer:
|
||||
Takes certain traits in gene grouping from a core and places them into a disk.
|
||||
|
||||
Biological genetic bombarder:
|
||||
Takes traits from a disk and replaces/adds to the genes in a xenobiological creature.
|
||||
*/
|
||||
/obj/item/weapon/disk/xenobio
|
||||
name = "biological data disk"
|
||||
desc = "A small disk used for carrying data on genetics."
|
||||
icon = 'icons/obj/hydroponics_machines.dmi'
|
||||
icon_state = "disk"
|
||||
w_class = 1.0
|
||||
|
||||
var/list/genes = list()
|
||||
var/genesource = "unknown"
|
||||
|
||||
/obj/item/weapon/disk/xenobio/attack_self(var/mob/user as mob)
|
||||
if(genes.len)
|
||||
var/choice = alert(user, "Are you sure you want to wipe the disk?", "Xenobiological Data", "No", "Yes")
|
||||
if(src && user && genes && choice && choice == "Yes" && user.Adjacent(get_turf(src)))
|
||||
user << "You wipe the disk data."
|
||||
name = initial(name)
|
||||
desc = initial(name)
|
||||
genes = list()
|
||||
genesource = "unknown"
|
||||
|
||||
/obj/item/weapon/storage/box/xenobiodisk
|
||||
name = "biological disk box"
|
||||
desc = "A box of biological data disks, apparently."
|
||||
|
||||
/obj/item/weapon/storage/box/xenobiodisk/New()
|
||||
..()
|
||||
for(var/i = 0 to 7)
|
||||
new /obj/item/weapon/disk/xenobio(src)
|
||||
|
||||
/obj/machinery/xenobio
|
||||
density = 1
|
||||
anchored = 1
|
||||
use_power = 1
|
||||
|
||||
var/obj/item/weapon/disk/xenobio/loaded_disk //Currently loaded data disk.
|
||||
|
||||
var/open = 0
|
||||
var/active = 0
|
||||
var/action_time = 5
|
||||
var/last_action = 0
|
||||
var/eject_disk = 0
|
||||
var/failed_task = 0
|
||||
var/disk_needs_genes = 0
|
||||
|
||||
/obj/machinery/xenobio/attack_ai(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/xenobio/attack_hand(mob/user as mob)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/xenobio/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(default_deconstruction_screwdriver(user, W))
|
||||
return
|
||||
if(default_deconstruction_crowbar(user, W))
|
||||
return
|
||||
if(istype(W,/obj/item/weapon/disk/xenobio))
|
||||
if(loaded_disk)
|
||||
user << "There is already a data disk loaded."
|
||||
return
|
||||
else
|
||||
var/obj/item/weapon/disk/xenobio/B = W
|
||||
|
||||
if(B.genes && B.genes.len)
|
||||
if(!disk_needs_genes)
|
||||
user << "That disk already has gene data loaded."
|
||||
return
|
||||
else
|
||||
if(disk_needs_genes)
|
||||
user << "That disk does not have any gene data loaded."
|
||||
return
|
||||
|
||||
user.drop_from_inventory(W)
|
||||
W.forceMove(src)
|
||||
loaded_disk = W
|
||||
user << "You load [W] into [src]."
|
||||
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/xenobio/process()
|
||||
|
||||
..()
|
||||
if(!active) return
|
||||
|
||||
if(world.time > last_action + action_time)
|
||||
finished_task()
|
||||
|
||||
/obj/machinery/xenobio/proc/finished_task()
|
||||
active = 0
|
||||
in_use = 0
|
||||
if(failed_task)
|
||||
failed_task = 0
|
||||
visible_message("\icon[src] [src] pings unhappily, flashing a red warning light.")
|
||||
else
|
||||
visible_message("\icon[src] [src] pings happily.")
|
||||
|
||||
if(eject_disk)
|
||||
eject_disk = 0
|
||||
if(loaded_disk)
|
||||
loaded_disk.forceMove(get_turf(src))
|
||||
visible_message("\icon[src] [src] beeps and spits out [loaded_disk].")
|
||||
loaded_disk = null
|
||||
|
||||
/obj/machinery/xenobio/extractor
|
||||
name = "biological product destructive analyzer"
|
||||
icon = 'icons/obj/hydroponics_machines.dmi'
|
||||
icon_state = "traitcopier"
|
||||
circuit = /obj/item/weapon/circuitboard/bioproddestanalyzer
|
||||
|
||||
var/obj/item/xenoproduct/product
|
||||
var/datum/xeno/traits/genetics // Currently scanned xeno genetic structure.
|
||||
var/degradation = 0 // Increments with each scan, stops allowing gene mods after a certain point.
|
||||
|
||||
/obj/machinery/xenobio/extractor/New()
|
||||
..()
|
||||
circuit = new circuit(src)
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/xenobio/extractor/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/xenoproduct))
|
||||
if(product)
|
||||
user << "There is already a xenobiological product loaded."
|
||||
return
|
||||
else
|
||||
var/obj/item/xenoproduct/B = W
|
||||
user.drop_from_inventory(B)
|
||||
B.forceMove(src)
|
||||
product = B
|
||||
user << "You load [B] into [src]."
|
||||
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/xenobio/extractor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(!user)
|
||||
return
|
||||
|
||||
var/list/data = list()
|
||||
|
||||
var/list/geneMasks[0]
|
||||
for(var/gene_tag in xenobio_controller.gene_tag_masks)
|
||||
geneMasks.Add(list(list("tag" = gene_tag, "mask" = xenobio_controller.gene_tag_masks[gene_tag])))
|
||||
data["geneMasks"] = geneMasks
|
||||
|
||||
data["activity"] = active
|
||||
data["degradation"] = degradation
|
||||
|
||||
if(loaded_disk)
|
||||
data["disk"] = 1
|
||||
else
|
||||
data["disk"] = 0
|
||||
|
||||
if(product)
|
||||
data["loaded"] = "[product.source] [product.product]"
|
||||
else
|
||||
data["loaded"] = 0
|
||||
|
||||
if(genetics)
|
||||
data["hasGenetics"] = 1
|
||||
data["sourceName"] = genetics.source
|
||||
else
|
||||
data["hasGenetics"] = 0
|
||||
data["sourceName"] = 0
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "xenobio_isolator.tmpl", "B.P.D. Analyzer UI", 470, 450)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/xenobio/proc/eject_disk()
|
||||
if(!loaded_disk) return
|
||||
loaded_disk.forceMove(loc)
|
||||
visible_message("\icon[src] [src] beeps and spits out [loaded_disk].")
|
||||
loaded_disk = null
|
||||
|
||||
/obj/machinery/xenobio/extractor/Topic(href, href_list)
|
||||
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["eject_product"])
|
||||
if(!product) return
|
||||
|
||||
product.forceMove(get_turf(src))
|
||||
visible_message("\icon[src] [src] beeps and spits out [product].")
|
||||
product = null
|
||||
|
||||
if(href_list["eject_disk"])
|
||||
eject_disk()
|
||||
|
||||
if(href_list["scan_genome"])
|
||||
|
||||
if(!product) return
|
||||
|
||||
last_action = world.time
|
||||
active = 1
|
||||
|
||||
if(product && product.product)
|
||||
genetics = product.traits
|
||||
degradation = 0
|
||||
|
||||
qdel(product)
|
||||
product = null
|
||||
|
||||
if(href_list["get_gene"])
|
||||
|
||||
if(!genetics || !loaded_disk) return
|
||||
|
||||
last_action = world.time
|
||||
active = 1
|
||||
|
||||
var/datum/xeno/genes/G = genetics.get_gene(href_list["get_gene"])
|
||||
if(!G) return
|
||||
loaded_disk.genes += G
|
||||
|
||||
loaded_disk.genesource = "[genetics.source]"
|
||||
|
||||
loaded_disk.name += " ([xenobio_controller.gene_tag_masks[href_list["get_gene"]]], [genetics.source])"
|
||||
loaded_disk.desc += " The label reads \'gene [xenobio_controller.gene_tag_masks[href_list["get_gene"]]], sampled from [genetics.source]\'."
|
||||
eject_disk = 1
|
||||
|
||||
degradation += rand(20,60)
|
||||
if(degradation >= 100)
|
||||
failed_task = 1
|
||||
genetics = null
|
||||
degradation = 0
|
||||
|
||||
if(href_list["clear_buffer"])
|
||||
if(!genetics) return
|
||||
genetics = null
|
||||
degradation = 0
|
||||
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/xenobio/editor
|
||||
name = "biological genetic bombarder"
|
||||
icon = 'icons/obj/cryogenics.dmi'
|
||||
icon_state = "cellold0"
|
||||
disk_needs_genes = 1
|
||||
circuit = /obj/item/weapon/circuitboard/biobombarder
|
||||
|
||||
var/mob/living/simple_animal/xeno/slime/occupant
|
||||
|
||||
/obj/machinery/xenobio/editor/New()
|
||||
..()
|
||||
circuit = new circuit(src)
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/xenobio/editor/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/G = W
|
||||
if(occupant)
|
||||
user << "There is already an organism loaded."
|
||||
return
|
||||
else
|
||||
if(isxeno(G.affecting))
|
||||
var/mob/living/simple_animal/xeno/X = G.affecting
|
||||
if(do_after(user, 30) && X.Adjacent(src) && user.Adjacent(src) && X.Adjacent(user) && !occupant)
|
||||
user.drop_from_inventory(G)
|
||||
X.forceMove(src)
|
||||
occupant = X
|
||||
user << "You load [X] into [src]."
|
||||
else
|
||||
user << "<span class='danger'>This specimen is incompatible with the machinery!</span>"
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/xenobio/editor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
|
||||
if(!user)
|
||||
return
|
||||
|
||||
var/list/data = list()
|
||||
|
||||
data["activity"] = active
|
||||
|
||||
if(occupant)
|
||||
data["degradation"] = occupant.stability
|
||||
else
|
||||
data["degradation"] = 0
|
||||
|
||||
if(loaded_disk && loaded_disk.genes.len)
|
||||
data["disk"] = 1
|
||||
data["sourceName"] = loaded_disk.genesource
|
||||
data["locus"] = ""
|
||||
|
||||
for(var/datum/xeno/genes/X in loaded_disk.genes)
|
||||
if(data["locus"] != "") data["locus"] += ", "
|
||||
data["locus"] += "[xenobio_controller.gene_tag_masks[X.genetype]]"
|
||||
|
||||
else
|
||||
data["disk"] = 0
|
||||
data["sourceName"] = 0
|
||||
data["locus"] = 0
|
||||
|
||||
if(occupant)
|
||||
data["loaded"] = "[occupant]"
|
||||
else
|
||||
data["loaded"] = 0
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "xenobio_editor.tmpl", "biological genetic bombarder UI", 470, 450)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/xenobio/editor/Topic(href, href_list)
|
||||
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["apply_gene"])
|
||||
if(!loaded_disk || !occupant) return
|
||||
|
||||
last_action = world.time
|
||||
active = 1
|
||||
occupant.nameVar = "modified"
|
||||
|
||||
if(prob(occupant.stability))
|
||||
failed_task = 1
|
||||
occupant.stability = 101
|
||||
|
||||
for(var/datum/xeno/genes/gene in loaded_disk.genes)
|
||||
occupant.traitdat.apply_gene(gene)
|
||||
occupant.stability += rand(5,10)
|
||||
occupant.ProcessTraits()
|
||||
|
||||
if(href_list["eject_disk"])
|
||||
eject_disk()
|
||||
|
||||
if(href_list["eject_xeno"])
|
||||
eject_xeno()
|
||||
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
/obj/machinery/xenobio/editor/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.restrained())
|
||||
return
|
||||
move_into_editor(user,target)
|
||||
|
||||
/obj/machinery/xenobio/editor/proc/move_into_editor(var/mob/user,var/mob/living/victim)
|
||||
|
||||
if(src.occupant)
|
||||
user << "<span class='danger'>The [src] is full, empty it first!</span>"
|
||||
return
|
||||
|
||||
if(in_use)
|
||||
user << "<span class='danger'>The [src] is locked and running, wait for it to finish.</span>"
|
||||
return
|
||||
|
||||
if(!(istype(victim, /mob/living/simple_animal/xeno/slime)) )
|
||||
user << "<span class='danger'>This is not a suitable subject for the [src]!</span>"
|
||||
return
|
||||
|
||||
user.visible_message("<span class='danger'>[user] starts to put [victim] into the [src]!</span>")
|
||||
src.add_fingerprint(user)
|
||||
if(do_after(user, 30) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant)
|
||||
user.visible_message("<span class='danger'>[user] stuffs [victim] into the [src]!</span>")
|
||||
if(victim.client)
|
||||
victim.client.perspective = EYE_PERSPECTIVE
|
||||
victim.client.eye = src
|
||||
victim.forceMove(src)
|
||||
occupant = victim
|
||||
|
||||
/obj/machinery/xenobio/editor/proc/eject_contents()
|
||||
eject_disk()
|
||||
eject_xeno()
|
||||
|
||||
/obj/machinery/xenobio/editor/proc/eject_xeno()
|
||||
if(occupant)
|
||||
occupant.forceMove(loc)
|
||||
occupant = null
|
||||
|
||||
/obj/item/weapon/circuitboard/bioproddestanalyzer
|
||||
name = T_BOARD("biological product destructive analyzer")
|
||||
build_path = "/obj/machinery/xenobio/extractor"
|
||||
board_type = "machine"
|
||||
origin_tech = list(TECH_DATA = 4, TECH_BIO = 4)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/manipulator = 2,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 1,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 3
|
||||
)
|
||||
|
||||
/obj/item/weapon/circuitboard/biobombarder
|
||||
name = T_BOARD("biological genetic bombarder")
|
||||
build_path = "/obj/machinery/xenobio/editor"
|
||||
board_type = "machine"
|
||||
origin_tech = list(TECH_DATA = 4, TECH_BIO = 4)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/manipulator = 2,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 2
|
||||
)
|
||||
|
||||
146
code/modules/xenobio2/machinery/injector.dm
Normal file
146
code/modules/xenobio2/machinery/injector.dm
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
This file contains:
|
||||
|
||||
Manual Injector:
|
||||
Manually injects chemicals into a xenobiological creature from a linked machine.
|
||||
|
||||
*/
|
||||
/obj/machinery/xenobio2/manualinjector
|
||||
name = "biological injector"
|
||||
desc = "Injects biological organisms that are inserted with the contents of an inserted beaker at the command of a remote computer."
|
||||
density = 1
|
||||
anchored = 1
|
||||
use_power = 1
|
||||
icon = 'icons/obj/biogenerator.dmi'
|
||||
icon_state = "biogen-work"
|
||||
var/mob/living/occupant
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker
|
||||
var/obj/machinery/computer/xenobio2/computer
|
||||
|
||||
circuit = /obj/item/weapon/circuitboard/xenobioinjectormachine
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/New()
|
||||
..()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
reagents = R
|
||||
R.my_atom = src
|
||||
beaker = new /obj/item/weapon/reagent_containers/glass/beaker(src)
|
||||
circuit = new circuit(src)
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/update_icon()
|
||||
if(beaker)
|
||||
if(occupant)
|
||||
icon_state = "biogen-stand"
|
||||
else
|
||||
icon_state = "biogen-work"
|
||||
else
|
||||
icon_state = "biogen-empty"
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.restrained())
|
||||
return
|
||||
move_into_injector(user,target)
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/proc/move_into_injector(var/mob/user,var/mob/living/victim)
|
||||
if(src.occupant)
|
||||
user << "<span class='danger'>The injector is full, empty it first!</span>"
|
||||
return
|
||||
|
||||
if(!(istype(victim, /mob/living/simple_animal/xeno)) && !emagged)
|
||||
user << "<span class='danger'>This is not a suitable subject for the injector!</span>"
|
||||
return
|
||||
|
||||
user.visible_message("<span class='danger'>[user] starts to put [victim] into the injector!</span>")
|
||||
src.add_fingerprint(user)
|
||||
if(do_after(user, 30) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant)
|
||||
user.visible_message("<span class='danger'>[user] stuffs [victim] into the injector!</span>")
|
||||
if(victim.client)
|
||||
victim.client.perspective = EYE_PERSPECTIVE
|
||||
victim.client.eye = src
|
||||
victim.forceMove(src)
|
||||
src.occupant = victim
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/proc/eject_contents()
|
||||
eject_xeno()
|
||||
eject_beaker()
|
||||
return
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/proc/eject_xeno()
|
||||
if(occupant)
|
||||
occupant.forceMove(loc)
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/proc/eject_beaker()
|
||||
if(beaker)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B = beaker
|
||||
B.loc = loc
|
||||
beaker = null
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/proc/inject_reagents()
|
||||
if(!occupant)
|
||||
return
|
||||
if(isxeno(occupant))
|
||||
var/mob/living/simple_animal/xeno/X = occupant
|
||||
beaker.reagents.trans_to_holder(X.reagents, computer.transfer_amount, 1, 0)
|
||||
else
|
||||
beaker.reagents.trans_to_mob(occupant, computer.transfer_amount)
|
||||
|
||||
/obj/machinery/xenobio2/manualinjector/attackby(var/obj/item/W, var/mob/user)
|
||||
|
||||
//Let's try to deconstruct first.
|
||||
if(istype(W, /obj/item/weapon/screwdriver))
|
||||
default_deconstruction_screwdriver(user, W)
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/crowbar) && !occupant)
|
||||
default_deconstruction_crowbar(user, W)
|
||||
return
|
||||
|
||||
//are you smashing a beaker in me? Well then insert that shit!
|
||||
if(istype(W, /obj/item/weapon/reagent_containers/glass/beaker))
|
||||
beaker = W
|
||||
user.drop_from_inventory(W)
|
||||
W.loc = src
|
||||
return
|
||||
|
||||
//Did you want to link it?
|
||||
if(istype(W, /obj/item/device/multitool))
|
||||
var/obj/item/device/multitool/P = W
|
||||
if(P.connectable)
|
||||
if(istype(P.connectable, /obj/machinery/computer/xenobio2))
|
||||
var/obj/machinery/computer/xenobio2/C = P.connectable
|
||||
computer = C
|
||||
C.injector = src
|
||||
user << "<span class='warning'> You link the [src] to the [P.connectable]!</span>"
|
||||
else
|
||||
user << "<span class='warning'> You store the [src] in the [P]'s buffer!</span>"
|
||||
P.connectable = src
|
||||
return
|
||||
|
||||
if(panel_open)
|
||||
user << "<span class='warning'>Close the panel first!</span>"
|
||||
|
||||
var/obj/item/weapon/grab/G = W
|
||||
|
||||
if(!istype(G))
|
||||
return ..()
|
||||
|
||||
if(G.state < 2)
|
||||
user << "<span class='danger'>You need a better grip to do that!</span>"
|
||||
return
|
||||
|
||||
move_into_injector(user,G.affecting)
|
||||
|
||||
|
||||
/obj/item/weapon/circuitboard/xenobioinjectormachine
|
||||
name = T_BOARD("biological injector")
|
||||
build_path = "/obj/machinery/xenobio2/manualinjector"
|
||||
board_type = "machine"
|
||||
origin_tech = list() //To be filled,
|
||||
req_components = list() //To be filled,
|
||||
114
code/modules/xenobio2/machinery/injector_computer.dm
Normal file
114
code/modules/xenobio2/machinery/injector_computer.dm
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
This file contains:
|
||||
|
||||
Manual Injector:
|
||||
Manually injects chemicals into a xenobiological creature from a linked machine.
|
||||
|
||||
*/
|
||||
/obj/machinery/computer/xenobio2
|
||||
name = "injector control console"
|
||||
desc = "Used to control mechanized biological injectors."
|
||||
icon_keyboard = "med_key"
|
||||
icon_screen = "dna"
|
||||
light_color = "#315ab4"
|
||||
use_power = 1
|
||||
idle_power_usage = 250
|
||||
active_power_usage = 500
|
||||
circuit = /obj/item/weapon/circuitboard/xenobio2computer
|
||||
var/obj/machinery/xenobio2/manualinjector/injector
|
||||
var/transfer_amount
|
||||
var/active
|
||||
|
||||
/obj/machinery/computer/xenobio2/Destroy()
|
||||
..()
|
||||
injector.computer = null
|
||||
|
||||
/obj/machinery/computer/xenobio2/attack_hand(mob/user)
|
||||
if(..())
|
||||
return 1
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/xenobio2/attackby(var/obj/item/W, var/mob/user)
|
||||
|
||||
//Did you want to link it?
|
||||
if(istype(W, /obj/item/device/multitool))
|
||||
var/obj/item/device/multitool/P = W
|
||||
if(P.connectable)
|
||||
if(istype(P.connectable, /obj/machinery/xenobio2/manualinjector))
|
||||
var/obj/machinery/xenobio2/manualinjector/I = P.connectable
|
||||
injector = I
|
||||
I.computer = src
|
||||
user << "<span class='warning'> You link the [src] to the [P.connectable]!</span>"
|
||||
else
|
||||
user << "<span class='warning'> You store the [src] in the [P]'s buffer!</span>"
|
||||
P.connectable = src
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/xenobio2/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(!user)
|
||||
return
|
||||
if(!injector)
|
||||
return
|
||||
|
||||
var/list/data = list()
|
||||
|
||||
data["activity"] = active
|
||||
data["beaker"] = injector.beaker
|
||||
if(injector.occupant)
|
||||
data["occupied"] = 1
|
||||
if(isxeno(injector.occupant))
|
||||
var/mob/living/simple_animal/xeno/X = injector.occupant
|
||||
data["compatible"] = 1
|
||||
data["instability"] = 100 * (X.mut_level / X.mut_max)
|
||||
else
|
||||
data["compatible"] = null
|
||||
|
||||
if(injector.beaker)
|
||||
data["reagentAmount"] = injector.beaker.reagents.total_volume
|
||||
data["reagentMax"] = injector.beaker.reagents.maximum_volume
|
||||
data["reagentMin"] = 0
|
||||
else
|
||||
data["reagentAmount"] = null
|
||||
data["reagentMax"] = 1
|
||||
data["reagentMin"] = 0
|
||||
|
||||
if(injector.occupant)
|
||||
data["occupantHealth"] = injector.occupant.health
|
||||
data["occupantHealthMax"] = injector.occupant.maxHealth
|
||||
else
|
||||
data["occupantHealth"] = null
|
||||
data["occupantHealthMax"] = null
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "xenobio_computer.tmpl", "Injector Control Console UI", 470, 450)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/computer/xenobio2/Topic(href, href_list)
|
||||
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["inject_target"])
|
||||
active = 1
|
||||
spawn(5)
|
||||
injector.inject_reagents()
|
||||
active = 0
|
||||
if(href_list["eject_occupant"])
|
||||
injector.eject_xeno()
|
||||
|
||||
if(href_list["eject_beaker"])
|
||||
injector.eject_beaker()
|
||||
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
/obj/item/weapon/circuitboard/xenobio2computer
|
||||
name = T_BOARD("injector control console")
|
||||
build_path = "/obj/item/weapon/circuitboard/xenobio2computer"
|
||||
board_type = "computer"
|
||||
origin_tech = list() //To be filled,
|
||||
151
code/modules/xenobio2/machinery/slime_replicator.dm
Normal file
151
code/modules/xenobio2/machinery/slime_replicator.dm
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
Here lives the slime replicator
|
||||
This machine consumes cores to create a slime.
|
||||
To create more of these cores, stick the slime core in the extractor.
|
||||
*/
|
||||
/obj/machinery/slime/replicator
|
||||
name = "slime core growth apparatus"
|
||||
desc = "A machine for creating slimes from cores. Amazing!"
|
||||
icon = 'icons/obj/xenoarchaeology.dmi'
|
||||
icon_state = "restruct_0"
|
||||
density = 1
|
||||
anchored = 1
|
||||
circuit = /obj/item/weapon/circuitboard/slimereplicator
|
||||
var/obj/item/xenoproduct/slime/core/core = null
|
||||
var/inuse
|
||||
var/occupiedcolor = "#22FF22"
|
||||
var/emptycolor = "#FF2222"
|
||||
var/operatingcolor = "#FFFF22"
|
||||
|
||||
/obj/machinery/slime/replicator/New()
|
||||
..()
|
||||
circuit = new circuit(src)
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
|
||||
RefreshParts()
|
||||
update_light_color()
|
||||
|
||||
|
||||
/obj/machinery/slime/replicator/attackby(var/obj/item/W, var/mob/user)
|
||||
//Let's try to deconstruct first.
|
||||
if(istype(W, /obj/item/weapon/screwdriver) && !inuse)
|
||||
default_deconstruction_screwdriver(user, W)
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/crowbar))
|
||||
default_deconstruction_crowbar(user, W)
|
||||
return
|
||||
|
||||
var/obj/item/xenoproduct/slime/core/G = W
|
||||
|
||||
if(!istype(G))
|
||||
return ..()
|
||||
|
||||
if(core)
|
||||
user << "<span class='warning'>[src] is already filled!</span>"
|
||||
return
|
||||
if(panel_open)
|
||||
user << "<span class='warning'>Close the panel first!</span>"
|
||||
core = G
|
||||
user.drop_from_inventory(G)
|
||||
G.forceMove(src)
|
||||
update_light_color()
|
||||
|
||||
/obj/machinery/slime/replicator/proc/update_light_color()
|
||||
if(src.core && !(inuse))
|
||||
set_light(2, 2, occupiedcolor)
|
||||
else if(src.core)
|
||||
set_light(2, 2, operatingcolor)
|
||||
else
|
||||
set_light(2, 2, emptycolor)
|
||||
|
||||
/obj/machinery/slime/replicator/proc/replicate_slime()
|
||||
if(!src.core)
|
||||
src.visible_message("\icon[src] [src] pings unhappily.")
|
||||
else if(inuse)
|
||||
return
|
||||
|
||||
inuse = 1
|
||||
update_light_color()
|
||||
icon_state = "restruct_1"
|
||||
spawn(30)
|
||||
var/mob/living/simple_animal/xeno/slime/S = new(src)
|
||||
S.traitdat = new() //New instance, so that if the core is deleted, the slime retains a trait datum.
|
||||
S.nameVar = core.nameVar
|
||||
S.name = "[S.nameVar] baby slime"
|
||||
core.traits.copy_traits(S.traitdat)
|
||||
S.ProcessTraits()
|
||||
spawn(30)
|
||||
qdel(core)
|
||||
core = null //If qdel's being a bit slow or acting up, let's just make sure we can't clone the core.
|
||||
inuse = 0
|
||||
eject_slime()
|
||||
icon_state = "restruct_0"
|
||||
update_light_color()
|
||||
src.updateUsrDialog()
|
||||
|
||||
/obj/machinery/slime/replicator/proc/eject_slime()
|
||||
for(var/mob/thing in contents)
|
||||
thing.forceMove(loc)
|
||||
|
||||
/obj/machinery/slime/replicator/proc/eject_core()
|
||||
if(core)
|
||||
core.forceMove(loc)
|
||||
core = null
|
||||
|
||||
/obj/machinery/slime/replicator/proc/eject_contents()
|
||||
eject_slime()
|
||||
eject_core()
|
||||
|
||||
//Here lies the UI
|
||||
/obj/machinery/slime/replicator/attack_hand(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/slime/replicator/interact(mob/user as mob)
|
||||
var/dat = ""
|
||||
if(!inuse)
|
||||
dat = {"
|
||||
<b>Slime core container holds:</b><br>
|
||||
[core]<br>
|
||||
"}
|
||||
if (core && !(stat & (NOPOWER|BROKEN)))
|
||||
dat += "<A href='?src=\ref[src];action=replicate'>Start the replication process</a><BR>"
|
||||
if(core)
|
||||
dat += "<A href='?src=\ref[src];action=eject'>Eject the core</a><BR>"
|
||||
else
|
||||
dat += "Please wait..."
|
||||
var/datum/browser/popup = new(user, "Slime Replicator", "Slime Replicator", src)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/slime/replicator/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
switch(href_list["action"])
|
||||
if ("replicate")
|
||||
replicate_slime()
|
||||
if("eject")
|
||||
eject_core()
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
//Circuit board below,
|
||||
/obj/item/weapon/circuitboard/slimereplicator
|
||||
name = T_BOARD("Slime replicator")
|
||||
build_path = "/obj/machinery/slime/replicator"
|
||||
board_type = "machine"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_BIO = 3)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/manipulator = 2,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 1,
|
||||
/obj/item/weapon/stock_parts/micro_laser = 1
|
||||
)
|
||||
|
||||
|
||||
55
code/modules/xenobio2/mob/slime/slime life.dm
Normal file
55
code/modules/xenobio2/mob/slime/slime life.dm
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Slime specific life events go here.
|
||||
*/
|
||||
#define HAPPYLEVEL 200
|
||||
#define ANGRYLEVEL 10
|
||||
/mob/living/simple_animal/xeno/slime/Life()
|
||||
. = ..()
|
||||
if(..())
|
||||
if(health)
|
||||
if(is_child)
|
||||
if(nutrition >= 275)
|
||||
growthcounter++
|
||||
nutrition -= hunger_factor
|
||||
if(nutrition <= 75)
|
||||
growthcounter--
|
||||
if(growthcounter >= growthpoint)
|
||||
src.GrowUp()
|
||||
|
||||
else
|
||||
if(nutrition < 0)
|
||||
nutrition = 0
|
||||
if((prob(10) && !emote_on)) //Slimes might display their food-based emotions over time.
|
||||
var/image/I = new(src.icon)
|
||||
I.color = "#FFFFFF"
|
||||
I.layer = src.layer + 0.2
|
||||
if((nutrition >= HAPPYLEVEL))
|
||||
if((nutrition >= 1.5 * HAPPYLEVEL))
|
||||
I.icon_state = "aslime-:33"
|
||||
else
|
||||
I.icon_state = "aslime-:3"
|
||||
|
||||
else if((nutrition > ANGRYLEVEL))
|
||||
if((nutrition >= 10 * ANGRYLEVEL))
|
||||
I.icon_state = "aslime-pout"
|
||||
else if((nutrition >= 5 * ANGRYLEVEL))
|
||||
I.icon_state = "aslime-sad"
|
||||
else
|
||||
I.icon_state = "aslime-angry"
|
||||
overlays += I
|
||||
emote_on = 1
|
||||
spawn(30)
|
||||
GenerateAdultIcon()
|
||||
emote_on = null
|
||||
|
||||
else
|
||||
if(is_child)
|
||||
icon_state = "slime baby dead"
|
||||
else
|
||||
overlays.Cut()
|
||||
icon_state = "slime adult dead"
|
||||
color = traitdat.traits[TRAIT_XENO_COLOR]
|
||||
|
||||
return 0 //Everything worked okay
|
||||
|
||||
return //xeno/Life() returned 0.
|
||||
129
code/modules/xenobio2/mob/slime/slime procs.dm
Normal file
129
code/modules/xenobio2/mob/slime/slime procs.dm
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
Slime specific procs go here.
|
||||
*/
|
||||
#define SHINYOVERLAY 0
|
||||
#define LIGHTOVERLAY 1
|
||||
#define MAXOVERLAY 2 //Should be 1 + last overlay, to give the chance for matte slimes
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/RandomizeTraits()
|
||||
traitdat.traits[TRAIT_XENO_COLDRES] = rand(30,270)
|
||||
traitdat.traits[TRAIT_XENO_HEATRES] = rand(30,270)
|
||||
traitdat.traits[TRAIT_XENO_CHEMVOL] = round(rand(20,40)) //Wow, a slime core with the capacity to hold 2/3rd's a beaker's worth of chemicals.
|
||||
traitdat.traits[TRAIT_XENO_HEALTH] = round(rand(50, 75))
|
||||
traitdat.traits[TRAIT_XENO_HUNGER] = rand(1, 20)
|
||||
traitdat.traits[TRAIT_XENO_STARVEDAMAGE] = rand(1, 4)
|
||||
traitdat.traits[TRAIT_XENO_EATS] = prob(95) //Odds are, that thing'll need to eat.
|
||||
traitdat.traits[TRAIT_XENO_HOSTILE] = prob(60) //Let's increase this probabilty.
|
||||
if(prob(10))
|
||||
traitdat.traits[TRAIT_XENO_CHROMATIC] = 1
|
||||
traitdat.traits[TRAIT_XENO_HOSTILE] = 0
|
||||
traitdat.traits[TRAIT_XENO_GLOW_STRENGTH] = round(rand(1,3))
|
||||
traitdat.traits[TRAIT_XENO_GLOW_RANGE] = round(rand(1,3))
|
||||
traitdat.traits[TRAIT_XENO_STRENGTH] = round(rand(4,9))
|
||||
traitdat.traits[TRAIT_XENO_STR_RANGE] =round(rand(0,2))
|
||||
traitdat.traits[TRAIT_XENO_CANLEARN] = prob(68)
|
||||
traitdat.traits[TRAIT_XENO_SPEED] = round(rand(-10,10))
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/RandomChemicals()
|
||||
..()
|
||||
if(prob(40))
|
||||
var/hasMutToxin
|
||||
for(var/R in traitdat.chems)
|
||||
if(R == "mutationtoxin")
|
||||
hasMutToxin = 1
|
||||
var/chemamount
|
||||
if(hasMutToxin)
|
||||
var/list/chemchoices = (xenoChemList - traitdat.chems)
|
||||
|
||||
var/chemtype = pick(chemchoices)
|
||||
chemamount = rand(1,5)
|
||||
traitdat.chems[chemtype] = chemamount
|
||||
else
|
||||
chemamount = rand(1,5)
|
||||
traitdat.chems["mutationtoxin"] = chemamount
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/proc/GrowUp()
|
||||
GenerateAdult()
|
||||
|
||||
maxHealth = traitdat.get_trait(TRAIT_XENO_HEALTH)
|
||||
health = maxHealth
|
||||
is_child = 0
|
||||
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/Mutate()
|
||||
..()
|
||||
cores = round(rand(1,9))
|
||||
if(is_child)
|
||||
RandomizeTraits()
|
||||
GenerateChild()
|
||||
else
|
||||
GenerateAdult()
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/proc/GenerateChild()
|
||||
overlays.Cut()
|
||||
name = "[nameVar] baby slime"
|
||||
real_name = "[nameVar] baby slime"
|
||||
desc = "A shifting blob of [nameVar] goo."
|
||||
icon_state = "slime baby"
|
||||
icon_living = "slime baby"
|
||||
icon_dead = "slime baby dead"
|
||||
color = traitdat.traits[TRAIT_XENO_COLOR]
|
||||
maxHealth = traitdat.traits[TRAIT_XENO_HEALTH]/2
|
||||
health = maxHealth
|
||||
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/proc/GenerateAdult()
|
||||
overlays.Cut()
|
||||
name = "[nameVar] slime"
|
||||
real_name = "[nameVar] slime"
|
||||
desc = "A shifting mass of [nameVar] goo."
|
||||
color = ""
|
||||
icon_state = ""
|
||||
overlay = round(rand(0, MAXOVERLAY))
|
||||
GenerateAdultIcon()
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/proc/GenerateAdultIcon() //Hack and slash adventure game to make slimes have no color on light effects later
|
||||
overlays.Cut()
|
||||
var/image/Img = new(src.icon)
|
||||
Img.icon_state = "slime adult"
|
||||
Img.color = traitdat.traits[TRAIT_XENO_COLOR]
|
||||
Img.layer = src.layer
|
||||
overlays += Img
|
||||
|
||||
switch(overlay)
|
||||
if(SHINYOVERLAY)
|
||||
var/image/I = new(src.icon)
|
||||
I.icon = src.icon
|
||||
I.icon_state = "slime shiny"
|
||||
I.layer = src.layer + 0.1
|
||||
I.color = "#FFFFFF"
|
||||
overlays += I
|
||||
if(LIGHTOVERLAY)
|
||||
var/image/I = new(src.icon)
|
||||
I.icon = src.icon
|
||||
I.icon_state = ""
|
||||
I.icon_state = "slime light"
|
||||
I.layer = src.layer + 0.1
|
||||
I.color = "#FFFFFF"
|
||||
overlays += I
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/handle_reagents()
|
||||
if(!stasis)
|
||||
if(!reagents)
|
||||
return
|
||||
if(reagents.total_volume <= 0)
|
||||
return
|
||||
if(reagents.has_reagent("docilitytoxin")) //Toxin that makes them docile? Good for quelling angry mobs.
|
||||
hostile = 0
|
||||
traitdat.traits[TRAIT_XENO_HOSTILE] = 0
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/ProcessTraits()
|
||||
..()
|
||||
if(is_child)
|
||||
GenerateChild()
|
||||
else
|
||||
GenerateAdult()
|
||||
|
||||
94
code/modules/xenobio2/mob/slime/slime.dm
Normal file
94
code/modules/xenobio2/mob/slime/slime.dm
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Slime definitions, Life and New live here.
|
||||
*/
|
||||
/mob/living/simple_animal/xeno/slime //Adult values are found here
|
||||
nameVar = "grey" //When mutated, nameVar might change.
|
||||
desc = "A shifting, mass of goo."
|
||||
faction = "slime"
|
||||
speak_emote = list("garbles", "chirps", "blurbles")
|
||||
colored = 1
|
||||
color = "#CACACA"
|
||||
icon = 'icons/mob/slime2.dmi'
|
||||
icon_state = "slime adult"
|
||||
icon_living = "slime adult"
|
||||
icon_dead = "slime adult dead"
|
||||
internal_vol = 200
|
||||
mut_max = 50
|
||||
mutable = COLORMUT
|
||||
var/is_child = 1
|
||||
var/cores = 3
|
||||
var/growthcounter = 0
|
||||
var/growthpoint = 50 //At what point they grow up.
|
||||
var/shiny = 0
|
||||
move_to_delay = 17 //Slimes shouldn't be able to go faster than humans.
|
||||
default_chems = list("slimejelly" = 5)
|
||||
attacktext = "absorbed some of"
|
||||
response_help = "pats"
|
||||
response_disarm = "tries to stop"
|
||||
response_harm = "hits"
|
||||
|
||||
var/emote_on = null
|
||||
|
||||
maleable = MAX_MALEABLE
|
||||
|
||||
//Slimes can speak all of the languages, oh no!
|
||||
universal_speak = 1
|
||||
speak_chance = 1
|
||||
speak = list("Hello?",
|
||||
"Where is this going?",
|
||||
"What is that?",
|
||||
"What is in the box?",
|
||||
"Cargo.",
|
||||
"Transport?",
|
||||
"Special?",
|
||||
"Slime?")
|
||||
|
||||
//Overlay information
|
||||
var/overlay = 1 // 1 = normal lighting, 0 = shiny, 2 = too shiny, -1 = no overlay
|
||||
|
||||
chemreact = list( "nutriment" = list("nutr" = 0.5),
|
||||
"radium" = list("toxic" = 0.3, "mut" = 1),
|
||||
"mutagen" = list("nutr" = 0.4, "mut" = 2),
|
||||
"water" = list("nutr" = -0.1),
|
||||
"milk" = list("nutr" = 0.3),
|
||||
"sacid" = list("toxic" = 1),
|
||||
"pacid" = list("toxic" = 2),
|
||||
"chlorine" = list("toxic" = 0.5),
|
||||
"ammonia" = list("toxic" = 0.5),
|
||||
"sodawater" = list("toxic" = 0.1, "nutr" = -0.1),
|
||||
"beer" = list("nutr" = 0.6),
|
||||
"diethylamine" = list("nutr" = 0.9),
|
||||
"sugar" = list("toxic" = 0.4, "nutr" = 0.2),
|
||||
"eznutrient" = list("nutr" = 0.8),
|
||||
"cryoxadone" = list("toxic" = 0.4),
|
||||
"flourine" = list("toxic" = 0.1),
|
||||
"robustharvest" = list("nutr" = 1.5),
|
||||
"glucose" = list("nutr" = 0.5),
|
||||
"blood" = list("nutr" = 0.75, "toxic" = 0.05, "mut" = 0.45),
|
||||
"fuel" = list("toxic" = 0.4),
|
||||
"toxin" = list("toxic" = 0.5),
|
||||
"carpotoxin" = list("toxic" = 1, "mut" = 1.5),
|
||||
"phoron" = list("toxic" = 1.5, "mut" = 0.03),
|
||||
"virusfood" = list("nutr" = 1.5, "mut" = 0.32),
|
||||
"cyanide" = list("toxic" = 3.5),
|
||||
"slimejelly" = list("nutr" = 0.5),
|
||||
"amutationtoxin" = list("toxic" = 0.1, "heal" = 1.5, "mut" = 3),
|
||||
"mutationtoxin" = list("toxic" = 0.1, "heal" = 1, "mut" = 1.5),
|
||||
"gold" = list("heal" = 0.3, "nutr" = 0.7, "mut" = 0.3),
|
||||
"uranium" = list("heal" = 0.3, "toxic" = 0.7, "mut" = 1.2),
|
||||
"glycerol" = list("nutr" = 0.6),
|
||||
"woodpulp" = list("heal" = 0.1, "nutr" = 0.7),
|
||||
"docilitytoxin" = list("nutr" = 0.3) )
|
||||
|
||||
/mob/living/simple_animal/xeno/slime/New()
|
||||
..()
|
||||
for(var/datum/language/L in (typesof(/datum/language) - /datum/language))
|
||||
languages += L
|
||||
speak += "[station_name()]?"
|
||||
traitdat.source = "Slime"
|
||||
resistances[BURN] = 4
|
||||
resistances[BRUTE] = 0.2
|
||||
resistances[TOX] = 1.5
|
||||
GenerateChild()
|
||||
return 1
|
||||
|
||||
12
code/modules/xenobio2/mob/slime/slime_core.dm
Normal file
12
code/modules/xenobio2/mob/slime/slime_core.dm
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Slime core lives here.
|
||||
*/
|
||||
/obj/item/xenoproduct/slime/core
|
||||
name = "slime core"
|
||||
desc = "Gooey."
|
||||
icon = 'icons/mob/slime2.dmi'
|
||||
icon_state = "slime extract"
|
||||
source = "Slime"
|
||||
product = "core"
|
||||
|
||||
|
||||
65
code/modules/xenobio2/mob/slime/slime_monkey.dm
Normal file
65
code/modules/xenobio2/mob/slime/slime_monkey.dm
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Slime cube lives here.
|
||||
*/
|
||||
/obj/item/slime_cube
|
||||
name = "slimy monkey cube"
|
||||
desc = "Wonder what might come out of this."
|
||||
icon = 'icons/mob/slime2.dmi'
|
||||
icon_state = "slime cube"
|
||||
var/searching = 0
|
||||
|
||||
/obj/item/slime_cube/attack_self(mob/user as mob)
|
||||
if(!searching)
|
||||
user << "<span class='warning'>You stare at the slimy cube, watching as some activity occurs.</span>"
|
||||
icon_state = "slime cube active"
|
||||
searching = 1
|
||||
request_player()
|
||||
spawn(600) reset_search()
|
||||
|
||||
/obj/item/slime_cube/proc/request_player()
|
||||
for(var/mob/observer/dead/O in player_list)
|
||||
if(!O.MayRespawn())
|
||||
continue
|
||||
if(O.client)
|
||||
if(O.client.prefs.be_special & BE_ALIEN)
|
||||
question(O.client)
|
||||
|
||||
/obj/item/slime_cube/proc/question(var/client/C)
|
||||
spawn(0)
|
||||
if(!C) return
|
||||
var/response = alert(C, "Someone is requesting a soul for a promethean. Would you like to play as one?", "Promethean request", "Yes", "No", "Never for this round")
|
||||
if(response == "Yes")
|
||||
response = alert(C, "Are you sure you want to play as a promethean?", "Promethean request", "Yes", "No")
|
||||
if(!C || 2 == searching) return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located.
|
||||
if(response == "Yes")
|
||||
transfer_personality(C.mob)
|
||||
else if (response == "Never for this round")
|
||||
C.prefs.be_special ^= BE_ALIEN
|
||||
|
||||
/obj/item/slime_cube/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
|
||||
icon_state = "slime cube"
|
||||
if(searching == 1)
|
||||
searching = 0
|
||||
var/turf/T = get_turf_or_move(src.loc)
|
||||
for (var/mob/M in viewers(T))
|
||||
M.show_message("<span class='warning'>The activity in the cube dies down. Maybe it will spark another time.</span>")
|
||||
|
||||
/obj/item/slime_cube/proc/transfer_personality(var/mob/candidate)
|
||||
announce_ghost_joinleave(candidate, 0, "They are a promethean now.")
|
||||
src.searching = 2
|
||||
var/mob/living/carbon/human/S = new(get_turf(src))
|
||||
S.client = candidate.client
|
||||
S. << "<b>You are a promethean, brought into existence on [station_name()].</b>"
|
||||
S.mind.assigned_role = "Promethean"
|
||||
S.set_species("Promethean")
|
||||
S.shapeshifter_set_colour("#05FF9B")
|
||||
for(var/mob/M in viewers(get_turf_or_move(loc)))
|
||||
M.show_message("<span class='warning'>The monkey cube suddenly takes the shape of a humanoid!</span>")
|
||||
var/newname = sanitize(input(S, "You are a Promethean. Would you like to change your name to something else?", "Name change") as null|text, MAX_NAME_LEN)
|
||||
if (newname)
|
||||
S.real_name = newname
|
||||
S.name = S.real_name
|
||||
S.dna.real_name = newname
|
||||
if(S.mind) S.mind.name = S.name
|
||||
qdel(src)
|
||||
|
||||
165
code/modules/xenobio2/mob/xeno procs.dm
Normal file
165
code/modules/xenobio2/mob/xeno procs.dm
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Basic definition of creatures for Xenobiology
|
||||
|
||||
Includes:
|
||||
Proc for metabolism
|
||||
Proc for mutating
|
||||
Procs for copying speech, if applicable
|
||||
Procs for targeting
|
||||
*/
|
||||
/mob/living/simple_animal/xeno/proc/ProcessTraits()
|
||||
if(maleable >= MAX_MALEABLE)
|
||||
maxHealth = traitdat.get_trait(TRAIT_XENO_HEALTH)
|
||||
health = maxHealth
|
||||
if(traitdat.chemlist.len) //Let's make sure that this has a length.
|
||||
chemreact = traitdat.chemlist
|
||||
else
|
||||
traitdat.chemlist = chemreact
|
||||
chromatic = traitdat.traits[TRAIT_XENO_CHROMATIC]
|
||||
if(maleable >= MINOR_MALEABLE)
|
||||
if(colored)
|
||||
color = traitdat.traits[TRAIT_XENO_COLOR]
|
||||
speed = traitdat.traits[TRAIT_XENO_SPEED]
|
||||
hunger_factor = traitdat.traits[TRAIT_XENO_HUNGER]
|
||||
starve_damage = traitdat.traits[TRAIT_XENO_STARVEDAMAGE]
|
||||
minbodytemp = T20C - traitdat.traits[TRAIT_XENO_COLDRES]
|
||||
maxbodytemp = T20C + traitdat.traits[TRAIT_XENO_HEATRES]
|
||||
|
||||
if(traitdat.traits[TRAIT_XENO_BIOLUMESCENT])
|
||||
set_light(traitdat.traits[TRAIT_XENO_GLOW_RANGE], traitdat.traits[TRAIT_XENO_GLOW_STRENGTH], traitdat.traits[TRAIT_XENO_BIO_COLOR])
|
||||
else
|
||||
set_light(0, 0, "#000000") //Should kill any light that shouldn't be there.
|
||||
|
||||
hostile = traitdat.traits[TRAIT_XENO_HOSTILE]
|
||||
|
||||
speed = traitdat.traits[TRAIT_XENO_SPEED]
|
||||
|
||||
if(traitdat.traits[TRAIT_XENO_CANSPEAK])
|
||||
speak_chance = traitdat.traits[TRAIT_XENO_SPEAKCHANCE]
|
||||
else
|
||||
speak_chance = 0
|
||||
|
||||
melee_damage_lower = traitdat.get_trait(TRAIT_XENO_STRENGTH) - traitdat.get_trait(TRAIT_XENO_STR_RANGE)
|
||||
melee_damage_upper = traitdat.traits[TRAIT_XENO_STRENGTH] + traitdat.get_trait(TRAIT_XENO_STR_RANGE)
|
||||
|
||||
|
||||
|
||||
//Metabolism proc, simplified for xenos. Heavily based on botanical metabolism.
|
||||
/mob/living/simple_animal/xeno/proc/handle_reagents()
|
||||
if(!stasis)
|
||||
if(!reagents)
|
||||
return
|
||||
|
||||
//Let's handle some chemical smoke, for scientific smoke bomb purposes.
|
||||
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
|
||||
if(smoke.reagents.total_volume)
|
||||
smoke.reagents.trans_to_mob(src, 10, CHEM_BLOOD, copy = 1)
|
||||
|
||||
reagents.trans_to_obj(temp_chem_holder, min(reagents.total_volume,rand(1,4)))
|
||||
var/reagent_total
|
||||
var/list/reagent_response = list()
|
||||
for(var/datum/reagent/R in temp_chem_holder.reagents.reagent_list)
|
||||
|
||||
reagent_total = temp_chem_holder.reagents.get_reagent_amount(R.id)
|
||||
|
||||
reagent_response = chemreact[R.id]
|
||||
|
||||
if(reagent_response["toxic"])
|
||||
adjustToxLoss(reagent_response["toxic"] * reagent_total)
|
||||
|
||||
if(reagent_response["heal"])
|
||||
heal_overall_damage(reagent_response["heal"] * reagent_total)
|
||||
|
||||
if(reagent_response["nutr"])
|
||||
nutrition += reagent_response["nutr"] * reagent_total
|
||||
|
||||
if(reagent_response["mut"])
|
||||
mut_level += reagent_response["mut"] * reagent_total
|
||||
|
||||
temp_chem_holder.reagents.clear_reagents()
|
||||
|
||||
return 1 //Everything worked out okay.
|
||||
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/xeno/proc/Mutate()
|
||||
nameVar = "mutated"
|
||||
if((COLORMUT & mutable))
|
||||
traitdat.traits[TRAIT_XENO_COLOR] = "#"
|
||||
for(var/i=0, i<6, i++)
|
||||
traitdat.traits[TRAIT_XENO_COLOR] += pick(hexNums)
|
||||
traitdat.traits[TRAIT_XENO_BIO_COLOR] = "#"
|
||||
for(var/i=0, i<6, i++)
|
||||
traitdat.traits[TRAIT_XENO_BIO_COLOR] += pick(hexNums)
|
||||
|
||||
RandomChemicals()
|
||||
//if(SPECIESMUT & mutable)
|
||||
//Placeholder, currently no xenos that have species mutations.
|
||||
RandomizeTraits()
|
||||
ProcessTraits()
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/xeno/proc/RandomizeTraits()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/xeno/hear_say(var/message, var/verb = "says", var/datum/language/language, var/alt_name = "",var/italics = 0, var/mob/speaker = null)
|
||||
if(traitdat.traits[TRAIT_XENO_CANLEARN])
|
||||
/*
|
||||
Until this gets sorted out to a functioning point, or waiting on Psi's saycode update.
|
||||
var/learned_message = say_understands(speaker, language)
|
||||
if(!message || isxeno(speaker))
|
||||
return
|
||||
if(learned_message) //Is it understood?
|
||||
var/complete_message = ",[language.key] [message]"
|
||||
if(!(complete_message in speak))
|
||||
speech_buffer.Add(complete_message)
|
||||
log_debug("Added '[complete_message]'.")
|
||||
else
|
||||
*/
|
||||
if(!(message in speak))
|
||||
speech_buffer.Add(message)
|
||||
..(message,verb,language,alt_name,italics,speaker)
|
||||
|
||||
/mob/living/simple_animal/xeno/proc/ProcessSpeechBuffer()
|
||||
if(speech_buffer.len)
|
||||
if(prob(traitdat.get_trait(TRAIT_XENO_LEARNCHANCE)) && traitdat.get_trait(TRAIT_XENO_CANLEARN))
|
||||
var/chosen = pick(speech_buffer)
|
||||
speak.Add(chosen)
|
||||
/* Uncoment for logging of speech list.
|
||||
log_debug("Added [chosen] to speak list.")
|
||||
log_debug("Speechlist cut.") */
|
||||
speech_buffer.Cut()
|
||||
//
|
||||
/mob/living/simple_animal/xeno/proc/BuildReagentLists()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/xeno/bullet_act(var/obj/item/projectile/P)
|
||||
//Shamelessly stolen from ablative armor.
|
||||
if((traitdat.traits[TRAIT_XENO_CHROMATIC]) && istype(P, /obj/item/projectile/beam))
|
||||
visible_message("<span class='danger'>)\The beam reflects off of the [src]!</span>")
|
||||
// Find a turf near or on the original location to bounce to
|
||||
var/new_x = P.starting.x + pick(0, -1, 1, -2, 2)
|
||||
var/new_y = P.starting.y + pick(0, -1, 1, -2, 2)
|
||||
var/turf/curloc = get_turf(src)
|
||||
|
||||
// redirect the projectile
|
||||
P.redirect(new_x, new_y, curloc, src)
|
||||
|
||||
return -1
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/xeno/proc/RandomChemicals()
|
||||
traitdat.chems.Cut() //Clear the amount first.
|
||||
|
||||
var/num_chems = round(rand(1,4))
|
||||
var/list/chemchoices = xenoChemList
|
||||
|
||||
for(var/i = 1 to num_chems)
|
||||
var/chemtype = pick(chemchoices)
|
||||
chemchoices -= chemtype
|
||||
var/chemamount = rand(1,5)
|
||||
traitdat.chems[chemtype] = chemamount
|
||||
|
||||
traitdat.chems += default_chems
|
||||
101
code/modules/xenobio2/mob/xeno.dm
Normal file
101
code/modules/xenobio2/mob/xeno.dm
Normal file
@@ -0,0 +1,101 @@
|
||||
//First we define certain flags, can be expanded upon later.
|
||||
|
||||
/*
|
||||
Basic definition of creatures for Xenobiology
|
||||
Also includes Life and New
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/xeno
|
||||
name = "Xeno"
|
||||
real_name = "Xeno"
|
||||
faction = "xeno" //Needs to be set.
|
||||
desc = "Something's broken, yell at someone."
|
||||
melee_damage_lower = 0
|
||||
melee_damage_upper = 0
|
||||
attacktext = "hit"
|
||||
attack_sound = null
|
||||
friendly = "touches"
|
||||
environment_smash = 0
|
||||
|
||||
var/datum/xeno/traits/traitdat //Trait datum.
|
||||
|
||||
var/internal_vol = 1000 //Internal volume for ingesting/injected reagents
|
||||
|
||||
var/obj/temp_chem_holder //Used in handle_reagents()
|
||||
|
||||
var/mutable = NOMUT //Flag for mutation.
|
||||
var/nameVar = "Blah"
|
||||
var/mut_instability = 0
|
||||
var/stasis = 0
|
||||
var/mut_level = 0 //How mutated a specimen is. Irrelevant while mutable = NOMUT.
|
||||
var/mut_max = 100000
|
||||
var/colored = 1
|
||||
var/maleable = MIN_MALEABLE //How easy is it to manipulate traitdat.traits after it's alive.
|
||||
var/stability = 0 //Used in gene manipulation
|
||||
|
||||
//Traits that might not be maleable.
|
||||
var/list/chemreact = list()
|
||||
var/hunger_factor = 10
|
||||
var/chromatic = 0
|
||||
var/starve_damage = 0
|
||||
|
||||
//Used for speech learning
|
||||
var/list/speech_buffer = list()
|
||||
|
||||
var/list/default_chems = list()
|
||||
|
||||
|
||||
//Life additions
|
||||
/mob/living/simple_animal/xeno/Life()
|
||||
if(stasis)
|
||||
stasis--
|
||||
if(stasis < 0)
|
||||
stasis = 0
|
||||
return 0
|
||||
|
||||
..()
|
||||
if(!(stat == DEAD))
|
||||
handle_reagents()
|
||||
if((mut_level >= mut_max) && !(mutable & NOMUT))
|
||||
Mutate()
|
||||
mut_level -= mut_max
|
||||
|
||||
ProcessSpeechBuffer()
|
||||
|
||||
//Have to feed the xenos somehow.
|
||||
if(nutrition < 0)
|
||||
nutrition = 0
|
||||
if((nutrition > 0 ) && traitdat.traits[TRAIT_XENO_EATS])
|
||||
if(nutrition >= 300)
|
||||
nutrition -= hunger_factor
|
||||
else
|
||||
if(traitdat.traits[TRAIT_XENO_EATS])
|
||||
health = starve_damage
|
||||
|
||||
return 1 //Everything worked okay.
|
||||
|
||||
/mob/living/simple_animal/xeno/New()
|
||||
|
||||
traitdat = new()
|
||||
|
||||
ProcessTraits()
|
||||
|
||||
..()
|
||||
if(colored)
|
||||
color = traitdat.get_trait(TRAIT_XENO_COLOR)
|
||||
create_reagents(internal_vol)
|
||||
temp_chem_holder = new()
|
||||
temp_chem_holder.create_reagents(20)
|
||||
nutrition = 350
|
||||
for(var/R in default_chems)
|
||||
traitdat.chems[R] = default_chems[R]
|
||||
|
||||
traitdat.source = name
|
||||
|
||||
if(!health)
|
||||
stat = DEAD
|
||||
|
||||
/mob/living/simple_animal/xeno/Destroy()
|
||||
traitdat.Destroy() //Let's clean up after ourselves.
|
||||
traitdat = null
|
||||
..()
|
||||
18
code/modules/xenobio2/mob/xeno_product.dm
Normal file
18
code/modules/xenobio2/mob/xeno_product.dm
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Xenobiological product lives here as a basic type.
|
||||
*/
|
||||
/obj/item/xenoproduct
|
||||
name = "Xenobiological product"
|
||||
desc = "How did this get here?."
|
||||
icon = 'icons/mob/slime2.dmi'
|
||||
icon_state = "slime extract"
|
||||
var/datum/xeno/traits/traits
|
||||
var/source = "Unknown"
|
||||
var/product = "mess"
|
||||
var/nameVar = "blah"
|
||||
|
||||
/obj/item/xenoproduct/Destroy()
|
||||
traits.Destroy() //Let's not leave any traits hanging around.
|
||||
traits = null
|
||||
..()
|
||||
|
||||
64
code/modules/xenobio2/tools/slime_handling_tools.dm
Normal file
64
code/modules/xenobio2/tools/slime_handling_tools.dm
Normal file
@@ -0,0 +1,64 @@
|
||||
/* What this file contains:
|
||||
|
||||
* A specialized stun prod, for handling fiesty slimes
|
||||
|
||||
* A specialized stun gun, for handling many fiesty slimes
|
||||
|
||||
* A stun projectile for handling xenomorphs.
|
||||
|
||||
*/
|
||||
/obj/item/weapon/melee/baton/slime
|
||||
name = "slimebaton"
|
||||
desc = "A modified stun baton designed to stun slimes for handling."
|
||||
icon_state = "slimebaton"
|
||||
item_state = "slimebaton"
|
||||
slot_flags = SLOT_BELT
|
||||
force = 9
|
||||
lightcolor = "#33CCFF"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_BIO = 4)
|
||||
agonyforce = 10 //It's not supposed to be great at stunning human beings.
|
||||
var/stasisforce = 60 //How much stasis it does to slimes, and 1/3rd to non-slimes.
|
||||
|
||||
/obj/item/weapon/melee/baton/slime/attack(mob/M, mob/user)
|
||||
if(istype(M, /mob/living/simple_animal/xeno))
|
||||
var/mob/living/simple_animal/xeno/X = M
|
||||
if(istype(M, /mob/living/simple_animal/xeno/slime))
|
||||
X.stasis += stasisforce
|
||||
else
|
||||
X.stasis += (stasisforce / 6)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/melee/baton/slime/loaded/New()
|
||||
..()
|
||||
bcell = new/obj/item/weapon/cell/high(src)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
// Xeno stun gun + projectile
|
||||
/obj/item/weapon/gun/energy/taser/xeno
|
||||
name = "xeno taser gun"
|
||||
desc = "Straight out of NT's testing laboratories, this small gun is used to subdue non-humanoid xeno life forms. While marketed towards handling slimes, it may be useful for other creatures."
|
||||
icon_state = "taserold"
|
||||
fire_sound = 'sound/weapons/taser2.ogg'
|
||||
max_shots = 10
|
||||
projectile_type = /obj/item/projectile/beam/stun/xeno
|
||||
|
||||
/obj/item/projectile/beam/stun/xeno
|
||||
icon_state = "omni"
|
||||
agony = 4
|
||||
var/stasisforce = 40
|
||||
|
||||
muzzle_type = /obj/effect/projectile/laser_omni/muzzle
|
||||
tracer_type = /obj/effect/projectile/laser_omni/tracer
|
||||
impact_type = /obj/effect/projectile/laser_omni/impact
|
||||
|
||||
/obj/item/projectile/beam/stun/xeno/on_hit(var/atom/target, var/blocked = 0)
|
||||
if(istype(target, /mob/living/simple_animal/xeno))
|
||||
var/mob/living/simple_animal/xeno/X = target
|
||||
if(istype(target, /mob/living/simple_animal/xeno/slime))
|
||||
X.stasis += stasisforce
|
||||
else
|
||||
X.stasis += (stasisforce / 8)
|
||||
else
|
||||
..()
|
||||
185
code/modules/xenobio2/tools/xeno_trait_scanner.dm
Normal file
185
code/modules/xenobio2/tools/xeno_trait_scanner.dm
Normal file
@@ -0,0 +1,185 @@
|
||||
/obj/item/device/analyzer/xeno_analyzer
|
||||
name = "exotic biological analyzer"
|
||||
desc = "A device to investigate the genetic data of a biological target."
|
||||
var/form_title
|
||||
var/last_data
|
||||
|
||||
/obj/item/device/analyzer/xeno_analyzer/proc/print_report_verb()
|
||||
set name = "Print Plant Report"
|
||||
set category = "Object"
|
||||
set src = usr
|
||||
|
||||
if(usr.stat || usr.restrained() || usr.lying)
|
||||
return
|
||||
print_report(usr)
|
||||
|
||||
/obj/item/device/analyzer/xeno_analyzer/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["print"])
|
||||
print_report(usr)
|
||||
|
||||
/obj/item/device/analyzer/xeno_analyzer/proc/print_report(var/mob/living/user)
|
||||
if(!last_data)
|
||||
user << "There is no scan data to print."
|
||||
return
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src))
|
||||
P.name = "paper - [form_title]"
|
||||
P.info = "[last_data]"
|
||||
if(istype(user,/mob/living/carbon/human))
|
||||
user.put_in_hands(P)
|
||||
user.visible_message("\The [src] spits out a piece of paper.")
|
||||
return
|
||||
|
||||
/obj/item/device/analyzer/xeno_analyzer/attack_self(mob/user as mob)
|
||||
print_report(user)
|
||||
return 0
|
||||
|
||||
/obj/item/device/analyzer/xeno_analyzer/afterattack(var/target, mob/user, flag)
|
||||
if(!flag) return
|
||||
|
||||
var/datum/xeno/traits/trait_info
|
||||
var/datum/reagents/prod_reagents
|
||||
var/targetName
|
||||
var/growth_level
|
||||
var/growth_max
|
||||
if(istype(target,/obj/structure/table))
|
||||
return ..()
|
||||
else if(istype(target,/mob/living/simple_animal/xeno))
|
||||
|
||||
var/mob/living/simple_animal/xeno/X = target
|
||||
if(istype(X, /mob/living/simple_animal/xeno/slime))
|
||||
var/mob/living/simple_animal/xeno/slime/S = X
|
||||
if(S.is_child)
|
||||
growth_level = S.growthcounter
|
||||
growth_max = S.growthpoint
|
||||
|
||||
targetName = X.name
|
||||
trait_info = X.traitdat
|
||||
|
||||
else if(istype(target,/obj/item/xenoproduct))
|
||||
|
||||
var/obj/item/xenoproduct/P = target
|
||||
trait_info = P.traits
|
||||
targetName = P.name
|
||||
prod_reagents = P.reagents
|
||||
|
||||
if(!trait_info)
|
||||
user << "<span class='danger'>[src] can tell you nothing about \the [target].</span>"
|
||||
return
|
||||
|
||||
form_title = "[targetName]"
|
||||
var/dat = "<h3>Biological data for [form_title]</h3>"
|
||||
user.visible_message("<span class='notice'>[user] runs the scanner over \the [target].</span>")
|
||||
|
||||
dat += "<h2>General Data</h2>"
|
||||
|
||||
|
||||
dat += "<tr><td><b>Health: </b></td><td>[trait_info.get_trait(TRAIT_XENO_HEALTH)]</td></tr>"
|
||||
|
||||
if(prod_reagents && prod_reagents.reagent_list && prod_reagents.reagent_list.len)
|
||||
dat += "<h2>Reagent Data</h2>"
|
||||
|
||||
dat += "<br>This sample contains: "
|
||||
for(var/datum/reagent/R in prod_reagents.reagent_list)
|
||||
dat += "<br>- [R.name], [prod_reagents.get_reagent_amount(R.id)] unit(s)"
|
||||
|
||||
dat += "<h2>Other Data</h2>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_EATS))
|
||||
dat += "This subject requires nutritional intake.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_HUNGER))
|
||||
if(trait_info.get_trait(TRAIT_XENO_HUNGER) < 7)
|
||||
dat += "It appears to have a slower metabolism.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_HUNGER) > 15)
|
||||
dat += "It appears to have a greater metabolism.<br>"
|
||||
else
|
||||
dat += "It appears to have an average metabolism.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_IMMUTABLE) == -1)
|
||||
dat += "This plant is highly mutable.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_IMMUTABLE) > 0)
|
||||
dat += "This plant does not possess genetics that are alterable.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_HEALTH))
|
||||
if(trait_info.get_trait(TRAIT_XENO_HEALTH) < 20)
|
||||
dat += "It bears characteristics that indicate resilience to damage.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_HEALTH) > 10)
|
||||
dat += "It bears characteristics that indicate susceptibility to damage.<br>"
|
||||
else
|
||||
dat += "It bears no characters indicating resilience to damage.<br>"
|
||||
|
||||
if(growth_max)
|
||||
if(growth_level < 35)
|
||||
dat += "It appears to be far to growing up.<br>"
|
||||
else if(growth_level > 40)
|
||||
dat += "It appears to be close to growing up.<br>"
|
||||
else
|
||||
dat += "It appears to be growing.<br>"
|
||||
else
|
||||
dat += "It appears to be fully grown.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_COLDRES))
|
||||
if(trait_info.get_trait(TRAIT_XENO_COLDRES) < 10)
|
||||
dat += "It bears characteristics that indicate resilience to colder temperatures.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_COLDRES) > 20)
|
||||
dat += "It bears characteristics that indicate susceptibility to colder temperatures.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_HEATRES))
|
||||
if(trait_info.get_trait(TRAIT_XENO_HEATRES) < 10)
|
||||
dat += "It bears characteristics that indicate resilience to warmer temperatures.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_HEATRES) > 20)
|
||||
dat += "It bears characteristics that indicate susceptibility to warmer temperatures.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_SPEED))
|
||||
if(trait_info.get_trait(TRAIT_XENO_SPEED) < 0)
|
||||
dat += "It appears to be agile.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_SPEED) > 0)
|
||||
dat += "It appears to be slower.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_CANSPEAK))
|
||||
dat += "<br>The subject appears to be able to articulate."
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_SPEAKCHANCE))
|
||||
if(trait_info.get_trait(TRAIT_XENO_SPEAKCHANCE) < 10)
|
||||
dat += "The subject appears to articulate infrequently.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_SPEAKCHANCE) > 20)
|
||||
dat += "The subject appears to articulate frequently.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_CANLEARN))
|
||||
dat += "<br>The subject appears to have process verbal information."
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_LEARNCHANCE))
|
||||
if(trait_info.get_trait(TRAIT_XENO_LEARNCHANCE) < 50)
|
||||
dat += "The subject appears to comprehend verbal information infrequently.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_LEARNCHANCE) > 51)
|
||||
dat += "The subject appears to comprehend verbal information frequently.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_STRENGTH) < 5)
|
||||
dat += "It appears to have lower average physical capacity.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_STRENGTH) > 7)
|
||||
dat += "It appears to have greater average physical capacity.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_STR_RANGE))
|
||||
if(trait_info.get_trait(TRAIT_XENO_STR_RANGE) < 50)
|
||||
dat += "The subject appears to have more consistent attacks.<br>"
|
||||
else if(trait_info.get_trait(TRAIT_XENO_STR_RANGE) > 51)
|
||||
dat += "The subject appears to have more varied attacks.<br>"
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_BIOLUMESCENT))
|
||||
dat += "<br>It is [trait_info.get_trait(TRAIT_XENO_BIO_COLOR) ? "<font color='[trait_info.get_trait(TRAIT_XENO_BIO_COLOR)]'>bio-luminescent</font>" : "bio-luminescent"]."
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_HOSTILE))
|
||||
dat += "<br>The subject appears to have hostile tendencies."
|
||||
|
||||
if(trait_info.get_trait(TRAIT_XENO_CHROMATIC))
|
||||
dat += "<br>The subject appears to have chromatic particles inside of it."
|
||||
|
||||
|
||||
if(dat)
|
||||
last_data = dat
|
||||
dat += "<br><br>\[<a href='?src=\ref[src];print=1'>print report</a>\]"
|
||||
user << browse(dat,"window=xeno_analyzer")
|
||||
|
||||
return
|
||||
Reference in New Issue
Block a user