Merge remote-tracking branch 'Upstream/master' into TGUI-3.0

This commit is contained in:
Artur
2020-07-09 22:14:20 +03:00
31 changed files with 1145 additions and 846 deletions

View File

@@ -69,7 +69,7 @@
/turf/open/floor/plasteel/white,
/area/ruin/space/has_grav/powered/ancient_shuttle)
"j" = (
/obj/machinery/computer/prototype_cloning,
/obj/machinery/computer/cloning/prototype,
/obj/machinery/light{
dir = 1
},

File diff suppressed because it is too large Load Diff

View File

@@ -109,7 +109,7 @@
/obj/machinery/clonepod/attack_ai(mob/user)
return examine(user)
//Start growing a clone in the pod!
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
if(panel_open)
return FALSE

View File

@@ -8,6 +8,7 @@
circuit = /obj/item/circuitboard/computer/cloning
req_access = list(ACCESS_HEADS) //ONLY USED FOR RECORD DELETION RIGHT NOW.
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
var/clonepod_type = /obj/machinery/clonepod
var/list/pods //Linked cloning pods
var/temp = "Inactive"
var/scantemp_ckey
@@ -17,6 +18,7 @@
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
var/loading = 0 // Nice loading text
var/autoprocess = 0
var/use_records = TRUE // Old experimental cloner.
var/list/records = list()
light_color = LIGHT_COLOR_BLUE
@@ -36,29 +38,32 @@
return ..()
/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null)
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.clonemind == mind)
return null
if(pod.is_operational() && !(pod.occupant || pod.mess))
return pod
if(!pods)
return
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.get_clone_mind == CLONEPOD_GET_MIND && pod.clonemind == mind)
return null
if(pod.is_operational() && !(pod.occupant || pod.mess))
return pod
/obj/machinery/computer/cloning/proc/HasEfficientPod()
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.is_operational() && pod.efficiency > 5)
return TRUE
if(!pods)
return
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.is_operational() && pod.efficiency > 5)
return TRUE
/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null)
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.clonemind == mind)
return pod
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
. = pod
if(!pods)
return
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.clonemind == mind)
return pod
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
. = pod
/obj/machinery/computer/cloning/process()
if(!(scanner && LAZYLEN(pods) && autoprocess))
@@ -73,7 +78,7 @@
if(pod.occupant)
continue //how though?
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["blood_type"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
temp = "[R.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
records -= R
@@ -103,12 +108,10 @@
return null
/obj/machinery/computer/cloning/proc/findcloner()
var/obj/machinery/clonepod/podf = null
var/obj/machinery/clonepod/podf
for(var/direction in GLOB.cardinals)
podf = locate(/obj/machinery/clonepod, get_step(src, direction))
if (!isnull(podf) && podf.is_operational())
podf = locate(clonepod_type, get_step(src, direction))
if(podf?.is_operational())
AttachCloner(podf)
/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod)
@@ -132,7 +135,7 @@
else if(istype(W, /obj/item/multitool))
var/obj/item/multitool/P = W
if(istype(P.buffer, /obj/machinery/clonepod))
if(istype(P.buffer, clonepod_type))
if(get_area(P.buffer) != get_area(src))
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
P.buffer = null
@@ -157,13 +160,14 @@
var/dat = ""
dat += "<a href='byond://?src=[REF(src)];refresh=1'>Refresh</a>"
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
if(!autoprocess)
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
if(use_records)
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
if(!autoprocess)
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
else
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
else
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
else
dat += "<span class='linkOff'>Autoclone</span>"
dat += "<span class='linkOff'>Autoclone</span>"
dat += "<h3>Cloning Pod Status</h3>"
dat += "<div class='statusDisplay'>[temp]&nbsp;</div>"
@@ -190,26 +194,29 @@
else if(loading)
dat += "[scanner_occupant] => Scanning..."
else
if(scanner_occupant.ckey != scantemp_ckey)
scantemp = "Ready to Scan"
scantemp_ckey = scanner_occupant.ckey
if(use_records)
if(scanner_occupant.ckey != scantemp_ckey)
scantemp = "Ready to Scan"
scantemp_ckey = scanner_occupant.ckey
else
scantemp = "Ready to Clone"
dat += "[scanner_occupant] => [scantemp]"
dat += "</div>"
if(scanner_occupant)
dat += "<a href='byond://?src=[REF(src)];scan=1'>Start Scan</a>"
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
dat += "<a href='byond://?src=[REF(src)];scan=1'>[use_records ? "Start Scan" : "Clone"]</a>"
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
else
dat += "<span class='linkOff'>Start Scan</span>"
// Database
dat += "<h3>Database Functions</h3>"
if (src.records.len && src.records.len > 0)
dat += "<a href='byond://?src=[REF(src)];menu=2'>View Records ([src.records.len])</a><br>"
else
dat += "<span class='linkOff'>View Records (0)</span><br>"
if (src.diskette)
dat += "<a href='byond://?src=[REF(src)];disk=eject'>Eject Disk</a><br>"
dat += "<span class='linkOff'>[use_records ? "Start Scan" : "Clone"]</span>"
if(use_records)
// Database
dat += "<h3>Database Functions</h3>"
if (src.records.len && src.records.len > 0)
dat += "<a href='byond://?src=[REF(src)];menu=2'>View Records ([src.records.len])</a><br>"
else
dat += "<span class='linkOff'>View Records (0)</span><br>"
if (src.diskette)
dat += "<a href='byond://?src=[REF(src)];disk=eject'>Eject Disk</a><br>"
@@ -290,24 +297,19 @@
autoprocess = FALSE
STOP_PROCESSING(SSmachines, src)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
loading = 1
loading = TRUE
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
var/prev_locked = scanner.locked
scanner.locked = TRUE
spawn(20)
src.scan_occupant(scanner.occupant)
loading = 0
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
scanner.locked = prev_locked
addtimer(CALLBACK(src, .proc/finish_scan, scanner.occupant, prev_locked), 2 SECONDS)
. = TRUE
//No locking an open scanner.
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
@@ -317,8 +319,17 @@
else
scanner.locked = FALSE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
. = TRUE
else if(href_list["view_rec"])
else if (href_list["refresh"])
src.updateUsrDialog()
playsound(src, "terminal_type", 25, 0)
. = TRUE
if(. || !use_records)
return
if(href_list["view_rec"])
playsound(src, "terminal_type", 25, 0)
src.active_record = find_record("id", href_list["view_rec"], records)
if(active_record)
@@ -330,6 +341,7 @@
src.menu = 3
else
src.temp = "Record missing."
. = TRUE
else if (href_list["del_rec"])
if ((!src.active_record) || (src.menu < 3))
@@ -353,8 +365,9 @@
else
src.temp = "<font class='bad'>Access Denied.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
else if (href_list["disk"]) //Load or eject.
else if (href_list["disk"] && use_records) //Load or eject.
switch(href_list["disk"])
if("load")
if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
@@ -392,10 +405,7 @@
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
src.temp = "Save successful."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
else if (href_list["refresh"])
src.updateUsrDialog()
playsound(src, "terminal_type", 25, 0)
. = TRUE
else if (href_list["clone"])
var/datum/data/record/C = find_record("id", href_list["clone"], records)
@@ -415,7 +425,7 @@
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"]))
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], C.fields["traumas"]))
temp = "[C.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
@@ -429,14 +439,28 @@
else
temp = "<font class='bad'>Data corruption.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
else if (href_list["menu"])
src.menu = text2num(href_list["menu"])
else if (href_list["menu"] && use_records)
menu = text2num(href_list["menu"])
playsound(src, "terminal_type", 25, 0)
. = TRUE
/obj/machinery/computer/cloning/proc/finish_scan(mob/living/L, prev_locked)
if(!scanner || !L)
return
src.add_fingerprint(usr)
src.updateUsrDialog()
return
if(use_records)
scan_occupant(L)
else
clone_occupant(L)
loading = FALSE
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
scanner.locked = prev_locked
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
@@ -455,30 +479,9 @@
if(isbrain(mob_occupant))
dna = B.stored_dna
if(!istype(dna))
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(mob_occupant.suiciding || mob_occupant.hellbound)
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
return
if ((!mob_occupant.ckey) || (!mob_occupant.client))
scantemp = "<font class='bad'>Mental interface failure.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if (find_record("ckey", mob_occupant.ckey, records))
scantemp = "<font class='average'>Subject already in database.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(SSeconomy.full_ancap && !has_bank_account)
scantemp = "<font class='average'>Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
if(!can_scan(dna, mob_occupant, FALSE, has_bank_account))
return
var/datum/data/record/R = new()
if(dna.species)
// We store the instance rather than the path, because some
@@ -529,3 +532,78 @@
board.records = records
scantemp = "Subject successfully scanned."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
//Used by the experimental cloning computer.
/obj/machinery/computer/cloning/proc/clone_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
if(ishuman(mob_occupant))
var/mob/living/carbon/C = mob_occupant
dna = C.has_dna()
if(isbrain(mob_occupant))
var/mob/living/brain/B = mob_occupant
dna = B.stored_dna
if(!can_scan(dna, mob_occupant, TRUE))
return
var/clone_species
if(dna.species)
clone_species = dna.species
else
var/datum/species/rando_race = pick(GLOB.roundstart_races)
clone_species = rando_race.type
var/obj/machinery/clonepod/pod = GetAvailablePod()
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!LAZYLEN(pods))
temp = "<font class='bad'>No Clonepods detected.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!pod)
temp = "<font class='bad'>No Clonepods available.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
/obj/machinery/computer/cloning/proc/can_scan(datum/dna/dna, mob/living/mob_occupant, experimental = FALSE, datum/bank_account/account)
if(!istype(dna))
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(!experimental)
if(mob_occupant.suiciding || mob_occupant.hellbound)
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
return
if (!experimental)
if(!mob_occupant.ckey || !mob_occupant.client)
scantemp = "<font class='bad'>Mental interface failure.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if (find_record("ckey", mob_occupant.ckey, records))
scantemp = "<font class='average'>Subject already in database.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(SSeconomy.full_ancap && !account)
scantemp = "<font class='average'>Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
return TRUE
//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
/obj/machinery/computer/cloning/prototype
name = "prototype cloning console"
desc = "Used to operate an experimental cloner."
icon_screen = "dna"
icon_keyboard = "med_key"
circuit = /obj/item/circuitboard/computer/cloning/prototype
clonepod_type = /obj/machinery/clonepod/experimental

View File

@@ -1,298 +0,0 @@
//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead
/obj/machinery/clonepod/experimental
name = "experimental cloning pod"
desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations."
icon = 'icons/obj/machines/cloning.dmi'
icon_state = "pod_0"
req_access = null
circuit = /obj/item/circuitboard/machine/clonepod/experimental
internal_radio = FALSE
//Start growing a human clone in the pod!
/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks)
if(panel_open)
return FALSE
if(mess || attempting)
return FALSE
attempting = TRUE //One at a time!!
countdown.start()
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
if(efficiency > 2)
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
H.dna.remove_mutation_group(unclean_mutations)
if(efficiency > 5 && prob(20))
H.easy_randmut(POSITIVE)
if(efficiency < 3 && prob(50))
var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
if(ismob(M))
H = M
H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
occupant = H
if(!clonename) //to prevent null names
clonename = "clone ([rand(1,999)])"
H.real_name = clonename
icon_state = "pod_1"
//Get the clone body ready
maim_clone(H)
ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
ADD_TRAIT(H, TRAIT_MUTE, "cloning")
ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
H.Unconscious(80)
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
if(LAZYLEN(candidates))
var/mob/C = pick(candidates)
H.key = C.key
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
if(grab_ghost_when == CLONER_MATURE_CLONE)
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
if(H)
H.faction |= factions
H.set_cloned_appearance()
H.suiciding = FALSE
attempting = FALSE
return TRUE
//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
/obj/machinery/computer/prototype_cloning
name = "prototype cloning console"
desc = "Used to operate an experimental cloner."
icon_screen = "dna"
icon_keyboard = "med_key"
circuit = /obj/item/circuitboard/computer/prototype_cloning
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
var/list/pods //Linked experimental cloning pods
var/temp = "Inactive"
var/scantemp = "Ready to Scan"
var/loading = FALSE // Nice loading text
light_color = LIGHT_COLOR_BLUE
/obj/machinery/computer/prototype_cloning/Initialize()
. = ..()
updatemodules(TRUE)
/obj/machinery/computer/prototype_cloning/Destroy()
if(pods)
for(var/P in pods)
DetachCloner(P)
pods = null
return ..()
/obj/machinery/computer/prototype_cloning/proc/GetAvailablePod(mind = null)
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/experimental/pod = P
if(pod.is_operational() && !(pod.occupant || pod.mess))
return pod
/obj/machinery/computer/prototype_cloning/proc/updatemodules(findfirstcloner)
scanner = findscanner()
if(findfirstcloner && !LAZYLEN(pods))
findcloner()
/obj/machinery/computer/prototype_cloning/proc/findscanner()
var/obj/machinery/dna_scannernew/scannerf = null
// Loop through every direction
for(var/direction in GLOB.cardinals)
// Try to find a scanner in that direction
scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction))
// If found and operational, return the scanner
if (!isnull(scannerf) && scannerf.is_operational())
return scannerf
// If no scanner was found, it will return null
return null
/obj/machinery/computer/prototype_cloning/proc/findcloner()
var/obj/machinery/clonepod/experimental/podf = null
for(var/direction in GLOB.cardinals)
podf = locate(/obj/machinery/clonepod/experimental, get_step(src, direction))
if (!isnull(podf) && podf.is_operational())
AttachCloner(podf)
/obj/machinery/computer/prototype_cloning/proc/AttachCloner(obj/machinery/clonepod/experimental/pod)
if(!pod.connected)
pod.connected = src
LAZYADD(pods, pod)
/obj/machinery/computer/prototype_cloning/proc/DetachCloner(obj/machinery/clonepod/experimental/pod)
pod.connected = null
LAZYREMOVE(pods, pod)
/obj/machinery/computer/prototype_cloning/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/multitool))
var/obj/item/multitool/P = W
if(istype(P.buffer, /obj/machinery/clonepod/experimental))
if(get_area(P.buffer) != get_area(src))
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
P.buffer = null
return
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
var/obj/machinery/clonepod/experimental/pod = P.buffer
if(pod.connected)
pod.connected.DetachCloner(pod)
AttachCloner(pod)
else
P.buffer = src
to_chat(user, "<font color = #666633>-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-</font color>")
return
else
return ..()
/obj/machinery/computer/prototype_cloning/attack_hand(mob/user)
if(..())
return
interact(user)
/obj/machinery/computer/prototype_cloning/interact(mob/user)
user.set_machine(src)
add_fingerprint(user)
if(..())
return
updatemodules(TRUE)
var/dat = ""
dat += "<a href='byond://?src=[REF(src)];refresh=1'>Refresh</a>"
dat += "<h3>Cloning Pod Status</h3>"
dat += "<div class='statusDisplay'>[temp]&nbsp;</div>"
if (isnull(src.scanner) || !LAZYLEN(pods))
dat += "<h3>Modules</h3>"
//dat += "<a href='byond://?src=[REF(src)];relmodules=1'>Reload Modules</a>"
if (isnull(src.scanner))
dat += "<font class='bad'>ERROR: No Scanner detected!</font><br>"
if (!LAZYLEN(pods))
dat += "<font class='bad'>ERROR: No Pod detected</font><br>"
// Scan-n-Clone
if (!isnull(src.scanner))
var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
dat += "<h3>Cloning</h3>"
dat += "<div class='statusDisplay'>"
if(!scanner_occupant)
dat += "Scanner Unoccupied"
else if(loading)
dat += "[scanner_occupant] => Scanning..."
else
scantemp = "Ready to Clone"
dat += "[scanner_occupant] => [scantemp]"
dat += "</div>"
if(scanner_occupant)
dat += "<a href='byond://?src=[REF(src)];clone=1'>Clone</a>"
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
else
dat += "<span class='linkOff'>Clone</span>"
var/datum/browser/popup = new(user, "cloning", "Prototype Cloning System Control")
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
/obj/machinery/computer/prototype_cloning/Topic(href, href_list)
if(..())
return
if(loading)
return
else if ((href_list["clone"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
loading = TRUE
updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
spawn(20)
clone_occupant(scanner.occupant)
loading = FALSE
updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
//No locking an open scanner.
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
if ((!scanner.locked) && (scanner.occupant))
scanner.locked = TRUE
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
scanner.locked = FALSE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
else if (href_list["refresh"])
updateUsrDialog()
playsound(src, "terminal_type", 25, 0)
add_fingerprint(usr)
updateUsrDialog()
return
/obj/machinery/computer/prototype_cloning/proc/clone_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
if(ishuman(mob_occupant))
var/mob/living/carbon/C = mob_occupant
dna = C.has_dna()
if(isbrain(mob_occupant))
var/mob/living/brain/B = mob_occupant
dna = B.stored_dna
if(!istype(dna))
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
return
var/clone_species
if(dna.species)
clone_species = dna.species
else
var/datum/species/rando_race = pick(GLOB.roundstart_races)
clone_species = rando_race.type
var/obj/machinery/clonepod/pod = GetAvailablePod()
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!LAZYLEN(pods))
temp = "<font class='bad'>No Clonepods detected.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!pod)
temp = "<font class='bad'>No Clonepods available.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)

View File

@@ -212,6 +212,11 @@
desc = "A heretical poster depicting the titular star of an equally heretical book."
icon_state = "poster4"
/obj/structure/sign/poster/contraband/post_ratvar
name = "Post This Ratvar"
desc = "Oh what in the hell? Those cultists have animated paper technology and they use it for a meme?"
icon_state = "postvar"
/obj/structure/sign/poster/contraband/syndicate_recruitment
name = "Syndicate Recruitment"
desc = "See the galaxy! Shatter corrupt megacorporations! Join today!"

View File

@@ -116,9 +116,9 @@
build_path = /obj/machinery/computer/cloning
var/list/records = list()
/obj/item/circuitboard/computer/prototype_cloning
/obj/item/circuitboard/computer/cloning/prototype
name = "Prototype Cloning (Computer Board)"
build_path = /obj/machinery/computer/prototype_cloning
build_path = /obj/machinery/computer/cloning/prototype
/obj/item/circuitboard/computer/arcade/battle
name = "Arcade Battle (Computer Board)"

View File

@@ -22,6 +22,11 @@
var/occupant_weight = 0
var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier
var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants
var/entrance_name = "door" //name of the entrance to the item
var/escape_time = 200 //how long it takes for mobs above small sizes to escape (for small sizes, its randomly 1.5 to 2x this)
var/load_time = 30 //how long it takes for mobs to be loaded into the pet carrier
var/has_lock_sprites = TRUE //whether to load the lock overlays or not
var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it?
/obj/item/pet_carrier/Destroy()
if(occupants.len)
@@ -51,20 +56,20 @@
else
. += "<span class='notice'>It has nothing inside.</span>"
if(user.canUseTopic(src))
. += "<span class='notice'>Activate it in your hand to [open ? "close" : "open"] its door.</span>"
. += "<span class='notice'>Activate it in your hand to [open ? "close" : "open"] its [entrance_name].</span>"
if(!open)
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] its door.</span>"
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] its [entrance_name].</span>"
/obj/item/pet_carrier/attack_self(mob/living/user)
if(open)
to_chat(user, "<span class='notice'>You close [src]'s door.</span>")
to_chat(user, "<span class='notice'>You close [src]'s [entrance_name].</span>")
playsound(user, 'sound/effects/bin_close.ogg', 50, TRUE)
open = FALSE
else
if(locked)
to_chat(user, "<span class='warning'>[src] is locked!</span>")
return
to_chat(user, "<span class='notice'>You open [src]'s door.</span>")
to_chat(user, "<span class='notice'>You open [src]'s [entrance_name].</span>")
playsound(user, 'sound/effects/bin_open.ogg', 50, TRUE)
open = TRUE
update_icon()
@@ -86,7 +91,7 @@
if(user.a_intent == INTENT_HARM)
return ..()
if(!open)
to_chat(user, "<span class='warning'>You need to open [src]'s door!</span>")
to_chat(user, "<span class='warning'>You need to open [src]'s [entrance_name]!</span>")
return
if(target.mob_size > max_occupant_weight)
if(ishuman(target))
@@ -94,13 +99,15 @@
if(iscatperson(H))
to_chat(user, "<span class='warning'>You'd need a lot of catnip and treats, plus maybe a laser pointer, for that to work.</span>")
else
to_chat(user, "<span class='warning'>Humans, generally, do not fit into pet carriers.</span>")
to_chat(user, "<span class='warning'>Humans, generally, do not fit into [name]s.</span>")
else
to_chat(user, "<span class='warning'>You get the feeling [target] isn't meant for a [name].</span>")
return
if(user == target)
to_chat(user, "<span class='warning'>Why would you ever do that?</span>")
return
if(ishostile(target) && !allows_hostiles && target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers
to_chat(user, "<span class='warning'>You have a feeling you shouldn't keep this as a pet.</span>")
load_occupant(user, target)
/obj/item/pet_carrier/relaymove(mob/living/user, direction)
@@ -110,8 +117,8 @@
remove_occupant(user)
return
else if(!locked)
loc.visible_message("<span class='notice'>[user] pushes open the door to [src]!</span>", \
"<span class='warning'>[user] pushes open the door of [src]!</span>")
loc.visible_message("<span class='notice'>[user] pushes open the [entrance_name] to [src]!</span>", \
"<span class='warning'>[user] pushes open the [entrance_name] of [src]!</span>")
open = TRUE
update_icon()
return
@@ -119,12 +126,19 @@
container_resist(user)
/obj/item/pet_carrier/container_resist(mob/living/user)
//don't do the whole resist timer thing if it's open!
if(open)
loc.visible_message("<span class='notice'>[user] climbs out of [src]!</span>", \
"<span class='warning'>[user] jumps out of [src]!</span>")
remove_occupant(user)
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.mob_size <= MOB_SIZE_SMALL)
to_chat(user, "<span class='notice'>You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)</span>")
to_chat(loc, "<span class='warning'>You see [user] reach through the bars and fumble for the lock switch!</span>")
if(!do_after(user, rand(300, 400), target = user) || open || !locked || !(user in occupants))
to_chat(user, "<span class='notice'>You begin to try escaping the [src] and start fumbling for the lock switch... (This will take some time.)</span>")
to_chat(loc, "<span class='warning'>You see [user] attempting to unlock the [src]!</span>")
if(!do_after(user, rand(escape_time * 1.5, escape_time * 2), target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("<span class='warning'>[user] flips the lock switch on [src] by reaching through!</span>", null, null, null, user)
to_chat(user, "<span class='boldannounce'>Bingo! The lock pops open!</span>")
@@ -132,12 +146,12 @@
playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE)
update_icon()
else
loc.visible_message("<span class='warning'>[src] starts rattling as something pushes against the door!</span>", null, null, null, user)
loc.visible_message("<span class='warning'>[src] starts rattling as something pushes against the [entrance_name]!</span>", null, null, null, user)
to_chat(user, "<span class='notice'>You start pushing out of [src]... (This will take about 20 seconds.)</span>")
if(!do_after(user, 200, target = user) || open || !locked || !(user in occupants))
if(!do_after(user, escape_time, target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("<span class='warning'>[user] shoves out of [src]!</span>", null, null, null, user)
to_chat(user, "<span class='notice'>You shove open [src]'s door against the lock's resistance and fall out!</span>")
to_chat(user, "<span class='notice'>You shove open [src]'s [entrance_name] against the lock's resistance and fall out!</span>")
locked = FALSE
open = TRUE
update_icon()
@@ -151,7 +165,7 @@
/obj/item/pet_carrier/update_overlays()
. = ..()
if(!open)
if(!open && has_lock_sprites)
. += "[locked ? "" : "un"]locked"
/obj/item/pet_carrier/MouseDrop(atom/over_atom)
@@ -170,7 +184,7 @@
user.visible_message("<span class='notice'>[user] starts loading [target] into [src].</span>", \
"<span class='notice'>You start loading [target] into [src]...</span>", null, null, target)
to_chat(target, "<span class='userdanger'>[user] starts loading you into [user.p_their()] [name]!</span>")
if(!do_mob(user, target, 30))
if(!do_mob(user, target, load_time))
return
if(target in occupants)
return
@@ -192,9 +206,74 @@
/obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf)
if(!(occupant in occupants) || !istype(occupant))
return
occupant.forceMove(new_turf ? new_turf : drop_location())
occupant.forceMove(new_turf ? new_turf : get_turf(src))
occupants -= occupant
occupant_weight -= occupant.mob_size
occupant.setDir(SOUTH)
//bluespace jar, a reskin of the pet carrier that can fit people and smashes when thrown
/obj/item/pet_carrier/bluespace
name = "bluespace jar"
desc = "A jar, that seems to be bigger on the inside, somehow allowing lifeforms to fit through its narrow entrance."
open = FALSE //starts closed so it looks better on menus
icon_state = "bluespace_jar"
item_state = "bluespace_jar"
lefthand_file = ""
righthand_file = ""
max_occupant_weight = MOB_SIZE_HUMAN //can fit people, like a bluespace bodybag!
load_time = 40 //loading things into a jar takes longer than a regular pet carrier
entrance_name = "lid"
w_class = WEIGHT_CLASS_SMALL //it's a jar
throw_speed = 3
throw_range = 7
max_occupants = 1 //far less than a regular carrier or bluespace bodybag, because it can be thrown to release the contents
allows_hostiles = TRUE //can fit hostile creatures, with the move resist restrictions in place, this means they still cannot take things like legions/goliaths/etc regardless
has_lock_sprites = FALSE //jar doesn't show the regular lock overlay
custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
escape_time = 10 //half the time of a bluespace bodybag
var/datum/gas_mixture/occupant_gas_supply
/obj/item/pet_carrier/bluespace/update_icon_state()
if(open)
icon_state = "bluespace_jar_open"
else
icon_state = "bluespace_jar"
/obj/item/pet_carrier/bluespace/throw_impact()
. = ..()
//delete the item upon impact, releasing the creature inside (this is handled by its deletion)
if(occupants.len)
loc.visible_message("<span class='warning'>The bluespace jar smashes, releasing [occupants[1]]!</span>")
playsound(src, "shatter", 70, 1)
qdel(src)
/obj/item/pet_carrier/bluespace/add_occupant(mob/living/occupant) //update the gas supply as required, this acts like magical internals
. = ..()
if(!occupant_gas_supply)
occupant_gas_supply = new
if(isanimal(occupant))
var/mob/living/simple_animal/animal = occupant
occupant_gas_supply.temperature = animal.minbodytemp //simple animals only care about temperature when their turf isnt a location
else
if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
/obj/item/pet_carrier/bluespace/remove_occupant(mob/living/occupant)
. = ..()
if(ishuman(occupant))
REMOVE_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
REMOVE_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
/obj/item/pet_carrier/bluespace/return_air()
if(!occupant_gas_supply)
occupant_gas_supply = new
return occupant_gas_supply
#undef pet_carrier_full

View File

@@ -326,6 +326,7 @@
w_class = WEIGHT_CLASS_BULKY
flags_1 = CONDUCT_1
custom_materials = list(/datum/material/iron=3000)
var/max_items = 7
/obj/item/storage/bag/tray/ComponentInitialize()
. = ..()
@@ -333,6 +334,7 @@
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food, /obj/item/reagent_containers/glass, /datum/reagent/consumable, /obj/item/kitchen/knife, /obj/item/kitchen/rollingpin, /obj/item/kitchen/fork, /obj/item/storage/box)) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Kitchen Tools, and ingredient boxes.
STR.insert_preposition = "on"
STR.max_items = max_items
/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
. = ..()
@@ -373,6 +375,14 @@
. = ..()
update_icon()
//bluespace tray, holds more items
/obj/item/storage/bag/tray/bluespace
name = "bluespace tray"
icon_state = "bluespace_tray"
desc = "A tray created using bluespace technology to fit more food on it."
max_items = 30 // far more items
custom_materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500)
/*
* Chemistry bag
*/

View File

@@ -268,6 +268,7 @@ obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/ite
/obj/machinery/portable_atmospherics/canister/obj_break(damage_flag)
if((stat & BROKEN) || (flags_1 & NODECONSTRUCT_1))
return
stat |= BROKEN
canister_break()
/obj/machinery/portable_atmospherics/canister/proc/canister_break()

View File

@@ -76,6 +76,7 @@
/obj/item/clothing/head/hooded
var/obj/item/clothing/suit/hooded/suit
dynamic_hair_suffix = ""
/obj/item/clothing/head/hooded/Destroy()
suit = null

View File

@@ -61,6 +61,7 @@
filling_color = "#ee7bee"
bitesize_mod = 2
foodtype = VEGETABLES
juice_results = list (/datum/reagent/consumable/laughsyrup = 0)
tastes = list ("a prancing rabbit" = 1) //Vib Ribbon sends her regards.. wherever she is.
wine_power = 90
wine_flavor = "a vector-graphic rabbit dancing on your tongue"

View File

@@ -23,6 +23,13 @@
heatmod = 0.5 // = 1/4x heat damage
burnmod = 0.5 // = 1/2x generic burn damage
species_language_holder = /datum/language_holder/jelly
mutant_brain = /obj/item/organ/brain/jelly
/obj/item/organ/brain/jelly
name = "slime nucleus"
desc = "A slimey membranous mass from a slime person"
icon_state = "brain-slime"
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(regenerate_limbs)

View File

@@ -95,3 +95,23 @@
build_path = /obj/item/storage/bag/ore/holding
category = list("Bluespace Designs")
departmental_flags = DEPARTMENTAL_FLAG_CARGO
/datum/design/bluespace_tray
name = "Bluespace Tray"
desc = "A tray created using bluespace technology to fit more food on it."
id = "bluespace_tray"
build_type = PROTOLATHE
build_path = /obj/item/storage/bag/tray/bluespace
materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500)
category = list("Bluespace Designs")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
/datum/design/bluespace_carrier
name = "Bluespace Jar"
desc = "A jar used to contain creatures, using the power of bluespace."
id = "bluespace_carrier"
build_type = PROTOLATHE
build_path = /obj/item/pet_carrier/bluespace
materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
category = list("Bluespace Designs")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE

View File

@@ -13,7 +13,7 @@
display_name = "Applied Bluespace Research"
description = "Using bluespace to make things faster and better."
prereq_ids = list("bluespace_basic", "engineering")
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic")
design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray", "bluespace_carrier")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
/datum/techweb_node/adv_bluespace

View File

@@ -50,6 +50,36 @@
-->
<div class="commit sansserif">
<h2 class="date">09 July 2020</h2>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">bluespace tray added, allowing twice as many items as the regular tray, printable at the service lathe, researched through science</li>
<li class="rscadd">bluespace jar added, a kind of pet carrier that allows human sized mobs inside, and smashes when thrown, researched and printed through science</li>
</ul>
<h2 class="date">08 July 2020</h2>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">The kill-once objective now works properly.</li>
</ul>
<h3 class="author">EmeraldSundisk updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">CogStation now has an apothecary</li>
<li class="rscdel">Removes an outdated note on sleepers</li>
<li class="tweak">Readjusts CogStation's chemistry lab</li>
<li class="tweak">Slight area designation adjustments for Robotics</li>
<li class="bugfix">The arrivals plaque should be readable now</li>
</ul>
<h3 class="author">Owai-Seek updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Margarine, Chili Cheese Fries.</li>
<li class="tweak">Egg Wraps are now categorized under egg foods.</li>
<li class="bugfix">Tuna Sandwich crafting/sprite is now visible.</li>
<li class="imageadd">Icons for chicken, cooked chicken, steak, grilled carp, corndogs</li>
<li class="imageadd">Icons for chili cheese fries, margarine, BLT sandwich</li>
<li class="imageadd">(Unused) icons for raw meatballs, and lard</li>
</ul>
<h2 class="date">07 July 2020</h2>
<h3 class="author">KasparoVy updated:</h3>
<ul class="changes bgimages16">

View File

@@ -26274,3 +26274,25 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
use custom sprite sizes so just ignore these changes.
- bugfix: Fixed the "Move it to the threshold" button; it now does what it says.
- tweak: Reworded some text to be clearer.
2020-07-08:
DeltaFire15:
- bugfix: The kill-once objective now works properly.
EmeraldSundisk:
- rscadd: CogStation now has an apothecary
- rscdel: Removes an outdated note on sleepers
- tweak: Readjusts CogStation's chemistry lab
- tweak: Slight area designation adjustments for Robotics
- bugfix: The arrivals plaque should be readable now
Owai-Seek:
- rscadd: Margarine, Chili Cheese Fries.
- tweak: Egg Wraps are now categorized under egg foods.
- bugfix: Tuna Sandwich crafting/sprite is now visible.
- imageadd: Icons for chicken, cooked chicken, steak, grilled carp, corndogs
- imageadd: Icons for chili cheese fries, margarine, BLT sandwich
- imageadd: (Unused) icons for raw meatballs, and lard
2020-07-09:
timothyteakettle:
- rscadd: bluespace tray added, allowing twice as many items as the regular tray,
printable at the service lathe, researched through science
- rscadd: bluespace jar added, a kind of pet carrier that allows human sized mobs
inside, and smashes when thrown, researched and printed through science

View File

@@ -1,9 +0,0 @@
author: "Owai-Seek"
delete-after: True
changes:
- rscadd: "Margarine, Chili Cheese Fries."
- tweak: "Egg Wraps are now categorized under egg foods."
- bugfix: "Tuna Sandwich crafting/sprite is now visible."
- imageadd: "Icons for chicken, cooked chicken, steak, grilled carp, corndogs"
- imageadd: "Icons for chili cheese fries, margarine, BLT sandwich"
- imageadd: "(Unused) icons for raw meatballs, and lard"

View File

@@ -1,8 +0,0 @@
author: "EmeraldSundisk"
delete-after: True
changes:
- rscadd: "CogStation now has an apothecary"
- rscdel: "Removes an outdated note on sleepers"
- tweak: "Readjusts CogStation's chemistry lab"
- tweak: "Slight area designation adjustments for Robotics"
- bugfix: "The arrivals plaque should be readable now"

View File

@@ -1,4 +0,0 @@
author: "DeltaFire15"
delete-after: True
changes:
- bugfix: "The kill-once objective now works properly."

View File

@@ -0,0 +1,5 @@
author: "Chiirno"
delete-after: True
changes:
- code_imp: "Gave jellypeople a unique brain object /obj/item/organ/brain/jelly"
- imageadd: "added an icon for jellypeople brains."

View File

@@ -0,0 +1,5 @@
author: "EmeraldSundisk"
delete-after: True
changes:
- rscadd: "Adds a pool to PubbyStation"
- tweak: "Slight adjustments to the surrounding area as to fit said pool"

View File

@@ -0,0 +1,4 @@
author: "Sneakyrat6"
delete-after: True
changes:
- bugfix: "Fixes hair falling out of hoodies."

View File

@@ -0,0 +1,4 @@
author: "TheObserver-sys"
delete-after: True
changes:
- bugfix: "Actually adds the juice reagent to make laugh peas donuts."

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -63,7 +63,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
startHunger = M.nutrition
if(pollStarted == FALSE)
pollStarted = TRUE
candies = pollGhostCandidates("Do you want and agree to play as a clone of [M], respect their character and not engage in ERP without permission from the original?", ignore_category = POLL_IGNORE_CLONE)
candies = pollGhostCandidates("Do you want to play as [M]'s defective clone? (Don't ERP without permission from the original)", ignore_category = POLL_IGNORE_CLONE)
log_reagent("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.")
if(20 to INFINITY)
if(LAZYLEN(candies) && playerClone == FALSE) //If there's candidates, clone the person and put them in there!

View File

@@ -745,7 +745,6 @@
#include "code\game\machinery\dna_scanner.dm"
#include "code\game\machinery\doppler_array.dm"
#include "code\game\machinery\droneDispenser.dm"
#include "code\game\machinery\exp_cloner.dm"
#include "code\game\machinery\firealarm.dm"
#include "code\game\machinery\flasher.dm"
#include "code\game\machinery\gulag_item_reclaimer.dm"