mirror of
https://github.com/KabKebab/GS13.git
synced 2026-07-12 08:27:24 +01:00
Merge branch 'master' of https://github.com/quotefox/Hyper-Station-13
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user