Merge branch 'master' of https://github.com/quotefox/Hyper-Station-13
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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³"
|
||||
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³"
|
||||
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
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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."
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -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"] "}
|
||||
|
||||
@@ -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")
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -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]°K|[tank_temperature - T0C]°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()]°K|[return_temperature() - T0C]°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]°K|[tank_temperature - T0C]°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()]°K|[return_temperature() - T0C]°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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 we’ll 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!'"
|
||||
|
||||
@@ -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"]]"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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>")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
|
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 //
|
||||
|
||||
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 11 KiB |
@@ -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"
|
||||
|
||||