Files
vgstation13/code/modules/RCD/RCD.dm
CrazyAmphibian 1c920c8714 code (#37469)
2025-03-18 05:31:46 -05:00

390 lines
11 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
var/list/settings //for stuff like window directions and construction options.
var/current_menu=null //we are keeping both systems of schematics for the sake of backwards compatability
var/list/datum/rcd_scematic_grouping/schem_groups=null
var/datum/rcd_grouped_schematic/selected_schem=null
var/list/client/loaded_clients=null //store a list of clients who have loaded all the images, so we can skip trying to send it to them.
/obj/item/device/rcd/New()
. = ..()
schem_groups=new()
settings=new()
loaded_clients=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) i don't know why this in in here. commented out instead of removed in case it FSU
rebuild_ui()
interface.show(user)
/obj/item/device/rcd/proc/rebuild_ui()
var/dat = ""
dat += {"
<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,FALSE,src.selected==C)
for(var/client/client in interface.clients)
C.send_list_assets(client)
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 style='color:#fff;' 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,src.selected==C)
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
rebuild_ui()
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)