Files
vgstation13/code/modules/RCD/RCD.dm
Peter Wedder dc34bdc095 Improvements to the service cyborg experience (#35311)
* Gives service cyborgs several new improvements to make them less painful to play.

Adds the chemical synthesizer.

Rename borg synth, add coffee and tea to it, preserve whitelist temperature when scanning.

Add impropers and change desc

Make rapid service fabricator not spark inelegantly.

Give service cyborgs the chem synth and a shaker to boot.

Adds some spicy chemicals to emagged service borg

Add chloral beer to emagged service borgs

Remove's brobot and mickey finn entirely

Allow the RSF to dispense directly into borg grippers

Remove cooking upgrade and make it part of the default loadout.

Make the portable seed extractor as good as an unupgraded static o ne. Also update the name and description to be less confusing.

Give the chem synth its own sprite

Adds a rag to service cyborgs.

Add champagne and poison wine to scannable reagents

* Remove debug printout

* Replace tot cleaver with regular cleaver

* Shut up the linter.
2023-11-06 03:15:22 -06:00

378 lines
10 KiB
Plaintext

//Main class for the modular RCD system.
/obj/item/device/rcd
name = "\improper Rapid-Construction-Device (RCD)"
desc = "Used to rapidly construct things, or deconstruct them, for that matter."
icon = 'icons/obj/RCD.dmi'
icon_state = "rcd"
flags = FPRINT
siemens_coefficient = 1
w_class = W_CLASS_MEDIUM
force = 10
throwforce = 10
throw_speed = 1
throw_range = 5
starting_materials = list(MAT_IRON = 75000, MAT_GLASS = 30000)
w_type = RECYK_ELECTRONIC
melt_temperature = MELTPOINT_STEEL // Lots of metal
origin_tech = Tc_ENGINEERING + "=4;" + Tc_MATERIALS + "=2"
var/frequency = 0
var/id = null
//list of schematics, in definitions of RCD subtypes, no organization is needed, in New() these get organized.
var/list/schematics = list(/datum/rcd_schematic/test)
// Make sparks. LOTS OF SPARKS.
var/sparky = TRUE
var/z_last_checked = 0
// A list schematics can use for storing mutual data.
var/list/data
var/tmp/busy = FALSE
var/datum/rcd_schematic/selected
var/list/favorites = list()
var/tmp/next_spark = 0
var/datum/html_interface/rcd/interface
var/obj/abstract/screen/close/closer
/obj/item/device/rcd/New()
. = ..()
//interface gets created BEFORE the schematics get created, so they can modify the HEAD content (RPD pipe colour picker).
interface = new(src, sanitize(name))
data = list()
favorites = list()
init_schematics()
rebuild_ui()
var/turf/T = get_turf(src)
if(T)
z_last_checked = T.z
//create and organize the schematics
/obj/item/device/rcd/proc/init_schematics()
var/list/old_schematics = schematics
schematics = list()
for(var/path in old_schematics)
var/datum/rcd_schematic/C = new path(src)
if(!schematics[C.category])
schematics[C.category] = list()
schematics[C.category] += C
/obj/item/device/rcd/Destroy()
for(var/cat in schematics)
for(var/datum/rcd_schematic/C in schematics[cat])
qdel(C)
qdel(interface)
schematics = null
interface = null
data = null
. = ..()
/obj/item/device/rcd/dropped(var/mob/living/dropped_by)
..()
if(istype(dropped_by))
dropped_by.hud_used.toggle_show_schematics_display(null,1, src)
/obj/item/device/rcd/attack_self(var/mob/user)
var/turf/T = get_turf(src)
if(T?.z != z_last_checked)
rebuild_ui()
interface.show(user)
/obj/item/device/rcd/proc/rebuild_ui()
var/dat = ""
dat += {"
<b>Selected:</b> <span id="selectedname"></span>
<h2>Options</h2>
<div id="schematic_options">
</div>
<h2>Available schematics</h2>
<div id='fav_list'></div>
"}
for(var/cat in schematics)
dat += "<b>[cat]:</b><ul style='list-style-type:disc'>"
var/list/L = schematics[cat]
for(var/datum/rcd_schematic/C in L)
var/turf/T = get_turf(src)
if(!T || ((C.flags & RCD_Z_DOWN) && !HasBelow(T.z)) || ((C.flags & RCD_Z_UP) && !HasAbove(T.z)))
continue
dat += C.schematic_list_line(interface)
dat += "</ul>"
interface.updateLayout(dat)
if(selected)
update_options_menu()
interface.updateContent("selectedname", selected.name)
rebuild_favs()
/obj/item/device/rcd/proc/rebuild_favs()
var/dat = "<b>Favorites:</b> <span title='You can cycle through these with ctrl+mousewheel outside of the UI.'>(?)</span><ul style='list-style-type:disc'>"
for (var/datum/rcd_schematic/C in favorites)
dat += C.schematic_list_line(interface, TRUE)
dat += "</ul>"
interface.updateContent("fav_list", dat)
/obj/item/device/rcd/Topic(var/href, var/list/href_list)
. = ..()
if (. || usr.isStunned() || !(src in usr))
return 1
if (href_list["schematic"])
var/datum/rcd_schematic/C = find_schematic(href_list["schematic"])
if (!istype(C))
return 1
switch (href_list["act"])
if ("select")
try_switch(usr, C)
if ("fav")
favorites |= C
rebuild_ui()
if ("defav")
favorites -= C
rebuild_ui()
if ("favorder")
var/index = favorites.Find(C)
if (href_list["order"] == "up")
if (index == favorites.len)
return 1
favorites.Swap(index, index + 1)
else
if (index == 1)
return 1
favorites.Swap(index, index - 1)
rebuild_favs()
return 1
// The href didn't get handled by us so we pass it down to the selected schematic.
if (selected)
return selected.Topic(href, href_list)
// Find schematic by `\ref[]`
/obj/item/device/rcd/proc/find_schematic(var/ref)
// Hahaha my old code is shit now I gotta deal with it.
for (var/cat in schematics)
. = locate(ref) in schematics[cat]
if (.)
break
/obj/item/device/rcd/proc/try_switch(var/mob/user, var/datum/rcd_schematic/C)
if (busy && ~C.flags & RCD_ALLOW_SWITCH)
return 1
if (selected && !selected.deselect(usr, C))
return 1
if (!C.select(usr, selected))
return 1
do_spark()
selected = C
update_options_menu()
rebuild_favs()
interface.updateContent("selectedname", selected.name)
/obj/item/device/rcd/preattack(atom/movable/A, mob/user, proximity_flag, click_parameters)
if(A == user)
afterattack(get_turf(user), user) // Skip right to afterattack()
return TRUE
/obj/item/device/rcd/afterattack(var/atom/A, var/mob/user)
if(!selected)
return 1
if(~selected.flags & (RCD_SELF_SANE | RCD_RANGE) && !(user.Adjacent(A) && A.Adjacent(user))) // If RCD_SELF_SANE and RCD_RANGE are disabled we use adjacency.
return 1
if(selected.flags & RCD_RANGE && ~selected.flags & RCD_SELF_SANE && get_dist(A, user) > 1) // RCD_RANGE is used AND we're NOT SELF_SANE, use range(1)
return 1
if(selected.flags & RCD_GET_TURF) // Get the turf because RCD_GET_TURF is on.
A = get_turf(A)
if (!A)
return // Thing clicked was in nullspace, so we won't pass a null turf.
if(~selected.flags & RCD_SELF_SANE && get_energy(user) < selected.energy_cost) // Handle energy amounts, but only if not SELF_SANE.
return 1
busy = TRUE // Busy to prevent switching schematic while it's in use.
var/t = selected.attack(A, user)
if(!t) // No errors
if(~selected.flags & RCD_SELF_COST) // Handle energy costs unless the schematic does it itself.
use_energy(selected.energy_cost, user)
else
if(istext(t))
to_chat(user, "<span class='warning'>\the [src]'s error light flickers: [t]</span>")
else
to_chat(user, "<span class='warning'>\the [src]'s error light flickers.</span>")
busy = FALSE
return 1
/obj/item/device/rcd/proc/do_spark()
if (sparky && next_spark < world.time)
spark(src, 5, FALSE)
next_spark = world.time + 0.5 SECONDS
else
playsound(src, 'sound/machines/click.ogg', 20, 1)
/obj/item/device/rcd/proc/get_energy(var/mob/user)
return INFINITY
/obj/item/device/rcd/proc/use_energy(var/amount, var/mob/user)
return
/obj/item/device/rcd/proc/update_options_menu()
if(selected)
for(var/client/client in interface.clients)
selected.send_assets(client)
interface.updateContent("schematic_options", selected.get_HTML(args))
else
interface.updateContent("schematic_options", " ")
// Called by schematics to delay their actions
/obj/item/device/rcd/proc/delay(var/mob/user, var/atom/target, var/amount)
return do_after(user, target, amount)
/obj/item/device/rcd/MouseWheeled(var/mob/user, var/delta_x, var/delta_y, var/params)
var/modifiers = params2list(params)
if (modifiers["ctrl"])
if (!favorites.len)
return
var/index = 1
if (selected in favorites)
index = favorites.Find(selected)
if (delta_y <= 0)
index++
if (index > favorites.len)
index = 1
else
index = index - 1 || favorites.len
var/datum/rcd_schematic/C = favorites[index]
try_switch(user, C)
else if (selected)
selected.MouseWheeled(user, delta_x, delta_y, params)
/obj/item/device/rcd/borg/attack_self(var/mob/living/user)
if(!selected || user.shown_schematics_background || !selected.show(user))
user.hud_used.toggle_show_schematics_display(schematics["Construction"], 0, src)
/obj/item/device/rcd/borg
var/cell_power_per_energy = 30
/obj/item/device/rcd/borg/use_energy(var/amount, var/mob/user)
if(!isrobot(user))
return
var/mob/living/silicon/robot/R = user
if(!R.cell)
return
R.cell.use(amount * cell_power_per_energy)
/obj/item/device/rcd/borg/get_energy(var/mob/user)
if(!isrobot(user))
return 0
var/mob/living/silicon/robot/R = user
if(!R.cell)
return
return R.cell.charge / cell_power_per_energy
//Matter based RCDs.
/obj/item/device/rcd/matter
var/matter = 0
var/max_matter = 30
/obj/item/device/rcd/matter/attack_self(var/mob/living/user)
if(!selected || user.shown_schematics_background || !selected.show(user))
user.hud_used.toggle_show_schematics_display(schematics["Construction"], 0, src)
/obj/item/device/rcd/matter/examine(var/mob/user)
..()
to_chat(user, "It currently holds [matter]/[max_matter] matter-units.")
/obj/item/device/rcd/matter/attackby(var/obj/item/stack/S, var/mob/user)
..()
if(istype(S,/obj/item/stack/rcd_ammo))
if((matter + 10) > max_matter)
to_chat(user, "<span class='notice'>\the [src] can't hold any more matter-units.</span>")
return 1
matter += 10
S.use(1)
playsound(src, 'sound/machines/click.ogg', 20, 1)
to_chat(user, "<span class='notice'>\the [src] now holds [matter]/[max_matter] matter-units.</span>")
return 1
if(S.is_screwdriver(user))
to_chat(user, "<span class='notice'>You unscrew the access panel and release the cartridge chamber.</span>")
while(matter >= 10)
new /obj/item/stack/rcd_ammo(user.loc, 1)
matter -= 10
return 1
/obj/item/device/rcd/matter/use_energy(var/amount, var/mob/user)
matter -= amount
to_chat(user, "<span class='notice'>\the [src] currently holds [matter]/[max_matter] matter-units.")
/obj/item/device/rcd/matter/get_energy(var/mob/user)
return matter
/obj/item/device/rcd/proc/show_default(var/mob/living/user)
if(selected)
if(selected.show(user,1))
return
user.hud_used.toggle_show_schematics_display(null, 1, src)
/obj/item/device/rcd/mech
schematics = list(
/datum/rcd_schematic/decon,
/datum/rcd_schematic/con_floors,
/datum/rcd_schematic/con_walls,
/datum/rcd_schematic/con_airlock,
/datum/rcd_schematic/con_window,
)
/obj/item/device/rcd/mech/attack_self(var/mob/living/user)
if(!selected || user.shown_schematics_background || !selected.show(user))
user.hud_used.toggle_show_schematics_display(schematics["Construction"], 0, src)