Merge branch 'master' of https://github.com/PolarisSS13/Polaris into attackcall

This commit is contained in:
Yoshax
2016-05-29 00:56:57 +01:00
50 changed files with 2642 additions and 642 deletions

View File

@@ -0,0 +1,211 @@
//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/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

View 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

View File

@@ -0,0 +1,191 @@
/*
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 = occupant.traitdat
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)
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
)

View File

@@ -0,0 +1,429 @@
/*
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
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 biological genetic bombarder is full, empty it first!</span>"
return
if(in_use)
user << "<span class='danger'>The biological genetic bombarder 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 biological genetic bombarder!</span>"
return
user.visible_message("<span class='danger'>[user] starts to put [victim] into the biological genetic bombarder!</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 biological genetic bombarder!</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
)

View File

@@ -0,0 +1,145 @@
/*
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()
for(var/obj/thing in (contents - component_parts - circuit - beaker))
thing.forceMove(loc)
if(occupant)
occupant.forceMove(loc)
occupant = null
return
/obj/machinery/xenobio2/manualinjector/proc/eject_beaker()
if(beaker)
var/obj/item/weapon/reagent_containers/glass/beaker/B = beaker
B.loc = loc
beaker = null
return
/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,

View File

@@ -0,0 +1,113 @@
/*
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["instability"] = (X.mut_level / X.mut_max) * 100
else
data["instability"] = 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_contents()
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,

View File

@@ -0,0 +1,147 @@
/*
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 = core.traits
S.ProcessTraits()
qdel(core)
spawn(30)
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
)

View 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.

View File

@@ -0,0 +1,114 @@
/*
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_CHROMATIC] = prob(5)
if(traitdat.traits[TRAIT_XENO_CHROMATIC])
traitdat.traits[TRAIT_XENO_HOSTILE] = 0
else
traitdat.traits[TRAIT_XENO_HOSTILE] = prob(30)
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/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()

View File

@@ -0,0 +1,92 @@
/*
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."
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 = 200
mutable = COLORMUT
var/is_child = 1
var/cores = 3
var/growthcounter = 0
var/growthpoint = 150 //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),
"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

View 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"

View 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)

View File

@@ -0,0 +1,168 @@
/*
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.
if(!(chromatic))
hostile = 0 //No. No laser-reflecting hostile creatures. Bad.
else
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
if(reagents.total_volume <= 0)
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/proc/bulet_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
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

View File

@@ -0,0 +1,97 @@
//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"
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/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(src.stat == DEAD)
return 0
if(stasis)
stasis--
if(stasis < 0)
stasis = 0
return 0
..()
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

View File

@@ -0,0 +1,12 @@
/*
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"

View 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
..()