This commit is contained in:
quotefox
2019-12-03 03:50:03 +00:00
56 changed files with 1072 additions and 209 deletions
+6
View File
@@ -185,6 +185,12 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
//We will round to this value in damage calculations.
#define DAMAGE_PRECISION 0.1
//bullet_act() return values
#define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default.
#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs.
//items total mass, used to calculate their attacks' stamina costs. If not defined, the cost will be (w_class * 1.25)
#define TOTAL_MASS_TINY_ITEM 1.25
#define TOTAL_MASS_SMALL_ITEM 2.5
+6
View File
@@ -1,10 +1,16 @@
// simple is_type and similar inline helpers
#if DM_VERSION < 513
#define islist(L) (istype(L, /list))
#endif
#define in_range(source, user) (get_dist(source, user) <= 1 && (get_step(source, 0)?:z) == (get_step(user, 0)?:z))
#if DM_VERSION < 513
#define ismovableatom(A) (istype(A, /atom/movable))
#else
#define ismovableatom(A) ismovable(A)
#endif
#define isatom(A) (isloc(A))
+1
View File
@@ -35,6 +35,7 @@
#define LOG_GAME (1 << 12)
#define LOG_ADMIN_PRIVATE (1 << 13)
#define LOG_ASAY (1 << 14)
#define LOG_CLONING (1 << 15)
//Individual logging panel pages
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK)
+4
View File
@@ -100,6 +100,10 @@
#define NUKE_ON_TIMING 2
#define NUKE_ON_EXPLODING 3
//cloning defines. These are flags.
#define CLONING_SUCCESS (1<<0)
#define CLONING_DELETE_RECORD (1<<1)
//these flags are used to tell the DNA modifier if a plant gene cannot be extracted or modified.
#define PLANT_GENE_REMOVABLE (1<<0)
#define PLANT_GENE_EXTRACTABLE (1<<1)
+8
View File
@@ -30,7 +30,11 @@
// round() acts like floor(x, 1) by default but can't handle other values
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
#if DM_VERSION < 513
#define CLAMP(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
#else
#define CLAMP(CLVALUE,CLMIN,CLMAX) clamp(CLVALUE,CLMIN,CLMAX)
#endif
// Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive
#define WRAP(val, min, max) ( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) )
@@ -39,7 +43,11 @@
#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) )
// Tangent
#if DM_VERSION < 513
#define TAN(x) (sin(x) / cos(x))
#else
#define TAN(x) tan(x)
#endif
// Cotangent
#define COT(x) (1 / TAN(x))
+1 -1
View File
@@ -476,7 +476,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define PDAIMG(what) {"<span class="pda16x16 [#what]"></span>"}
//Filters
#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"border"=4,"color"="#04080FAA")
#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"color"="#04080FAA")
#define EYE_BLUR(size) list("type"="blur", "size"=size)
#define GRAVITY_MOTION_BLUR list("type"="motion_blur","x"=0,"y"=0)
+1 -1
View File
@@ -2,7 +2,7 @@
#define TYPEID_NULL "0"
#define TYPEID_NORMAL_LIST "f"
//helper macros
#define GET_TYPEID(ref) ( ( (lentext(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, lentext(ref)-6) ) )
#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, length(ref)-6) ) )
#define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST)
+1 -1
View File
@@ -514,7 +514,7 @@
used_key_list[input_key] = 1
return input_key
#if DM_VERSION > 512
#if DM_VERSION > 513
#error Remie said that lummox was adding a way to get a lists
#error contents via list.values, if that is true remove this
#error otherwise, update the version and bug lummox
+4
View File
@@ -58,6 +58,10 @@
if (CONFIG_GET(flag/log_game))
WRITE_LOG(GLOB.world_game_log, "GAME: [text]")
/proc/log_cloning(text, mob/initiator)
if(CONFIG_GET(flag/log_cloning))
WRITE_LOG(GLOB.world_cloning_log, "CLONING: [text]")
/proc/log_access(text)
if (CONFIG_GET(flag/log_access))
WRITE_LOG(GLOB.world_game_log, "ACCESS: [text]")
+11 -11
View File
@@ -305,9 +305,9 @@
//is in the other string at the same spot (assuming it is not a replace char).
//This is used for fingerprints
var/newtext = text
if(lentext(text) != lentext(compare))
if(length(text) != length(compare))
return 0
for(var/i = 1, i < lentext(text), i++)
for(var/i = 1, i < length(text), i++)
var/a = copytext(text,i,i+1)
var/b = copytext(compare,i,i+1)
//if it isn't both the same letter, or if they are both the replacement character
@@ -327,7 +327,7 @@
if(!text || !character)
return 0
var/count = 0
for(var/i = 1, i <= lentext(text), i++)
for(var/i = 1, i <= length(text), i++)
var/a = copytext(text,i,i+1)
if(a == character)
count++
@@ -608,8 +608,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
continue
var/buffer = ""
var/early_culling = TRUE
for(var/pos = 1, pos <= lentext(string), pos++)
var/let = copytext(string, pos, (pos + 1) % lentext(string))
for(var/pos = 1, pos <= length(string), pos++)
var/let = copytext(string, pos, (pos + 1) % length(string))
if(early_culling && !findtext(let,GLOB.is_alphanumeric))
continue
early_culling = FALSE
@@ -617,9 +617,9 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
if(!findtext(buffer,GLOB.is_alphanumeric))
continue
var/punctbuffer = ""
var/cutoff = lentext(buffer)
for(var/pos = lentext(buffer), pos >= 0, pos--)
var/let = copytext(buffer, pos, (pos + 1) % lentext(buffer))
var/cutoff = length(buffer)
for(var/pos = length(buffer), pos >= 0, pos--)
var/let = copytext(buffer, pos, (pos + 1) % length(buffer))
if(findtext(let,GLOB.is_alphanumeric))
break
if(findtext(let,GLOB.is_punctuation))
@@ -629,8 +629,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
var/exclaim = FALSE
var/question = FALSE
var/periods = 0
for(var/pos = lentext(punctbuffer), pos >= 0, pos--)
var/punct = copytext(punctbuffer, pos, (pos + 1) % lentext(punctbuffer))
for(var/pos = length(punctbuffer), pos >= 0, pos--)
var/punct = copytext(punctbuffer, pos, (pos + 1) % length(punctbuffer))
if(!exclaim && findtext(punct,"!"))
exclaim = TRUE
if(!question && findtext(punct,"?"))
@@ -652,7 +652,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
buffer = copytext(buffer, 1, cutoff) + punctbuffer
if(!findtext(buffer,GLOB.is_alphanumeric))
continue
if(!buffer || lentext(buffer) > 280 || lentext(buffer) <= cullshort || buffer in accepted)
if(!buffer || length(buffer) > 280 || length(buffer) <= cullshort || buffer in accepted)
continue
accepted += buffer
+2 -2
View File
@@ -9,8 +9,8 @@
return t
proc/TextPreview(var/string,var/len=40)
if(lentext(string) <= len)
if(!lentext(string))
if(length(string) <= len)
if(!length(string))
return "\[...\]"
else
return string
+6 -1
View File
@@ -451,10 +451,15 @@ Turf and target are separate in case you want to teleport some distance from a t
var/y = min(world.maxy, max(1, A.y + dy))
return locate(x,y,A.z)
#if DM_VERSION > 513
#warn if you're getting this warning it means 513 is stable
#warn and you should remove this tidbit
#endif
#if DM_VERSION < 513
/proc/arctan(x)
var/y=arcsin(x/sqrt(1+x*x))
return y
#endif
/*
Gets all contents of contents and returns them all in a list.
*/
+2
View File
@@ -26,6 +26,8 @@ GLOBAL_VAR(query_debug_log)
GLOBAL_PROTECT(query_debug_log)
GLOBAL_VAR(world_job_debug_log)
GLOBAL_PROTECT(world_job_debug_log)
GLOBAL_VAR(world_cloning_log)
GLOBAL_PROTECT(world_cloning_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
@@ -39,6 +39,8 @@
/datum/config_entry/flag/log_game // log game events
/datum/config_entry/flag/log_cloning // log cloning actions.
/datum/config_entry/flag/log_vote // log voting
/datum/config_entry/flag/log_whisper // log client whisper
+1 -1
View File
@@ -371,7 +371,7 @@
updateappearance(icon_update=0)
if(LAZYLEN(mutation_index))
dna.mutation_index = mutation_index
dna.mutation_index = mutation_index.Copy()
domutcheck()
if(mrace || newfeatures || ui)
+51 -31
View File
@@ -74,6 +74,23 @@
if(heal_level > 100)
heal_level = 100
/obj/machinery/clonepod/attack_hand(mob/user)
. = ..()
if(.)
return
user.examinate(src)
/obj/machinery/clonepod/attack_ai(mob/user)
return attack_hand(user)
/obj/machinery/clonepod/examine(mob/user)
. = ..()
. += "<span class='notice'>The <i>linking</i> device can be <i>scanned<i> with a multitool.</span>"
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Cloning speed at <b>[speed_coeff*50]%</b>.<br>Predicted amount of cellular damage: <b>[100-heal_level]%</b>.</span>"
if(efficiency > 5)
. += "<span class='notice'>Pod has been upgraded to support autoprocessing and apply beneficial mutations.</span>"
//The return of data disks?? Just for transferring between genetics machine/cloning machine.
//TO-DO: Make the genetics machine accept them.
/obj/item/disk/data
@@ -129,41 +146,42 @@
return examine(user)
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks)
/obj/machinery/clonepod/proc/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas, empty)
if(panel_open)
return FALSE
if(mess || attempting)
return FALSE
clonemind = locate(mindref) in SSticker.minds
if(!istype(clonemind)) //not a mind
return FALSE
if(!QDELETED(clonemind.current))
if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body
if(!empty) //Doesn't matter if we're just making a copy
clonemind = locate(mindref) in SSticker.minds
if(!istype(clonemind)) //not a mind
return FALSE
if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
// if(clonemind.last_death != last_death) //The soul has advanced, the record has not.
// return FALSE
if(!QDELETED(clonemind.current))
if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body
return NONE
if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
return NONE
if(!clonemind.active)
// get_ghost() will fail if they're unable to reenter their body
var/mob/dead/observer/G = clonemind.get_ghost()
if(!G)
return NONE
if(G.suiciding) // The ghost came from a body that is suiciding.
return NONE
if(clonemind.damnation_type) //Can't clone the damned.
INVOKE_ASYNC(src, .proc/horrifyingsound)
mess = TRUE
icon_state = "pod_g"
update_icon()
return FALSE
if(clonemind.active) //somebody is using that mind
if( ckey(clonemind.key)!=ckey )
return FALSE
else
// get_ghost() will fail if they're unable to reenter their body
var/mob/dead/observer/G = clonemind.get_ghost()
if(!G)
return FALSE
if(G.suiciding) // The ghost came from a body that is suiciding.
return FALSE
if(clonemind.damnation_type) //Can't clone the damned.
INVOKE_ASYNC(src, .proc/horrifyingsound)
mess = TRUE
update_icon()
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, null, mrace, features)
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
if(prob(50 - efficiency*10)) //Chance to give a bad mutation.
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) //100% bad mutation. Can be cured with mutadone.
@@ -184,15 +202,16 @@
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
H.Unconscious(80)
clonemind.transfer_to(H)
if(!empty)
clonemind.transfer_to(H)
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_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(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
@@ -381,6 +400,7 @@
unattached_flesh.Cut()
occupant = null
clonemind = null
/obj/machinery/clonepod/proc/malfunction()
var/mob/living/mob_occupant = occupant
@@ -391,7 +411,7 @@
mess = TRUE
maim_clone(mob_occupant) //Remove every bit that's grown back so far to drop later, also destroys bits that haven't grown yet
update_icon()
if(mob_occupant.mind != clonemind)
if(clonemind && mob_occupant.mind != clonemind)
clonemind.transfer_to(mob_occupant)
mob_occupant.grab_ghost() // We really just want to make you suffer.
flash_color(mob_occupant, flash_color="#960000", flash_time=100)
+85 -28
View File
@@ -39,7 +39,7 @@
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.clonemind == mind)
if(pod.occupant && mind && pod.clonemind == mind)
return null
if(pod.is_operational() && !(pod.occupant || pod.mess))
return pod
@@ -60,6 +60,9 @@
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
. = pod
/proc/grow_clone_from_record(obj/machinery/clonepod/pod, datum/data/record/R, empty)
return pod.growclone(R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mindref"], R.fields["last_death"], R.fields["blood_type"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"], empty)
/obj/machinery/computer/cloning/process()
if(!(scanner && LAZYLEN(pods) && autoprocess))
return
@@ -76,8 +79,11 @@
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"]))
var/result = grow_clone_from_record(pod, R)
if(result & CLONING_SUCCESS)
temp = "[R.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
log_cloning("Cloning of [key_name(R.fields["mindref"])] automatically started via autoprocess - [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
if(result & CLONING_DELETE_RECORD)
records -= R
/obj/machinery/computer/cloning/proc/updatemodules(findfirstcloner)
@@ -201,6 +207,7 @@
if(scanner_occupant)
dat += "<a href='byond://?src=[REF(src)];scan=1'>Start Scan</a>"
dat += "<a href='byond://?src=[REF(src)];scan=1;body_only=1'>Body-Only Scan</a>"
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
else
dat += "<span class='linkOff'>Start Scan</span>"
@@ -228,8 +235,11 @@
if (!src.active_record)
dat += "<font class='bad'>Record not found.</font>"
else
dat += "<h4>[src.active_record.fields["name"]]</h4>"
dat += "Scan ID [src.active_record.fields["id"]] <a href='byond://?src=[REF(src)];clone=[active_record.fields["id"]]'>Clone</a><br>"
var/body_only = active_record.fields["body_only"]
dat += "<h4>[active_record.fields["name"]][body_only ? " - BODY-ONLY" : ""]</h4>"
dat += "Scan ID [active_record.fields["id"]] \
[!body_only ? "<a href='byond://?src=[REF(src)];clone=[active_record.fields["id"]]'>Clone</a>" : "" ]\
<a href='byond://?src=[REF(src)];clone=[active_record.fields["id"]];empty=TRUE'>Empty Clone</a><br>"
var/obj/item/implant/health/H = locate(src.active_record.fields["imp"])
@@ -297,13 +307,14 @@
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
var/body_only = href_list["body_only"]
loading = 1
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
spawn(20)
src.scan_occupant(scanner.occupant)
src.scan_occupant(scanner.occupant, usr, body_only)
loading = 0
src.updateUsrDialog()
@@ -336,9 +347,23 @@
if ((!src.active_record) || (src.menu < 3))
return
if (src.menu == 3) //If we are viewing a record, confirm deletion
src.temp = "Delete record?"
src.menu = 4
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
var/has_access = FALSE
if(ishuman(usr))
var/mob/living/carbon/human/user = usr
var/obj/item/card/id/C = user.get_idcard(TRUE)
if(C)
if(check_access(C))
has_access = TRUE
if(active_record.fields["body_only"]) //Body-only scans are not as important and can be deleted freely
has_access = TRUE
if(has_access)
temp = "Delete record?"
menu = 4
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
else
temp = "Access Denied"
menu = 2
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if (src.menu == 4)
var/obj/item/card/id/C = usr.get_active_held_item()
@@ -400,9 +425,14 @@
else if (href_list["clone"])
var/datum/data/record/C = find_record("id", href_list["clone"], records)
var/empty = href_list["empty"]
//Look for that player! They better be dead!
if(C)
if(C.fields["body_only"] && !empty)
temp = "<font class='bad'>Cannot initiate regular cloning with body-only scans.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
var/obj/machinery/clonepod/pod = GetAvailablePod()
var/success = FALSE
//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>"
@@ -410,20 +440,31 @@
else if(!pod)
temp = "<font class='bad'>No Clonepods available.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!CONFIG_GET(flag/revival_cloning))
else if(!CONFIG_GET(flag/revival_cloning) && !empty)
temp = "<font class='bad'>Unable to initiate cloning cycle.</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 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"]))
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)
if(active_record == C)
active_record = null
menu = 1
else
var/result = grow_clone_from_record(pod, C, empty)
if(result & CLONING_SUCCESS)
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)
if(active_record == C)
active_record = null
menu = 1
success = TRUE
if(!empty)
log_cloning("[key_name(usr)] initiated cloning of [key_name(C.fields["mindref"])] via [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
else
log_cloning("[key_name(usr)] initiated EMPTY cloning of [key_name(C.fields["mindref"])] via [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
if(result & CLONING_DELETE_RECORD)
if(active_record == C)
active_record = null
if(!success)
temp = "[C.fields["name"]] => <font class='bad'>Initialisation failure.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
@@ -439,9 +480,11 @@
src.updateUsrDialog()
return
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
/obj/machinery/computer/cloning/proc/scan_occupant(occupant, mob/M, body_only)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
// Do not use unless you know what they are.
if(ishuman(mob_occupant))
var/mob/living/carbon/C = mob_occupant
dna = C.has_dna()
@@ -453,7 +496,7 @@
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)
if(!body_only && (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
@@ -461,7 +504,7 @@
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))
if (!body_only && isnull(mob_occupant.mind))
scantemp = "<font class='bad'>Mental interface failure.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
@@ -490,6 +533,7 @@
R.fields["blood_type"] = dna.blood_type
R.fields["features"] = dna.features
R.fields["factions"] = mob_occupant.faction
R.fields["body_only"] = body_only
R.fields["quirks"] = list()
for(var/V in mob_occupant.roundstart_quirks)
var/datum/quirk/T = V
@@ -498,17 +542,30 @@
if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
R.fields["mind"] = "[REF(mob_occupant.mind)]"
//Add an implant if needed
var/obj/item/implant/health/imp
for(var/obj/item/implant/health/HI in mob_occupant.implants)
imp = HI
break
if(!imp)
imp = new /obj/item/implant/health(mob_occupant)
imp.implant(mob_occupant)
R.fields["imp"] = "[REF(imp)]"
if(!body_only)
//Add an implant if needed
var/obj/item/implant/health/imp
for(var/obj/item/implant/health/HI in mob_occupant.implants)
imp = HI
break
if(!imp)
imp = new /obj/item/implant/health(mob_occupant)
imp.implant(mob_occupant)
R.fields["imp"] = "[REF(imp)]"
var/datum/data/record/old_record = find_record("mindref", REF(mob_occupant.mind), records)
if(body_only)
old_record = find_record("UE", dna.unique_enzymes, records) //Body-only records cannot be identified by mind, so we use the DNA
if(old_record && ((old_record.fields["UI"] != dna.uni_identity) || (!old_record.fields["body_only"]))) //Never overwrite a mind-and-body record if it exists
old_record = null
if(old_record)
records -= old_record
scantemp = "Record updated."
else
scantemp = "Subject successfully scanned."
src.records += R
log_cloning("[M ? key_name(M) : "Autoprocess"] added the [body_only ? "body-only " : ""]record of [key_name(mob_occupant)] to [src] at [AREACOORD(src)].")
var/obj/item/circuitboard/computer/cloning/board = circuit
board.records = records
scantemp = "Subject successfully scanned."
+3 -3
View File
@@ -9,7 +9,7 @@
internal_radio = FALSE
//Start growing a human clone in the pod!
/obj/machinery/clonepod/experimental/growclone(ckey, clonename, ui, se, datum/species/mrace, list/features, factions)
/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -20,7 +20,7 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
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)
@@ -292,7 +292,7 @@
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, clone_species, dna.features, mob_occupant.faction)
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)
+1 -1
View File
@@ -515,7 +515,7 @@ GLOBAL_LIST_EMPTY(allCasters)
if(href_list["set_channel_name"])
channel_name = stripped_input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "", MAX_NAME_LEN)
while (findtext(channel_name," ") == 1)
channel_name = copytext(channel_name,2,lentext(channel_name)+1)
channel_name = copytext(channel_name,2,length(channel_name)+1)
updateUsrDialog()
else if(href_list["set_channel_lock"])
c_locked = !c_locked
+1 -1
View File
@@ -243,7 +243,7 @@
else
line1 = "CARGO"
line2 = SSshuttle.supply.getTimerStr()
if(lentext(line2) > CHARS_PER_LINE)
if(length(line2) > CHARS_PER_LINE)
line2 = "Error"
update_display(line1, line2)
@@ -461,3 +461,56 @@
//NC.mergeConnectedNetworksOnTurf()
last_piece = NC
return 1
//Dunno where else to put this so shrug
/obj/item/mecha_parts/mecha_equipment/ripleyupgrade
name = "Ripley MK-II Conversion Kit"
desc = "A pressurized canopy attachment kit for an Autonomous Power Loader Unit \"Ripley\" MK-I mecha, to convert it to the slower, but space-worthy MK-II design. This kit cannot be removed, once applied."
icon_state = "ripleyupgrade"
/obj/item/mecha_parts/mecha_equipment/ripleyupgrade/can_attach(obj/mecha/working/ripley/M)
if(M.type != /obj/mecha/working/ripley)
to_chat(loc, "<span class='warning'>This conversion kit can only be applied to APLU MK-I models.</span>")
return FALSE
if(M.cargo.len)
to_chat(loc, "<span class='warning'>[M]'s cargo hold must be empty before this conversion kit can be applied.</span>")
return FALSE
if(!M.maint_access) //non-removable upgrade, so lets make sure the pilot or owner has their say.
to_chat(loc, "<span class='warning'>[M] must have maintenance protocols active in order to allow this conversion kit.</span>")
return FALSE
if(M.occupant) //We're actualy making a new mech and swapping things over, it might get weird if players are involved
to_chat(loc, "<span class='warning'>[M] must be unoccupied before this conversion kit can be applied.</span>")
return FALSE
if(!M.cell) //Turns out things break if the cell is missing
to_chat(loc, "<span class='warning'>The conversion process requires a cell installed.</span>")
return FALSE
return TRUE
/obj/item/mecha_parts/mecha_equipment/ripleyupgrade/attach(obj/mecha/M)
var/obj/mecha/working/ripley/mkii/N = new /obj/mecha/working/ripley/mkii(get_turf(M),1)
if(!N)
return
QDEL_NULL(N.cell)
if (M.cell)
N.cell = M.cell
M.cell.forceMove(N)
M.cell = null
N.step_energy_drain = M.step_energy_drain //For the scanning module
N.armor = N.armor.setRating(energy = M.armor["energy"]) //for the capacitor
for(var/obj/item/mecha_parts/E in M.contents)
// if(istype(E, /obj/item/mecha_parts/concealed_weapon_bay)) //why is the bay not just a variable change who did this
// E.forceMove(N)
for(var/obj/item/mecha_parts/mecha_equipment/E in M.equipment) //Move the equipment over...
E.detach()
E.attach(N)
M.equipment -= E
N.dna_lock = M.dna_lock
N.maint_access = M.maint_access
N.strafe = M.strafe
N.obj_integrity = M.obj_integrity //This is not a repair tool
if (M.name != "\improper APLU MK-I \"Ripley\"")
N.name = M.name
M.wreckage = 0
qdel(M)
playsound(get_turf(N),'sound/items/ratchet.ogg',50,1)
return
+73 -35
View File
@@ -18,7 +18,9 @@
var/list/queue = list()
var/processing_queue = 0
var/screen = "main"
var/link_on_init = TRUE
var/temp
var/datum/component/remote_materials/rmat
var/list/part_sets = list(
"Cyborg",
"Ripley",
@@ -33,13 +35,11 @@
"Misc"
)
/obj/machinery/mecha_part_fabricator/Initialize()
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container,
list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), 0,
TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
materials.precise_insertion = TRUE
stored_research = new
return ..()
/obj/machinery/mecha_part_fabricator/Initialize(mapload)
stored_research = new
rmat = AddComponent(/datum/component/remote_materials, "mechfab", mapload && link_on_init)
RefreshParts() //Recalculating local material sizes if the fab isn't linked
return ..()
/obj/machinery/mecha_part_fabricator/RefreshParts()
var/T = 0
@@ -47,8 +47,7 @@
//maximum stocking amount (default 300000, 600000 at T4)
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
T += M.rating
GET_COMPONENT(materials, /datum/component/material_container)
materials.max_amount = (200000 + (T*50000))
rmat.set_local_size((200000 + (T*50000)))
//resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55)
T = 1.15
@@ -62,6 +61,12 @@
T += Ml.rating
time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01)
/obj/machinery/mecha_part_fabricator/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Storing up to <b>[rmat.local_size]</b> material units.<br>Material consumption at <b>[component_coeff*100]%</b>.<br>Build time reduced by <b>[100-time_coeff*100]%</b>.<span>"
/obj/machinery/mecha_part_fabricator/emag_act()
if(obj_flags & EMAGGED)
@@ -104,16 +109,22 @@
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/output
GET_COMPONENT(materials, /datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
output += "<span class=\"res_name\">[M.name]: </span>[M.amount] cm&sup3;"
if(M.amount >= MINERAL_MATERIAL_AMOUNT)
output += "<span style='font-size:80%;'>- Remove \[<a href='?src=[REF(src)];remove_mat=1;material=[mat_id]'>1</a>\]"
if(M.amount >= (MINERAL_MATERIAL_AMOUNT * 10))
output += " | \[<a href='?src=[REF(src)];remove_mat=10;material=[mat_id]'>10</a>\]"
output += " | \[<a href='?src=[REF(src)];remove_mat=50;material=[mat_id]'>All</a>\]</span>"
output += "<br/>"
var/datum/component/material_container/materials = rmat.mat_container
if(materials)
for(var/mat_id in materials.materials)
var/datum/material/M = mat_id
var/amount = materials.materials[mat_id]
var/ref = REF(M)
output += "<span class=\"res_name\">[M.name]: </span>[amount] cm&sup3;"
if(amount >= MINERAL_MATERIAL_AMOUNT)
output += "<span style='font-size:80%;'>- Remove \[<a href='?src=[REF(src)];remove_mat=1;material=[ref]'>1</a>\]"
if(amount >= (MINERAL_MATERIAL_AMOUNT * 10))
output += " | \[<a href='?src=[REF(src)];remove_mat=10;material=[ref]'>10</a>\]"
output += " | \[<a href='?src=[REF(src)];remove_mat=50;material=[ref]'>50</a>\]</span>"
output += "<br>"
else
output += "<font color='red'>No material storage connected, please contact the quartermaster.</font><br>"
return output
/obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D)
@@ -125,18 +136,29 @@
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
if(D.reagents_list.len) // No reagents storage - no reagent designs.
return FALSE
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = rmat.mat_container
if(materials.has_materials(get_resources_w_coeff(D)))
return TRUE
return FALSE
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D)
being_built = D
desc = "It's building \a [initial(D.name)]."
var/list/res_coef = get_resources_w_coeff(D)
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/component/material_container/materials = rmat.mat_container
if (!materials)
say("No access to material storage, please contact the quartermaster.")
return FALSE
if (rmat.on_hold())
say("Mineral access is on hold, please contact the quartermaster.")
return FALSE
if(!check_resources(D))
say("Not enough resources. Queue processing stopped.")
return FALSE
being_built = D
desc = "It's building \a [initial(D.name)]."
materials.use_amount(res_coef)
rmat.silo_log(src, "built", -1, "[D.name]", res_coef)
add_overlay("fab-active")
use_power = ACTIVE_POWER_USE
updateUsrDialog()
@@ -191,13 +213,10 @@
while(D)
if(stat&(NOPOWER|BROKEN))
return FALSE
if(!check_resources(D))
say("Not enough resources. Queue processing stopped.")
temp = {"<span class='alert'>Not enough resources to build next part.</span><br>
<a href='?src=[REF(src)];process_queue=1'>Try again</a> | <a href='?src=[REF(src)];clear_temp=1'>Return</a><a>"}
if(build_part(D))
remove_from_queue(1)
else
return FALSE
remove_from_queue(1)
build_part(D)
D = listgetindex(queue, 1)
say("Queue processing finished successfully.")
@@ -379,16 +398,32 @@
break
if(href_list["remove_mat"] && href_list["material"])
GET_COMPONENT(materials, /datum/component/material_container)
materials.retrieve_sheets(text2num(href_list["remove_mat"]), href_list["material"])
var/datum/material/Mat = locate(href_list["material"])
eject_sheets(Mat, text2num(href_list["remove_mat"]))
updateUsrDialog()
return
/obj/machinery/mecha_part_fabricator/on_deconstruction()
GET_COMPONENT(materials, /datum/component/material_container)
materials.retrieve_all()
..()
/obj/machinery/mecha_part_fabricator/proc/do_process_queue()
if(processing_queue || being_built)
return FALSE
processing_queue = 1
process_queue()
processing_queue = 0
/obj/machinery/mecha_part_fabricator/proc/eject_sheets(eject_sheet, eject_amt)
var/datum/component/material_container/mat_container = rmat.mat_container
if (!mat_container)
say("No access to material storage, please contact the quartermaster.")
return 0
if (rmat.on_hold())
say("Mineral access is on hold, please contact the quartermaster.")
return 0
var/count = mat_container.retrieve_sheets(text2num(eject_amt), eject_sheet, drop_location())
var/list/matlist = list()
matlist[eject_sheet] = text2num(eject_amt)
rmat.silo_log(src, "ejected", -count, "sheets", matlist)
return count
/obj/machinery/mecha_part_fabricator/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
var/stack_name = material2name(id_inserted)
@@ -417,3 +452,6 @@
return FALSE
return TRUE
/obj/machinery/mecha_part_fabricator/maint
link_on_init = FALSE
+34 -5
View File
@@ -69,6 +69,12 @@
var/melee_cooldown = 10
var/melee_can_hit = 1
var/silicon_pilot = FALSE //set to true if an AI or MMI is piloting.
var/enter_delay = 40 //Time taken to enter the mech
var/enclosed = TRUE //Set to false for open-cockpit mechs
var/silicon_icon_state = null //if the mech has a different icon when piloted by an AI or MMI
//Action datums
var/datum/action/innate/mecha/mech_eject/eject_action = new
var/datum/action/innate/mecha/mech_toggle_internals/internals_action = new
@@ -116,7 +122,8 @@
icon_state += "-open"
add_radio()
add_cabin()
add_airtank()
if (enclosed)
add_airtank()
spark_system.set_up(2, 0, src)
spark_system.attach(src)
smoke_system.set_up(3, src)
@@ -133,6 +140,11 @@
diag_hud_set_mechcell()
diag_hud_set_mechstat()
/obj/mecha/update_icon()
if (silicon_pilot && silicon_icon_state)
icon_state = silicon_icon_state
. = ..()
/obj/mecha/get_cell()
return cell
@@ -273,6 +285,11 @@
to_chat(user, "It's equipped with:")
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
to_chat(user, "[icon2html(ME, user)] \A [ME].")
if(!enclosed)
if(silicon_pilot)
to_chat(user, "[src] appears to be piloting itself...")
else if(occupant && occupant != user) //!silicon_pilot implied
to_chat(user, "You can see [occupant] inside.")
//processing internal damage, temperature, air regulation, alert updates, lights power use.
/obj/mecha/process()
@@ -392,13 +409,19 @@
diag_hud_set_mechcell()
diag_hud_set_mechstat()
/obj/mecha/fire_act() //Check if we should ignite the pilot of an open-canopy mech
if (occupant && !enclosed && !silicon_pilot)
if (occupant.fire_stacks < 5)
occupant.fire_stacks += 1
occupant.IgniteMob()
/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits.
return
/obj/mecha/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
. = ..()
if(speaker == occupant)
if(radio.broadcasting)
if(radio?.broadcasting)
radio.talk_into(speaker, text, , spans, message_language)
//flick speech bubble
var/list/speech_bubble_recipients = list()
@@ -474,7 +497,7 @@
. = ..()
if(.)
events.fireEvent("onMove",get_turf(src))
if (internal_tank.disconnect()) // Something moved us and broke connection
if (internal_tank?.disconnect()) // Something moved us and broke connection
occupant_message("<span class='warning'>Air port connection teared off!</span>")
log_message("Lost connection to gas port.")
@@ -500,7 +523,7 @@
user.forceMove(get_turf(src))
to_chat(user, "<span class='notice'>You climb out from [src].</span>")
return 0
if(internal_tank.connected_port)
if(internal_tank?.connected_port)
if(world.time - last_message > 20)
occupant_message("<span class='warning'>Unable to move while connected to the air system port!</span>")
last_message = world.time
@@ -688,6 +711,7 @@
AI.disconnect_shell()
RemoveActions(AI, TRUE)
occupant = null
silicon_pilot = FALSE
AI.forceMove(card)
card.AI = AI
AI.controlled_mech = null
@@ -729,7 +753,9 @@
AI.ai_restore_power()
AI.forceMove(src)
occupant = AI
silicon_pilot = TRUE
icon_state = initial(icon_state)
update_icon()
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
if(!internal_damage)
SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
@@ -832,7 +858,7 @@
visible_message("[user] starts to climb into [name].")
if(do_after(user, 40, target = src))
if(do_after(user, enter_delay, target = src))
if(obj_integrity <= 0)
to_chat(user, "<span class='warning'>You cannot get in the [name], it has been destroyed!</span>")
else if(occupant)
@@ -905,6 +931,7 @@
var/mob/living/brainmob = mmi_as_oc.brainmob
mmi_as_oc.mecha = src
occupant = brainmob
silicon_pilot = TRUE
brainmob.forceMove(src) //should allow relaymove
brainmob.reset_perspective(src)
brainmob.remote_control = src
@@ -946,6 +973,7 @@
RemoveActions(occupant)
occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
occupant = null
silicon_pilot = FALSE
return
else
if(!AI.linked_core)
@@ -963,6 +991,7 @@
return
var/mob/living/L = occupant
occupant = null //we need it null when forceMove calls Exited().
silicon_pilot = FALSE
if(mob_container.forceMove(newloc))//ejecting mob container
log_message("[mob_container] moved out.")
L << browse(null, "window=exosuit")
+2 -1
View File
@@ -3,7 +3,8 @@
/obj/mecha/proc/GrantActions(mob/living/user, human_occupant = 0)
if(human_occupant)
eject_action.Grant(user, src)
internals_action.Grant(user, src)
if(enclosed)
internals_action.Grant(user, src)
cycle_action.Grant(user, src)
lights_action.Grant(user, src)
stats_action.Grant(user, src)
+7 -14
View File
@@ -171,36 +171,29 @@
list(
"key" = TOOL_WRENCH,
"back_key" = TOOL_CROWBAR,
"desc" = "Internal armor is installed."
"desc" = "Outer plating is installed."
),
//17
list(
"key" = TOOL_WELDER,
"back_key" = TOOL_WRENCH,
"desc" = "Internal armor is wrenched."
"desc" = "Outer Plating is wrenched."
),
//18
list(
"key" = /obj/item/stack/sheet/plasteel,
"amount" = 5,
"key" = /obj/item/stack/rods,
"amount" = 10,
"back_key" = TOOL_WELDER,
"desc" = "Internal armor is welded."
"desc" = "Outer Plating is welded."
),
//19
list(
"key" = TOOL_WRENCH,
"back_key" = TOOL_CROWBAR,
"desc" = "External armor is installed."
),
//20
list(
"key" = TOOL_WELDER,
"back_key" = TOOL_WRENCH,
"desc" = "External armor is wrenched."
"back_key" = TOOL_WIRECUTTER,
"desc" = "Cockpit wire screen is installed."
),
)
+1 -1
View File
@@ -76,7 +76,7 @@
var/answer = {"<b>Name:</b> [M.name]
<b>Integrity:</b> [M.obj_integrity/M.max_integrity*100]%
<b>Cell charge:</b> [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]
<b>Airtank:</b> [M.return_pressure()]kPa
<b>Airtank:</b> [M.internal_tank?"[round(M.return_pressure(), 0.01)]":"Not Equipped"] kPa<br>
<b>Pilot:</b> [M.occupant||"None"]
<b>Location:</b> [get_area(M)||"Unknown"]
<b>Active equipment:</b> [M.selected||"None"] "}
+3
View File
@@ -114,6 +114,9 @@
/obj/mecha/bullet_act(obj/item/projectile/Proj) //wrapper
if (!enclosed && occupant && !silicon_pilot) //allows bullets to hit the pilot of open-canopy mechs
occupant.bullet_act(Proj) //If the sides are open, the occupant can be hit
return BULLET_ACT_HIT
log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).", color="red")
. = ..()
+22 -17
View File
@@ -71,19 +71,24 @@
/obj/mecha/proc/get_stats_part()
var/integrity = obj_integrity/max_integrity*100
var/cell_charge = get_charge()
var/datum/gas_mixture/int_tank_air = internal_tank.return_air()
var/tank_pressure = internal_tank ? round(int_tank_air.return_pressure(),0.01) : "None"
var/tank_temperature = internal_tank ? int_tank_air.temperature : "Unknown"
var/cabin_pressure = round(return_pressure(),0.01)
var/datum/gas_mixture/int_tank_air = 0
var/tank_pressure = 0
var/tank_temperature = 0
var/cabin_pressure = 0
if (internal_tank)
int_tank_air = internal_tank.return_air()
tank_pressure = internal_tank ? round(int_tank_air.return_pressure(),0.01) : "None"
tank_temperature = internal_tank ? int_tank_air.temperature : "Unknown"
cabin_pressure = round(return_pressure(),0.01)
. = {"[report_internal_damage()]
[integrity<30?"<span class='userdanger'>DAMAGE LEVEL CRITICAL</span><br>":null]
<b>Integrity: </b> [integrity]%<br>
<b>Powercell charge: </b>[isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]<br>
<b>Air source: </b>[use_internal_tank?"Internal Airtank":"Environment"]<br>
<b>Airtank pressure: </b>[tank_pressure]kPa<br>
<b>Airtank temperature: </b>[tank_temperature]&deg;K|[tank_temperature - T0C]&deg;C<br>
<b>Cabin pressure: </b>[cabin_pressure>WARNING_HIGH_PRESSURE ? "<span class='danger'>[cabin_pressure]</span>": cabin_pressure]kPa<br>
<b>Cabin temperature: </b> [return_temperature()]&deg;K|[return_temperature() - T0C]&deg;C<br>
<b>Air source: </b>[internal_tank?"[use_internal_tank?"Internal Airtank":"Environment"]":"Environment"]<br>
<b>Airtank pressure: </b>[internal_tank?"[tank_pressure]kPa":"N/A"]<br>
<b>Airtank temperature: </b>[internal_tank?"[tank_temperature]&deg;K|[tank_temperature - T0C]&deg;C":"N/A"]<br>
<b>Cabin pressure: </b>[internal_tank?"[cabin_pressure>WARNING_HIGH_PRESSURE ? "<span class='danger'>[cabin_pressure]</span>": cabin_pressure]kPa":"N/A"]<br>
<b>Cabin temperature: </b> [internal_tank?"[return_temperature()]&deg;K|[return_temperature() - T0C]&deg;C":"N/A"]<br>
[dna_lock?"<b>DNA-locked:</b><br> <span style='font-size:10px;letter-spacing:-1px;'>[dna_lock]</span> \[<a href='?src=[REF(src)];reset_dna=1'>Reset</a>\]<br>":""]<br>
[thrusters_action.owner ? "<b>Thrusters: </b> [thrusters_active ? "Enabled" : "Disabled"]<br>" : ""]
[defense_action.owner ? "<b>Defence Mode: </b> [defence_mode ? "Enabled" : "Disabled"]<br>" : ""]
@@ -100,14 +105,14 @@
<div class='header'>Electronics</div>
<div class='links'>
<b>Radio settings:</b><br>
Microphone: <a href='?src=[REF(src)];rmictoggle=1'><span id="rmicstate">[radio.broadcasting?"Engaged":"Disengaged"]</span></a><br>
Speaker: <a href='?src=[REF(src)];rspktoggle=1'><span id="rspkstate">[radio.listening?"Engaged":"Disengaged"]</span></a><br>
Microphone: [radio? "<a href='?src=[REF(src)];rmictoggle=1'><span id=\"rmicstate\">[radio.broadcasting?"Engaged":"Disengaged"]</span></a>":"Error"]<br>
Speaker: [radio? "<a href='?src=[REF(src)];rspktoggle=1'><span id=\"rspkstate\">[radio.listening?"Engaged":"Disengaged"]</span></a>":"Error"]<br>
Frequency:
<a href='?src=[REF(src)];rfreq=-10'>-</a>
<a href='?src=[REF(src)];rfreq=-2'>-</a>
<span id="rfreq">[format_frequency(radio.frequency)]</span>
<a href='?src=[REF(src)];rfreq=2'>+</a>
<a href='?src=[REF(src)];rfreq=10'>+</a><br>
[radio? "<a href='?src=[REF(src)];rfreq=-10'>-</a>":"-"]
[radio? "<a href='?src=[REF(src)];rfreq=-2'>-</a>":"-"]
<span id="rfreq">[radio?"[format_frequency(radio.frequency)]":"Error"]</span>
[radio? "<a href='?src=[REF(src)];rfreq=2'>+</a>":"+"]
[radio? "<a href='?src=[REF(src)];rfreq=10'>+</a><br>":"+"]
</div>
</div>
<div class='wr'>
@@ -115,7 +120,7 @@
<div class='links'>
<a href='?src=[REF(src)];toggle_id_upload=1'><span id='t_id_upload'>[add_req_access?"L":"Unl"]ock ID upload panel</span></a><br>
<a href='?src=[REF(src)];toggle_maint_access=1'><span id='t_maint_access'>[maint_access?"Forbid":"Permit"] maintenance protocols</span></a><br>
<a href='?src=[REF(src)];toggle_port_connection=1'><span id='t_port_connection'>[internal_tank.connected_port?"Disconnect from":"Connect to"] gas port</span></a><br>
[internal_tank?"<a href='?src=[REF(src)];toggle_port_connection=1'><span id='t_port_connection'>[internal_tank.connected_port?"Disconnect from":"Connect to"] gas port</span></a><br>":""]
<a href='?src=[REF(src)];dna_lock=1'>DNA-lock</a><br>
<a href='?src=[REF(src)];view_log=1'>View internal log</a><br>
<a href='?src=[REF(src)];change_name=1'>Change exosuit name</a><br>
+16
View File
@@ -161,6 +161,22 @@
welder_salvage += part
parts -= part
/obj/structure/mecha_wreckage/ripley/mkii
name = "\improper Ripley MK-II wreckage"
icon_state = "ripleymkii-broken"
/obj/structure/mecha_wreckage/ripley/mkii/Initialize()
. = ..()
var/list/parts = list(/obj/item/mecha_parts/part/ripley_torso,
/obj/item/mecha_parts/part/ripley_left_arm,
/obj/item/mecha_parts/part/ripley_right_arm,
/obj/item/mecha_parts/part/ripley_left_leg,
/obj/item/mecha_parts/part/ripley_right_leg)
for(var/i = 0; i < 2; i++)
if(parts.len && prob(40))
var/part = pick(parts)
welder_salvage += part
parts -= part
/obj/structure/mecha_wreckage/ripley/firefighter
name = "\improper Firefighter wreckage"
+44 -10
View File
@@ -1,10 +1,11 @@
/obj/mecha/working/ripley
desc = "Autonomous Power Loader Unit. This newer model is refitted with powerful armour against the dangers of planetary mining."
name = "\improper APLU \"Ripley\""
desc = "Autonomous Power Loader Unit MK-I. Designed primarily around heavy lifting, the Ripley can be outfitted with utility equipment to fill a number of roles."
name = "\improper APLU MK-I \"Ripley\""
icon_state = "ripley"
step_in = 3 //Move speed, lower is faster.
var/fast_pressure_step_in = 2
var/slow_pressure_step_in = 3
silicon_icon_state = "ripley-empty"
step_in = 1.5 //Move speed, lower is faster.
var/fast_pressure_step_in = 1.5 //step_in while in low pressure conditions
var/slow_pressure_step_in = 2.0 //step_in while in normal pressure conditions
max_temperature = 20000
max_integrity = 200
lights_power = 8
@@ -15,6 +16,9 @@
var/list/cargo = new
var/cargo_capacity = 15
var/hides = 0
enclosed = FALSE //Normal ripley has an open cockpit design
enter_delay = 10 //can enter in a quarter of the time of other mechs
opacity = FALSE //Ripley has a window
/obj/mecha/working/ripley/Move()
. = ..()
@@ -55,18 +59,38 @@
else
add_overlay(occupant ? "ripley-g-full" : "ripley-g-full-open")
/obj/mecha/working/ripley/check_for_internal_damage(list/possible_int_damage,ignore_threshold=null)
if (!enclosed)
possible_int_damage -= (MECHA_INT_TEMP_CONTROL + MECHA_INT_TANK_BREACH) //if we don't even have an air tank, these two doesn't make a ton of sense.
. = ..()
/obj/mecha/working/ripley/Initialize()
. = ..()
AddComponent(/datum/component/armor_plate,3,/obj/item/stack/sheet/animalhide/goliath_hide,list("melee" = 10, "bullet" = 5, "laser" = 5))
/obj/mecha/working/ripley/mkii
desc = "Autonomous Power Loader Unit MK-II. This prototype Ripley is refitted with a pressurized cabin, trading its prior speed for atmospheric protection"
name = "\improper APLU MK-II \"Ripley\""
icon_state = "ripleymkii"
fast_pressure_step_in = 2 //step_in while in low pressure conditions
slow_pressure_step_in = 4 //step_in while in normal pressure conditions
step_in = 4
armor = list("melee" = 40, "bullet" = 20, "laser" = 10, "energy" = 20, "bomb" = 40, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
wreckage = /obj/structure/mecha_wreckage/ripley/mkii
enclosed = TRUE
enter_delay = 40
silicon_icon_state = null
opacity = TRUE
/obj/mecha/working/ripley/firefighter
desc = "Autonomous Power Loader Unit. This model is refitted with additional thermal protection."
name = "\improper APLU \"Firefighter\""
desc = "Autonomous Power Loader Unit MK-III. This model is refitted with a pressurized cabin and additional thermal protection."
name = "\improper APLU MK-III \"Firefighter\""
icon_state = "firefighter"
step_in = 4
fast_pressure_step_in = 2
slow_pressure_step_in = 4
fast_pressure_step_in = 2 //step_in while in low pressure conditions
slow_pressure_step_in = 4 //step_in while in normal pressure conditions
step_in = 4
max_temperature = 65000
max_integrity = 250
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
@@ -74,6 +98,10 @@
armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
max_equip = 5 // More armor, less tools
wreckage = /obj/structure/mecha_wreckage/ripley/firefighter
enclosed = TRUE
enter_delay = 40
silicon_icon_state = null
opacity = TRUE
/obj/mecha/working/ripley/deathripley
@@ -81,11 +109,17 @@
name = "\improper DEATH-RIPLEY"
icon_state = "deathripley"
armor = list("melee" = 40, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 40, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
slow_pressure_step_in = 3
fast_pressure_step_in = 2 //step_in while in low pressure conditions
slow_pressure_step_in = 4 //step_in while in normal pressure conditions
step_in = 4
opacity=0
lights_power = 7
wreckage = /obj/structure/mecha_wreckage/ripley/deathripley
step_energy_drain = 0
enclosed = TRUE
enter_delay = 40
silicon_icon_state = null
opacity = TRUE
/obj/mecha/working/ripley/deathripley/Initialize()
. = ..()
@@ -39,6 +39,9 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
/obj/item/stack/sheet/glass/fifty
amount = 50
/obj/item/stack/sheet/glass/five
amount = 5
/obj/item/stack/sheet/glass/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.glass_recipes
return ..()
@@ -55,6 +55,9 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \
/obj/item/stack/sheet/mineral/sandstone/thirty
amount = 30
/obj/item/stack/sheet/mineral/sandstone/twelve
amount = 12
/*
* Sandbags
*/
+7 -7
View File
@@ -104,12 +104,12 @@
playing = FALSE
hearing_mobs = null
return
if(!lentext(note))
if(!length(note))
continue
var/cur_note = text2ascii(note) - 96
if(cur_note < 1 || cur_note > 7)
continue
for(var/i=2 to lentext(note))
for(var/i=2 to length(note))
var/ni = copytext(note,i,i+1)
if(!text2num(ni))
if(ni == "#" || ni == "b" || ni == "n")
@@ -209,7 +209,7 @@
lines.Cut(MUSIC_MAXLINES + 1)
var/linenum = 1
for(var/l in lines)
if(lentext(l) > MUSIC_MAXLINECHARS)
if(length(l) > MUSIC_MAXLINECHARS)
to_chat(usr, "Line [linenum] too long!")
lines.Remove(l)
else
@@ -236,11 +236,11 @@
if(!in_range(instrumentObj, usr))
return
if(lentext(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
if(length(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no")
if(cont == "no")
break
while(lentext(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
while(length(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
ParseSong(t)
else if(href_list["help"])
@@ -272,7 +272,7 @@
return
if(lines.len > MUSIC_MAXLINES)
return
if(lentext(newline) > MUSIC_MAXLINECHARS)
if(length(newline) > MUSIC_MAXLINECHARS)
newline = copytext(newline, 1, MUSIC_MAXLINECHARS)
lines.Add(newline)
@@ -287,7 +287,7 @@
var/content = html_encode(input("Enter your line: ", instrumentObj.name, lines[num]) as text|null)
if(!content || !in_range(instrumentObj, usr))
return
if(lentext(content) > MUSIC_MAXLINECHARS)
if(length(content) > MUSIC_MAXLINECHARS)
content = copytext(content, 1, MUSIC_MAXLINECHARS)
if(num > lines.len || num < 1)
return
+1
View File
@@ -100,6 +100,7 @@ GLOBAL_VAR(restart_counter)
GLOB.picture_log_directory = "data/picture_logs/[override_dir]"
GLOB.world_game_log = "[GLOB.log_directory]/game.log"
GLOB.world_cloning_log = "[GLOB.log_directory]/cloning.log"
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
+4 -4
View File
@@ -2152,7 +2152,7 @@
return
src.admincaster_feed_channel.channel_name = stripped_input(usr, "Provide a Feed Channel Name.", "Network Channel Handler", "")
while (findtext(src.admincaster_feed_channel.channel_name," ") == 1)
src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,lentext(src.admincaster_feed_channel.channel_name)+1)
src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,length(src.admincaster_feed_channel.channel_name)+1)
src.access_news_network()
else if(href_list["ac_set_channel_lock"])
@@ -2194,7 +2194,7 @@
return
src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story.", "Network Channel Handler", ""))
while (findtext(src.admincaster_feed_message.returnBody(-1)," ") == 1)
src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.returnBody(-1),2,lentext(src.admincaster_feed_message.returnBody(-1))+1)
src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.returnBody(-1),2,length(src.admincaster_feed_message.returnBody(-1))+1)
src.access_news_network()
else if(href_list["ac_submit_new_message"])
@@ -2255,7 +2255,7 @@
return
src.admincaster_wanted_message.criminal = adminscrub(input(usr, "Provide the name of the Wanted person.", "Network Security Handler", ""))
while(findtext(src.admincaster_wanted_message.criminal," ") == 1)
src.admincaster_wanted_message.criminal = copytext(admincaster_wanted_message.criminal,2,lentext(admincaster_wanted_message.criminal)+1)
src.admincaster_wanted_message.criminal = copytext(admincaster_wanted_message.criminal,2,length(admincaster_wanted_message.criminal)+1)
src.access_news_network()
else if(href_list["ac_set_wanted_desc"])
@@ -2263,7 +2263,7 @@
return
src.admincaster_wanted_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important.", "Network Security Handler", ""))
while (findtext(src.admincaster_wanted_message.body," ") == 1)
src.admincaster_wanted_message.body = copytext(src.admincaster_wanted_message.body,2,lentext(src.admincaster_wanted_message.body)+1)
src.admincaster_wanted_message.body = copytext(src.admincaster_wanted_message.body,2,length(src.admincaster_wanted_message.body)+1)
src.access_news_network()
else if(href_list["ac_submit_wanted"])
+5 -5
View File
@@ -307,11 +307,11 @@ GLOBAL_PROTECT(VVpixelmovement)
// the type with the base type removed from the begaining
var/fancytype = types[D.type]
if (findtext(fancytype, types[type]))
fancytype = copytext(fancytype, lentext(types[type])+1)
var/shorttype = copytext("[D.type]", lentext("[type]")+1)
if (lentext(shorttype) > lentext(fancytype))
fancytype = copytext(fancytype, length(types[type])+1)
var/shorttype = copytext("[D.type]", length("[type]")+1)
if (length(shorttype) > length(fancytype))
shorttype = fancytype
if (!lentext(shorttype))
if (!length(shorttype))
shorttype = "/"
.["[D]([shorttype])[REF(D)]#[i]"] = D
@@ -534,7 +534,7 @@ GLOBAL_PROTECT(VVpixelmovement)
if (prompt != "Continue")
return FALSE
return TRUE
/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0)
if(!check_rights(R_VAREDIT))
+376 -9
View File
@@ -82,7 +82,7 @@
crate_type = /obj/structure/closet/crate/internals
/datum/supply_pack/emergency/radiatione_emergency
name = "Emergenc Radiation Protection Crate"
name = "Emergency Radiation Protection Crate"
desc = "Survive the Nuclear Apocalypse and Supermatter Engine alike with two sets of Radiation suits. Each set contains a helmet, suit, and Geiger counter. We'll even throw in a few pill bottles that are able to handles radiation and the affects of the poisoning."
cost = 2500
contains = list(/obj/item/clothing/head/radiation,
@@ -293,7 +293,7 @@
/datum/supply_pack/medical/anitvirus
name = "Virus Containment Crate"
desc = "Viro let out a death plague Mk II again? Someone didnt wash there hands? Old plagues born anew? Well this crate is for you! Hope you cure it before it brakes out of the station... This crate needs medical access to open and has two bio suits, a box of needles and beakers, five spaceacillin needles, and a medibot."
desc = "Viro let out a death plague Mk II again? Someone didnt wash their hands? Old plagues born anew? Well this crate is for you! Hope you cure it before it breaks out of the station... This crate needs medical access to open and has two bio suits, a box of needles and beakers, five spaceacillin needles, and a medibot."
cost = 3000
access = ACCESS_MEDICAL
contains = list(/mob/living/simple_animal/bot/medbot,
@@ -311,6 +311,56 @@
crate_name = "virus containment unit crate"
crate_type = /obj/structure/closet/crate/secure/plasma
/datum/supply_pack/emergency/medicalemergency
name = "Emergency Medical Supplies"
desc = "Emergency supplies for a front-line medic. Contains two boxes of body bags, a medical HUD, a defib unit, medical belt, toxin bottles, epipens, and several types of medical kits."
cost = 6600
contains = list(/obj/item/storage/box/bodybags,
/obj/item/storage/box/bodybags,
/obj/item/clothing/glasses/hud/health,
/obj/item/defibrillator/loaded,
/obj/item/storage/belt/medical,
/obj/item/storage/firstaid/toxin,
/obj/item/storage/firstaid/o2,
/obj/item/storage/firstaid/brute,
/obj/item/storage/firstaid/fire,
/obj/item/reagent_containers/glass/bottle/toxin,
/obj/item/reagent_containers/glass/bottle/toxin,
/obj/item/storage/box/medipens)
crate_name = "medical emergency crate"
crate_type = /obj/structure/closet/crate/medical
/datum/supply_pack/emergency/medemergencylite
name = "Emergency Medical Supplies (Lite)"
desc = "A less than optimal, but still effective, set of tools for emergency care. Contains a box of bodybags, a medical HUD, healing sprays, charcoal, some gauze, and some spare medipens."
cost = 2800
contains = list(/obj/item/storage/box/bodybags,
/obj/item/stack/medical/gauze,
/obj/item/clothing/glasses/hud/health,
/obj/item/reagent_containers/medspray/styptic,
/obj/item/reagent_containers/medspray/silver_sulf,
/obj/item/reagent_containers/medspray/synthflesh,
/obj/item/reagent_containers/glass/bottle/charcoal,
/obj/item/reagent_containers/glass/bottle/charcoal,
/obj/item/reagent_containers/hypospray/medipen,
/obj/item/reagent_containers/hypospray/medipen,
/obj/item/reagent_containers/hypospray/medipen)
crate_name = "medical emergency crate (lite)"
crate_type = /obj/structure/closet/crate/medical
/datum/supply_pack/emergency/mre
name = "MRE supply kit (emergency rations)"
desc = "The lights are out. Oxygen's running low. You've run out of food except space weevils. Don't let this be you! Order our NT branded MRE kits today! This pack contains 5 MRE packs with a randomized menu and an oxygen tank."
cost = 2000
contains = list(/obj/item/storage/box/mre/menu1/safe,
/obj/item/storage/box/mre/menu1/safe,
/obj/item/storage/box/mre/menu2/safe,
/obj/item/storage/box/mre/menu2/safe,
/obj/item/storage/box/mre/menu3,
/obj/item/storage/box/mre/menu4/safe)
crate_name = "MRE crate (emergency rations)"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Security ////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -813,7 +863,7 @@
/datum/supply_pack/engineering/industrialrcd
name = "Industrial RCD"
desc = "A industrial RCD in case the station has gone through more then one meteor storm and the CE needs to bring out the somthing a bit more reliable. Dose not contain spare ammo for the industrial RCD or any other RCD modles."
desc = "A industrial RCD in case the station has gone through more then one meteor storm and the CE needs to bring out the somthing a bit more reliable. Does not contain spare ammo for the industrial RCD or any other RCD modles."
cost = 4500
access = ACCESS_CE
contains = list(/obj/item/construction/rcd/industrial)
@@ -860,6 +910,18 @@
crate_name = "power cell crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
/datum/supply_pack/engineering/powertools
name = "Power Tools Crate"
desc = "Setting up the aux base? Working out in space? Maybe you just hate doing things by hand. Grab some power tools and slash your workload in half! Contains a hardhat, hazard vest, Hand Drill, and Jaws of Life"
cost = 6500
access = ACCESS_ENGINE
contains = list(/obj/item/clothing/head/hardhat,
/obj/item/clothing/suit/hazardvest,
/obj/item/screwdriver/power,
/obj/item/crowbar/power)
crate_name = "power tools crate"
crate_type = /obj/structure/closet/crate/secure/engineering
/datum/supply_pack/engineering/shuttle_engine
name = "Shuttle Engine Crate"
desc = "Through advanced bluespace-shenanigans, our engineers have managed to fit an entire shuttle engine into one tiny little crate. Requires CE access to open."
@@ -1282,6 +1344,16 @@
group = "Medical"
crate_type = /obj/structure/closet/crate/medical
/datum/supply_pack/medical/bodybags
name = "Bodybags"
desc = "For when the bodies hit the floor. Contains 4 boxes of bodybags."
cost = 1200
contains = list(/obj/item/storage/box/bodybags,
/obj/item/storage/box/bodybags,
/obj/item/storage/box/bodybags,
/obj/item/storage/box/bodybags,)
crate_name = "bodybag crate"
/datum/supply_pack/medical/firstaidbruises
name = "Bruise Treatment Kit Crate"
desc = "Contains three first aid kits focused on healing bruises and broken bones."
@@ -1343,7 +1415,7 @@
/datum/supply_pack/science/adv_surgery_tools
name = "Med-Co Advanced surgery tools"
desc = "A full set of Med-Co advanced surgery tools, this crate also comes with a spay of synth flesh as well as a can of . Requires Surgery access to open."
desc = "A full set of Med-Co advanced surgery tools, this crate both a can of synthflesh and a can of sterilizine. Requires Surgery access to open."
cost = 5000
access = ACCESS_SURGERY
contains = list(/obj/item/storage/belt/medical/surgery_belt_adv,
@@ -1494,6 +1566,37 @@
group = "Science"
crate_type = /obj/structure/closet/crate/science
/datum/supply_pack/science/aliens
name = "Advanced Alien Alloy Crate Crate"
desc = "Hello brothers from the stars!!! Our fellow brethren have made contact at long last and gave us gifts man! They really did build the prymi- Connection Error- Bro well send you a sheet of advanced alien alloy."
cost = 15000
contraband = TRUE
DropPodOnly = TRUE
contains = list(/obj/item/stack/sheet/mineral/abductor)
crate_name = "alien bro alloy crate"
/datum/supply_pack/science/beakers
name = "Chemistry Beakers Crate"
desc = "Glassware for any chemistry lab! Contains four small beakers, three large, two plastic, and one metamaterial. As well as three droppers and two pairs of latex gloves."
cost = 2000
contains = list(/obj/item/reagent_containers/glass/beaker,
/obj/item/reagent_containers/glass/beaker,
/obj/item/reagent_containers/glass/beaker,
/obj/item/reagent_containers/glass/beaker,
/obj/item/reagent_containers/glass/beaker/large,
/obj/item/reagent_containers/glass/beaker/large,
/obj/item/reagent_containers/glass/beaker/large,
/obj/item/reagent_containers/glass/beaker/plastic,
/obj/item/reagent_containers/glass/beaker/plastic,
/obj/item/reagent_containers/glass/beaker/meta,
/obj/item/reagent_containers/glass/beaker/noreact,
/obj/item/reagent_containers/dropper,
/obj/item/reagent_containers/dropper,
/obj/item/reagent_containers/dropper,
/obj/item/clothing/gloves/color/latex,
/obj/item/clothing/gloves/color/latex)
crate_name = "chemistry beaker crate"
/datum/supply_pack/science/robotics/mecha_odysseus
name = "Circuit Crate (Odysseus)"
desc = "Ever wanted to build your own giant medical robot? Well, now you can! Contains the Odysseus main control board and Odysseus peripherals board. Requires Robotics access to open."
@@ -1525,6 +1628,15 @@
/obj/item/integrated_electronics/wirer)
crate_name = "circuitry starter pack crate"
/datum/supply_pack/science/nitrilegloves
name = "Nitrile Gloves Crate"
desc = "Handling toxic chemicals? Well worry not, keep your flesh intact with some nitrile made gloves! Contains three pairs of nitrile gloves."
cost = 1500
contains = list(/obj/item/clothing/gloves/color/latex/nitrile,
/obj/item/clothing/gloves/color/latex/nitrile,
/obj/item/clothing/gloves/color/latex/nitrile)
crate_name = "nitrile gloves crate"
/datum/supply_pack/science/plasma
name = "Plasma Assembly Crate"
desc = "Everything you need to burn something to the ground, this contains three plasma assembly sets. Each set contains a plasma tank, igniter, proximity sensor, and timer! Warranty void if exposed to high temperatures. Requires Toxins access to open."
@@ -1572,10 +1684,19 @@
crate_name = "shield generators crate"
crate_type = /obj/structure/closet/crate/secure/science
/datum/supply_pack/science/slime
name = "Slime Core Crate"
desc = "Ran out of slimes? No problem, contains one gray slime core. Requires Xenobio access to open."
cost = 1000
access = ACCESS_XENOBIOLOGY
contains = list(/obj/item/slime_extract/grey)
crate_name = "slime core crate"
crate_type = /obj/structure/closet/crate/secure/science
/datum/supply_pack/science/tablets
name = "Tablet Crate"
desc = "What's a computer? Contains five cargo tablets."
cost = 5000
cost = 3000
contains = list(/obj/item/modular_computer/tablet/preset/cargo,
/obj/item/modular_computer/tablet/preset/cargo,
/obj/item/modular_computer/tablet/preset/cargo,
@@ -1622,6 +1743,20 @@
crate_name = "advanced lighting crate"
crate_type = /obj/structure/closet/crate/secure
/datum/supply_pack/service/janitor/advanced
name = "Advanced Sanitation Crate"
desc = "Contains all the essentials for an advanced spacefaring cleanup crew. This kit includes a trashbag of holding, an advanced mop, a bottle of space cleaner, a floor buffer, and a holosign projector."
cost = 5000
access = ACCESS_JANITOR
contains = list(/obj/item/storage/bag/trash/bluespace,
/obj/item/reagent_containers/spray/cleaner,
/obj/item/mop/advanced,
/obj/item/lightreplacer,
/obj/item/janiupgrade,
/obj/item/holosign_creator)
crate_name = "advanced santation crate"
crate_type = /obj/structure/closet/crate/secure
/datum/supply_pack/service/cargo_supples
name = "Cargo Supplies Crate"
desc = "Sold everything that wasn't bolted down? You can get right back to work with this crate containing stamps, an export scanner, destination tagger, hand labeler and some package wrapping."
@@ -1658,6 +1793,65 @@
crate_name = "ice cream vat crate"
crate_type = /obj/structure/closet/crate
/datum/supply_pack/service/buildabar
name = "Build a Bar Crate"
desc = "Looking to set up your own little safe haven? Maintenance bar too much of a bummer to work on? Maybe you just want to set up shop right in front of the bartender. Whatever your reasons, get a jump-start on this with this handy kit. Contains circuitboards for bar equipment, some parts, and some basic bartending supplies. (Batteries not Included)"
cost = 3750
contains = list(/obj/item/storage/box/drinkingglasses,
/obj/item/storage/box/drinkingglasses,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/manipulator,
/obj/item/stock_parts/manipulator,
/obj/item/stock_parts/manipulator,
/obj/item/stock_parts/capacitor,
/obj/item/stock_parts/capacitor,
/obj/item/stack/sheet/metal/ten,
/obj/item/stack/sheet/metal/five,
/obj/item/stack/sheet/glass/five,
/obj/item/stack/cable_coil/random,
/obj/item/reagent_containers/rag,
/obj/item/book/manual/wiki/barman_recipes,
/obj/item/book/granter/action/drink_fling,
/obj/item/reagent_containers/food/drinks/shaker,
/obj/item/clothing/under/waiter,
/obj/item/clothing/under/rank/bartender,
/obj/item/clothing/under/rank/bartender/skirt,
/obj/item/clothing/accessory/waistcoat,
/obj/item/circuitboard/machine/chem_dispenser/drinks/beer,
/obj/item/circuitboard/machine/chem_dispenser/drinks,
/obj/item/circuitboard/machine/dish_drive)
crate_name = "build a bar crate"
/datum/supply_pack/service/maintgarden
name = "Maintenance Garden Crate"
desc = "Set up your own tiny paradise with do-it-yourself botany kit. Contains sandstone for dirt plots, pest spray, ammonia, a portable seed generator, basic botanical tools, and some seeds to start off with."
cost = 2350
contains = list(/obj/item/storage/bag/plants/portaseeder,
/obj/item/reagent_containers/spray/pestspray,
/obj/item/stack/sheet/mineral/sandstone/twelve,
/obj/item/reagent_containers/glass/bucket,
/obj/item/reagent_containers/glass/bottle/ammonia,
/obj/item/reagent_containers/glass/bottle/ammonia,
/obj/item/hatchet,
/obj/item/cultivator,
/obj/item/plant_analyzer,
/obj/item/flashlight,
/obj/item/seeds/carrot,
/obj/item/seeds/carrot,
/obj/item/seeds/tower,
/obj/item/seeds/tower,
/obj/item/seeds/watermelon,
/obj/item/seeds/watermelon,
/obj/item/seeds/grass,
/obj/item/seeds/grass)
crate_name = "maint garden crate"
crate_type = /obj/structure/closet/crate/hydroponics
/datum/supply_pack/service/janitor
name = "Janitorial Supplies Crate"
desc = "Fight back against dirt and grime with Nanotrasen's Janitorial Essentials(tm)! Contains three buckets, caution signs, and cleaner grenades. Also has a single mop, spray cleaner, rag, NT soap and a trash bag."
@@ -1974,6 +2168,25 @@
/obj/item/reagent_containers/food/snacks/grown/banana)
crate_name = "food crate"
/datum/supply_pack/organic/fiestatortilla
name = "Fiesta Crate"
desc = "Spice up the kitchen with this fiesta themed food order! Contains 8 tortilla based food items, as well as a sombrero, moustache, and cloak!"
cost = 2750
contains = list(/obj/item/clothing/head/sombrero,
/obj/item/clothing/suit/hooded/cloak/david,
/obj/item/clothing/mask/fakemoustache,
/obj/item/reagent_containers/food/snacks/taco,
/obj/item/reagent_containers/food/snacks/taco,
/obj/item/reagent_containers/food/snacks/taco/plain,
/obj/item/reagent_containers/food/snacks/taco/plain,
/obj/item/reagent_containers/food/snacks/enchiladas,
/obj/item/reagent_containers/food/snacks/enchiladas,
/obj/item/reagent_containers/food/snacks/carneburrito,
/obj/item/reagent_containers/food/snacks/cheesyburrito,
/obj/item/reagent_containers/glass/bottle/capsaicin,
/obj/item/reagent_containers/glass/bottle/capsaicin)
crate_name = "fiesta crate"
/datum/supply_pack/organic/cream_piee
name = "High-yield Clown-grade Cream Pie Crate"
desc = "Designed by Aussec's Advanced Warfare Research Division, these high-yield, Clown-grade cream pies are powered by a synergy of performance and efficiency. Guaranteed to provide maximum results."
@@ -1985,8 +2198,8 @@
crate_type = /obj/structure/closet/crate/secure
/datum/supply_pack/organic/hunting
name = "Huntting gear"
desc = "Even in space, we can fine prey to hunt, this crate contains everthing a fine hunter needs to have a sporting time. This crate needs armory access to open. A true huntter only needs a fine bottle of cognac, a nice coat, some good o' cigars, and of cource a huntting shotgun. "
name = "Hunting gear"
desc = "Even in space, we can find prey to hunt, this crate contains everthing a fine hunter needs to have a sporting time. This crate needs armory access to open. A true huntter only needs a fine bottle of cognac, a nice coat, some good o' cigars, and of cource a hunting shotgun. "
cost = 3500
contraband = TRUE
contains = list(/obj/item/clothing/head/flatcap,
@@ -2000,6 +2213,42 @@
crate_name = "sporting crate"
crate_type = /obj/structure/closet/crate/secure // Would have liked a wooden crate but access >:(
/datum/supply_pack/organic/fakemeat
name = "Meat Crate"
desc = "Run outta meat already? Keep the lizards content with this freezer filled with cruelty-free chemically compounded meat! Contains 4 slabs of meat product, and two slabs of *carp*."
cost = 1700
contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
/obj/item/reagent_containers/food/snacks/carpmeat/imitation,
/obj/item/reagent_containers/food/snacks/carpmeat/imitation)
crate_name = "meaty crate"
crate_type = /obj/structure/closet/crate/freezer
/datum/supply_pack/organic/monkeydripmeat
name = "*Meat* Crate"
desc = "Need some meat? With this do-it-yourself kit you'll be swimming in it! Contains a monkey cube, an IV drip, and some cryoxadone!"
cost = 2150
contraband = TRUE
contains = list(/obj/item/reagent_containers/food/snacks/monkeycube,
/obj/item/restraints/handcuffs/cable,
/obj/machinery/iv_drip,
/obj/item/reagent_containers/glass/beaker/cryoxadone,
/obj/item/reagent_containers/glass/beaker/cryoxadone)
crate_name = "monkey meat crate"
/datum/supply_pack/organic/mixedboxes
name = "Mixed Ingredient Boxes"
desc = "Get overwhelmed with inspiration by ordering these boxes of surprise ingredients! Get four boxes filled with an assortment of products!"
cost = 2300
contains = list(/obj/item/storage/box/ingredients/wildcard,
/obj/item/storage/box/ingredients/wildcard,
/obj/item/storage/box/ingredients/wildcard,
/obj/item/storage/box/ingredients/wildcard)
crate_name = "wildcard food crate"
crate_type = /obj/structure/closet/crate/freezer
/datum/supply_pack/organic/hydroponics
name = "Hydroponics Crate"
desc = "Supplies for growing a great garden! Contains two bottles of ammonia, two Plant-B-Gone spray bottles, a hatchet, cultivator, plant analyzer, as well as a pair of leather gloves and a botanist's apron."
@@ -2124,6 +2373,21 @@
crate_name = "valentine crate"
crate_type = /obj/structure/closet/crate/secure
/datum/supply_pack/organic/strangeseeds
name = "Strange Seeds Crate"
desc = "After our chemical waste mysteriously disappeared we've discovered many strange and interesting species of plants, and they're yours for the taking! Contains 8 packs of strange seeds."
cost = 4500
contains = list(/obj/item/seeds/random,
/obj/item/seeds/random,
/obj/item/seeds/random,
/obj/item/seeds/random,
/obj/item/seeds/random,
/obj/item/seeds/random,
/obj/item/seeds/random,
/obj/item/seeds/random)
crate_name = "strange seeds crate"
crate_type = /obj/structure/closet/crate/hydroponics
/datum/supply_pack/organic/exoticseeds
name = "Exotic Seeds Crate"
desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!"
@@ -2276,6 +2540,18 @@
/mob/living/simple_animal/hostile/retaliate/poison/snake)
crate_name = "snake crate"
/datum/supply_pack/critter/mouse
name = "Mouse Crate"
desc = "Good for snakes and lizards of all ages. Contains ~12 feeder mice."
cost = 2000
contains = list(/mob/living/simple_animal/mouse,)
crate_name = "mouse crate"
/datum/supply_pack/critter/mouse/generate()
. = ..()
for(var/i in 1 to 11)
new /mob/living/simple_animal/mouse(.)
/datum/supply_pack/critter/secbat
name = "Security Bat Crate"
desc = "Contains five security bats, perfect to Bat-up any security officer."
@@ -2648,7 +2924,10 @@
name = "Kinkmate construction kit"
cost = 2000
contraband = TRUE
contains = list(/obj/item/vending_refill/kink, /obj/item/circuitboard/machine/kinkmate)
contains = list(/obj/item/vending_refill/kink,
/obj/item/vending_refill/kink,
/obj/item/vending_refill/kink,
/obj/item/circuitboard/machine/kinkmate)
crate_name = "Kinkmate construction kit"
//////////////////////////////////////////////////////////////////////////////
@@ -2687,6 +2966,35 @@
crate_name = "captain pen"
crate_type = /obj/structure/closet/crate/secure/weapon //It is a combat pen
/datum/supply_pack/misc/randombedsheets
name = "Bedsheet Crate (R)"
desc = "Snuggle up in some sweet sheets with this assorted bedsheet crate. Each set comes with eight random bedsheets for your slumbering pleasure!"
cost = 2000
contains = list(/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random) //I'm lazy, and I copy paste stuff.
crate_name = "random bedsheet crate"
/datum/supply_pack/misc/coloredsheets
name = "Bedsheet Crate (C)"
desc = "Give your night life a splash of color with this crate filled with bedsheets! Contains a total of nine different-colored sheets."
cost = 1250
contains = list(/obj/item/bedsheet/blue,
/obj/item/bedsheet/green,
/obj/item/bedsheet/orange,
/obj/item/bedsheet/purple,
/obj/item/bedsheet/red,
/obj/item/bedsheet/yellow,
/obj/item/bedsheet/brown,
/obj/item/bedsheet/black,
/obj/item/bedsheet/rainbow)
crate_name = "colored bedsheet crate"
/datum/supply_pack/misc/bicycle
name = "Bicycle"
desc = "Nanotrasen reminds all employees to never toy with powers outside their control."
@@ -2722,6 +3030,36 @@
/obj/item/book/random/triple)
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/misc/cbtpack
name = "CBT Equipment"
desc = "(*!&@#CBT is a special term coined by high ranking syndicate operatives for a special form of information extraction. While the training required to use this shipment is highly classified, the distribution of it's contents are not. In addition to this crates unusual contents, we have added a bar of soap.#@*$"
hidden = TRUE
cost = 2400
contains = list(/mob/living/simple_animal/chicken,
/obj/item/toy/beach_ball/holoball,
/obj/item/melee/baton/cattleprod,
/obj/item/soap/syndie)
crate_name = "cbt crate"
crate_type = /obj/structure/closet/crate/large
/datum/supply_pack/misc/casinocrate
name = "Casino Crate"
desc = "Start up your own grand casino with this crate filled with slot machine and arcade boards!"
cost = 3000
contains = list(/obj/item/circuitboard/computer/arcade/battle,
/obj/item/circuitboard/computer/arcade/battle,
/obj/item/circuitboard/computer/arcade/orion_trail,
/obj/item/circuitboard/computer/arcade/orion_trail,
/obj/item/circuitboard/computer/arcade/minesweeper,
/obj/item/circuitboard/computer/arcade/minesweeper,
/obj/item/circuitboard/computer/slot_machine,
/obj/item/circuitboard/computer/slot_machine,
/obj/item/circuitboard/computer/slot_machine,
/obj/item/circuitboard/computer/slot_machine,
/obj/item/circuitboard/computer/slot_machine,
/obj/item/circuitboard/computer/slot_machine)
crate_name = "casino crate"
/datum/supply_pack/misc/paper
name = "Bureaucracy Crate"
desc = "High stacks of papers on your desk Are a big problem - make it Pea-sized with these bureaucratic supplies! Contains five pens, some camera film, hand labeler supplies, a paper bin, three folders, two clipboards and two stamps as well as a briefcase."//that was too forced
@@ -2804,11 +3142,13 @@
/datum/supply_pack/misc/lewd
name = "Lewd Crate" // OwO
desc = "Psss want to have a good time with your sluts? Well I got what you want maid clothing, dildos, collars and more!"
desc = "Psss want to have a good time with your sluts? Well I got what you want! Maid clothing, dildos, collars and more!"
cost = 5000
contraband = TRUE
contains = list(/obj/item/dildo/custom,
/obj/item/dildo/custom,
/obj/item/circuitboard/machine/kinkmate,
/obj/item/vending_refill/kink,
/obj/item/vending_refill/kink,
/obj/item/vending_refill/kink,
/obj/item/clothing/under/maid,
@@ -2859,6 +3199,33 @@
/obj/item/autosurgeon/womb)
crate_name = "promiscuous organs"
/datum/supply_pack/misc/shower
name = "Shower Supplies"
desc = "Everyone needs a bit of R&R. Make sure you get can get yours by ordering this crate filled with towels, rubber duckies, and some soap!"
cost = 1000
contains = list(/obj/item/reagent_containers/rag/towel,
/obj/item/reagent_containers/rag/towel,
/obj/item/reagent_containers/rag/towel,
/obj/item/reagent_containers/rag/towel,
/obj/item/reagent_containers/rag/towel,
/obj/item/reagent_containers/rag/towel,
/obj/item/bikehorn/rubberducky,
/obj/item/bikehorn/rubberducky,
/obj/item/soap/nanotrasen)
crate_name = "shower crate"
/datum/supply_pack/misc/spacehermitstarter
name = "Space Hermit Starter Pack"
desc = "So sick of the station you wish to leave and never come back? Or perhaps you need to find a place of solitutde and privacy? Jumping out of an external airlock may just be the solution for you! But not before you buy this crate - contains a mining hardsuit, a proto-kinetic accelerator, GPS, luxury bluespace shelter aswell as a deluxe bluespace shelter.(Jetpack not included)"
cost = 5000
contraband = TRUE
contains = list(/obj/item/clothing/suit/space/hardsuit/mining,
/obj/item/gun/energy/kinetic_accelerator,
/obj/item/survivalcapsule/deluxe,
/obj/item/survivalcapsule/luxury,
/obj/item/gps)
crate_name = "space hermit crate"
/datum/supply_pack/misc/toner
name = "Toner Crate"
desc = "Spent too much ink printing butt pictures? Fret not, with these six toner refills, you'll be printing butts 'till the cows come home!'"
+2 -2
View File
@@ -357,8 +357,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Flavor Text</h2>"
dat += "<a href='?_src_=prefs;preference=flavor_text;task=input'><b>Set Examine Text</b></a><br>"
if(lentext(features["flavor_text"]) <= 40)
if(!lentext(features["flavor_text"]))
if(length(features["flavor_text"]) <= 40)
if(!length(features["flavor_text"]))
dat += "\[...\]"
else
dat += "[features["flavor_text"]]"
+14 -1
View File
@@ -636,11 +636,24 @@
/datum/crafting_recipe/wheelchair
name = "Wheelchair"
result = /obj/vehicle/ridden/wheelchair
reqs = list(/obj/item/stack/sheet/plasteel = 2,
reqs = list(/obj/item/stack/sheet/metal = 10,
/obj/item/stack/rods = 8)
time = 100
category = CAT_MISC
/datum/crafting_recipe/motorized_wheelchair
name = "Motorized Wheelchair"
result = /obj/vehicle/ridden/wheelchair/motorized
reqs = list(/obj/item/stack/sheet/metal = 10,
/obj/item/stack/rods = 8,
/obj/item/stock_parts/manipulator = 2,
/obj/item/stock_parts/capacitor = 1)
parts = list(/obj/item/stock_parts/manipulator = 2,
/obj/item/stock_parts/capacitor = 1)
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH)
time = 200
category = CAT_MISC
/datum/crafting_recipe/rcl
name = "Makeshift Rapid Cable Layer"
result = /obj/item/twohanded/rcl/ghetto
+1 -1
View File
@@ -231,7 +231,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
var/r_val
var/b_val
var/g_val
var/color_format = lentext(input_color)
var/color_format = length(input_color)
if(color_format == 3)
r_val = hex2num(copytext(input_color, 1, 2))*16
g_val = hex2num(copytext(input_color, 2, 3))*16
@@ -781,7 +781,7 @@
broken_plural = TRUE
else
var/holder = broken[1] //our one and only element
if(holder[lentext(holder)] == "s")
if(holder[length(holder)] == "s")
broken_plural = TRUE
//Put the items in that list into a string of text
for(var/B in broken)
@@ -793,7 +793,7 @@
damaged_plural = TRUE
else
var/holder = damaged[1]
if(holder[lentext(holder)] == "s")
if(holder[length(holder)] == "s")
damaged_plural = TRUE
for(var/D in damaged)
damaged_message += D
+4 -4
View File
@@ -67,8 +67,8 @@
/proc/slur(n,var/strength=50)
strength = min(strength,50)
var/phrase = html_decode(n)
var/leng = lentext(phrase)
var/counter=lentext(phrase)
var/leng = length(phrase)
var/counter=length(phrase)
var/newphrase=""
var/newletter=""
while(counter>=1)
@@ -102,8 +102,8 @@
/proc/cultslur(n) // Inflicted on victims of a stun talisman
var/phrase = html_decode(n)
var/leng = lentext(phrase)
var/counter=lentext(phrase)
var/leng = length(phrase)
var/counter=length(phrase)
var/newphrase=""
var/newletter=""
while(counter>=1)
+1 -1
View File
@@ -25,7 +25,7 @@
if(flavor_text && flavor_text != "")
// We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown.
var/msg = html_decode(replacetext(flavor_text, "\n", " "))
if(lentext(msg) <= 40)
if(length(msg) <= 40)
return "<span class='notice'>[html_encode(msg)]</span>"
else
return "<span class='notice'>[html_encode(copytext(msg, 1, 37))]... <a href='?src=[REF(src)];flavor_more=1'>More...</span></a>"
@@ -476,6 +476,15 @@
category = list("Phazon")
//Exosuit Equipment
/datum/design/ripleyupgrade
name = "Ripley MK-1 to MK-II conversion kit"
id = "ripleyupgrade"
build_type = MECHFAB
build_path = /obj/item/mecha_parts/mecha_equipment/ripleyupgrade
materials = list(MAT_METAL=10000,MAT_PLASMA=10000)
construction_time = 100
category = list("Exosuit Equipment")
/datum/design/mech_hydraulic_clamp
name = "Exosuit Engineering Equipment (Hydraulic Clamp)"
id = "mech_hydraulic_clamp"
+1 -1
View File
@@ -34,7 +34,7 @@
display_name = "Mechanical Exosuits"
description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human."
design_ids = list("mecha_tracking", "mechacontrol", "mechapower", "mech_recharger", "ripley_chassis", "firefighter_chassis", "ripley_torso", "ripley_left_arm", "ripley_right_arm", "ripley_left_leg", "ripley_right_leg",
"ripley_main", "ripley_peri", "mech_hydraulic_clamp")
"ripley_main", "ripley_peri", "ripleyupgrade", "mech_hydraulic_clamp")
/datum/techweb_node/mech_tools
id = "mech_tools"
@@ -0,0 +1,168 @@
/obj/vehicle/ridden/wheelchair/motorized
name = "motorized wheelchair"
desc = "A chair with big wheels. It seems to have a motor in it."
max_integrity = 150
var/speed = 2
var/power_efficiency = 1
var/power_usage = 100
var/panel_open = FALSE
var/list/required_parts = list(/obj/item/stock_parts/manipulator,
/obj/item/stock_parts/manipulator,
/obj/item/stock_parts/capacitor)
var/obj/item/stock_parts/cell/power_cell
/obj/vehicle/ridden/wheelchair/motorized/CheckParts(list/parts_list)
..()
refresh_parts()
/obj/vehicle/ridden/wheelchair/motorized/proc/refresh_parts()
speed = 1 // Should never be under 1
for(var/obj/item/stock_parts/manipulator/M in contents)
speed += M.rating
for(var/obj/item/stock_parts/capacitor/C in contents)
power_efficiency = C.rating
var/datum/component/riding/D = GetComponent(/datum/component/riding)
D.vehicle_move_delay = round(CONFIG_GET(number/movedelay/run_delay) * delay_multiplier) / speed
/obj/vehicle/ridden/wheelchair/motorized/obj_destruction(damage_flag)
var/turf/T = get_turf(src)
for(var/atom/movable/A in contents)
A.forceMove(T)
//if(isliving(A))
// var/mob/living/L = A
// L.update_mobility()
..()
/obj/vehicle/ridden/wheelchair/motorized/driver_move(mob/living/user, direction)
if(istype(user))
if(!canmove)
return FALSE
if(!power_cell)
to_chat(user, "<span class='warning'>There seems to be no cell installed in [src].</span>")
canmove = FALSE
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
return FALSE
if(power_cell.charge < power_usage / max(power_efficiency, 1))
to_chat(user, "<span class='warning'>The display on [src] blinks 'Out of Power'.</span>")
canmove = FALSE
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
return FALSE
if(user.get_num_arms() < arms_required)
to_chat(user, "<span class='warning'>You don't have enough arms to operate the motor controller!</span>")
canmove = FALSE
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
return FALSE
power_cell.use(power_usage / max(power_efficiency, 1))
return ..()
/obj/vehicle/ridden/wheelchair/motorized/set_move_delay(mob/living/user)
return
/obj/vehicle/ridden/wheelchair/motorized/post_buckle_mob(mob/living/user)
. = ..()
density = TRUE
/obj/vehicle/ridden/wheelchair/motorized/post_unbuckle_mob()
. = ..()
density = FALSE
/obj/vehicle/ridden/wheelchair/motorized/attack_hand(mob/living/user)
if(power_cell && panel_open)
power_cell.update_icon()
user.put_in_hands(power_cell)
power_cell = null
to_chat(user, "<span class='notice'>You remove the power cell from [src].</span>")
return
return ..()
/obj/vehicle/ridden/wheelchair/motorized/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_SCREWDRIVER)
I.play_tool_sound(src)
panel_open = !panel_open
user.visible_message("<span class='notice'>[user] [panel_open ? "opens" : "closes"] the maintenance panel on [src].</span>", "<span class='notice'>You [panel_open ? "open" : "close"] the maintenance panel.</span>")
return
if(panel_open)
if(istype(I, /obj/item/stock_parts/cell))
if(power_cell)
to_chat(user, "<span class='warning'>There is a power cell already installed.</span>")
else
I.forceMove(src)
power_cell = I
to_chat(user, "<span class='notice'>You install the [I].</span>")
refresh_parts()
return
if(istype(I, /obj/item/stock_parts))
var/obj/item/stock_parts/B = I
var/P
for(var/obj/item/stock_parts/A in contents)
for(var/D in required_parts)
if(ispath(A.type, D))
P = D
break
if(istype(B, P) && istype(A, P))
if(B.get_part_rating() > A.get_part_rating())
B.forceMove(src)
user.put_in_hands(A)
user.visible_message("<span class='notice'>[user] replaces [A] with [B] in [src].</span>", "<span class='notice'>You replace [A] with [B].</span>")
break
refresh_parts()
return
return ..()
/obj/vehicle/ridden/wheelchair/motorized/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You begin to detach the wheels...</span>")
if(I.use_tool(src, user, 40, volume=50))
to_chat(user, "<span class='notice'>You detach the wheels and deconstruct the chair.</span>")
new /obj/item/stack/rods(drop_location(), 8)
new /obj/item/stack/sheet/metal(drop_location(), 10)
var/turf/T = get_turf(src)
for(var/atom/movable/A in contents)
A.forceMove(T)
//if(isliving(A))
// var/mob/living/L = A
// L.update_mobility()
qdel(src)
return TRUE
/obj/vehicle/ridden/wheelchair/motorized/examine(mob/user)
. = ..()
if((obj_flags & EMAGGED) && panel_open)
. += "There is a bomb under the maintenance panel."
. += "There is a small screen on it, [(in_range(user, src) || isobserver(user)) ? "[power_cell ? "it reads:" : "but it is dark."]" : "but you can't see it from here."]"
if(!power_cell || (!in_range(user, src) && !isobserver(user)))
return
. += "Speed: [speed]"
. += "Energy efficiency: [power_efficiency]"
. += "Power: [power_cell.charge] out of [power_cell.maxcharge]"
/obj/vehicle/ridden/wheelchair/motorized/Bump(atom/movable/M)
. = ..()
// Here is the shitty emag functionality.
if(obj_flags & EMAGGED && (istype(M, /turf/closed) || isliving(M)))
explosion(src, -1, 1, 3, 2, 0)
visible_message("<span class='boldwarning'>[src] explodes!!</span>")
return
// If the speed is higher than delay_multiplier throw the person on the wheelchair away
if(M.density && speed > delay_multiplier && has_buckled_mobs())
var/mob/living/H = buckled_mobs[1]
var/atom/throw_target = get_edge_target_turf(H, pick(GLOB.cardinals))
unbuckle_mob(H)
H.throw_at(throw_target, 2, 3)
H.Knockdown(100)
H.adjustStaminaLoss(40)
if(isliving(M))
var/mob/living/D = M
throw_target = get_edge_target_turf(D, pick(GLOB.cardinals))
D.throw_at(throw_target, 2, 3)
D.Knockdown(80)
D.adjustStaminaLoss(35)
visible_message("<span class='danger'>[src] crashes into [M], sending [H] and [D] flying!</span>")
else
visible_message("<span class='danger'>[src] crashes into [M], sending [H] flying!</span>")
playsound(src, 'sound/effects/bang.ogg', 50, 1)
/obj/vehicle/ridden/wheelchair/motorized/emag_act(mob/user)
if((obj_flags & EMAGGED) || !panel_open)
return
to_chat(user, "<span class='warning'>A bomb appears in [src], what the fuck?</span>")
obj_flags |= EMAGGED
+12 -7
View File
@@ -1,4 +1,4 @@
/obj/vehicle/ridden/wheelchair //ported from Hippiestation (by Jujumatic) Then ported by Fermis from tg!
/obj/vehicle/ridden/wheelchair //ported from Hippiestation (by Jujumatic)
name = "wheelchair"
desc = "A chair with big wheels. It looks like you can move in this on your own."
icon = 'icons/obj/vehicles.dmi'
@@ -9,7 +9,8 @@
legs_required = 0 //You'll probably be using this if you don't have legs
canmove = TRUE
density = FALSE //Thought I couldn't fix this one easily, phew
arms_required = 1
// Run speed delay is multiplied with this for vehicle move delay.
var/delay_multiplier = 6.7
/obj/vehicle/ridden/wheelchair/Initialize()
. = ..()
@@ -42,16 +43,19 @@
canmove = FALSE
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
return FALSE
var/datum/component/riding/D = GetComponent(/datum/component/riding)
//1.5 (movespeed as of this change) multiplied by 6.7 gets ABOUT 10 (rounded), the old constant for the wheelchair that gets divided by how many arms they have
//if that made no sense this simply makes the wheelchair speed change along with movement speed delay
D.vehicle_move_delay = round((CONFIG_GET(number/movedelay/run_delay) * 4) / min(user.get_num_arms(), 2), world.tick_lag)
set_move_delay(user)
return ..()
/obj/vehicle/ridden/wheelchair/proc/set_move_delay(mob/living/user)
var/datum/component/riding/D = GetComponent(/datum/component/riding)
//1.5 (movespeed as of this change) multiplied by 6.7 gets ABOUT 10 (rounded), the old constant for the wheelchair that gets divided by how many arms they have
//if that made no sense this simply makes the wheelchair speed change along with movement speed delay
D.vehicle_move_delay = round(CONFIG_GET(number/movedelay/run_delay) * delay_multiplier) / min(user.get_num_arms(), 2)
/obj/vehicle/ridden/wheelchair/Moved()
. = ..()
cut_overlays()
playsound(src, 'sound/effects/roll.ogg', 75, 1)
playsound(src, 'sound/effects/roll.ogg', 75, TRUE)
if(has_buckled_mobs())
handle_rotation_overlayed()
@@ -69,6 +73,7 @@
handle_rotation(newdir)
/obj/vehicle/ridden/wheelchair/wrench_act(mob/living/user, obj/item/I) //Attackby should stop it attacking the wheelchair after moving away during decon
..()
to_chat(user, "<span class='notice'>You begin to detach the wheels...</span>")
if(I.use_tool(src, user, 40, volume=50))
to_chat(user, "<span class='notice'>You detach the wheels and deconstruct the chair.</span>")
+3
View File
@@ -146,6 +146,9 @@ LOG_MANIFEST
## Enable logging pictures
# LOG_PICTURES
## log cloning actions
LOG_CLONING
##Log camera pictures - Must have picture logging enabled
PICTURE_LOGGING_CAMERA
Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

@@ -43,6 +43,9 @@
icon_state = "hemiknot"
name = "Knotted Hemi"
/datum/sprite_accessory/penis/thick
icon_state = "thick"
name = "thick"
////////////////////////
// Taur cocks go here //
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+1
View File
@@ -2812,6 +2812,7 @@
#include "code\modules\vehicles\atv.dm"
#include "code\modules\vehicles\bicycle.dm"
#include "code\modules\vehicles\lavaboat.dm"
#include "code\modules\vehicles\motorized_wheelchair.dm"
#include "code\modules\vehicles\pimpin_ride.dm"
#include "code\modules\vehicles\ridden.dm"
#include "code\modules\vehicles\scooter.dm"