mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-23 04:51:32 +01:00
Shell May Cry: A comprehensive rework of synthetics. (#20721)
https://www.youtube.com/watch?v=9mPvZ96pHJI A pull request commissioned by the Synthetic Lore Team to comprehensively rework synthetics (read: IPCs) and how they work in Aurora. The objective is to make IPCs as unique as possible from humans, upgrading the robotic feel and atmosphere, while also preserving a good sense of balance in-game. Key features: - A comprehensive expansion of synthetic organs, all of which now fulfill a purpose: hydraulics, cooling units, power systems, actuators, diagnostics units. - Customizable organs with benefits and drawbacks, such as with cooling units and power systems. - Unique ways to repair the organs and more involved steps. - Unique damage mechanics - every organ has wiring and electronics which affect its functioning, and they are defended by plating which provides natural armour. - Improved and immersive diagnostics. - Unique features, benefits, and drawbacks for every IPC frame. - A rework of the positronic brain, which can be either destroyed or shut down, alongside effects caused by low integrity. - A rework of how EMPs affect IPC organs. - Non-binary damage states for each organ. To-do: - [x] Finish the unique features for each frame. - [x] Look into if mechanical synthskin is possible. - [x] Power system. - [x] Posibrain mechanics. - [ ] Passive cooling expansion. - [x] EMP mechanics. - [x] Repair mechanics. - [x] Mob weight mechanics. - [ ] Gurney for heavy mobs. - [x] New augments. - [ ] IPC tag scanning and flashing. --------- Signed-off-by: Werner <1331699+Arrow768@users.noreply.github.com> Co-authored-by: Matt Atlas <liermattia@gmail.com> Co-authored-by: Geeves <22774890+Geevies@users.noreply.github.com> Co-authored-by: Werner <1331699+Arrow768@users.noreply.github.com>
This commit is contained in:
co-authored by
Matt Atlas
Geeves
Werner
parent
1898ad3417
commit
e0aa218843
@@ -142,7 +142,7 @@
|
||||
if(user.isSynthetic() && ishuman(user)) // Let's do something with it, if we're a robot.
|
||||
var/mob/living/carbon/human/H = user
|
||||
charge_to_give = charge_to_give - (core.max_energy - core.energy)
|
||||
var/obj/item/organ/internal/cell/C = H.internal_organs_by_name[BP_CELL]
|
||||
var/obj/item/organ/internal/machine/power_core/C = H.internal_organs_by_name[BP_CELL]
|
||||
var/obj/item/cell/potato = C.get_cell()
|
||||
potato.give(charge_to_give)
|
||||
to_chat(user, SPAN_NOTICE("Redirected energy to internal microcell."))
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
minimal_player_age = 7
|
||||
outfit = /obj/outfit/job/warden
|
||||
|
||||
blacklisted_species = list(SPECIES_IPC_G1, SPECIES_IPC_G2, SPECIES_IPC_XION, SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER)
|
||||
blacklisted_species = list(SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER)
|
||||
|
||||
/obj/outfit/job/warden
|
||||
name = "Warden"
|
||||
@@ -163,7 +163,7 @@
|
||||
)
|
||||
minimal_player_age = 3
|
||||
outfit = /obj/outfit/job/forensics
|
||||
blacklisted_species = list(SPECIES_IPC_G1, SPECIES_IPC_G2, SPECIES_IPC_XION, SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER)
|
||||
blacklisted_species = list(SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER)
|
||||
|
||||
/obj/outfit/job/forensics
|
||||
name = "Investigator"
|
||||
@@ -222,7 +222,7 @@
|
||||
minimal_player_age = 7
|
||||
outfit = /obj/outfit/job/officer
|
||||
|
||||
blacklisted_species = list(SPECIES_IPC_G1, SPECIES_IPC_G2, SPECIES_IPC_XION, SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER)
|
||||
blacklisted_species = list(SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER)
|
||||
|
||||
/obj/outfit/job/officer
|
||||
name = "Security Officer"
|
||||
@@ -289,7 +289,7 @@
|
||||
SPECIES_SKRELL_AXIORI = 50
|
||||
)
|
||||
|
||||
blacklisted_species = list(SPECIES_IPC_G1, SPECIES_IPC_G2, SPECIES_IPC_XION, SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER)
|
||||
blacklisted_species = list(SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER)
|
||||
|
||||
/obj/outfit/job/intern_sec
|
||||
name = "Security Cadet"
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
///The connected surgery computer
|
||||
var/obj/machinery/computer/operating/computer = null
|
||||
|
||||
/// If the patient must be lying on this surgery table for it to set the patient as occupant.
|
||||
var/occupant_must_be_lying = TRUE
|
||||
|
||||
/obj/machinery/optable/mechanics_hints(mob/user, distance, is_adjacent)
|
||||
. += ..()
|
||||
. += "Click your target with Grab intent, then click on the table with an empty hand, to place them on it."
|
||||
@@ -154,6 +157,7 @@
|
||||
if((user.a_intent != I_HELP) && buckled)
|
||||
user_unbuckle(user)
|
||||
return
|
||||
|
||||
if(user != occupant_resolved && !use_check_and_message(user)) // Skip checks if you're doing it to yourself or turning it off, this is an anti-griefing mechanic more than anything.
|
||||
user.visible_message(SPAN_WARNING("\The [user] begins switching [suppressing ? "off" : "on"] \the [src]'s neural suppressor."))
|
||||
if(!do_after(user, 3 SECONDS, src, DO_UNIQUE))
|
||||
@@ -201,10 +205,11 @@
|
||||
//does not mean it's suppressed, just that it's occupying the table
|
||||
var/mob/living/carbon/human/new_occupant = locate() in loc
|
||||
if(istype(new_occupant))
|
||||
if(new_occupant.lying)
|
||||
//Set the occupant weakref and get his view
|
||||
occupant = WEAKREF(new_occupant)
|
||||
acquire_view(new_occupant)
|
||||
if(occupant_must_be_lying && !new_occupant.lying)
|
||||
return FALSE
|
||||
//Set the occupant weakref and get his view
|
||||
occupant = WEAKREF(new_occupant)
|
||||
acquire_view(new_occupant)
|
||||
|
||||
//We have a patient, and it's not synthetic
|
||||
else if(!occupant_resolved.isSynthetic())
|
||||
@@ -257,11 +262,17 @@
|
||||
add_fingerprint(patient)
|
||||
add_fibers(patient)
|
||||
|
||||
patient.resting = TRUE
|
||||
patient.forceMove(loc)
|
||||
move_patient_to_table(patient, giver)
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Actually moves a patient to the table.
|
||||
*/
|
||||
/obj/machinery/optable/proc/move_patient_to_table(mob/living/carbon/patient, mob/living/carbon/giver)
|
||||
patient.resting = TRUE
|
||||
patient.forceMove(loc)
|
||||
|
||||
/obj/machinery/optable/mouse_drop_receive(atom/dropped, mob/user, params)
|
||||
//If the user is a ghost, stop.
|
||||
if(isghost(user))
|
||||
@@ -333,3 +344,28 @@
|
||||
return TRUE
|
||||
if(default_part_replacement(user, attacking_item))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/optable/robotics
|
||||
name = "machinery chair"
|
||||
desc = "Some sort of hybrid between an operating table and a chair, typically used by machinists and roboticists to strap synthetics to while they work on them. \
|
||||
It comes with an access cable for easy access to a synthetic's diagnostics unit."
|
||||
icon_state = "machinist_or_table"
|
||||
density = FALSE
|
||||
occupant_must_be_lying = FALSE
|
||||
can_buckle = list(/mob/living/carbon/human)
|
||||
|
||||
/obj/machinery/optable/robotics/mechanics_hints(mob/user, distance, is_adjacent)
|
||||
. = ..()
|
||||
. += list("Use a <b>non-help</b> intent to unbuckle.")
|
||||
|
||||
/obj/machinery/optable/robotics/refresh_icon_state()
|
||||
return
|
||||
|
||||
/obj/machinery/optable/robotics/move_patient_to_table(mob/living/carbon/patient, mob/living/carbon/giver)
|
||||
buckle(patient, giver)
|
||||
visible_message(SPAN_NOTICE("[giver] buckles [patient] to \the [src]."))
|
||||
|
||||
/obj/machinery/optable/robotics/buckle(atom/movable/buckling_atom, mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
playsound(src, 'sound/effects/metal_close.ogg', 20)
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
/// The zlevel that this computer is spawned on.
|
||||
var/starting_z_level = null
|
||||
|
||||
/// The access cable inserted into this computer, if any.
|
||||
var/obj/item/access_cable/inserted_cable
|
||||
|
||||
/obj/machinery/computer/Initialize()
|
||||
. = ..()
|
||||
overlay_layer = layer
|
||||
@@ -36,6 +39,12 @@
|
||||
power_change()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/Destroy()
|
||||
if(inserted_cable)
|
||||
inserted_cable.retract()
|
||||
inserted_cable = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = TRUE)
|
||||
if(!operable() || !is_station_level(z) || user.stat)
|
||||
user.unset_machine()
|
||||
@@ -47,7 +56,6 @@
|
||||
if(prob(20/severity))
|
||||
set_broken()
|
||||
|
||||
|
||||
/obj/machinery/computer/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
@@ -194,6 +202,15 @@
|
||||
update_icon()
|
||||
return TRUE
|
||||
else
|
||||
if(istype(attacking_item, /obj/item/access_cable))
|
||||
var/obj/item/access_cable/access_cable = attacking_item
|
||||
if(inserted_cable)
|
||||
to_chat(user, SPAN_WARNING("There's already a cable in the universal port!"))
|
||||
return
|
||||
|
||||
if(do_after(user, 1 SECONDS))
|
||||
visible_message(SPAN_NOTICE("[user] slots \the [access_cable] into \the [src]."))
|
||||
insert_cable(access_cable, user)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
@@ -218,6 +235,19 @@
|
||||
to_chat(user, SPAN_WARNING("\The [src]'s non-stick surface prevents you from attaching a sticker to it!"))
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/computer/insert_cable(obj/item/access_cable/cable, mob/user)
|
||||
. = ..()
|
||||
inserted_cable = cable
|
||||
cable.create_cable(src)
|
||||
|
||||
/obj/machinery/computer/cable_interact(obj/item/access_cable/cable, mob/user)
|
||||
. = ..()
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/remove_cable(obj/item/access_cable/cable)
|
||||
..()
|
||||
inserted_cable = null
|
||||
|
||||
/obj/machinery/computer/terminal
|
||||
name = "terminal"
|
||||
icon = 'icons/obj/machinery/modular_terminal.dmi'
|
||||
|
||||
@@ -554,7 +554,7 @@
|
||||
var/choice = alert(M, "Would you like to save your tag data?", "Tag Persistence", "Yes", "No")
|
||||
if(choice == "Yes")
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/internal/ipc_tag/tag = H.internal_organs_by_name[BP_IPCTAG]
|
||||
var/obj/item/organ/internal/machine/ipc_tag/tag = H.internal_organs_by_name[BP_IPCTAG]
|
||||
if(tag)
|
||||
M.client.prefs.machine_ownership_status = tag.ownership_info
|
||||
M.client.prefs.machine_serial_number = tag.serial_number
|
||||
|
||||
@@ -297,7 +297,7 @@ Class Procs:
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/CanUseTopic(var/mob/user)
|
||||
/obj/machinery/CanUseTopic(mob/user)
|
||||
if(stat & BROKEN)
|
||||
return STATUS_CLOSE
|
||||
|
||||
@@ -306,18 +306,18 @@ Class Procs:
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/CouldUseTopic(var/mob/user)
|
||||
/obj/machinery/CouldUseTopic(mob/user)
|
||||
..()
|
||||
if(clicksound && iscarbon(user))
|
||||
playsound(src, clicksound, clickvol)
|
||||
user.set_machine(src)
|
||||
|
||||
/obj/machinery/CouldNotUseTopic(var/mob/user)
|
||||
/obj/machinery/CouldNotUseTopic(mob/user)
|
||||
user.unset_machine()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/machinery/attack_ai(mob/user as mob)
|
||||
/obj/machinery/attack_ai(mob/user)
|
||||
if(!ai_can_interact(user))
|
||||
return
|
||||
if(isrobot(user))
|
||||
@@ -328,33 +328,27 @@ Class Procs:
|
||||
else
|
||||
return src.attack_hand(user)
|
||||
|
||||
/obj/machinery/attack_hand(mob/user as mob)
|
||||
/obj/machinery/attack_hand(mob/user)
|
||||
if(!operable(MAINT))
|
||||
return 1
|
||||
return TRUE
|
||||
if(user.lying || user.stat)
|
||||
return 1
|
||||
if ( ! (istype(usr, /mob/living/carbon/human) || \
|
||||
istype(usr, /mob/living/silicon)))
|
||||
return TRUE
|
||||
if (!istype(usr, /mob/living/carbon/human) && !istype(usr, /mob/living/silicon))
|
||||
to_chat(usr, SPAN_WARNING("You don't have the dexterity to do this!"))
|
||||
return 1
|
||||
/*
|
||||
//distance checks are made by atom/proc/DblClick
|
||||
if ((get_dist(src, user) > 1 || !istype(src.loc, /turf)) && !istype(user, /mob/living/silicon))
|
||||
return 1
|
||||
*/
|
||||
if (ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.getBrainLoss() >= 60)
|
||||
visible_message(SPAN_WARNING("[H] stares cluelessly at [src] and drools."))
|
||||
return 1
|
||||
else if(prob(H.getBrainLoss()))
|
||||
to_chat(user, SPAN_WARNING("You momentarily forget how to use [src]."))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
src.add_fingerprint(user)
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/attack_ranged(mob/user, params)
|
||||
. = ..()
|
||||
if(isipc(user))
|
||||
var/mob/living/carbon/human/robot = user
|
||||
var/obj/item/organ/internal/machine/wireless_access/wireless_access_point = robot.internal_organs_by_name[BP_WIRELESS_ACCESS]
|
||||
if(wireless_access_point?.access_terminal(src))
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/attackby(obj/item/attacking_item, mob/user)
|
||||
if(obj_flags & OBJ_FLAG_SIGNALER)
|
||||
if(issignaler(attacking_item))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/machinery/mecha_part_fabricator
|
||||
name = "mechatronic fabricator"
|
||||
desc = "A general purpose fabricator that can be used to fabricate robotic equipment."
|
||||
name = "synthetic fabricator"
|
||||
desc = "A general purpose fabricator that can be used to fabricate equipment for synthetics or exosuits."
|
||||
icon = 'icons/obj/machinery/robotics_fabricator.dmi'
|
||||
icon_state = "fab"
|
||||
density = TRUE
|
||||
@@ -15,6 +15,7 @@
|
||||
/obj/item/stock_parts/micro_laser,
|
||||
/obj/item/stock_parts/console_screen
|
||||
)
|
||||
manufacturer = "hephaestus"
|
||||
|
||||
/**
|
||||
* A `/list` of enqueued `/datum/design` to be printed, processed in the queue
|
||||
@@ -36,6 +37,9 @@
|
||||
|
||||
var/datum/research/files
|
||||
|
||||
/// The looping sound for production.
|
||||
var/datum/looping_sound/synth_fab/fab_loop
|
||||
|
||||
var/list/categories = list()
|
||||
var/category = null
|
||||
var/sync_message = ""
|
||||
@@ -57,11 +61,13 @@
|
||||
. = ..()
|
||||
|
||||
files = new /datum/research(src) //Setup the research data holder.
|
||||
fab_loop = new(src)
|
||||
limb_manufacturer = GLOB.basic_robolimb.company
|
||||
update_categories()
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/update_icon()
|
||||
ClearOverlays()
|
||||
update_fab_audio()
|
||||
if(panel_open)
|
||||
AddOverlays("[icon_state]_panel")
|
||||
if(!(stat & (NOPOWER|BROKEN)))
|
||||
@@ -72,9 +78,19 @@
|
||||
AddOverlays(emissive_appearance(icon, "[icon_state]_lights_working"))
|
||||
AddOverlays("[icon_state]_lights_working")
|
||||
|
||||
/// Starts and stops the necessary audio.
|
||||
/obj/machinery/mecha_part_fabricator/proc/update_fab_audio()
|
||||
if(!fab_loop)
|
||||
return
|
||||
|
||||
if(build_callback_timer)
|
||||
fab_loop.start()
|
||||
else
|
||||
fab_loop.stop()
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/dismantle()
|
||||
for(var/f in materials)
|
||||
eject_materials(f, -1)
|
||||
eject_materials(f, materials[f])
|
||||
|
||||
//Stop the queue building if you're dismantling
|
||||
deltimer(build_callback_timer)
|
||||
@@ -106,27 +122,36 @@
|
||||
do_hair_pull(user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
/obj/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "SyntheticFabricator", "Synthetic Fabricator", 900, 700)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["manufacturer"] = manufacturer
|
||||
var/datum/design/current = queue.len ? queue[1] : null
|
||||
if(current)
|
||||
data["current"] = current.name
|
||||
data["queue"] = get_queue_names()
|
||||
data["buildable"] = get_build_options()
|
||||
data["category"] = category
|
||||
data["categories"] = categories
|
||||
data["available_categories"] = list()
|
||||
for(var/possible_category in categories)
|
||||
data["available_categories"] += list(list("name" = possible_category))
|
||||
|
||||
if(GLOB.fabricator_robolimbs)
|
||||
var/list/T = list()
|
||||
for(var/A in GLOB.fabricator_robolimbs)
|
||||
var/datum/robolimb/R = GLOB.fabricator_robolimbs[A]
|
||||
T += list(list("id" = A, "company" = R.company))
|
||||
T += list(list("name" = R.company, "type" = A))
|
||||
data["manufacturers"] = T
|
||||
data["manufacturer"] = limb_manufacturer
|
||||
data["selected_manufacturer"] = limb_manufacturer
|
||||
|
||||
data["materials"] = get_materials()
|
||||
data["maxres"] = res_max_amount
|
||||
data["maximum_resource_amount"] = res_max_amount
|
||||
data["sync"] = sync_message
|
||||
|
||||
//If we have something in the queue that we're trying to build, show the time left if the build is undergoing, otherwise null
|
||||
@@ -136,42 +161,46 @@
|
||||
data["timeleft"] = round(timeleft(build_callback_timer))
|
||||
else
|
||||
data["timeleft"] = null
|
||||
return data
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "mechfab.tmpl", "Exosuit Fabricator UI", 800, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/Topic(href, href_list)
|
||||
if(..())
|
||||
/obj/machinery/mecha_part_fabricator/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(href_list["build"])
|
||||
var/path = text2path(href_list["build"])
|
||||
add_to_queue(path)
|
||||
switch(action)
|
||||
if("build")
|
||||
var/path = text2path(params["build"])
|
||||
add_to_queue(path)
|
||||
. = TRUE
|
||||
|
||||
if(href_list["remove"])
|
||||
remove_from_queue(text2num(href_list["remove"]))
|
||||
if("remove")
|
||||
remove_from_queue(text2num(params["remove"]))
|
||||
. = TRUE
|
||||
|
||||
if(href_list["category"])
|
||||
if(href_list["category"] in categories)
|
||||
category = href_list["category"]
|
||||
if("category")
|
||||
if(params["category"] in categories)
|
||||
category = params["category"]
|
||||
. = TRUE
|
||||
|
||||
if(href_list["manufacturer"])
|
||||
if(href_list["manufacturer"] in GLOB.fabricator_robolimbs)
|
||||
limb_manufacturer = href_list["manufacturer"]
|
||||
if("manufacturer")
|
||||
if(params["manufacturer"] in GLOB.fabricator_robolimbs)
|
||||
limb_manufacturer = params["manufacturer"]
|
||||
. = TRUE
|
||||
|
||||
if(href_list["eject"])
|
||||
eject_materials(href_list["eject"], text2num(href_list["amount"]))
|
||||
if("eject")
|
||||
eject_materials(params["eject"], text2num(params["amount"]))
|
||||
. = TRUE
|
||||
|
||||
if(href_list["sync"])
|
||||
sync()
|
||||
else
|
||||
sync_message = ""
|
||||
if("sync")
|
||||
sync()
|
||||
. = TRUE
|
||||
else
|
||||
sync_message = ""
|
||||
|
||||
return 1
|
||||
if(.)
|
||||
playsound(src, 'sound/machines/synthfab/synthfab_button.ogg', 50)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/attackby(obj/item/attacking_item, mob/user)
|
||||
if(build_callback_timer)
|
||||
@@ -195,7 +224,7 @@
|
||||
return TRUE
|
||||
|
||||
var/sname = "[M.name]"
|
||||
if(materials[M.material.name] + M.perunit <= res_max_amount)
|
||||
if(materials[M.material.name] + SHEET_MATERIAL_AMOUNT <= res_max_amount)
|
||||
if(M.amount >= 1)
|
||||
var/count = 0
|
||||
var/mutable_appearance/MA = mutable_appearance(icon, "material_insertion")
|
||||
@@ -206,7 +235,7 @@
|
||||
//now play the progress bar animation
|
||||
flick_overlay_view(mutable_appearance(icon, "fab_progress"), 1 SECONDS)
|
||||
|
||||
while(materials[M.material.name] + M.perunit <= res_max_amount && M.amount >= 1)
|
||||
while(materials[M.material.name] + SHEET_MATERIAL_AMOUNT <= res_max_amount && M.amount >= 1)
|
||||
materials[M.material.name] += M.perunit
|
||||
M.use(1)
|
||||
count++
|
||||
@@ -344,6 +373,7 @@
|
||||
|
||||
else
|
||||
visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] flashes: Insufficient materials to complete build: [D.name]."))
|
||||
remove_from_queue(1)
|
||||
|
||||
update_icon()
|
||||
|
||||
@@ -383,17 +413,17 @@
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_queue_names()
|
||||
. = list()
|
||||
for(var/i = 2 to queue.len)
|
||||
for(var/i = 1 to queue.len)
|
||||
var/datum/design/D = queue[i]
|
||||
. += D.name
|
||||
. += list(list("name" = D.name, "time" = get_design_time(D), "index" = i))
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_build_options()
|
||||
. = list()
|
||||
for(var/path in files.known_designs)
|
||||
var/datum/design/D = files.known_designs[path]
|
||||
if(!D.build_path || !(D.build_type & MECHFAB) || !D.category)
|
||||
if(!D.build_path || !(D.build_type & MECHFAB) || !D.category || (D.category != category))
|
||||
continue
|
||||
. += list(list("name" = D.name, "id" = D.type, "category" = D.category, "resourses" = get_design_resourses(D), "time" = get_design_time(D)))
|
||||
. += list(list("name" = D.name, "desc" = D.desc, "type" = D.type, "category" = D.category, "resources" = get_design_resourses(D), "time" = get_design_time(D)))
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_design_resourses(var/datum/design/D)
|
||||
var/list/F = list()
|
||||
@@ -417,25 +447,19 @@
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_materials()
|
||||
. = list()
|
||||
for(var/T in materials)
|
||||
. += list(list("mat" = capitalize(T), "amt" = materials[T]))
|
||||
. += list(list("name" = capitalize(T), "amount" = materials[T]))
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
|
||||
var/recursive = amount == -1 ? 1 : 0
|
||||
/obj/machinery/mecha_part_fabricator/proc/eject_materials(var/material, var/amount)
|
||||
if(!amount)
|
||||
return
|
||||
material = lowertext(material)
|
||||
var/material/mattype = SSmaterials.get_material_by_name(material)
|
||||
var/stack_type = mattype.stack_type
|
||||
|
||||
var/obj/item/stack/material/S = new stack_type(loc)
|
||||
if(amount <= 0)
|
||||
amount = S.max_amount
|
||||
var/ejected = min(round(materials[material] / S.perunit), amount)
|
||||
S.amount = min(ejected, amount)
|
||||
if(S.amount <= 0)
|
||||
qdel(S)
|
||||
return
|
||||
materials[material] -= ejected * S.perunit
|
||||
if(recursive && materials[material] >= S.perunit)
|
||||
eject_materials(material, -1)
|
||||
var/real_amount = round(amount / SHEET_MATERIAL_AMOUNT)
|
||||
var/obj/item/stack/material/S = new stack_type(loc, real_amount)
|
||||
S.update_icon()
|
||||
materials[material] -= amount
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/sync()
|
||||
sync_message = "Error: no console found."
|
||||
|
||||
@@ -117,6 +117,9 @@
|
||||
return
|
||||
|
||||
var/obj/item/cell/target
|
||||
|
||||
// We use the reactor variable to see if this is an IPC that's charging.
|
||||
var/obj/item/organ/internal/machine/reactor/reactor
|
||||
if(isrobot(occupant))
|
||||
var/mob/living/silicon/robot/R = occupant
|
||||
|
||||
@@ -132,9 +135,15 @@
|
||||
|
||||
if(ishuman(occupant))
|
||||
var/mob/living/carbon/human/H = occupant
|
||||
var/obj/item/organ/internal/cell/IC = H.internal_organs_by_name[BP_CELL]
|
||||
if(IC)
|
||||
var/obj/item/organ/internal/machine/power_core/IC = H.internal_organs_by_name[BP_CELL]
|
||||
if(istype(IC))
|
||||
target = IC.cell
|
||||
|
||||
// Different reactor types have different external recharge speeds.
|
||||
reactor = H.internal_organs_by_name[BP_REACTOR]
|
||||
if(!istype(reactor))
|
||||
return
|
||||
|
||||
if((!target || target.percent() > 95) && istype(H.back, /obj/item/rig))
|
||||
var/obj/item/rig/R = H.back
|
||||
if(R.cell && !R.cell.fully_charged())
|
||||
@@ -143,7 +152,11 @@
|
||||
if(target && !target.fully_charged())
|
||||
var/diff = min(target.maxcharge - target.charge, charging_power * CELLRATE * seconds_per_tick) // Capped by charging_power / tick
|
||||
var/charge_used = cell.use(diff)
|
||||
target.give(charge_used*charging_efficiency)
|
||||
|
||||
if(!reactor) // not an IPC
|
||||
target.give(charge_used * charging_efficiency)
|
||||
else
|
||||
reactor.generate_power(charge_used * charging_efficiency * reactor.external_charge_multiplier)
|
||||
|
||||
if(isDrone(occupant))
|
||||
var/mob/living/silicon/robot/drone/D = occupant
|
||||
@@ -172,6 +185,13 @@
|
||||
if(cell)
|
||||
cell.emp_act(severity)
|
||||
|
||||
/obj/machinery/recharge_station/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(occupant && (user != occupant))
|
||||
if(do_after(user, 1 SECOND, src))
|
||||
user.visible_message(SPAN_NOTICE("[user] lowers the manual release lever on \the [src]."), SPAN_NOTICE("You lower the manual release lever on \the [src]."))
|
||||
go_out()
|
||||
|
||||
/obj/machinery/recharge_station/attackby(obj/item/attacking_item, mob/user)
|
||||
if(!occupant)
|
||||
if(default_deconstruction_screwdriver(user, attacking_item))
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
if(!emagged)
|
||||
playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
|
||||
emagged = 1
|
||||
to_chat(user, SPAN_NOTICE("You you disable the security protocols"))
|
||||
to_chat(user, SPAN_NOTICE("You disable the security protocols."))
|
||||
src.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -157,6 +157,6 @@
|
||||
if(!emagged)
|
||||
playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
|
||||
emagged = 1
|
||||
to_chat(user, SPAN_NOTICE("You you disable the security protocols"))
|
||||
to_chat(user, SPAN_NOTICE("You disable the security protocols."))
|
||||
src.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
@@ -234,6 +234,6 @@
|
||||
if(!emagged)
|
||||
playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
|
||||
emagged = 1
|
||||
to_chat(user, SPAN_NOTICE("You you disable the security protocols"))
|
||||
to_chat(user, SPAN_NOTICE("You disable the security protocols."))
|
||||
src.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
@@ -420,7 +420,7 @@
|
||||
make_announcement("pings, \"Resuscitation successful.\"", "notice")
|
||||
playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
|
||||
H.resuscitate()
|
||||
var/obj/item/organ/internal/cell/potato = H.internal_organs_by_name[BP_CELL]
|
||||
var/obj/item/organ/internal/machine/power_core/potato = H.internal_organs_by_name[BP_CELL]
|
||||
if(istype(potato) && potato.cell)
|
||||
var/obj/item/cell/C = potato.cell
|
||||
C.give(chargecost)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
var/on = 0 //is it turned on?
|
||||
var/cover_open = 0 //is the cover open?
|
||||
var/obj/item/cell/cell
|
||||
var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here
|
||||
var/max_cooling = 24 //in degrees per second - probably don't need to mess with heat capacity here
|
||||
var/charge_consumption = 8.3 //charge per second at max_cooling
|
||||
var/thermostat = T20C
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
var/charge_usage = (temp_adj/max_cooling)*charge_consumption
|
||||
|
||||
H.bodytemperature -= temp_adj*efficiency
|
||||
H.bodytemperature = max(T0C, H.bodytemperature - temp_adj*efficiency)
|
||||
|
||||
cell.use(charge_usage)
|
||||
|
||||
|
||||
@@ -83,6 +83,25 @@
|
||||
var/obj/item/organ/external/S = H.get_organ(target_zone)
|
||||
|
||||
if (S && (S.status & ORGAN_ASSISTED))
|
||||
var/datum/component/synthetic_endoskeleton/endoskeleton = H.GetComponent(/datum/component/synthetic_endoskeleton)
|
||||
if(istype(endoskeleton) && endoskeleton.damage)
|
||||
if(target_mob == user)
|
||||
if(endoskeleton.damage >= endoskeleton.max_damage * 0.5)
|
||||
to_chat(user, SPAN_WARNING("Your control over your limbs is too damaged to apply the nanopaste precisely!"))
|
||||
return
|
||||
application_time *= application_multiplier // It takes longer to apply nanopaste to yourself than to someone else.
|
||||
|
||||
if (application_in_progress == FALSE)
|
||||
application_in_progress = TRUE
|
||||
user.visible_message(SPAN_NOTICE("\The [user] begins to apply nanite past to the broken support systems of [user != target_mob ? " \the [target_mob]'s" : "\the [user]'s"] endoskeleton..."), \
|
||||
SPAN_NOTICE("You begin to apply nanite paste to the broken support systems of [user != target_mob ? " \the [target_mob]'s" : "your"] [endoskeleton]..."))
|
||||
if(do_mob(user, target_mob, application_time))
|
||||
SEND_SIGNAL(target_mob, COMSIG_SYNTH_ENDOSKELETON_REPAIR, rand(15, 30))
|
||||
user.visible_message(SPAN_NOTICE("\The [user] mends the broken links in [user != target_mob ? " \the [target_mob]'s" : "\the [user]'s"] endoskeleton with \the [src]."),\
|
||||
SPAN_NOTICE("You successfully mend the broken links in[user == target_mob ? "your" : "[target_mob]'s"] endoskeleton with \the [src]."))
|
||||
use(1)
|
||||
application_in_progress = FALSE
|
||||
|
||||
if(S.get_damage())
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
|
||||
@@ -144,7 +163,7 @@
|
||||
return FALSE
|
||||
|
||||
if (isipc(M))
|
||||
var/obj/item/organ/internal/surge/s = M.internal_organs_by_name["surge"]
|
||||
var/obj/item/organ/internal/machine/surge/s = M.internal_organs_by_name[BP_SURGE_PROTECTOR]
|
||||
if(isnull(s))
|
||||
user.visible_message(
|
||||
SPAN_NOTICE("[user] is trying to apply [src] to [(M == user) ? ("itself") : (M)]!"),
|
||||
@@ -154,9 +173,9 @@
|
||||
if (!do_mob(user, M, 2))
|
||||
return FALSE
|
||||
|
||||
s = new /obj/item/organ/internal/surge()
|
||||
s = new /obj/item/organ/internal/machine/surge()
|
||||
M.internal_organs += s
|
||||
M.internal_organs_by_name["surge"] = s
|
||||
M.internal_organs_by_name[BP_SURGE_PROTECTOR] = s
|
||||
user.visible_message(
|
||||
SPAN_NOTICE("[user] applies some nanite paste to [(M == user) ? ("itself") : (M)]!"),
|
||||
SPAN_NOTICE("You apply [src] to [(M == user) ? ("youself") : (M)].")
|
||||
|
||||
@@ -68,11 +68,11 @@
|
||||
/obj/item/implanter/ipc_tag
|
||||
name = "IPC tag implanter"
|
||||
desc = "A special implanter used for implanting synthetics with a special tag."
|
||||
var/obj/item/organ/internal/ipc_tag/ipc_tag
|
||||
var/obj/item/organ/internal/machine/ipc_tag/ipc_tag
|
||||
|
||||
/obj/item/implanter/ipc_tag/Initialize()
|
||||
. = ..()
|
||||
ipc_tag = new /obj/item/organ/internal/ipc_tag(src)
|
||||
ipc_tag = new /obj/item/organ/internal/machine/ipc_tag(src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/implanter/ipc_tag/update_icon()
|
||||
@@ -121,7 +121,7 @@
|
||||
ipc_tag = null
|
||||
update_icon()
|
||||
return
|
||||
if(istype(attacking_item, /obj/item/organ/internal/ipc_tag))
|
||||
if(istype(attacking_item, /obj/item/organ/internal/machine/ipc_tag))
|
||||
if(ipc_tag)
|
||||
to_chat(user, SPAN_WARNING("\The [src] already has an IPC tag loaded."))
|
||||
return
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
to_chat(user, SPAN_WARNING("You analyze \the [target_mob], but find that they're not an IPC at all!"))
|
||||
return
|
||||
var/mob/living/carbon/human/IPC = target_mob
|
||||
var/obj/item/organ/internal/ipc_tag/tag = IPC.internal_organs_by_name[BP_IPCTAG]
|
||||
var/obj/item/organ/internal/machine/ipc_tag/tag = IPC.internal_organs_by_name[BP_IPCTAG]
|
||||
if(isnull(tag) || !tag)
|
||||
to_chat(user, SPAN_WARNING("Error: Serial Identification Missing."))
|
||||
return
|
||||
|
||||
@@ -11,16 +11,17 @@
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 50)
|
||||
recyclable = TRUE
|
||||
|
||||
/// Note %age converted to actual charge in New()
|
||||
var/charge = 0
|
||||
var/maxcharge = 2500
|
||||
/// Maximum cell charge.
|
||||
var/maxcharge = 1000
|
||||
/// True if rigged to explode
|
||||
var/rigged = FALSE
|
||||
/// If not 100% reliable, it will build up faults.
|
||||
var/minor_fault = 0
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 50)
|
||||
recyclable = TRUE
|
||||
|
||||
/// Percentage of maxcharge to recharge per minute, though it will trickle charge every process tick (every ~2 seconds), leave null for no self-recharge
|
||||
var/self_charge_percentage
|
||||
|
||||
@@ -126,10 +127,10 @@
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 80)
|
||||
|
||||
/obj/item/cell/infinite/check_charge()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
/obj/item/cell/infinite/use()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
/obj/item/cell/potato
|
||||
name = "potato battery"
|
||||
@@ -139,8 +140,6 @@
|
||||
icon_state = "potato_cell" //"potato_battery"
|
||||
charge = 100
|
||||
maxcharge = 300
|
||||
minor_fault = 1
|
||||
|
||||
|
||||
/obj/item/cell/slime
|
||||
name = "charged slime core"
|
||||
|
||||
@@ -355,6 +355,30 @@
|
||||
/obj/proc/do_signaler()
|
||||
return
|
||||
|
||||
|
||||
/**
|
||||
* Called when an access cable - from an IPC or from a roboticist tool - is inserted into an object.
|
||||
*/
|
||||
/obj/proc/insert_cable(obj/item/access_cable/cable, mob/user)
|
||||
user.drop_from_inventory(cable)
|
||||
cable.forceMove(src)
|
||||
cable.target = src
|
||||
|
||||
/**
|
||||
* Called when an access cable is removed from something, forcibly or not.
|
||||
* Override as needed to clear variables up.
|
||||
*/
|
||||
/obj/proc/remove_cable(obj/item/access_cable/cable)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
cable.target = null
|
||||
|
||||
/**
|
||||
* Called when an access cable - from an IPC or from a roboticist tool - is used on an object to interact with it.
|
||||
* For example, brings up diagnostics for an access port if it's hooked into one.
|
||||
*/
|
||||
/obj/proc/cable_interact(obj/item/access_cable/cable, mob/user)
|
||||
return
|
||||
|
||||
/*#############################################
|
||||
PERSISTENT
|
||||
#############################################*/
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
new /obj/item/storage/belt/utility(src)
|
||||
new /obj/item/storage/belt/utility/alt(src)
|
||||
new /obj/item/storage/toolbox/mechanical(src)
|
||||
new /obj/item/modular_computer/laptop/preset/supply/robotics(src)
|
||||
|
||||
// Miner
|
||||
/obj/structure/closet/secure_closet/miner
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
new /obj/item/device/taperecorder(src)
|
||||
new /obj/item/sampler(src)
|
||||
new /obj/item/storage/box/shells/tranquilizer(src)
|
||||
new /obj/item/modular_computer/laptop/preset/supply/robotics(src)
|
||||
|
||||
/// Used for when we want to populate the contents of this locker ourself. Good for away sites
|
||||
/obj/structure/closet/secure_closet/RD/empty
|
||||
|
||||
Reference in New Issue
Block a user