Testmerge Conflict fix?

This commit is contained in:
Artur
2020-01-22 20:17:42 +01:00
parent 8b21a60ac9
commit 255f2ce449
30 changed files with 1585 additions and 1588 deletions

View File

@@ -108,7 +108,10 @@
#define NUKE_ON_TIMING 2 #define NUKE_ON_TIMING 2
#define NUKE_ON_EXPLODING 3 #define NUKE_ON_EXPLODING 3
#define MACHINE_NOT_ELECTRIFIED 0
#define MACHINE_ELECTRIFIED_PERMANENT -1
#define MACHINE_DEFAULT_ELECTRIFY_TIME 30
//these flags are used to tell the DNA modifier if a plant gene cannot be extracted or modified. //these flags are used to tell the DNA modifier if a plant gene cannot be extracted or modified.
#define PLANT_GENE_REMOVABLE (1<<0) #define PLANT_GENE_REMOVABLE (1<<0)
#define PLANT_GENE_EXTRACTABLE (1<<1) #define PLANT_GENE_EXTRACTABLE (1<<1)

View File

@@ -1,6 +1,6 @@
// Ensure the frequency is within bounds of what it should be sending/receiving at // Ensure the frequency is within bounds of what it should be sending/receiving at
/proc/sanitize_frequency(frequency, free = FALSE) /proc/sanitize_frequency(frequency, free = FALSE)
. = round(frequency) frequency = round(frequency)
if(free) if(free)
. = CLAMP(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ) . = CLAMP(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ)
else else

View File

@@ -39,12 +39,12 @@
//title_image = ntitle_image //title_image = ntitle_image
/datum/browser/proc/add_stylesheet(name, file) /datum/browser/proc/add_stylesheet(name, file)
stylesheets["[ckey(name)].css"] = file if(istype(name, /datum/asset/spritesheet))
register_asset("[ckey(name)].css", file) var/datum/asset/spritesheet/sheet = name
stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]"
/datum/browser/proc/add_script(name, file) else
scripts["[ckey(name)].js"] = file stylesheets["[ckey(name)].css"] = file
register_asset("[ckey(name)].js", file) register_asset("[ckey(name)].css", file)
/datum/browser/proc/set_content(ncontent) /datum/browser/proc/set_content(ncontent)
content = ncontent content = ncontent

View File

@@ -1,58 +1,58 @@
/datum/spawners_menu /datum/spawners_menu
var/mob/dead/observer/owner var/mob/dead/observer/owner
/datum/spawners_menu/New(mob/dead/observer/new_owner) /datum/spawners_menu/New(mob/dead/observer/new_owner)
if(!istype(new_owner)) if(!istype(new_owner))
qdel(src) qdel(src)
owner = new_owner owner = new_owner
/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state) /datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "spawners_menu", "Spawners Menu", 700, 600, master_ui, state) ui = new(user, src, ui_key, "spawners_menu", "Spawners Menu", 700, 600, master_ui, state)
ui.open() ui.open()
/datum/spawners_menu/ui_data(mob/user) /datum/spawners_menu/ui_data(mob/user)
var/list/data = list() var/list/data = list()
data["spawners"] = list() data["spawners"] = list()
for(var/spawner in GLOB.mob_spawners) for(var/spawner in GLOB.mob_spawners)
var/list/this = list() var/list/this = list()
this["name"] = spawner this["name"] = spawner
this["short_desc"] = "" this["short_desc"] = ""
this["flavor_text"] = "" this["flavor_text"] = ""
this["important_warning"] = "" this["important_warning"] = ""
this["refs"] = list() this["refs"] = list()
for(var/spawner_obj in GLOB.mob_spawners[spawner]) for(var/spawner_obj in GLOB.mob_spawners[spawner])
this["refs"] += "[REF(spawner_obj)]" this["refs"] += "[REF(spawner_obj)]"
if(!this["desc"]) if(!this["desc"])
if(istype(spawner_obj, /obj/effect/mob_spawn)) if(istype(spawner_obj, /obj/effect/mob_spawn))
var/obj/effect/mob_spawn/MS = spawner_obj var/obj/effect/mob_spawn/MS = spawner_obj
this["short_desc"] = MS.short_desc this["short_desc"] = MS.short_desc
this["flavor_text"] = MS.flavour_text this["flavor_text"] = MS.flavour_text
this["important_info"] = MS.important_info this["important_info"] = MS.important_info
else else
var/obj/O = spawner_obj var/obj/O = spawner_obj
this["desc"] = O.desc this["desc"] = O.desc
this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner]) this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner])
data["spawners"] += list(this) data["spawners"] += list(this)
return data return data
/datum/spawners_menu/ui_act(action, params) /datum/spawners_menu/ui_act(action, params)
if(..()) if(..())
return return
var/spawner_ref = pick(GLOB.mob_spawners[params["name"]]) var/spawner_ref = pick(GLOB.mob_spawners[params["name"]])
var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list
if(!MS) if(!MS)
return return
switch(action) switch(action)
if("jump") if("jump")
if(MS) if(MS)
owner.forceMove(get_turf(MS)) owner.forceMove(get_turf(MS))
. = TRUE . = TRUE
if("spawn") if("spawn")
if(MS) if(MS)
MS.attack_ghost(owner) MS.attack_ghost(owner)
. = TRUE . = TRUE

View File

@@ -728,6 +728,13 @@
/atom/proc/multitool_act(mob/living/user, obj/item/I) /atom/proc/multitool_act(mob/living/user, obj/item/I)
return return
/atom/proc/multitool_check_buffer(user, obj/item/I, silent = FALSE)
if(!istype(I, /obj/item/multitool))
if(user && !silent)
to_chat(user, "<span class='warning'>[I] has no data buffer!</span>")
return FALSE
return TRUE
/atom/proc/screwdriver_act(mob/living/user, obj/item/I) /atom/proc/screwdriver_act(mob/living/user, obj/item/I)
SEND_SIGNAL(src, COMSIG_ATOM_SCREWDRIVER_ACT, user, I) SEND_SIGNAL(src, COMSIG_ATOM_SCREWDRIVER_ACT, user, I)

View File

@@ -1,11 +1,13 @@
/obj/machinery/computer/launchpad /obj/machinery/computer/launchpad
name = "\improper launchpad control console" name = "launchpad control console"
desc = "Used to teleport objects to and from a launchpad." desc = "Used to teleport objects to and from a launchpad."
icon_screen = "teleport" icon_screen = "teleport"
icon_keyboard = "teleport_key" icon_keyboard = "teleport_key"
circuit = /obj/item/circuitboard/computer/launchpad_console circuit = /obj/item/circuitboard/computer/launchpad_console
var/sending = TRUE ui_x = 475
var/current_pad //current pad viewed on the screen ui_y = 260
var/selected_id
var/list/obj/machinery/launchpad/launchpads var/list/obj/machinery/launchpad/launchpads
var/maximum_pads = 4 var/maximum_pads = 4
@@ -18,7 +20,9 @@
return return
/obj/machinery/computer/launchpad/attackby(obj/item/W, mob/user, params) /obj/machinery/computer/launchpad/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/multitool)) if(W.tool_behaviour == TOOL_MULTITOOL)
if(!multitool_check_buffer(user, W))
return
var/obj/item/multitool/M = W var/obj/item/multitool/M = W
if(M.buffer && istype(M.buffer, /obj/machinery/launchpad)) if(M.buffer && istype(M.buffer, /obj/machinery/launchpad))
if(LAZYLEN(launchpads) < maximum_pads) if(LAZYLEN(launchpads) < maximum_pads)
@@ -36,55 +40,7 @@
return FALSE return FALSE
return TRUE return TRUE
/obj/machinery/computer/launchpad/proc/get_pad(number) /obj/machinery/computer/launchpad/proc/teleport(mob/user, obj/machinery/launchpad/pad, sending)
var/obj/machinery/launchpad/pad = launchpads[number]
return pad
/obj/machinery/computer/launchpad/ui_interact(mob/user)
. = ..()
var/list/t = list()
if(!LAZYLEN(launchpads))
obj_flags &= ~IN_USE //Yeah so if you deconstruct teleporter while its in the process of shooting it wont disable the console
t += "<div class='statusDisplay'>No launchpad located.</div><BR>"
else
for(var/i in 1 to LAZYLEN(launchpads))
if(pad_exists(i))
var/obj/machinery/launchpad/pad = get_pad(i)
if(pad.stat & NOPOWER)
t+= "<span class='linkOff'>[pad.display_name]</span>"
else
t+= "<A href='?src=[REF(src)];choose_pad=1;pad=[i]'>[pad.display_name]</A>"
else
launchpads -= get_pad(i)
t += "<BR>"
if(current_pad)
var/obj/machinery/launchpad/pad = get_pad(current_pad)
t += "<div class='statusDisplay'><b>[pad.display_name]</b></div>"
t += "<A href='?src=[REF(src)];change_name=1;pad=[current_pad]'>Rename</A>"
t += "<A href='?src=[REF(src)];remove=1;pad=[current_pad]'>Remove</A><BR><BR>"
t += "<A href='?src=[REF(src)];raisey=1;lowerx=1;pad=[current_pad]'>O</A>" //up-left
t += "<A href='?src=[REF(src)];raisey=1;pad=[current_pad]'>^</A>" //up
t += "<A href='?src=[REF(src)];raisey=1;raisex=1;pad=[current_pad]'>O</A><BR>" //up-right
t += "<A href='?src=[REF(src)];lowerx=1;pad=[current_pad]'><</A>"//left
t += "<A href='?src=[REF(src)];reset=1;pad=[current_pad]'>R</A>"//reset to 0
t += "<A href='?src=[REF(src)];raisex=1;pad=[current_pad]'>></A><BR>"//right
t += "<A href='?src=[REF(src)];lowery=1;lowerx=1;pad=[current_pad]'>O</A>"//down-left
t += "<A href='?src=[REF(src)];lowery=1;pad=[current_pad]'>v</A>"//down
t += "<A href='?src=[REF(src)];lowery=1;raisex=1;pad=[current_pad]'>O</A><BR>"//down-right
t += "<BR>"
t += "<div class='statusDisplay'>Current offset:</div><BR>"
t += "<div class='statusDisplay'>[abs(pad.y_offset)] [pad.y_offset > 0 ? "N":"S"] <a href='?src=[REF(src)];sety=1;pad=[current_pad]'>\[SET\]</a></div><BR>"
t += "<div class='statusDisplay'>[abs(pad.x_offset)] [pad.x_offset > 0 ? "E":"W"] <a href='?src=[REF(src)];setx=1;pad=[current_pad]'>\[SET\]</a></div><BR>"
t += "<BR><A href='?src=[REF(src)];launch=1;pad=[current_pad]'>Launch</A>"
t += " <A href='?src=[REF(src)];pull=1;pad=[current_pad]'>Pull</A>"
var/datum/browser/popup = new(user, "launchpad", name, 300, 500)
popup.set_content(t.Join())
popup.open()
/obj/machinery/computer/launchpad/proc/teleport(mob/user, obj/machinery/launchpad/pad)
if(QDELETED(pad)) if(QDELETED(pad))
to_chat(user, "<span class='warning'>ERROR: Launchpad not responding. Check launchpad integrity.</span>") to_chat(user, "<span class='warning'>ERROR: Launchpad not responding. Check launchpad integrity.</span>")
return return
@@ -93,66 +49,83 @@
return return
pad.doteleport(user, sending) pad.doteleport(user, sending)
/obj/machinery/computer/launchpad/Topic(href, href_list) /obj/machinery/computer/launchpad/proc/get_pad(number)
var/obj/machinery/launchpad/pad var/obj/machinery/launchpad/pad = launchpads[number]
if(href_list["pad"]) return pad
pad = get_pad(text2num(href_list["pad"]))
/obj/machinery/computer/launchpad/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "launchpad_console", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/launchpad/ui_data(mob/user)
var/list/data = list()
var/list/pad_list = list()
for(var/i in 1 to LAZYLEN(launchpads))
if(pad_exists(i))
var/obj/machinery/launchpad/pad = get_pad(i)
var/list/this_pad = list()
this_pad["name"] = pad.display_name
this_pad["id"] = i
if(pad.stat & NOPOWER)
this_pad["inactive"] = TRUE
pad_list += list(this_pad)
else
launchpads -= get_pad(i)
data["launchpads"] = pad_list
data["selected_id"] = selected_id
if(selected_id)
var/obj/machinery/launchpad/current_pad = launchpads[selected_id]
data["x"] = current_pad.x_offset
data["y"] = current_pad.y_offset
data["pad_name"] = current_pad.display_name
data["range"] = current_pad.range
data["selected_pad"] = current_pad
if(QDELETED(current_pad) || (current_pad.stat & NOPOWER))
data["pad_active"] = FALSE
return data
data["pad_active"] = TRUE
return data
/obj/machinery/computer/launchpad/ui_act(action, params)
if(..()) if(..())
return return
if(!LAZYLEN(launchpads)) var/obj/machinery/launchpad/current_pad = launchpads[selected_id]
updateDialog() switch(action)
return if("select_pad")
selected_id = text2num(params["id"])
. = TRUE
if("set_pos")
var/new_x = text2num(params["x"])
var/new_y = text2num(params["y"])
current_pad.set_offset(new_x, new_y)
. = TRUE
if("move_pos")
var/plus_x = text2num(params["x"])
var/plus_y = text2num(params["y"])
current_pad.set_offset(
x = current_pad.x_offset + plus_x,
y = current_pad.y_offset + plus_y
)
. = TRUE
if("rename")
. = TRUE
var/new_name = params["name"]
if(!new_name)
return
current_pad.display_name = new_name
if("remove")
if(usr && alert(usr, "Are you sure?", "Unlink Launchpad", "I'm Sure", "Abort") != "Abort")
launchpads -= current_pad
selected_id = null
. = TRUE
if("launch")
teleport(usr, current_pad, TRUE)
. = TRUE
if(href_list["choose_pad"]) if("pull")
current_pad = text2num(href_list["pad"]) teleport(usr, current_pad, FALSE)
. = TRUE
if(href_list["raisex"]) . = TRUE
if(pad.x_offset < pad.range)
pad.x_offset++
if(href_list["lowerx"])
if(pad.x_offset > (pad.range * -1))
pad.x_offset--
if(href_list["raisey"])
if(pad.y_offset < pad.range)
pad.y_offset++
if(href_list["lowery"])
if(pad.y_offset > (pad.range * -1))
pad.y_offset--
if(href_list["reset"])
pad.y_offset = 0
pad.x_offset = 0
if(href_list["change_name"])
var/new_name = stripped_input(usr, "What do you wish to name the launchpad?", "Launchpad", pad.display_name, 15)
if(!new_name)
return
pad.display_name = new_name
if(href_list["setx"])
var/newx = input(usr, "Input new x offset", pad.display_name, pad.x_offset) as null|num
if(!isnull(newx))
pad.x_offset = CLAMP(newx, -pad.range, pad.range)
if(href_list["sety"])
var/newy = input(usr, "Input new y offset", pad.display_name, pad.y_offset) as null|num
if(!isnull(newy))
pad.y_offset = CLAMP(newy, -pad.range, pad.range)
if(href_list["remove"])
if(usr && alert(usr, "Are you sure?", "Remove Launchpad", "I'm Sure", "Abort") != "Abort")
launchpads -= pad
if(href_list["launch"])
sending = TRUE
teleport(usr, pad)
if(href_list["pull"])
sending = FALSE
teleport(usr, pad)
updateDialog()

View File

@@ -6,6 +6,9 @@
icon_keyboard = "security_key" icon_keyboard = "security_key"
req_access = list(ACCESS_ARMORY) req_access = list(ACCESS_ARMORY)
circuit = /obj/item/circuitboard/computer/gulag_teleporter_console circuit = /obj/item/circuitboard/computer/gulag_teleporter_console
ui_x = 350
ui_y = 295
var/default_goal = 200 var/default_goal = 200
var/obj/machinery/gulag_teleporter/teleporter = null var/obj/machinery/gulag_teleporter/teleporter = null
var/obj/structure/gulag_beacon/beacon = null var/obj/structure/gulag_beacon/beacon = null
@@ -22,7 +25,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "gulag_console", name, 455, 440, master_ui, state) ui = new(user, src, ui_key, "gulag_console", name, ui_x, ui_y, master_ui, state)
ui.open() ui.open()
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user) /obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user)
@@ -50,13 +53,19 @@
data["teleporter_location"] = "([teleporter.x], [teleporter.y], [teleporter.z])" data["teleporter_location"] = "([teleporter.x], [teleporter.y], [teleporter.z])"
data["teleporter_lock"] = teleporter.locked data["teleporter_lock"] = teleporter.locked
data["teleporter_state_open"] = teleporter.state_open data["teleporter_state_open"] = teleporter.state_open
else
data["teleporter"] = null
if(beacon) if(beacon)
data["beacon"] = beacon data["beacon"] = beacon
data["beacon_location"] = "([beacon.x], [beacon.y], [beacon.z])" data["beacon_location"] = "([beacon.x], [beacon.y], [beacon.z])"
else
data["beacon"] = null
if(contained_id) if(contained_id)
data["id"] = contained_id data["id"] = contained_id
data["id_name"] = contained_id.registered_name data["id_name"] = contained_id.registered_name
data["goal"] = contained_id.goal data["goal"] = contained_id.goal
else
data["id"] = null
data["can_teleport"] = can_teleport data["can_teleport"] = can_teleport
return data return data
@@ -72,36 +81,41 @@
switch(action) switch(action)
if("scan_teleporter") if("scan_teleporter")
teleporter = findteleporter() teleporter = findteleporter()
return TRUE
if("scan_beacon") if("scan_beacon")
beacon = findbeacon() beacon = findbeacon()
return TRUE
if("handle_id") if("handle_id")
if(contained_id) if(contained_id)
id_eject(usr) id_eject(usr)
else else
id_insert(usr) id_insert(usr)
return TRUE
if("set_goal") if("set_goal")
var/new_goal = input("Set the amount of points:", "Points", contained_id.goal) as num|null var/new_goal = text2num(params["value"])
if(!isnum(new_goal)) if(!isnum(new_goal))
return return
if(!new_goal) if(!new_goal)
new_goal = default_goal new_goal = default_goal
if (new_goal > 1000)
to_chat(usr, "The entered amount of points is too large. Points have instead been set to the maximum allowed amount.")
contained_id.goal = CLAMP(new_goal, 0, 1000) //maximum 1000 points contained_id.goal = CLAMP(new_goal, 0, 1000) //maximum 1000 points
return TRUE
if("toggle_open") if("toggle_open")
if(teleporter.locked) if(teleporter.locked)
to_chat(usr, "The teleporter is locked") to_chat(usr, "<span class='alert'>The teleporter must be unlocked first.</span>")
return return
teleporter.toggle_open() teleporter.toggle_open()
return TRUE
if("teleporter_lock") if("teleporter_lock")
if(teleporter.state_open) if(teleporter.state_open)
to_chat(usr, "Close the teleporter before locking!") to_chat(usr, "<span class='alert'>The teleporter must be closed first.</span>")
return return
teleporter.locked = !teleporter.locked teleporter.locked = !teleporter.locked
return TRUE
if("teleport") if("teleport")
if(!teleporter || !beacon) if(!teleporter || !beacon)
return return
addtimer(CALLBACK(src, .proc/teleport, usr), 5) addtimer(CALLBACK(src, .proc/teleport, usr), 5)
return TRUE
/obj/machinery/computer/prisoner/gulag_teleporter_computer/proc/scan_machinery() /obj/machinery/computer/prisoner/gulag_teleporter_computer/proc/scan_machinery()
teleporter = findteleporter() teleporter = findteleporter()
@@ -129,12 +143,12 @@
say("[contained_id]'s ID card goal defaulting to [contained_id.goal] points.") say("[contained_id]'s ID card goal defaulting to [contained_id.goal] points.")
log_game("[key_name(user)] teleported [key_name(prisoner)] to the Labor Camp [COORD(beacon)] for [id_goal_not_set ? "default goal of ":""][contained_id.goal] points.") log_game("[key_name(user)] teleported [key_name(prisoner)] to the Labor Camp [COORD(beacon)] for [id_goal_not_set ? "default goal of ":""][contained_id.goal] points.")
teleporter.handle_prisoner(contained_id, temporary_record) teleporter.handle_prisoner(contained_id, temporary_record)
playsound(src, 'sound/weapons/emitter.ogg', 50, 1) playsound(src, 'sound/weapons/emitter.ogg', 50, TRUE)
prisoner.forceMove(get_turf(beacon)) prisoner.forceMove(get_turf(beacon))
prisoner.Stun(40) // small travel dizziness prisoner.Stun(40) // small travel dizziness
to_chat(prisoner, "<span class='warning'>The teleportation makes you a little dizzy.</span>") to_chat(prisoner, "<span class='warning'>The teleportation makes you a little dizzy.</span>")
new /obj/effect/particle_effect/sparks(get_turf(prisoner)) new /obj/effect/particle_effect/sparks(get_turf(prisoner))
playsound(src, "sparks", 50, 1) playsound(src, "sparks", 50, TRUE)
if(teleporter.locked) if(teleporter.locked)
teleporter.locked = FALSE teleporter.locked = FALSE
teleporter.toggle_open() teleporter.toggle_open()

View File

@@ -5,6 +5,8 @@
icon_keyboard = "teleport_key" icon_keyboard = "teleport_key"
light_color = LIGHT_COLOR_BLUE light_color = LIGHT_COLOR_BLUE
circuit = /obj/item/circuitboard/computer/teleporter circuit = /obj/item/circuitboard/computer/teleporter
ui_x = 475
ui_y = 130
var/regime_set = "Teleporter" var/regime_set = "Teleporter"
var/id var/id
var/obj/machinery/teleport/station/power_station var/obj/machinery/teleport/station/power_station
@@ -32,34 +34,30 @@
break break
return power_station return power_station
/obj/machinery/computer/teleporter/ui_interact(mob/user) obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
. = ..() datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
var/data = "<h3>Teleporter Status</h3>" ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!power_station) if(!ui)
data += "<div class='statusDisplay'>No power station linked.</div>" ui = new(user, src, ui_key, "teleporter", name, ui_x, ui_y, master_ui, state)
else if(!power_station.teleporter_hub) ui.open()
data += "<div class='statusDisplay'>No hub linked.</div>"
/obj/machinery/computer/teleporter/ui_data(mob/user)
var/list/data = list()
data["power_station"] = power_station ? TRUE : FALSE
data["teleporter_hub"] = power_station?.teleporter_hub ? TRUE : FALSE
data["regime_set"] = regime_set
data["target"] = !target ? "None" : "[get_area(target)] [(regime_set != "Gate") ? "" : "Teleporter"]"
data["calibrating"] = calibrating
if(power_station?.teleporter_hub?.calibrated || power_station?.teleporter_hub?.accuracy >= 3)
data["calibrated"] = TRUE
else else
data += "<div class='statusDisplay'>Current regime: [regime_set]<BR>" data["calibrated"] = FALSE
data += "Current target: [(!target) ? "None" : "[get_area(target)] [(regime_set != "Gate") ? "" : "Teleporter"]"]<BR>"
if(calibrating)
data += "Calibration: <font color='yellow'>In Progress</font>"
else if(power_station.teleporter_hub.calibrated || power_station.efficiency >= 3)
data += "Calibration: <font color='green'>Optimal</font>"
else
data += "Calibration: <font color='red'>Sub-Optimal</font>"
data += "</div><BR>"
data += "<A href='?src=[REF(src)];regimeset=1'>Change regime</A><BR>" return data
data += "<A href='?src=[REF(src)];settarget=1'>Set target</A><BR>"
data += "<BR><A href='?src=[REF(src)];calibrate=1'>Calibrate Hub</A>"
var/datum/browser/popup = new(user, "teleporter", name, 400, 400) /obj/machinery/computer/teleporter/ui_act(action, params)
popup.set_content(data)
popup.open()
/obj/machinery/computer/teleporter/Topic(href, href_list)
if(..()) if(..())
return return
@@ -70,38 +68,39 @@
say("Error: Calibration in progress. Stand by.") say("Error: Calibration in progress. Stand by.")
return return
if(href_list["regimeset"]) switch(action)
power_station.engaged = 0 if("regimeset")
power_station.teleporter_hub.update_icon() power_station.engaged = FALSE
power_station.teleporter_hub.calibrated = 0 power_station.teleporter_hub.update_icon()
reset_regime() power_station.teleporter_hub.calibrated = FALSE
if(href_list["settarget"]) reset_regime()
power_station.engaged = 0 . = TRUE
power_station.teleporter_hub.update_icon() if("settarget")
power_station.teleporter_hub.calibrated = 0 power_station.engaged = FALSE
set_target(usr) power_station.teleporter_hub.update_icon()
if(href_list["calibrate"]) power_station.teleporter_hub.calibrated = FALSE
if(!target) set_target(usr)
say("Error: No target set to calibrate to.") . = TRUE
return if("calibrate")
if(power_station.teleporter_hub.calibrated || power_station.efficiency >= 3) if(!target)
say("Hub is already calibrated!") say("Error: No target set to calibrate to.")
return return
say("Processing hub calibration to target...") if(power_station.teleporter_hub.calibrated || power_station.teleporter_hub.accuracy >= 3)
say("Hub is already calibrated!")
return
calibrating = 1 say("Processing hub calibration to target...")
power_station.update_icon() calibrating = TRUE
spawn(50 * (3 - power_station.efficiency)) //Better parts mean faster calibration
calibrating = 0
if(check_hub_connection())
power_station.teleporter_hub.calibrated = 1
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
power_station.update_icon() power_station.update_icon()
updateDialog() spawn(50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration
calibrating = FALSE
updateDialog() if(check_hub_connection())
power_station.teleporter_hub.calibrated = TRUE
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
power_station.update_icon()
. = TRUE
/obj/machinery/computer/teleporter/proc/check_hub_connection() /obj/machinery/computer/teleporter/proc/check_hub_connection()
if(!power_station) if(!power_station)

View File

@@ -16,6 +16,7 @@
var/power_efficiency = 1 var/power_efficiency = 1
var/x_offset = 0 var/x_offset = 0
var/y_offset = 0 var/y_offset = 0
var/indicator_icon = "launchpad_target"
/obj/machinery/launchpad/RefreshParts() /obj/machinery/launchpad/RefreshParts()
var/E = 0 var/E = 0
@@ -34,17 +35,28 @@
return return
if(panel_open) if(panel_open)
if(istype(I, /obj/item/multitool)) if(I.tool_behaviour == TOOL_MULTITOOL)
if(!multitool_check_buffer(user, I))
return
var/obj/item/multitool/M = I var/obj/item/multitool/M = I
M.buffer = src M.buffer = src
to_chat(user, "<span class='notice'>You save the data in the [I.name]'s buffer.</span>") to_chat(user, "<span class='notice'>You save the data in the [I.name]'s buffer.</span>")
return 1 return TRUE
if(default_deconstruction_crowbar(I)) if(default_deconstruction_crowbar(I))
return return
return ..() return ..()
/obj/machinery/launchpad/attack_ghost(mob/dead/observer/ghost)
. = ..()
if(.)
return
var/target_x = x + x_offset
var/target_y = y + y_offset
var/turf/target = locate(target_x, target_y, z)
ghost.forceMove(target)
/obj/machinery/launchpad/proc/isAvailable() /obj/machinery/launchpad/proc/isAvailable()
if(stat & NOPOWER) if(stat & NOPOWER)
return FALSE return FALSE
@@ -52,6 +64,14 @@
return FALSE return FALSE
return TRUE return TRUE
/obj/machinery/launchpad/proc/set_offset(x, y)
if(teleporting)
return
if(!isnull(x))
x_offset = CLAMP(x, -range, range)
if(!isnull(y))
y_offset = CLAMP(y, -range, range)
/obj/machinery/launchpad/proc/doteleport(mob/user, sending) /obj/machinery/launchpad/proc/doteleport(mob/user, sending)
if(teleporting) if(teleporting)
to_chat(user, "<span class='warning'>ERROR: Launchpad busy.</span>") to_chat(user, "<span class='warning'>ERROR: Launchpad busy.</span>")
@@ -69,12 +89,22 @@
var/area/A = get_area(target) var/area/A = get_area(target)
flick(icon_teleport, src) flick(icon_teleport, src)
playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, 1)
//Change the indicator's icon to show that we're teleporting
if(sending)
indicator_icon = "launchpad_launch"
else
indicator_icon = "launchpad_pull"
playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, TRUE)
teleporting = TRUE teleporting = TRUE
sleep(teleport_speed) sleep(teleport_speed)
//Set the indicator icon back to normal
indicator_icon = "launchpad_target"
if(QDELETED(src) || !isAvailable()) if(QDELETED(src) || !isAvailable())
return return
@@ -91,25 +121,25 @@
source = dest source = dest
dest = target dest = target
playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, 1) playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, TRUE)
var/first = TRUE var/first = TRUE
for(var/atom/movable/ROI in source) for(var/atom/movable/ROI in source)
if(ROI == src) if(ROI == src)
continue continue
// if it's anchored, don't teleport if(!istype(ROI) || isdead(ROI) || iscameramob(ROI) || istype(ROI, /obj/effect/dummy/phased_mob))
continue//don't teleport these
var/on_chair = "" var/on_chair = ""
if(ROI.anchored) if(ROI.anchored)// if it's anchored, don't teleport
if(isliving(ROI)) if(isliving(ROI))
var/mob/living/L = ROI var/mob/living/L = ROI
if(L.buckled) if(L.buckled)
// TP people on office chairs // TP people on office chairs
if(L.buckled.anchored) if(L.buckled.anchored)
continue continue
on_chair = " (on a chair)" on_chair = " (on a chair)"
else else
continue continue
else if(!isobserver(ROI)) else
continue continue
if(!first) if(!first)
log_msg += ", " log_msg += ", "
@@ -158,11 +188,11 @@
var/obj/item/storage/briefcase/launchpad/briefcase var/obj/item/storage/briefcase/launchpad/briefcase
/obj/machinery/launchpad/briefcase/Initialize(mapload, briefcase) /obj/machinery/launchpad/briefcase/Initialize(mapload, briefcase)
. = ..() . = ..()
if(!briefcase) if(!briefcase)
log_game("[src] has been spawned without a briefcase.") log_game("[src] has been spawned without a briefcase.")
return INITIALIZE_HINT_QDEL return INITIALIZE_HINT_QDEL
src.briefcase = briefcase src.briefcase = briefcase
/obj/machinery/launchpad/briefcase/Destroy() /obj/machinery/launchpad/briefcase/Destroy()
QDEL_NULL(briefcase) QDEL_NULL(briefcase)
@@ -255,7 +285,7 @@
/obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "launchpad_remote", "Briefcase Launchpad Remote", 550, 400, master_ui, state) //width, height ui = new(user, src, ui_key, "launchpad_remote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
ui.set_style("syndicate") ui.set_style("syndicate")
ui.open() ui.open()
@@ -270,10 +300,9 @@
return data return data
data["pad_name"] = pad.display_name data["pad_name"] = pad.display_name
data["abs_x"] = abs(pad.x_offset) data["range"] = pad.range
data["abs_y"] = abs(pad.y_offset) data["x"] = pad.x_offset
data["north_south"] = pad.y_offset > 0 ? "N":"S" data["y"] = pad.y_offset
data["east_west"] = pad.x_offset > 0 ? "E":"W"
return data return data
/obj/item/launchpad_remote/proc/teleport(mob/user, obj/machinery/launchpad/pad) /obj/item/launchpad_remote/proc/teleport(mob/user, obj/machinery/launchpad/pad)
@@ -289,76 +318,33 @@
if(..()) if(..())
return return
switch(action) switch(action)
if("right") if("set_pos")
if(pad.x_offset < pad.range) var/new_x = text2num(params["x"])
pad.x_offset++ var/new_y = text2num(params["y"])
pad.set_offset(new_x, new_y)
. = TRUE . = TRUE
if("move_pos")
if("left") var/plus_x = text2num(params["x"])
if(pad.x_offset > (pad.range * -1)) var/plus_y = text2num(params["y"])
pad.x_offset-- pad.set_offset(
x = pad.x_offset + plus_x,
y = pad.y_offset + plus_y
)
. = TRUE . = TRUE
if("up")
if(pad.y_offset < pad.range)
pad.y_offset++
. = TRUE
if("down")
if(pad.y_offset > (pad.range * -1))
pad.y_offset--
. = TRUE
if("up-right")
if(pad.y_offset < pad.range)
pad.y_offset++
if(pad.x_offset < pad.range)
pad.x_offset++
. = TRUE
if("up-left")
if(pad.y_offset < pad.range)
pad.y_offset++
if(pad.x_offset > (pad.range * -1))
pad.x_offset--
. = TRUE
if("down-right")
if(pad.y_offset > (pad.range * -1))
pad.y_offset--
if(pad.x_offset < pad.range)
pad.x_offset++
. = TRUE
if("down-left")
if(pad.y_offset > (pad.range * -1))
pad.y_offset--
if(pad.x_offset > (pad.range * -1))
pad.x_offset--
. = TRUE
if("reset")
pad.y_offset = 0
pad.x_offset = 0
. = TRUE
if("rename") if("rename")
. = TRUE . = TRUE
var/new_name = stripped_input(usr, "How do you want to rename the launchpad?", "Launchpad", pad.display_name, 15) var/new_name = params["name"]
if(!new_name) if(!new_name)
return return
pad.display_name = new_name pad.display_name = new_name
if("remove") if("remove")
. = TRUE . = TRUE
if(usr && alert(usr, "Are you sure?", "Unlink Launchpad", "I'm Sure", "Abort") != "Abort") if(usr && alert(usr, "Are you sure?", "Unlink Launchpad", "I'm Sure", "Abort") != "Abort")
pad = null pad = null
if("launch") if("launch")
sending = TRUE sending = TRUE
teleport(usr, pad) teleport(usr, pad)
. = TRUE . = TRUE
if("pull") if("pull")
sending = FALSE sending = FALSE
teleport(usr, pad) teleport(usr, pad)

View File

@@ -1,453 +1,453 @@
// SUIT STORAGE UNIT ///////////////// // SUIT STORAGE UNIT /////////////////
/obj/machinery/suit_storage_unit /obj/machinery/suit_storage_unit
name = "suit storage unit" name = "suit storage unit"
desc = "An industrial unit made to hold and decontaminate irradiated equipment. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit." desc = "An industrial unit made to hold and decontaminate irradiated equipment. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit."
icon = 'icons/obj/machines/suit_storage.dmi' icon = 'icons/obj/machines/suit_storage.dmi'
icon_state = "close" icon_state = "close"
density = TRUE density = TRUE
max_integrity = 250 max_integrity = 250
var/obj/item/clothing/suit/space/suit = null var/obj/item/clothing/suit/space/suit = null
var/obj/item/clothing/head/helmet/space/helmet = null var/obj/item/clothing/head/helmet/space/helmet = null
var/obj/item/clothing/mask/mask = null var/obj/item/clothing/mask/mask = null
var/obj/item/storage = null var/obj/item/storage = null
var/suit_type = null var/suit_type = null
var/helmet_type = null var/helmet_type = null
var/mask_type = null var/mask_type = null
var/storage_type = null var/storage_type = null
state_open = FALSE state_open = FALSE
var/locked = FALSE var/locked = FALSE
panel_open = FALSE panel_open = FALSE
var/safeties = TRUE var/safeties = TRUE
var/uv = FALSE var/uv = FALSE
var/uv_super = FALSE var/uv_super = FALSE
var/uv_cycles = 6 var/uv_cycles = 6
var/message_cooldown var/message_cooldown
var/breakout_time = 300 var/breakout_time = 300
/obj/machinery/suit_storage_unit/standard_unit /obj/machinery/suit_storage_unit/standard_unit
suit_type = /obj/item/clothing/suit/space/eva suit_type = /obj/item/clothing/suit/space/eva
helmet_type = /obj/item/clothing/head/helmet/space/eva helmet_type = /obj/item/clothing/head/helmet/space/eva
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/captain /obj/machinery/suit_storage_unit/captain
suit_type = /obj/item/clothing/suit/space/hardsuit/captain suit_type = /obj/item/clothing/suit/space/hardsuit/captain
mask_type = /obj/item/clothing/mask/gas/sechailer mask_type = /obj/item/clothing/mask/gas/sechailer
storage_type = /obj/item/tank/jetpack/oxygen/captain storage_type = /obj/item/tank/jetpack/oxygen/captain
/obj/machinery/suit_storage_unit/engine /obj/machinery/suit_storage_unit/engine
suit_type = /obj/item/clothing/suit/space/hardsuit/engine suit_type = /obj/item/clothing/suit/space/hardsuit/engine
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
storage_type= /obj/item/clothing/shoes/magboots storage_type= /obj/item/clothing/shoes/magboots
/obj/machinery/suit_storage_unit/ce /obj/machinery/suit_storage_unit/ce
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
storage_type= /obj/item/clothing/shoes/magboots/advance storage_type= /obj/item/clothing/shoes/magboots/advance
/obj/machinery/suit_storage_unit/security /obj/machinery/suit_storage_unit/security
suit_type = /obj/item/clothing/suit/space/hardsuit/security suit_type = /obj/item/clothing/suit/space/hardsuit/security
mask_type = /obj/item/clothing/mask/gas/sechailer mask_type = /obj/item/clothing/mask/gas/sechailer
storage_type = /obj/item/tank/jetpack/oxygen/security storage_type = /obj/item/tank/jetpack/oxygen/security
/obj/machinery/suit_storage_unit/hos /obj/machinery/suit_storage_unit/hos
suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos
mask_type = /obj/item/clothing/mask/gas/sechailer mask_type = /obj/item/clothing/mask/gas/sechailer
storage_type = /obj/item/tank/internals/oxygen storage_type = /obj/item/tank/internals/oxygen
/obj/machinery/suit_storage_unit/atmos /obj/machinery/suit_storage_unit/atmos
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
mask_type = /obj/item/clothing/mask/gas mask_type = /obj/item/clothing/mask/gas
storage_type = /obj/item/watertank/atmos storage_type = /obj/item/watertank/atmos
/obj/machinery/suit_storage_unit/mining /obj/machinery/suit_storage_unit/mining
suit_type = /obj/item/clothing/suit/hooded/explorer/standard suit_type = /obj/item/clothing/suit/hooded/explorer/standard
mask_type = /obj/item/clothing/mask/gas/explorer mask_type = /obj/item/clothing/mask/gas/explorer
/obj/machinery/suit_storage_unit/mining/eva /obj/machinery/suit_storage_unit/mining/eva
suit_type = /obj/item/clothing/suit/space/hardsuit/mining suit_type = /obj/item/clothing/suit/space/hardsuit/mining
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/cmo /obj/machinery/suit_storage_unit/cmo
suit_type = /obj/item/clothing/suit/space/hardsuit/medical suit_type = /obj/item/clothing/suit/space/hardsuit/medical
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/rd /obj/machinery/suit_storage_unit/rd
suit_type = /obj/item/clothing/suit/space/hardsuit/rd suit_type = /obj/item/clothing/suit/space/hardsuit/rd
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/syndicate /obj/machinery/suit_storage_unit/syndicate
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
mask_type = /obj/item/clothing/mask/gas/syndicate mask_type = /obj/item/clothing/mask/gas/syndicate
storage_type = /obj/item/tank/jetpack/oxygen/harness storage_type = /obj/item/tank/jetpack/oxygen/harness
/obj/machinery/suit_storage_unit/ert/command /obj/machinery/suit_storage_unit/ert/command
suit_type = /obj/item/clothing/suit/space/hardsuit/ert suit_type = /obj/item/clothing/suit/space/hardsuit/ert
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/security /obj/machinery/suit_storage_unit/ert/security
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/engineer /obj/machinery/suit_storage_unit/ert/engineer
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/ert/medical /obj/machinery/suit_storage_unit/ert/medical
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med
mask_type = /obj/item/clothing/mask/breath mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/internals/emergency_oxygen/double storage_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/machinery/suit_storage_unit/radsuit /obj/machinery/suit_storage_unit/radsuit
name = "radiation suit storage unit" name = "radiation suit storage unit"
suit_type = /obj/item/clothing/suit/radiation suit_type = /obj/item/clothing/suit/radiation
helmet_type = /obj/item/clothing/head/radiation helmet_type = /obj/item/clothing/head/radiation
storage_type = /obj/item/geiger_counter storage_type = /obj/item/geiger_counter
/obj/machinery/suit_storage_unit/open /obj/machinery/suit_storage_unit/open
state_open = TRUE state_open = TRUE
density = FALSE density = FALSE
/obj/machinery/suit_storage_unit/Initialize() /obj/machinery/suit_storage_unit/Initialize()
. = ..() . = ..()
wires = new /datum/wires/suit_storage_unit(src) wires = new /datum/wires/suit_storage_unit(src)
if(suit_type) if(suit_type)
suit = new suit_type(src) suit = new suit_type(src)
if(helmet_type) if(helmet_type)
helmet = new helmet_type(src) helmet = new helmet_type(src)
if(mask_type) if(mask_type)
mask = new mask_type(src) mask = new mask_type(src)
if(storage_type) if(storage_type)
storage = new storage_type(src) storage = new storage_type(src)
update_icon() update_icon()
/obj/machinery/suit_storage_unit/Destroy() /obj/machinery/suit_storage_unit/Destroy()
QDEL_NULL(suit) QDEL_NULL(suit)
QDEL_NULL(helmet) QDEL_NULL(helmet)
QDEL_NULL(mask) QDEL_NULL(mask)
QDEL_NULL(storage) QDEL_NULL(storage)
return ..() return ..()
/obj/machinery/suit_storage_unit/update_icon() /obj/machinery/suit_storage_unit/update_icon()
cut_overlays() cut_overlays()
if(uv) if(uv)
if(uv_super) if(uv_super)
add_overlay("super") add_overlay("super")
else if(occupant) else if(occupant)
add_overlay("uvhuman") add_overlay("uvhuman")
else else
add_overlay("uv") add_overlay("uv")
else if(state_open) else if(state_open)
if(stat & BROKEN) if(stat & BROKEN)
add_overlay("broken") add_overlay("broken")
else else
add_overlay("open") add_overlay("open")
if(suit) if(suit)
add_overlay("suit") add_overlay("suit")
if(helmet) if(helmet)
add_overlay("helm") add_overlay("helm")
if(storage) if(storage)
add_overlay("storage") add_overlay("storage")
else if(occupant) else if(occupant)
add_overlay("human") add_overlay("human")
/obj/machinery/suit_storage_unit/power_change() /obj/machinery/suit_storage_unit/power_change()
..() ..()
if(!is_operational() && state_open) if(!is_operational() && state_open)
open_machine() open_machine()
dump_contents() dump_contents()
update_icon() update_icon()
/obj/machinery/suit_storage_unit/proc/dump_contents() /obj/machinery/suit_storage_unit/proc/dump_contents()
dropContents() dropContents()
helmet = null helmet = null
suit = null suit = null
mask = null mask = null
storage = null storage = null
occupant = null occupant = null
/obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE) /obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1)) if(!(flags_1 & NODECONSTRUCT_1))
open_machine() open_machine()
dump_contents() dump_contents()
new /obj/item/stack/sheet/metal (loc, 2) new /obj/item/stack/sheet/metal (loc, 2)
qdel(src) qdel(src)
/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user) /obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A)) if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A))
return return
var/mob/living/target = A var/mob/living/target = A
if(!state_open) if(!state_open)
to_chat(user, "<span class='warning'>The unit's doors are shut!</span>") to_chat(user, "<span class='warning'>The unit's doors are shut!</span>")
return return
if(!is_operational()) if(!is_operational())
to_chat(user, "<span class='warning'>The unit is not operational!</span>") to_chat(user, "<span class='warning'>The unit is not operational!</span>")
return return
if(occupant || helmet || suit || storage) if(occupant || helmet || suit || storage)
to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>") to_chat(user, "<span class='warning'>It's too cluttered inside to fit in!</span>")
return return
if(target == user) if(target == user)
user.visible_message("<span class='warning'>[user] starts squeezing into [src]!</span>", "<span class='notice'>You start working your way into [src]...</span>") user.visible_message("<span class='warning'>[user] starts squeezing into [src]!</span>", "<span class='notice'>You start working your way into [src]...</span>")
else else
target.visible_message("<span class='warning'>[user] starts shoving [target] into [src]!</span>", "<span class='userdanger'>[user] starts shoving you into [src]!</span>") target.visible_message("<span class='warning'>[user] starts shoving [target] into [src]!</span>", "<span class='userdanger'>[user] starts shoving you into [src]!</span>")
if(do_mob(user, target, 30)) if(do_mob(user, target, 30))
if(occupant || helmet || suit || storage) if(occupant || helmet || suit || storage)
return return
if(target == user) if(target == user)
user.visible_message("<span class='warning'>[user] slips into [src] and closes the door behind [user.p_them()]!</span>", "<span class=notice'>You slip into [src]'s cramped space and shut its door.</span>") user.visible_message("<span class='warning'>[user] slips into [src] and closes the door behind [user.p_them()]!</span>", "<span class=notice'>You slip into [src]'s cramped space and shut its door.</span>")
else else
target.visible_message("<span class='warning'>[user] pushes [target] into [src] and shuts its door!<span>", "<span class='userdanger'>[user] shoves you into [src] and shuts the door!</span>") target.visible_message("<span class='warning'>[user] pushes [target] into [src] and shuts its door!<span>", "<span class='userdanger'>[user] shoves you into [src] and shuts the door!</span>")
close_machine(target) close_machine(target)
add_fingerprint(user) add_fingerprint(user)
/obj/machinery/suit_storage_unit/proc/cook() /obj/machinery/suit_storage_unit/proc/cook()
var/mob/living/mob_occupant = occupant var/mob/living/mob_occupant = occupant
if(uv_cycles) if(uv_cycles)
uv_cycles-- uv_cycles--
uv = TRUE uv = TRUE
locked = TRUE locked = TRUE
update_icon() update_icon()
if(occupant) if(occupant)
if(uv_super) if(uv_super)
mob_occupant.adjustFireLoss(rand(20, 36)) mob_occupant.adjustFireLoss(rand(20, 36))
else else
mob_occupant.adjustFireLoss(rand(10, 16)) mob_occupant.adjustFireLoss(rand(10, 16))
mob_occupant.emote("scream") mob_occupant.emote("scream")
addtimer(CALLBACK(src, .proc/cook), 50) addtimer(CALLBACK(src, .proc/cook), 50)
else else
uv_cycles = initial(uv_cycles) uv_cycles = initial(uv_cycles)
uv = FALSE uv = FALSE
locked = FALSE locked = FALSE
if(uv_super) if(uv_super)
visible_message("<span class='warning'>[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.</span>") visible_message("<span class='warning'>[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.</span>")
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1) playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1)
helmet = null helmet = null
qdel(helmet) qdel(helmet)
suit = null suit = null
qdel(suit) // Delete everything but the occupant. qdel(suit) // Delete everything but the occupant.
mask = null mask = null
qdel(mask) qdel(mask)
storage = null storage = null
qdel(storage) qdel(storage)
// The wires get damaged too. // The wires get damaged too.
wires.cut_all() wires.cut_all()
else else
if(!occupant) if(!occupant)
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>") visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
else else
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>") visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
mob_occupant.radiation = 0 mob_occupant.radiation = 0
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1) playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such. var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such.
if(suit) if(suit)
things_to_clear += suit things_to_clear += suit
things_to_clear += suit.GetAllContents() things_to_clear += suit.GetAllContents()
if(helmet) if(helmet)
things_to_clear += helmet things_to_clear += helmet
things_to_clear += helmet.GetAllContents() things_to_clear += helmet.GetAllContents()
if(mask) if(mask)
things_to_clear += mask things_to_clear += mask
things_to_clear += mask.GetAllContents() things_to_clear += mask.GetAllContents()
if(storage) if(storage)
things_to_clear += storage things_to_clear += storage
things_to_clear += storage.GetAllContents() things_to_clear += storage.GetAllContents()
if(occupant) if(occupant)
things_to_clear += occupant things_to_clear += occupant
things_to_clear += occupant.GetAllContents() things_to_clear += occupant.GetAllContents()
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG) SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
AM.clean_blood() AM.clean_blood()
AM.fingerprints = list() AM.fingerprints = list()
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive) var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
if(contamination) if(contamination)
qdel(contamination) qdel(contamination)
open_machine(FALSE) open_machine(FALSE)
if(occupant) if(occupant)
dump_contents() dump_contents()
/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb) /obj/machinery/suit_storage_unit/proc/shock(mob/user, prb)
if(!prob(prb)) if(!prob(prb))
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src) s.set_up(5, 1, src)
s.start() s.start()
if(electrocute_mob(user, src, src, 1, TRUE)) if(electrocute_mob(user, src, src, 1, TRUE))
return 1 return 1
/obj/machinery/suit_storage_unit/relaymove(mob/user) /obj/machinery/suit_storage_unit/relaymove(mob/user)
if(locked) if(locked)
if(message_cooldown <= world.time) if(message_cooldown <= world.time)
message_cooldown = world.time + 50 message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>") to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
return return
open_machine() open_machine()
dump_contents() dump_contents()
/obj/machinery/suit_storage_unit/container_resist(mob/living/user) /obj/machinery/suit_storage_unit/container_resist(mob/living/user)
if(!locked) if(!locked)
open_machine() open_machine()
dump_contents() dump_contents()
return return
user.changeNext_move(CLICK_CD_BREAKOUT) user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \ user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
"<span class='notice'>You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)</span>", \ "<span class='notice'>You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a thump from [src].</span>") "<span class='italics'>You hear a thump from [src].</span>")
if(do_after(user,(breakout_time), target = src)) if(do_after(user,(breakout_time), target = src))
if(!user || user.stat != CONSCIOUS || user.loc != src ) if(!user || user.stat != CONSCIOUS || user.loc != src )
return return
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \ user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
"<span class='notice'>You successfully break out of [src]!</span>") "<span class='notice'>You successfully break out of [src]!</span>")
open_machine() open_machine()
dump_contents() dump_contents()
add_fingerprint(user) add_fingerprint(user)
if(locked) if(locked)
visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \ visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
"<span class='notice'>You start kicking against the doors...</span>") "<span class='notice'>You start kicking against the doors...</span>")
addtimer(CALLBACK(src, .proc/resist_open, user), 300) addtimer(CALLBACK(src, .proc/resist_open, user), 300)
else else
open_machine() open_machine()
dump_contents() dump_contents()
/obj/machinery/suit_storage_unit/proc/resist_open(mob/user) /obj/machinery/suit_storage_unit/proc/resist_open(mob/user)
if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here. if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here.
visible_message("<span class='notice'>You see [user] burst out of [src]!</span>", \ visible_message("<span class='notice'>You see [user] burst out of [src]!</span>", \
"<span class='notice'>You escape the cramped confines of [src]!</span>") "<span class='notice'>You escape the cramped confines of [src]!</span>")
open_machine() open_machine()
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params) /obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
if(state_open && is_operational()) if(state_open && is_operational())
if(istype(I, /obj/item/clothing/head/mob_holder)) if(istype(I, /obj/item/clothing/head/mob_holder))
to_chat(user, "<span class='warning'>You can't quite fit that in while you hold it!</span>") to_chat(user, "<span class='warning'>You can't quite fit that in while you hold it!</span>")
return return
if(istype(I, /obj/item/clothing/suit)) if(istype(I, /obj/item/clothing/suit))
if(suit) if(suit)
to_chat(user, "<span class='warning'>The unit already contains a suit!.</span>") to_chat(user, "<span class='warning'>The unit already contains a suit!.</span>")
return return
if(!user.transferItemToLoc(I, src)) if(!user.transferItemToLoc(I, src))
return return
suit = I suit = I
else if(istype(I, /obj/item/clothing/head)) else if(istype(I, /obj/item/clothing/head))
if(helmet) if(helmet)
to_chat(user, "<span class='warning'>The unit already contains a helmet!</span>") to_chat(user, "<span class='warning'>The unit already contains a helmet!</span>")
return return
if(!user.transferItemToLoc(I, src)) if(!user.transferItemToLoc(I, src))
return return
helmet = I helmet = I
else if(istype(I, /obj/item/clothing/mask)) else if(istype(I, /obj/item/clothing/mask))
if(mask) if(mask)
to_chat(user, "<span class='warning'>The unit already contains a mask!</span>") to_chat(user, "<span class='warning'>The unit already contains a mask!</span>")
return return
if(!user.transferItemToLoc(I, src)) if(!user.transferItemToLoc(I, src))
return return
mask = I mask = I
else else
if(storage) if(storage)
to_chat(user, "<span class='warning'>The auxiliary storage compartment is full!</span>") to_chat(user, "<span class='warning'>The auxiliary storage compartment is full!</span>")
return return
if(!user.transferItemToLoc(I, src)) if(!user.transferItemToLoc(I, src))
return return
storage = I storage = I
visible_message("<span class='notice'>[user] inserts [I] into [src]</span>", "<span class='notice'>You load [I] into [src].</span>") visible_message("<span class='notice'>[user] inserts [I] into [src]</span>", "<span class='notice'>You load [I] into [src].</span>")
update_icon() update_icon()
return return
if(panel_open && is_wire_tool(I)) if(panel_open && is_wire_tool(I))
wires.interact(user) wires.interact(user)
return return
if(!state_open) if(!state_open)
if(default_deconstruction_screwdriver(user, "panel", "close", I)) if(default_deconstruction_screwdriver(user, "panel", "close", I))
return return
if(default_pry_open(I)) if(default_pry_open(I))
dump_contents() dump_contents()
return return
return ..() return ..()
/obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state) ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state)
ui.open() ui.open()
/obj/machinery/suit_storage_unit/ui_data() /obj/machinery/suit_storage_unit/ui_data()
var/list/data = list() var/list/data = list()
data["locked"] = locked data["locked"] = locked
data["open"] = state_open data["open"] = state_open
data["safeties"] = safeties data["safeties"] = safeties
data["uv_active"] = uv data["uv_active"] = uv
data["uv_super"] = uv_super data["uv_super"] = uv_super
if(helmet) if(helmet)
data["helmet"] = helmet.name data["helmet"] = helmet.name
else else
data["helmet"] = null data["helmet"] = null
if(suit) if(suit)
data["suit"] = suit.name data["suit"] = suit.name
else else
data["suit"] = null data["suit"] = null
if(mask) if(mask)
data["mask"] = mask.name data["mask"] = mask.name
else else
data["mask"] = null data["mask"] = null
if(storage) if(storage)
data["storage"] = storage.name data["storage"] = storage.name
else else
data["storage"] = null data["storage"] = null
if(occupant) if(occupant)
data["occupied"] = TRUE data["occupied"] = TRUE
else else
data["occupied"] = FALSE data["occupied"] = FALSE
return data return data
/obj/machinery/suit_storage_unit/ui_act(action, params) /obj/machinery/suit_storage_unit/ui_act(action, params)
if(..() || uv) if(..() || uv)
return return
switch(action) switch(action)
if("door") if("door")
if(state_open) if(state_open)
close_machine() close_machine()
else else
open_machine(0) open_machine(0)
if(occupant) if(occupant)
dump_contents() // Dump out contents if someone is in there. dump_contents() // Dump out contents if someone is in there.
. = TRUE . = TRUE
if("lock") if("lock")
if(state_open) if(state_open)
return return
locked = !locked locked = !locked
. = TRUE . = TRUE
if("uv") if("uv")
if(occupant && safeties) if(occupant && safeties)
return return
else if(!helmet && !mask && !suit && !storage && !occupant) else if(!helmet && !mask && !suit && !storage && !occupant)
return return
else else
if(occupant) if(occupant)
var/mob/living/mob_occupant = occupant var/mob/living/mob_occupant = occupant
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>") to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
cook() cook()
. = TRUE . = TRUE
if("dispense") if("dispense")
if(!state_open) if(!state_open)
return return
var/static/list/valid_items = list("helmet", "suit", "mask", "storage") var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
var/item_name = params["item"] var/item_name = params["item"]
if(item_name in valid_items) if(item_name in valid_items)
var/obj/item/I = vars[item_name] var/obj/item/I = vars[item_name]
vars[item_name] = null vars[item_name] = null
if(I) if(I)
I.forceMove(loc) I.forceMove(loc)
. = TRUE . = TRUE
update_icon() update_icon()

View File

@@ -54,7 +54,7 @@
to_chat(user, "<span class='warning'>[src] was shaken recently, it needs time to settle.</span>") to_chat(user, "<span class='warning'>[src] was shaken recently, it needs time to settle.</span>")
return return
user.visible_message("<span class='notice'>[user] starts shaking [src].</span>", "<span class='notice'>You start shaking [src].</span>", "<span class='italics'>You hear shaking and sloshing.</span>") user.visible_message("<span class='notice'>[user] starts shaking [src].</span>", "<span class='notice'>You start shaking [src].</span>", "<span class='hear'>You hear shaking and sloshing.</span>")
shaking = TRUE shaking = TRUE
@@ -95,16 +95,47 @@
// except it actually ASKS THE DEAD (wooooo) // except it actually ASKS THE DEAD (wooooo)
/obj/item/toy/eightball/haunted /obj/item/toy/eightball/haunted
shake_time = 150 shake_time = 30 SECONDS
cooldown_time = 1800 cooldown_time = 3 MINUTES
flags_1 = HEAR_1 flags_1 = HEAR_1
var/last_message var/last_message
var/selected_message var/selected_message
var/list/votes //these kind of store the same thing but one is easier to work with.
var/list/votes = list()
var/list/voted = list()
var/static/list/haunted_answers = list(
"yes" = list(
"It is certain",
"It is decidedly so",
"Without a doubt",
"Yes definitely",
"You may rely on it",
"As I see it, yes",
"Most likely",
"Outlook good",
"Yes",
"Signs point to yes"
),
"maybe" = list(
"Reply hazy try again",
"Ask again later",
"Better not tell you now",
"Cannot predict now",
"Concentrate and ask again"
),
"no" = list(
"Don't count on it",
"My reply is no",
"My sources say no",
"Outlook not so good",
"Very doubtful"
)
)
/obj/item/toy/eightball/haunted/Initialize(mapload) /obj/item/toy/eightball/haunted/Initialize(mapload)
. = ..() . = ..()
votes = list() for (var/answer in haunted_answers)
votes[answer] = 0
GLOB.poi_list |= src GLOB.poi_list |= src
/obj/item/toy/eightball/haunted/Destroy() /obj/item/toy/eightball/haunted/Destroy()
@@ -122,7 +153,7 @@
interact(user) interact(user)
return ..() return ..()
/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode, atom/movable/source) /obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
. = ..() . = ..()
last_message = raw_message last_message = raw_message
@@ -137,38 +168,31 @@
if(isobserver(usr)) if(isobserver(usr))
interact(usr) interact(usr)
/obj/item/toy/eightball/haunted/proc/get_vote_tallies()
var/list/answers = list()
for(var/ckey in votes)
var/selected = votes[ckey]
if(selected in answers)
answers[selected]++
else
answers[selected] = 1
return answers
/obj/item/toy/eightball/haunted/get_answer() /obj/item/toy/eightball/haunted/get_answer()
if(!votes.len) var/top_amount = 0
return pick(possible_answers) var/top_vote
var/list/tallied_votes = get_vote_tallies() for(var/vote in votes)
var/amount_of_votes = length(votes[vote])
if(amount_of_votes > top_amount)
top_vote = vote
top_amount = amount_of_votes
//If one option actually has votes and there's a tie, pick between them 50/50
else if(top_amount && amount_of_votes == top_amount && prob(50))
top_vote = vote
top_amount = amount_of_votes
// I miss python sorting, then I wouldn't have to muck about with if(isnull(top_vote))
// all this top_vote = pick(votes)
var/most_popular_answer
var/most_amount = 0
// yes, if there is a tie, there is an arbitary decision
// but we never said the spirit world was fair
for(var/A in tallied_votes)
var/amount = tallied_votes[A]
if(amount > most_amount)
most_popular_answer = A
return most_popular_answer for(var/vote in votes)
votes[vote] = 0
/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.observer_state) voted.Cut()
return top_vote
/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
@@ -179,21 +203,13 @@
var/list/data = list() var/list/data = list()
data["shaking"] = shaking data["shaking"] = shaking
data["question"] = selected_message data["question"] = selected_message
var/list/tallied_votes = get_vote_tallies()
data["answers"] = list() data["answers"] = list()
for(var/pa in haunted_answers)
for(var/pa in possible_answers)
var/list/L = list() var/list/L = list()
L["answer"] = pa L["answer"] = pa
var/amount = 0 L["amount"] = votes[pa]
if(pa in tallied_votes) L["selected"] = voted[user.ckey]
amount = tallied_votes[pa]
L["amount"] = amount
var/selected = FALSE
if(votes[user.ckey] == pa)
selected = TRUE
L["selected"] = selected
data["answers"] += list(L) data["answers"] += list(L)
return data return data
@@ -206,8 +222,11 @@
switch(action) switch(action)
if("vote") if("vote")
var/selected_answer = params["answer"] var/selected_answer = params["answer"]
if(!(selected_answer in possible_answers)) if(!(selected_answer in haunted_answers))
return
if(user.ckey in voted)
return return
else else
votes[user.ckey] = selected_answer votes[selected_answer] += 1
. = TRUE voted[user.ckey] = selected_answer
. = TRUE

View File

@@ -202,6 +202,11 @@
if(filename == P.filename) if(filename == P.filename)
return P return P
/datum/ntnet/proc/get_chat_channel_by_id(id)
for(var/datum/ntnet_conversation/chan in chat_channels)
if(chan.id == id)
return chan
// Resets the IDS alarm // Resets the IDS alarm
/datum/ntnet/proc/resetIDS() /datum/ntnet/proc/resetIDS()
intrusion_detection_alarm = FALSE intrusion_detection_alarm = FALSE

View File

@@ -9,6 +9,9 @@
icon_state = "bus" icon_state = "bus"
density = TRUE density = TRUE
circuit = /obj/item/circuitboard/machine/ntnet_relay circuit = /obj/item/circuitboard/machine/ntnet_relay
ui_x = 400
ui_y = 300
var/datum/ntnet/NTNet = null // This is mostly for backwards reference and to allow varedit modifications from ingame. var/datum/ntnet/NTNet = null // This is mostly for backwards reference and to allow varedit modifications from ingame.
var/enabled = 1 // Set to 0 if the relay was turned off var/enabled = 1 // Set to 0 if the relay was turned off
var/dos_failure = 0 // Set to 1 if the relay failed due to (D)DoS attack var/dos_failure = 0 // Set to 1 if the relay failed due to (D)DoS attack
@@ -66,7 +69,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "ntnet_relay", "NTNet Quantum Relay", 500, 300, master_ui, state) ui = new(user, src, ui_key, "ntnet_relay", "NTNet Quantum Relay", ui_x, ui_y, master_ui, state)
ui.open() ui.open()
@@ -88,10 +91,12 @@
dos_failure = 0 dos_failure = 0
update_icon() update_icon()
SSnetworks.station_network.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.") SSnetworks.station_network.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.")
return TRUE
if("toggle") if("toggle")
enabled = !enabled enabled = !enabled
SSnetworks.station_network.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].") SSnetworks.station_network.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].")
update_icon() update_icon()
return TRUE
/obj/machinery/ntnet_relay/Initialize() /obj/machinery/ntnet_relay/Initialize()
uid = gl_uid++ uid = gl_uid++
@@ -113,4 +118,4 @@
D.target = null D.target = null
D.error = "Connection to quantum relay severed" D.error = "Connection to quantum relay severed"
return ..() return ..()

View File

@@ -11,7 +11,6 @@
var/code = DEFAULT_SIGNALER_CODE var/code = DEFAULT_SIGNALER_CODE
var/frequency = FREQ_SIGNALER var/frequency = FREQ_SIGNALER
var/delay = 0
var/datum/radio_frequency/radio_connection var/datum/radio_frequency/radio_connection
var/suicider = null var/suicider = null
var/hearing_range = 1 var/hearing_range = 1
@@ -48,64 +47,50 @@
holder.update_icon() holder.update_icon()
return return
/obj/item/assembly/signaler/ui_interact(mob/user, flag1) /obj/item/assembly/signaler/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
. = ..() if(!is_secured(user))
if(is_secured(user))
var/t1 = "-------"
var/dat = {"
<TT>
<A href='byond://?src=[REF(src)];send=1'>Send Signal</A><BR>
<B>Frequency/Code</B> for signaler:<BR>
Frequency:
[format_frequency(src.frequency)]
<A href='byond://?src=[REF(src)];set=freq'>Set</A><BR>
Code:
[src.code]
<A href='byond://?src=[REF(src)];set=code'>Set</A><BR>
[t1]
</TT>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
var/ui_width = 280
var/ui_height = 132
ui = new(user, src, ui_key, "signaler", name, ui_width, ui_height, master_ui, state)
ui.open()
/obj/item/assembly/signaler/ui_data(mob/user)
var/list/data = list()
data["frequency"] = frequency
data["code"] = code
data["minFrequency"] = MIN_FREE_FREQ
data["maxFrequency"] = MAX_FREE_FREQ
/obj/item/assembly/signaler/Topic(href, href_list) return data
..()
if(!usr.canUseTopic(src, BE_CLOSE)) /obj/item/assembly/signaler/ui_act(action, params)
usr << browse(null, "window=radio") if(..())
onclose(usr, "radio")
return return
switch(action)
if("signal")
INVOKE_ASYNC(src, .proc/signal)
. = TRUE
if("freq")
frequency = unformat_frequency(params["freq"])
frequency = sanitize_frequency(frequency, TRUE)
set_frequency(frequency)
. = TRUE
if("code")
code = text2num(params["code"])
code = round(code)
. = TRUE
if("reset")
if(params["reset"] == "freq")
frequency = initial(frequency)
else
code = initial(code)
. = TRUE
if (href_list["set"]) update_icon()
if(href_list["set"] == "freq")
var/new_freq = input(usr, "Input a new signalling frequency", "Remote Signaller Frequency", format_frequency(frequency)) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_freq = unformat_frequency(new_freq)
new_freq = sanitize_frequency(new_freq, TRUE)
set_frequency(new_freq)
if(href_list["set"] == "code")
var/new_code = input(usr, "Input a new signalling code", "Remote Signaller Code", code) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_code = round(new_code)
new_code = CLAMP(new_code, 1, 100)
code = new_code
if(href_list["send"])
spawn( 0 )
signal()
if(usr)
attack_self(usr)
return
/obj/item/assembly/signaler/attackby(obj/item/W, mob/user, params) /obj/item/assembly/signaler/attackby(obj/item/W, mob/user, params)
if(issignaler(W)) if(issignaler(W))
var/obj/item/assembly/signaler/signaler2 = W var/obj/item/assembly/signaler/signaler2 = W

View File

@@ -24,7 +24,7 @@
/datum/notificationpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state) /datum/notificationpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "notificationpanel", "Notification Preferences", 700, 700, master_ui, state) ui = new(user, src, ui_key, "notificationpanel", "Notification Preferences", 270, 360, master_ui, state)
ui.open() ui.open()
/datum/notificationpanel/ui_data(mob/user) /datum/notificationpanel/ui_data(mob/user)

View File

@@ -14,7 +14,7 @@
icon_state = "mulebot0" icon_state = "mulebot0"
density = TRUE density = TRUE
move_resist = MOVE_FORCE_STRONG move_resist = MOVE_FORCE_STRONG
animate_movement = 1 animate_movement = FORWARD_STEPS
health = 50 health = 50
maxHealth = 50 maxHealth = 50
damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
@@ -29,10 +29,14 @@
model = "MULE" model = "MULE"
bot_core_type = /obj/machinery/bot_core/mulebot bot_core_type = /obj/machinery/bot_core/mulebot
var/ui_x = 350
var/ui_y = 425
var/id var/id
path_image_color = "#7F5200" path_image_color = "#7F5200"
var/base_icon = "mulebot"
var/atom/movable/load = null var/atom/movable/load = null
var/mob/living/passenger = null var/mob/living/passenger = null
var/turf/target // this is turf to navigate to (location of beacon) var/turf/target // this is turf to navigate to (location of beacon)
@@ -74,16 +78,16 @@
/mob/living/simple_animal/bot/mulebot/proc/set_id(new_id) /mob/living/simple_animal/bot/mulebot/proc/set_id(new_id)
id = new_id id = new_id
if(paicard) if(paicard)
bot_name = "\improper MULEbot ([new_id])" bot_name = "[initial(name)] ([new_id])"
else else
name = "\improper MULEbot ([new_id])" name = "[initial(name)] ([new_id])"
/mob/living/simple_animal/bot/mulebot/bot_reset() /mob/living/simple_animal/bot/mulebot/bot_reset()
..() ..()
reached_target = 0 reached_target = 0
/mob/living/simple_animal/bot/mulebot/attackby(obj/item/I, mob/user, params) /mob/living/simple_animal/bot/mulebot/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/screwdriver)) if(I.tool_behaviour == TOOL_SCREWDRIVER)
..() ..()
if(open) if(open)
on = FALSE on = FALSE
@@ -91,13 +95,13 @@
if(!user.transferItemToLoc(I, src)) if(!user.transferItemToLoc(I, src))
return return
cell = I cell = I
visible_message("[user] inserts a cell into [src].", visible_message("<span class='notice'>[user] inserts a cell into [src].</span>",
"<span class='notice'>You insert the new cell into [src].</span>") "<span class='notice'>You insert the new cell into [src].</span>")
else if(istype(I, /obj/item/crowbar) && open && cell) else if(I.tool_behaviour == TOOL_CROWBAR && open && cell)
cell.add_fingerprint(usr) cell.add_fingerprint(usr)
cell.forceMove(loc) cell.forceMove(loc)
cell = null cell = null
visible_message("[user] crowbars out the power cell from [src].", visible_message("<span class='notice'>[user] crowbars out the power cell from [src].</span>",
"<span class='notice'>You pry the powercell out of [src].</span>") "<span class='notice'>You pry the powercell out of [src].</span>")
else if(is_wire_tool(I) && open) else if(is_wire_tool(I) && open)
return attack_hand(user) return attack_hand(user)
@@ -115,21 +119,19 @@
return return
/mob/living/simple_animal/bot/mulebot/emag_act(mob/user) /mob/living/simple_animal/bot/mulebot/emag_act(mob/user)
. = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
if(emagged < 1) if(emagged < 1)
emagged = TRUE emagged = TRUE
if(!open) if(!open)
locked = !locked locked = !locked
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>") to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>")
flick("mulebot-emagged", src) flick("mulebot-emagged", src)
playsound(src, "sparks", 100, 0) playsound(src, "sparks", 100, FALSE)
return TRUE
/mob/living/simple_animal/bot/mulebot/update_icon() /mob/living/simple_animal/bot/mulebot/update_icon()
if(open) if(open)
icon_state="mulebot-hatch" icon_state="[base_icon]-hatch"
else else
icon_state = "mulebot[wires.is_cut(WIRE_AVOIDANCE)]" icon_state = "[base_icon][wires.is_cut(WIRE_AVOIDANCE)]"
cut_overlays() cut_overlays()
if(load && !ismob(load))//buckling handles the mob offsets if(load && !ismob(load))//buckling handles the mob offsets
load.pixel_y = initial(load.pixel_y) + 9 load.pixel_y = initial(load.pixel_y) + 9
@@ -152,7 +154,7 @@
/mob/living/simple_animal/bot/mulebot/bullet_act(obj/item/projectile/Proj) /mob/living/simple_animal/bot/mulebot/bullet_act(obj/item/projectile/Proj)
. = ..() . = ..()
if(. == BULLET_ACT_HIT && !QDELETED(src)) //Got hit and not blown up yet.) if(. && !QDELETED(src)) //Got hit and not blown up yet.
if(prob(50) && !isnull(load)) if(prob(50) && !isnull(load))
unload(0) unload(0)
if(prob(25)) if(prob(25))
@@ -171,7 +173,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "mulebot", name, 600, 375, master_ui, state) ui = new(user, src, ui_key, "mulebot", name, ui_x, ui_y, master_ui, state)
ui.open() ui.open()
/mob/living/simple_animal/bot/mulebot/ui_data(mob/user) /mob/living/simple_animal/bot/mulebot/ui_data(mob/user)
@@ -191,12 +193,15 @@
else else
data["load"] = load ? load.name : null data["load"] = load ? load.name : null
data["destination"] = destination ? destination : null data["destination"] = destination ? destination : null
data["home"] = home_destination
data["destinations"] = GLOB.deliverybeacontags
data["cell"] = cell ? TRUE : FALSE data["cell"] = cell ? TRUE : FALSE
data["cellPercent"] = cell ? cell.percent() : null data["cellPercent"] = cell ? cell.percent() : null
data["autoReturn"] = auto_return data["autoReturn"] = auto_return
data["autoPickup"] = auto_pickup data["autoPickup"] = auto_pickup
data["reportDelivery"] = report_delivery data["reportDelivery"] = report_delivery
data["haspai"] = paicard ? TRUE : FALSE data["haspai"] = paicard ? TRUE : FALSE
data["id"] = id
return data return data
/mob/living/simple_animal/bot/mulebot/ui_act(action, params) /mob/living/simple_animal/bot/mulebot/ui_act(action, params)
@@ -216,10 +221,10 @@
return return
. = TRUE . = TRUE
else else
bot_control(action, usr) // Kill this later. bot_control(action, usr, params) // Kill this later.
. = TRUE . = TRUE
/mob/living/simple_animal/bot/mulebot/bot_control(command, mob/user, pda = FALSE) /mob/living/simple_animal/bot/mulebot/bot_control(command, mob/user, list/params = list(), pda = FALSE)
if(pda && wires.is_cut(WIRE_RX)) // MULE wireless is controlled by wires. if(pda && wires.is_cut(WIRE_RX)) // MULE wireless is controlled by wires.
return return
@@ -234,15 +239,27 @@
if(mode == BOT_IDLE || mode == BOT_DELIVER) if(mode == BOT_IDLE || mode == BOT_DELIVER)
start_home() start_home()
if("destination") if("destination")
var/new_dest = input(user, "Enter Destination:", name, destination) as null|anything in GLOB.deliverybeacontags var/new_dest
if(pda)
new_dest = input(user, "Enter Destination:", name, destination) as null|anything in GLOB.deliverybeacontags
else
new_dest = params["value"]
if(new_dest) if(new_dest)
set_destination(new_dest) set_destination(new_dest)
if("setid") if("setid")
var/new_id = stripped_input(user, "Enter ID:", name, id, MAX_NAME_LEN) var/new_id
if(pda)
new_id = stripped_input(user, "Enter ID:", name, id, MAX_NAME_LEN)
else
new_id = params["value"]
if(new_id) if(new_id)
set_id(new_id) set_id(new_id)
if("sethome") if("sethome")
var/new_home = input(user, "Enter Home:", name, home_destination) as null|anything in GLOB.deliverybeacontags var/new_home
if(pda)
new_home = input(user, "Enter Home:", name, home_destination) as null|anything in GLOB.deliverybeacontags
else
new_home = params["value"]
if(new_home) if(new_home)
home_destination = new_home home_destination = new_home
if("unload") if("unload")
@@ -317,26 +334,28 @@
/mob/living/simple_animal/bot/mulebot/proc/buzz(type) /mob/living/simple_animal/bot/mulebot/proc/buzz(type)
switch(type) switch(type)
if(SIGH) if(SIGH)
audible_message("[src] makes a sighing buzz.", "<span class='italics'>You hear an electronic buzzing sound.</span>") audible_message("<span class='hear'>[src] makes a sighing buzz.</span>")
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
if(ANNOYED) if(ANNOYED)
audible_message("[src] makes an annoyed buzzing sound.", "<span class='italics'>You hear an electronic buzzing sound.</span>") audible_message("<span class='hear'>[src] makes an annoyed buzzing sound.</span>")
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0) playsound(loc, 'sound/machines/buzz-two.ogg', 50, FALSE)
if(DELIGHT) if(DELIGHT)
audible_message("[src] makes a delighted ping!", "<span class='italics'>You hear a ping.</span>") audible_message("<span class='hear'>[src] makes a delighted ping!</span>")
playsound(loc, 'sound/machines/ping.ogg', 50, 0) playsound(loc, 'sound/machines/ping.ogg', 50, FALSE)
// mousedrop a crate to load the bot // mousedrop a crate to load the bot
// can load anything if hacked // can load anything if hacked
/mob/living/simple_animal/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user) /mob/living/simple_animal/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user)
if(user.incapacitated() || user.lying) if(user.incapacitated() || user.lying)
return return
if(!istype(AM)) if(!istype(AM))
return return
if(!istype(AM) || isdead(AM) || iscameramob(AM) || istype(AM, /obj/effect/dummy/phased_mob))
return
load(AM) load(AM)
// called to load a crate // called to load a crate
@@ -449,10 +468,8 @@
process_bot() process_bot()
num_steps-- num_steps--
if(mode != BOT_IDLE) if(mode != BOT_IDLE)
spawn(0) var/process_timer = addtimer(CALLBACK(src, .proc/process_bot), 2, TIMER_LOOP|TIMER_STOPPABLE)
for(var/i=num_steps,i>0,i--) addtimer(CALLBACK(GLOBAL_PROC, /proc/deltimer, process_timer), (num_steps*2) + 1)
sleep(2)
process_bot()
/mob/living/simple_animal/bot/mulebot/proc/process_bot() /mob/living/simple_animal/bot/mulebot/proc/process_bot()
if(!on || client) if(!on || client)
@@ -491,6 +508,7 @@
B.setDir(newdir) B.setDir(newdir)
bloodiness-- bloodiness--
var/oldloc = loc var/oldloc = loc
var/moved = step_towards(src, next) // attempt to move var/moved = step_towards(src, next) // attempt to move
if(cell) if(cell)
@@ -516,11 +534,7 @@
buzz(SIGH) buzz(SIGH)
mode = BOT_WAIT_FOR_NAV mode = BOT_WAIT_FOR_NAV
blockcount = 0 blockcount = 0
spawn(20) addtimer(CALLBACK(src, .proc/process_blocked, next), 2 SECONDS)
calc_path(avoid=next)
if(path.len > 0)
buzz(DELIGHT)
mode = BOT_BLOCKED
return return
return return
else else
@@ -533,18 +547,26 @@
if(BOT_NAV) // calculate new path if(BOT_NAV) // calculate new path
mode = BOT_WAIT_FOR_NAV mode = BOT_WAIT_FOR_NAV
spawn(0) INVOKE_ASYNC(src, .proc/process_nav)
calc_path()
if(path.len > 0) /mob/living/simple_animal/bot/mulebot/proc/process_blocked(turf/next)
blockcount = 0 calc_path(avoid=next)
mode = BOT_BLOCKED if(path.len > 0)
buzz(DELIGHT) buzz(DELIGHT)
mode = BOT_BLOCKED
else /mob/living/simple_animal/bot/mulebot/proc/process_nav()
buzz(SIGH) calc_path()
mode = BOT_NO_ROUTE if(path.len > 0)
blockcount = 0
mode = BOT_BLOCKED
buzz(DELIGHT)
else
buzz(SIGH)
mode = BOT_NO_ROUTE
// calculates a path to the current destination // calculates a path to the current destination
// given an optional turf to avoid // given an optional turf to avoid
@@ -574,26 +596,28 @@
/mob/living/simple_animal/bot/mulebot/proc/start_home() /mob/living/simple_animal/bot/mulebot/proc/start_home()
if(!on) if(!on)
return return
spawn(0) INVOKE_ASYNC(src, .proc/do_start_home)
set_destination(home_destination)
mode = BOT_BLOCKED
update_icon() update_icon()
/mob/living/simple_animal/bot/mulebot/proc/do_start_home()
set_destination(home_destination)
mode = BOT_BLOCKED
// called when bot reaches current target // called when bot reaches current target
/mob/living/simple_animal/bot/mulebot/proc/at_target() /mob/living/simple_animal/bot/mulebot/proc/at_target()
if(!reached_target) if(!reached_target)
radio_channel = "Supply" //Supply channel radio_channel = RADIO_CHANNEL_SUPPLY //Supply channel
audible_message("[src] makes a chiming sound!", "<span class='italics'>You hear a chime.</span>") audible_message("<span class='hear'>[src] makes a chiming sound!</span>")
playsound(loc, 'sound/machines/chime.ogg', 50, 0) playsound(loc, 'sound/machines/chime.ogg', 50, FALSE)
reached_target = 1 reached_target = 1
if(pathset) //The AI called us here, so notify it of our arrival. if(pathset) //The AI called us here, so notify it of our arrival.
loaddir = dir //The MULE will attempt to load a crate in whatever direction the MULE is "facing". loaddir = dir //The MULE will attempt to load a crate in whatever direction the MULE is "facing".
if(calling_ai) if(calling_ai)
to_chat(calling_ai, "<span class='notice'>[icon2html(src, calling_ai)] [src] wirelessly plays a chiming sound!</span>") to_chat(calling_ai, "<span class='notice'>[icon2html(src, calling_ai)] [src] wirelessly plays a chiming sound!</span>")
playsound(calling_ai, 'sound/machines/chime.ogg',40, 0) playsound(calling_ai, 'sound/machines/chime.ogg',40, FALSE)
calling_ai = null calling_ai = null
radio_channel = "AI Private" //Report on AI Private instead if the AI is controlling us. radio_channel = RADIO_CHANNEL_AI_PRIVATE //Report on AI Private instead if the AI is controlling us.
if(load) // if loaded, unload at target if(load) // if loaded, unload at target
if(report_delivery) if(report_delivery)
@@ -645,7 +669,7 @@
log_combat(src, H, "run over", null, "(DAMTYPE: [uppertext(BRUTE)])") log_combat(src, H, "run over", null, "(DAMTYPE: [uppertext(BRUTE)])")
H.visible_message("<span class='danger'>[src] drives over [H]!</span>", \ H.visible_message("<span class='danger'>[src] drives over [H]!</span>", \
"<span class='userdanger'>[src] drives over you!</span>") "<span class='userdanger'>[src] drives over you!</span>")
playsound(loc, 'sound/effects/splat.ogg', 50, 1) playsound(loc, 'sound/effects/splat.ogg', 50, TRUE)
var/damage = rand(5,15) var/damage = rand(5,15)
H.apply_damage(2*damage, BRUTE, BODY_ZONE_HEAD, run_armor_check(BODY_ZONE_HEAD, "melee")) H.apply_damage(2*damage, BRUTE, BODY_ZONE_HEAD, run_armor_check(BODY_ZONE_HEAD, "melee"))
@@ -734,7 +758,7 @@
/mob/living/simple_animal/bot/mulebot/insertpai(mob/user, obj/item/paicard/card) /mob/living/simple_animal/bot/mulebot/insertpai(mob/user, obj/item/paicard/card)
if(..()) if(..())
visible_message("[src] safeties are locked on.") visible_message("<span class='notice'>[src] safeties are locked on.</span>")
#undef SIGH #undef SIGH
#undef ANNOYED #undef ANNOYED
@@ -742,3 +766,4 @@
/obj/machinery/bot_core/mulebot /obj/machinery/bot_core/mulebot
req_access = list(ACCESS_CARGO) req_access = list(ACCESS_CARGO)

View File

@@ -1,3 +1,5 @@
#define MAX_CHANNELS 1000
/datum/ntnet_conversation /datum/ntnet_conversation
var/id = null var/id = null
var/title = "Untitled Conversation" var/title = "Untitled Conversation"
@@ -8,7 +10,11 @@
var/static/ntnrc_uid = 0 var/static/ntnrc_uid = 0
/datum/ntnet_conversation/New() /datum/ntnet_conversation/New()
id = ntnrc_uid++ id = ntnrc_uid + 1
if(id > MAX_CHANNELS)
qdel(src)
return
ntnrc_uid = id
if(SSnetworks.station_network) if(SSnetworks.station_network)
SSnetworks.station_network.chat_channels.Add(src) SSnetworks.station_network.chat_channels.Add(src)
..() ..()
@@ -66,3 +72,5 @@
add_status_message("[client.username] has changed channel title from [title] to [newtitle]") add_status_message("[client.username] has changed channel title from [title] to [newtitle]")
title = newtitle title = newtitle
#undef MAX_CHANNELS

View File

@@ -71,7 +71,7 @@
// Check if the user can run program. Only humans can operate computer. Automatically called in run_program() // Check if the user can run program. Only humans can operate computer. Automatically called in run_program()
// User has to wear their ID for ID Scan to work. // User has to wear their ID for ID Scan to work.
// Can also be called manually, with optional parameter being access_to_check to scan the user's ID // Can also be called manually, with optional parameter being access_to_check to scan the user's ID
/datum/computer_file/program/proc/can_run(mob/user, loud = 0, access_to_check, transfer = 0) /datum/computer_file/program/proc/can_run(mob/user, loud = FALSE, access_to_check, transfer = FALSE)
// Defaults to required_access // Defaults to required_access
if(!access_to_check) if(!access_to_check)
if(transfer && transfer_access) if(transfer && transfer_access)
@@ -79,16 +79,16 @@
else else
access_to_check = required_access access_to_check = required_access
if(!access_to_check) // No required_access, allow it. if(!access_to_check) // No required_access, allow it.
return 1 return TRUE
if(!transfer && computer && (computer.obj_flags & EMAGGED)) //emags can bypass the execution locks but not the download ones. if(!transfer && computer && (computer.obj_flags & EMAGGED)) //emags can bypass the execution locks but not the download ones.
return 1 return TRUE
if(IsAdminGhost(user)) if(IsAdminGhost(user))
return 1 return TRUE
if(issilicon(user)) if(issilicon(user))
return 1 return TRUE
if(ishuman(user)) if(ishuman(user))
var/obj/item/card/id/D var/obj/item/card/id/D
@@ -101,17 +101,17 @@
if(!I && !D) if(!I && !D)
if(loud) if(loud)
to_chat(user, "<span class='danger'>\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.</span>") to_chat(user, "<span class='danger'>\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.</span>")
return 0 return FALSE
if(I) if(I)
if(access_to_check in I.GetAccess()) if(access_to_check in I.GetAccess())
return 1 return TRUE
else if(D) else if(D)
if(access_to_check in D.GetAccess()) if(access_to_check in D.GetAccess())
return 1 return TRUE
if(loud) if(loud)
to_chat(user, "<span class='danger'>\The [computer] flashes an \"Access Denied\" warning.</span>") to_chat(user, "<span class='danger'>\The [computer] flashes an \"Access Denied\" warning.</span>")
return 0 return FALSE
// This attempts to retrieve header data for UIs. If implementing completely new device of different type than existing ones // This attempts to retrieve header data for UIs. If implementing completely new device of different type than existing ones
// always include the device here in this proc. This proc basically relays the request to whatever is running the program. // always include the device here in this proc. This proc basically relays the request to whatever is running the program.
@@ -127,15 +127,15 @@
if(requires_ntnet && network_destination) if(requires_ntnet && network_destination)
generate_network_log("Connection opened to [network_destination].") generate_network_log("Connection opened to [network_destination].")
program_state = PROGRAM_STATE_ACTIVE program_state = PROGRAM_STATE_ACTIVE
return 1 return TRUE
return 0 return FALSE
// Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client. // Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client.
/datum/computer_file/program/proc/kill_program(forced = FALSE) /datum/computer_file/program/proc/kill_program(forced = FALSE)
program_state = PROGRAM_STATE_KILLED program_state = PROGRAM_STATE_KILLED
if(network_destination) if(network_destination)
generate_network_log("Connection to [network_destination] closed.") generate_network_log("Connection to [network_destination] closed.")
return 1 return TRUE
/datum/computer_file/program/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /datum/computer_file/program/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
@@ -158,17 +158,17 @@
// ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE. // ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE.
/datum/computer_file/program/ui_act(action,params,datum/tgui/ui) /datum/computer_file/program/ui_act(action,params,datum/tgui/ui)
if(..()) if(..())
return 1 return TRUE
if(computer) if(computer)
switch(action) switch(action)
if("PC_exit") if("PC_exit")
computer.kill_program() computer.kill_program()
ui.close() ui.close()
return 1 return TRUE
if("PC_shutdown") if("PC_shutdown")
computer.shutdown_computer() computer.shutdown_computer()
ui.close() ui.close()
return 1 return TRUE
if("PC_minimize") if("PC_minimize")
var/mob/user = usr var/mob/user = usr
if(!computer.active_program || !computer.all_components[MC_CPU]) if(!computer.active_program || !computer.all_components[MC_CPU])

View File

@@ -10,6 +10,8 @@
unsendable = 1 unsendable = 1
undeletable = 1 undeletable = 1
size = 4 size = 4
ui_x = 420
ui_y = 630
available_on_ntnet = 0 available_on_ntnet = 0
requires_ntnet = 0 requires_ntnet = 0
tgui_id = "ntos_configuration" tgui_id = "ntos_configuration"

View File

@@ -10,215 +10,225 @@
ui_header = "ntnrc_idle.gif" ui_header = "ntnrc_idle.gif"
available_on_ntnet = 1 available_on_ntnet = 1
tgui_id = "ntos_net_chat" tgui_id = "ntos_net_chat"
ui_x = 900
ui_y = 675
var/last_message = null // Used to generate the toolbar icon var/last_message // Used to generate the toolbar icon
var/username var/username
var/datum/ntnet_conversation/channel = null var/active_channel
var/operator_mode = 0 // Channel operator mode var/list/channel_history = list()
var/netadmin_mode = 0 // Administrator mode (invisible to other users + bypasses passwords) var/operator_mode = FALSE // Channel operator mode
var/netadmin_mode = FALSE // Administrator mode (invisible to other users + bypasses passwords)
/datum/computer_file/program/chatclient/New() /datum/computer_file/program/chatclient/New()
username = "DefaultUser[rand(100, 999)]" username = "DefaultUser[rand(100, 999)]"
/datum/computer_file/program/chatclient/ui_act(action, params) /datum/computer_file/program/chatclient/ui_act(action, params)
if(..()) if(..())
return 1 return
var/datum/ntnet_conversation/channel = SSnetworks.station_network.get_chat_channel_by_id(active_channel)
var/authed = FALSE
if(channel && ((channel.operator == src) || netadmin_mode))
authed = TRUE
switch(action) switch(action)
if("PRG_speak") if("PRG_speak")
. = 1 if(!channel || isnull(active_channel))
if(!channel)
return 1
var/mob/living/user = usr
var/message = reject_bad_text(input(user, "Enter message or leave blank to cancel: "))
if(!message || !channel)
return return
var/message = reject_bad_text(params["message"])
if(!message)
return
if(channel.password && !(src in channel.clients))
if(channel.password == message)
channel.add_client(src)
return TRUE
channel.add_message(message, username) channel.add_message(message, username)
var/mob/living/user = usr
user.log_talk(message, LOG_CHAT, tag="as [username] to channel [channel.title]") user.log_talk(message, LOG_CHAT, tag="as [username] to channel [channel.title]")
return TRUE
if("PRG_joinchannel") if("PRG_joinchannel")
. = 1 var/new_target = text2num(params["id"])
var/datum/ntnet_conversation/C if(isnull(new_target) || new_target == active_channel)
for(var/datum/ntnet_conversation/chan in SSnetworks.station_network.chat_channels) return
if(chan.id == text2num(params["id"]))
C = chan
break
if(!C)
return 1
if(netadmin_mode) if(netadmin_mode)
channel = C // Bypasses normal leave/join and passwords. Technically makes the user invisible to others. active_channel = new_target // Bypasses normal leave/join and passwords. Technically makes the user invisible to others.
return 1 return TRUE
if(C.password) active_channel = new_target
var/mob/living/user = usr channel = SSnetworks.station_network.get_chat_channel_by_id(new_target)
var/password = reject_bad_text(input(user,"Access Denied. Enter password:")) if(!(src in channel.clients) && !channel.password)
if(C && (password == C.password)) channel.add_client(src)
C.add_client(src) return TRUE
channel = C
return 1
C.add_client(src)
channel = C
if("PRG_leavechannel") if("PRG_leavechannel")
. = 1
if(channel) if(channel)
channel.remove_client(src) channel.remove_client(src)
channel = null active_channel = null
return TRUE
if("PRG_newchannel") if("PRG_newchannel")
. = 1 var/channel_title = reject_bad_text(params["new_channel_name"])
var/mob/living/user = usr
var/channel_title = reject_bad_text(input(user,"Enter channel name or leave blank to cancel:"))
if(!channel_title) if(!channel_title)
return return
var/datum/ntnet_conversation/C = new/datum/ntnet_conversation() var/datum/ntnet_conversation/C = new /datum/ntnet_conversation()
C.add_client(src) C.add_client(src)
C.operator = src C.operator = src
channel = C
C.title = channel_title C.title = channel_title
active_channel = C.id
return TRUE
if("PRG_toggleadmin") if("PRG_toggleadmin")
. = 1
if(netadmin_mode) if(netadmin_mode)
netadmin_mode = 0 netadmin_mode = FALSE
if(channel) if(channel)
channel.remove_client(src) // We shouldn't be in channel's user list, but just in case... channel.remove_client(src) // We shouldn't be in channel's user list, but just in case...
channel = null return TRUE
return 1
var/mob/living/user = usr var/mob/living/user = usr
if(can_run(usr, 1, ACCESS_NETWORK)) if(can_run(user, TRUE, ACCESS_NETWORK))
if(channel) for(var/C in SSnetworks.station_network.chat_channels)
var/response = alert(user, "Really engage admin-mode? You will be disconnected from your current channel!", "NTNRC Admin mode", "Yes", "No") var/datum/ntnet_conversation/chan = C
if(response == "Yes") chan.remove_client(src)
if(channel) netadmin_mode = TRUE
channel.remove_client(src) return TRUE
channel = null
else
return
netadmin_mode = 1
if("PRG_changename") if("PRG_changename")
. = 1 var/newname = sanitize(params["new_name"])
var/mob/living/user = usr
var/newname = sanitize(input(user,"Enter new nickname or leave blank to cancel:"))
if(!newname) if(!newname)
return 1 return
if(channel) for(var/C in SSnetworks.station_network.chat_channels)
channel.add_status_message("[username] is now known as [newname].") var/datum/ntnet_conversation/chan = C
if(src in chan.clients)
chan.add_status_message("[username] is now known as [newname].")
username = newname username = newname
return TRUE
if("PRG_savelog") if("PRG_savelog")
. = 1
if(!channel) if(!channel)
return return
var/mob/living/user = usr var/logname = stripped_input(params["log_name"])
var/logname = stripped_input(user,"Enter desired logfile name (.log) or leave blank to cancel:") if(!logname)
if(!logname || !channel) return
return 1 var/datum/computer_file/data/logfile = new /datum/computer_file/data/logfile()
var/datum/computer_file/data/logfile = new/datum/computer_file/data/logfile()
// Now we will generate HTML-compliant file that can actually be viewed/printed. // Now we will generate HTML-compliant file that can actually be viewed/printed.
logfile.filename = logname logfile.filename = logname
logfile.stored_data = "\[b\]Logfile dump from NTNRC channel [channel.title]\[/b\]\[BR\]" logfile.stored_data = "\[b\]Logfile dump from NTNRC channel [channel.title]\[/b\]\[BR\]"
for(var/logstring in channel.messages) for(var/logstring in channel.messages)
logfile.stored_data += "[logstring]\[BR\]" logfile.stored_data = "[logfile.stored_data][logstring]\[BR\]"
logfile.stored_data += "\[b\]Logfile dump completed.\[/b\]" logfile.stored_data = "[logfile.stored_data]\[b\]Logfile dump completed.\[/b\]"
logfile.calculate_size() logfile.calculate_size()
var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD] var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
if(!computer || !hard_drive || !hard_drive.store_file(logfile)) if(!computer || !hard_drive || !hard_drive.store_file(logfile))
if(!computer) if(!computer)
// This program shouldn't even be runnable without computer. // This program shouldn't even be runnable without computer.
CRASH("Var computer is null!") CRASH("Var computer is null!")
return 1
if(!hard_drive) if(!hard_drive)
computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive connection error\" warning.") computer.visible_message("<span class='warning'>\The [computer] shows an \"I/O Error - Hard drive connection error\" warning.</span>")
else // In 99.9% cases this will mean our HDD is full else // In 99.9% cases this will mean our HDD is full
computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive may be full. Please free some space and try again. Required space: [logfile.size]GQ\" warning.") computer.visible_message("<span class='warning'>\The [computer] shows an \"I/O Error - Hard drive may be full. Please free some space and try again. Required space: [logfile.size]GQ\" warning.</span>")
return TRUE
if("PRG_renamechannel") if("PRG_renamechannel")
. = 1 if(!authed)
if(!operator_mode || !channel) return
return 1 var/newname = reject_bad_text(params["new_name"])
var/mob/living/user = usr
var/newname = reject_bad_text(input(user, "Enter new channel name or leave blank to cancel:"))
if(!newname || !channel) if(!newname || !channel)
return return
channel.add_status_message("Channel renamed from [channel.title] to [newname] by operator.") channel.add_status_message("Channel renamed from [channel.title] to [newname] by operator.")
channel.title = newname channel.title = newname
return TRUE
if("PRG_deletechannel") if("PRG_deletechannel")
. = 1 if(authed)
if(channel && ((channel.operator == src) || netadmin_mode))
qdel(channel) qdel(channel)
channel = null active_channel = null
return TRUE
if("PRG_setpassword") if("PRG_setpassword")
. = 1 if(!authed)
if(!channel || ((channel.operator != src) && !netadmin_mode)) return
return 1
var/mob/living/user = usr var/new_password = sanitize(params["new_password"])
var/newpassword = sanitize(input(user, "Enter new password for this channel. Leave blank to cancel, enter 'nopassword' to remove password completely:")) if(!authed)
if(!channel || !newpassword || ((channel.operator != src) && !netadmin_mode)) return
return 1
if(newpassword == "nopassword") channel.password = new_password
channel.password = "" return TRUE
else
channel.password = newpassword
/datum/computer_file/program/chatclient/process_tick() /datum/computer_file/program/chatclient/process_tick()
..() . = ..()
var/datum/ntnet_conversation/channel = SSnetworks.station_network.get_chat_channel_by_id(active_channel)
if(program_state != PROGRAM_STATE_KILLED) if(program_state != PROGRAM_STATE_KILLED)
ui_header = "ntnrc_idle.gif" ui_header = "ntnrc_idle.gif"
if(channel) if(channel)
// Remember the last message. If there is no message in the channel remember null. // Remember the last message. If there is no message in the channel remember null.
last_message = channel.messages.len ? channel.messages[channel.messages.len - 1] : null last_message = length(channel.messages) ? channel.messages[length(channel.messages)] : null
else else
last_message = null last_message = null
return 1 return TRUE
if(channel && channel.messages && channel.messages.len) if(channel?.messages?.len)
ui_header = last_message == channel.messages[channel.messages.len - 1] ? "ntnrc_idle.gif" : "ntnrc_new.gif" ui_header = last_message == channel.messages[length(channel.messages)] ? "ntnrc_idle.gif" : "ntnrc_new.gif"
else else
ui_header = "ntnrc_idle.gif" ui_header = "ntnrc_idle.gif"
/datum/computer_file/program/chatclient/kill_program(forced = FALSE) /datum/computer_file/program/chatclient/kill_program(forced = FALSE)
if(channel) for(var/C in SSnetworks.station_network.chat_channels)
var/datum/ntnet_conversation/channel = C
channel.remove_client(src) channel.remove_client(src)
channel = null
..() ..()
/datum/computer_file/program/chatclient/ui_static_data(mob/user)
var/list/data = list()
data["can_admin"] = can_run(user, FALSE, ACCESS_NETWORK)
return data
/datum/computer_file/program/chatclient/ui_data(mob/user) /datum/computer_file/program/chatclient/ui_data(mob/user)
if(!SSnetworks.station_network || !SSnetworks.station_network.chat_channels) if(!SSnetworks.station_network || !SSnetworks.station_network.chat_channels)
return return list()
var/list/data = list() var/list/data = list()
data = get_header_data() data = get_header_data()
var/list/all_channels = list()
for(var/C in SSnetworks.station_network.chat_channels)
var/datum/ntnet_conversation/conv = C
if(conv && conv.title)
all_channels.Add(list(list(
"chan" = conv.title,
"id" = conv.id
)))
data["all_channels"] = all_channels
data["active_channel"] = active_channel
data["username"] = username
data["adminmode"] = netadmin_mode data["adminmode"] = netadmin_mode
var/datum/ntnet_conversation/channel = SSnetworks.station_network.get_chat_channel_by_id(active_channel)
if(channel) if(channel)
data["title"] = channel.title data["title"] = channel.title
var/list/messages[0] var/authed = FALSE
for(var/M in channel.messages) if(!channel.password)
messages.Add(list(list( authed = TRUE
"msg" = M if(netadmin_mode)
))) authed = TRUE
data["messages"] = messages var/list/clients = list()
var/list/clients[0]
for(var/C in channel.clients) for(var/C in channel.clients)
if(C == src)
authed = TRUE
var/datum/computer_file/program/chatclient/cl = C var/datum/computer_file/program/chatclient/cl = C
clients.Add(list(list( clients.Add(list(list(
"name" = cl.username "name" = cl.username
))) )))
data["clients"] = clients data["authed"] = authed
operator_mode = (channel.operator == src) ? 1 : 0 //no fishing for ui data allowed
data["is_operator"] = operator_mode || netadmin_mode if(authed)
data["clients"] = clients
else // Channel selection screen var/list/messages = list()
var/list/all_channels[0] for(var/M in channel.messages)
for(var/C in SSnetworks.station_network.chat_channels) messages.Add(list(list(
var/datum/ntnet_conversation/conv = C "msg" = M
if(conv && conv.title)
all_channels.Add(list(list(
"chan" = conv.title,
"id" = conv.id
))) )))
data["all_channels"] = all_channels data["messages"] = messages
data["is_operator"] = (channel.operator == src) || netadmin_mode
else
data["clients"] = list()
data["messages"] = list()
else
data["clients"] = list()
data["authed"] = FALSE
data["messages"] = list()
return data return data

View File

@@ -27,6 +27,9 @@
var/dev_printer = 0 // 0: None, 1: Standard var/dev_printer = 0 // 0: None, 1: Standard
var/dev_card = 0 // 0: None, 1: Standard var/dev_card = 0 // 0: None, 1: Standard
ui_x = 500
ui_y = 400
// Removes all traces of old order and allows you to begin configuration from scratch. // Removes all traces of old order and allows you to begin configuration from scratch.
/obj/machinery/lapvend/proc/reset_order() /obj/machinery/lapvend/proc/reset_order()
state = 0 state = 0
@@ -173,7 +176,7 @@
switch(action) switch(action)
if("pick_device") if("pick_device")
if(state) // We've already picked a device type if(state) // We've already picked a device type
return TRUE return FALSE
devtype = text2num(params["pick"]) devtype = text2num(params["pick"])
state = 1 state = 1
fabricate_and_recalc_price(FALSE) fabricate_and_recalc_price(FALSE)
@@ -185,7 +188,7 @@
try_purchase() try_purchase()
return TRUE return TRUE
if((state != 1) && devtype) // Following IFs should only be usable when in the Select Loadout mode if((state != 1) && devtype) // Following IFs should only be usable when in the Select Loadout mode
return TRUE return FALSE
switch(action) switch(action)
if("confirm_order") if("confirm_order")
state = 2 // Wait for ID swipe for payment processing state = 2 // Wait for ID swipe for payment processing
@@ -219,36 +222,53 @@
dev_card = text2num(params["card"]) dev_card = text2num(params["card"])
fabricate_and_recalc_price(FALSE) fabricate_and_recalc_price(FALSE)
return TRUE return TRUE
return TRUE return FALSE
/obj/machinery/lapvend/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /obj/machinery/lapvend/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
if(stat & (BROKEN | NOPOWER | MAINT)) if(stat & (BROKEN | NOPOWER | MAINT))
if(ui) if(ui)
ui.close() ui.close()
return TRUE return FALSE
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if (!ui) if (!ui)
ui = new(user, src, ui_key, "computer_fabricator", "Personal Computer Vendor", 500, 400, state = state) ui = new(user, src, ui_key, "computer_fabricator", "Personal Computer Vendor", ui_x, ui_y, state = state)
ui.open() ui.open()
/obj/machinery/lapvend/attackby(obj/item/I, mob/user) /obj/machinery/lapvend/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/stack/spacecash)) if(istype(I, /obj/item/stack/spacecash))
var/obj/item/stack/spacecash/c = I var/obj/item/stack/spacecash/c = I
if(!user.temporarilyRemoveItemFromInventory(c)) if(!user.temporarilyRemoveItemFromInventory(c))
return return
credits += c.value credits += c.value
visible_message("<span class='info'><span class='name'>[user]</span> inserts [c.value] credits into [src].</span>") visible_message("<span class='info'><span class='name'>[user]</span> inserts [c.value] credits into [src].</span>")
qdel(c) qdel(c)
return return
/*else if(istype(I, /obj/item/holochip))
var/obj/item/holochip/HC = I
credits += HC.credits
visible_message("<span class='info'>[user] inserts a $[HC.credits] holocredit chip into [src].</span>")
qdel(HC)
return
else if(istype(I, /obj/item/card/id))
if(state != 2)
return
var/obj/item/card/id/ID = I
var/datum/bank_account/account = ID.registered_account
var/target_credits = total_price - credits
if(!account.adjust_money(-target_credits))
say("Insufficient money on card to purchase!")
return
credits += target_credits
say("$[target_credits] has been desposited from your account.")
return */ //Goonconomy when
return ..() return ..()
// Simplified payment processing, returns 1 on success. // Simplified payment processing, returns 1 on success.
/obj/machinery/lapvend/proc/process_payment() /obj/machinery/lapvend/proc/process_payment()
if(total_price > credits) if(total_price > credits)
say("Insufficient credits.") say("Insufficient credits.")
return TRUE return FALSE
else else
return TRUE return TRUE
@@ -288,4 +308,4 @@
state = 3 state = 3
addtimer(CALLBACK(src, .proc/reset_order), 100) addtimer(CALLBACK(src, .proc/reset_order), 100)
return TRUE return TRUE
return TRUE return FALSE

View File

@@ -21,7 +21,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "emergency_shuttle_console", name, ui = new(user, src, ui_key, "emergency_shuttle_console", name,
400, 400, master_ui, state) 400, 350, master_ui, state)
ui.open() ui.open()
/obj/machinery/computer/emergency_shuttle/ui_data() /obj/machinery/computer/emergency_shuttle/ui_data()

View File

@@ -1,364 +1,364 @@
/** /**
* tgui * tgui
* *
* /tg/station user interface library * /tg/station user interface library
**/ **/
/** /**
* tgui datum (represents a UI). * tgui datum (represents a UI).
**/ **/
/datum/tgui /datum/tgui
/// The mob who opened/is using the UI. /// The mob who opened/is using the UI.
var/mob/user var/mob/user
/// The object which owns the UI. /// The object which owns the UI.
var/datum/src_object var/datum/src_object
/// The title of te UI. /// The title of te UI.
var/title var/title
/// The ui_key of the UI. This allows multiple UIs for one src_object. /// The ui_key of the UI. This allows multiple UIs for one src_object.
var/ui_key var/ui_key
/// The window_id for browse() and onclose(). /// The window_id for browse() and onclose().
var/window_id var/window_id
/// The window width. /// The window width.
var/width = 0 var/width = 0
/// The window height /// The window height
var/height = 0 var/height = 0
/// The style to be used for this UI. /// The style to be used for this UI.
var/style = "nanotrasen" var/style = "nanotrasen"
/// The interface (template) to be used for this UI. /// The interface (template) to be used for this UI.
var/interface var/interface
/// Update the UI every MC tick. /// Update the UI every MC tick.
var/autoupdate = TRUE var/autoupdate = TRUE
/// If the UI has been initialized yet. /// If the UI has been initialized yet.
var/initialized = FALSE var/initialized = FALSE
/// The data (and datastructure) used to initialize the UI. /// The data (and datastructure) used to initialize the UI.
var/list/initial_data var/list/initial_data
/// The static data used to initialize the UI. /// The static data used to initialize the UI.
var/list/initial_static_data var/list/initial_static_data
/// The status/visibility of the UI. /// The status/visibility of the UI.
var/status = UI_INTERACTIVE var/status = UI_INTERACTIVE
/// Topic state used to determine status/interactability. /// Topic state used to determine status/interactability.
var/datum/ui_state/state = null var/datum/ui_state/state = null
/// The parent UI. /// The parent UI.
var/datum/tgui/master_ui var/datum/tgui/master_ui
/// Children of this UI. /// Children of this UI.
var/list/datum/tgui/children = list() var/list/datum/tgui/children = list()
var/custom_browser_id = FALSE var/custom_browser_id = FALSE
var/ui_screen = "home" var/ui_screen = "home"
/** /**
* public * public
* *
* Create a new UI. * Create a new UI.
* *
* required user mob The mob who opened/is using the UI. * required user mob The mob who opened/is using the UI.
* required src_object datum The object or datum which owns the UI. * required src_object datum The object or datum which owns the UI.
* required ui_key string The ui_key of the UI. * required ui_key string The ui_key of the UI.
* required interface string The interface used to render the UI. * required interface string The interface used to render the UI.
* optional title string The title of the UI. * optional title string The title of the UI.
* optional width int The window width. * optional width int The window width.
* optional height int The window height. * optional height int The window height.
* optional master_ui datum/tgui The parent UI. * optional master_ui datum/tgui The parent UI.
* optional state datum/ui_state The state used to determine status. * optional state datum/ui_state The state used to determine status.
* *
* return datum/tgui The requested UI. * return datum/tgui The requested UI.
**/ **/
/datum/tgui/New(mob/user, datum/src_object, ui_key, interface, title, width = 0, height = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state, browser_id = null) /datum/tgui/New(mob/user, datum/src_object, ui_key, interface, title, width = 0, height = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state, browser_id = null)
src.user = user src.user = user
src.src_object = src_object src.src_object = src_object
src.ui_key = ui_key src.ui_key = ui_key
src.window_id = browser_id ? browser_id : "[REF(src_object)]-[ui_key]" // DO NOT replace with \ref here. src_object could potentially be tagged src.window_id = browser_id ? browser_id : "[REF(src_object)]-[ui_key]" // DO NOT replace with \ref here. src_object could potentially be tagged
src.custom_browser_id = browser_id ? TRUE : FALSE src.custom_browser_id = browser_id ? TRUE : FALSE
set_interface(interface) set_interface(interface)
if(title) if(title)
src.title = sanitize(title) src.title = sanitize(title)
if(width) if(width)
src.width = width src.width = width
if(height) if(height)
src.height = height src.height = height
src.master_ui = master_ui src.master_ui = master_ui
if(master_ui) if(master_ui)
master_ui.children += src master_ui.children += src
src.state = state src.state = state
var/datum/asset/assets = get_asset_datum(/datum/asset/group/tgui) var/datum/asset/assets = get_asset_datum(/datum/asset/group/tgui)
assets.send(user) assets.send(user)
/** /**
* public * public
* *
* Open this UI (and initialize it with data). * Open this UI (and initialize it with data).
**/ **/
/datum/tgui/proc/open() /datum/tgui/proc/open()
if(!user.client) if(!user.client)
return // Bail if there is no client. return // Bail if there is no client.
update_status(push = FALSE) // Update the window status. update_status(push = FALSE) // Update the window status.
if(status < UI_UPDATE) if(status < UI_UPDATE)
return // Bail if we're not supposed to open. return // Bail if we're not supposed to open.
var/window_size var/window_size
if(width && height) // If we have a width and height, use them. if(width && height) // If we have a width and height, use them.
window_size = "size=[width]x[height];" window_size = "size=[width]x[height];"
else else
window_size = "" window_size = ""
// Remove titlebar and resize handles for a fancy window // Remove titlebar and resize handles for a fancy window
var/have_title_bar var/have_title_bar
if(user.client.prefs.tgui_fancy) if(user.client.prefs.tgui_fancy)
have_title_bar = "titlebar=0;can_resize=0;" have_title_bar = "titlebar=0;can_resize=0;"
else else
have_title_bar = "titlebar=1;can_resize=1;" have_title_bar = "titlebar=1;can_resize=1;"
// Generate page html // Generate page html
var/html var/html
html = SStgui.basehtml html = SStgui.basehtml
// Allow the src object to override the html if needed // Allow the src object to override the html if needed
html = src_object.ui_base_html(html) html = src_object.ui_base_html(html)
// Replace template tokens with important UI data // Replace template tokens with important UI data
// NOTE: Intentional \ref usage; tgui datums can't/shouldn't // NOTE: Intentional \ref usage; tgui datums can't/shouldn't
// be tagged, so this is an effective unwrap // be tagged, so this is an effective unwrap
html = replacetextEx(html, "\[ref]", "\ref[src]") html = replacetextEx(html, "\[ref]", "\ref[src]")
html = replacetextEx(html, "\[style]", style) html = replacetextEx(html, "\[style]", style)
// Open the window. // Open the window.
user << browse(html, "window=[window_id];can_minimize=0;auto_format=0;[window_size][have_title_bar]") user << browse(html, "window=[window_id];can_minimize=0;auto_format=0;[window_size][have_title_bar]")
if (!custom_browser_id) if (!custom_browser_id)
// Instruct the client to signal UI when the window is closed. // Instruct the client to signal UI when the window is closed.
// NOTE: Intentional \ref usage; tgui datums can't/shouldn't // NOTE: Intentional \ref usage; tgui datums can't/shouldn't
// be tagged, so this is an effective unwrap // be tagged, so this is an effective unwrap
winset(user, window_id, "on-close=\"uiclose \ref[src]\"") winset(user, window_id, "on-close=\"uiclose \ref[src]\"")
if(!initial_data) if(!initial_data)
initial_data = src_object.ui_data(user) initial_data = src_object.ui_data(user)
if(!initial_static_data) if(!initial_static_data)
initial_static_data = src_object.ui_static_data(user) initial_static_data = src_object.ui_static_data(user)
SStgui.on_open(src) SStgui.on_open(src)
/** /**
* public * public
* *
* Reinitialize the UI. * Reinitialize the UI.
* (Possibly with a new interface and/or data). * (Possibly with a new interface and/or data).
* *
* optional template string The name of the new interface. * optional template string The name of the new interface.
* optional data list The new initial data. * optional data list The new initial data.
**/ **/
/datum/tgui/proc/reinitialize(interface, list/data, list/static_data) /datum/tgui/proc/reinitialize(interface, list/data, list/static_data)
if(interface) if(interface)
set_interface(interface) // Set a new interface. set_interface(interface) // Set a new interface.
if(data) if(data)
initial_data = data initial_data = data
if(static_data) if(static_data)
initial_static_data = static_data initial_static_data = static_data
open() open()
/** /**
* public * public
* *
* Close the UI, and all its children. * Close the UI, and all its children.
**/ **/
/datum/tgui/proc/close() /datum/tgui/proc/close()
user << browse(null, "window=[window_id]") // Close the window. user << browse(null, "window=[window_id]") // Close the window.
src_object.ui_close() src_object.ui_close()
SStgui.on_close(src) SStgui.on_close(src)
for(var/datum/tgui/child in children) // Loop through and close all children. for(var/datum/tgui/child in children) // Loop through and close all children.
child.close() child.close()
children.Cut() children.Cut()
state = null state = null
master_ui = null master_ui = null
qdel(src) qdel(src)
/** /**
* public * public
* *
* Set the style for this UI. * Set the style for this UI.
* *
* required style string The new UI style. * required style string The new UI style.
**/ **/
/datum/tgui/proc/set_style(style) /datum/tgui/proc/set_style(style)
src.style = lowertext(style) src.style = lowertext(style)
/** /**
* public * public
* *
* Set the interface (template) for this UI. * Set the interface (template) for this UI.
* *
* required interface string The new UI interface. * required interface string The new UI interface.
**/ **/
/datum/tgui/proc/set_interface(interface) /datum/tgui/proc/set_interface(interface)
src.interface = lowertext(interface) src.interface = lowertext(interface)
/** /**
* public * public
* *
* Enable/disable auto-updating of the UI. * Enable/disable auto-updating of the UI.
* *
* required state bool Enable/disable auto-updating. * required state bool Enable/disable auto-updating.
**/ **/
/datum/tgui/proc/set_autoupdate(state = TRUE) /datum/tgui/proc/set_autoupdate(state = TRUE)
autoupdate = state autoupdate = state
/** /**
* private * private
* *
* Package the data to send to the UI, as JSON. * Package the data to send to the UI, as JSON.
* This includes the UI data and config_data. * This includes the UI data and config_data.
* *
* return string The packaged JSON. * return string The packaged JSON.
**/ **/
/datum/tgui/proc/get_json(list/data, list/static_data) /datum/tgui/proc/get_json(list/data, list/static_data)
var/list/json_data = list() var/list/json_data = list()
json_data["config"] = list( json_data["config"] = list(
"title" = title, "title" = title,
"status" = status, "status" = status,
"screen" = ui_screen, "screen" = ui_screen,
"style" = style, "style" = style,
"interface" = interface, "interface" = interface,
"fancy" = user.client.prefs.tgui_fancy, "fancy" = user.client.prefs.tgui_fancy,
"locked" = user.client.prefs.tgui_lock && !custom_browser_id, "locked" = user.client.prefs.tgui_lock && !custom_browser_id,
"observer" = isobserver(user), "observer" = isobserver(user),
"window" = window_id, "window" = window_id,
// NOTE: Intentional \ref usage; tgui datums can't/shouldn't // NOTE: Intentional \ref usage; tgui datums can't/shouldn't
// be tagged, so this is an effective unwrap // be tagged, so this is an effective unwrap
"ref" = "\ref[src]" "ref" = "\ref[src]"
) )
if(!isnull(data)) if(!isnull(data))
json_data["data"] = data json_data["data"] = data
if(!isnull(static_data)) if(!isnull(static_data))
json_data["static_data"] = static_data json_data["static_data"] = static_data
// Generate the JSON. // Generate the JSON.
var/json = json_encode(json_data) var/json = json_encode(json_data)
// Strip #255/improper. // Strip #255/improper.
json = replacetext(json, "\proper", "") json = replacetext(json, "\proper", "")
json = replacetext(json, "\improper", "") json = replacetext(json, "\improper", "")
return json return json
/** /**
* private * private
* *
* Handle clicks from the UI. * Handle clicks from the UI.
* Call the src_object's ui_act() if status is UI_INTERACTIVE. * Call the src_object's ui_act() if status is UI_INTERACTIVE.
* If the src_object's ui_act() returns 1, update all UIs attacked to it. * If the src_object's ui_act() returns 1, update all UIs attacked to it.
**/ **/
/datum/tgui/Topic(href, href_list) /datum/tgui/Topic(href, href_list)
if(user != usr) if(user != usr)
return // Something is not right here. return // Something is not right here.
var/action = href_list["action"] var/action = href_list["action"]
var/params = href_list; params -= "action" var/params = href_list; params -= "action"
switch(action) switch(action)
if("tgui:initialize") if("tgui:initialize")
user << output(url_encode(get_json(initial_data, initial_static_data)), "[custom_browser_id ? window_id : "[window_id].browser"]:initialize") user << output(url_encode(get_json(initial_data, initial_static_data)), "[custom_browser_id ? window_id : "[window_id].browser"]:initialize")
initialized = TRUE initialized = TRUE
if("tgui:view") if("tgui:view")
if(params["screen"]) if(params["screen"])
ui_screen = params["screen"] ui_screen = params["screen"]
SStgui.update_uis(src_object) SStgui.update_uis(src_object)
if("tgui:log") if("tgui:log")
// Force window to show frills on fatal errors // Force window to show frills on fatal errors
if(params["fatal"]) if(params["fatal"])
winset(user, window_id, "titlebar=1;can-resize=1;size=600x600") winset(user, window_id, "titlebar=1;can-resize=1;size=600x600")
if("tgui:link") if("tgui:link")
user << link(params["url"]) user << link(params["url"])
if("tgui:fancy") if("tgui:fancy")
user.client.prefs.tgui_fancy = TRUE user.client.prefs.tgui_fancy = TRUE
if("tgui:nofrills") if("tgui:nofrills")
user.client.prefs.tgui_fancy = FALSE user.client.prefs.tgui_fancy = FALSE
else else
update_status(push = FALSE) // Update the window state. update_status(push = FALSE) // Update the window state.
if(src_object.ui_act(action, params, src, state)) // Call ui_act() on the src_object. if(src_object.ui_act(action, params, src, state)) // Call ui_act() on the src_object.
SStgui.update_uis(src_object) // Update if the object requested it. SStgui.update_uis(src_object) // Update if the object requested it.
/** /**
* private * private
* *
* Update the UI. * Update the UI.
* Only updates the data if update is true, otherwise only updates the status. * Only updates the data if update is true, otherwise only updates the status.
* *
* optional force bool If the UI should be forced to update. * optional force bool If the UI should be forced to update.
**/ **/
/datum/tgui/process(force = FALSE) /datum/tgui/process(force = FALSE)
var/datum/host = src_object.ui_host(user) var/datum/host = src_object.ui_host(user)
if(!src_object || !host || !user) // If the object or user died (or something else), abort. if(!src_object || !host || !user) // If the object or user died (or something else), abort.
close() close()
return return
if(status && (force || autoupdate)) if(status && (force || autoupdate))
update() // Update the UI if the status and update settings allow it. update() // Update the UI if the status and update settings allow it.
else else
update_status(push = TRUE) // Otherwise only update status. update_status(push = TRUE) // Otherwise only update status.
/** /**
* private * private
* *
* Push data to an already open UI. * Push data to an already open UI.
* *
* required data list The data to send. * required data list The data to send.
* optional force bool If the update should be sent regardless of state. * optional force bool If the update should be sent regardless of state.
**/ **/
/datum/tgui/proc/push_data(data, static_data, force = FALSE) /datum/tgui/proc/push_data(data, static_data, force = FALSE)
update_status(push = FALSE) // Update the window state. update_status(push = FALSE) // Update the window state.
if(!initialized) if(!initialized)
return // Cannot update UI if it is not set up yet. return // Cannot update UI if it is not set up yet.
if(status <= UI_DISABLED && !force) if(status <= UI_DISABLED && !force)
return // Cannot update UI, we have no visibility. return // Cannot update UI, we have no visibility.
// Send the new JSON to the update() Javascript function. // Send the new JSON to the update() Javascript function.
user << output(url_encode(get_json(data, static_data)), "[custom_browser_id ? window_id : "[window_id].browser"]:update") user << output(url_encode(get_json(data, static_data)), "[custom_browser_id ? window_id : "[window_id].browser"]:update")
/** /**
* private * private
* *
* Updates the UI by interacting with the src_object again, which will hopefully * Updates the UI by interacting with the src_object again, which will hopefully
* call try_ui_update on it. * call try_ui_update on it.
* *
* optional force_open bool If force_open should be passed to ui_interact. * optional force_open bool If force_open should be passed to ui_interact.
**/ **/
/datum/tgui/proc/update(force_open = FALSE) /datum/tgui/proc/update(force_open = FALSE)
src_object.ui_interact(user, ui_key, src, force_open, master_ui, state) src_object.ui_interact(user, ui_key, src, force_open, master_ui, state)
/** /**
* private * private
* *
* Update the status/visibility of the UI for its user. * Update the status/visibility of the UI for its user.
* *
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED). * optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
**/ **/
/datum/tgui/proc/update_status(push = FALSE) /datum/tgui/proc/update_status(push = FALSE)
var/status = src_object.ui_status(user, state) var/status = src_object.ui_status(user, state)
if(master_ui) if(master_ui)
status = min(status, master_ui.status) status = min(status, master_ui.status)
set_status(status, push) set_status(status, push)
if(status == UI_CLOSE) if(status == UI_CLOSE)
close() close()
/** /**
* private * private
* *
* Set the status/visibility of the UI. * Set the status/visibility of the UI.
* *
* required status int The status to set (UI_CLOSE/UI_DISABLED/UI_UPDATE/UI_INTERACTIVE). * required status int The status to set (UI_CLOSE/UI_DISABLED/UI_UPDATE/UI_INTERACTIVE).
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED). * optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
**/ **/
/datum/tgui/proc/set_status(status, push = FALSE) /datum/tgui/proc/set_status(status, push = FALSE)
if(src.status != status) // Only update if status has changed. if(src.status != status) // Only update if status has changed.
if(src.status == UI_DISABLED) if(src.status == UI_DISABLED)
src.status = status src.status = status
if(push) if(push)
update() update()
else else
src.status = status src.status = status
if(status == UI_DISABLED || push) // Update if the UI just because disabled, or a push is requested. if(status == UI_DISABLED || push) // Update if the UI just because disabled, or a push is requested.
push_data(null, force = TRUE) push_data(null, force = TRUE)
/datum/tgui/proc/log_message(message) /datum/tgui/proc/log_message(message)
log_tgui("[user] ([user.ckey]) using \"[title]\":\n[message]") log_tgui("[user] ([user.ckey]) using \"[title]\":\n[message]")

10
node_modules/.yarn-integrity generated vendored Normal file
View File

@@ -0,0 +1,10 @@
{
"systemParams": "win32-x64-72",
"modulesFolders": [],
"flags": [],
"linkedModules": [],
"topLevelPatterns": [],
"lockfileEntries": {},
"files": [],
"artifacts": {}
}

View File

@@ -220,6 +220,7 @@ This way, `Button` can pull out the `className` generated by the `Box`.
``` ```
`Box` units, like width, height and margins can be defined in two ways: `Box` units, like width, height and margins can be defined in two ways:
- By plain numbers (1 unit equals `0.5em`); - By plain numbers (1 unit equals `0.5em`);
- In absolute measures, by providing a full unit string (e.g. `100px`). - In absolute measures, by providing a full unit string (e.g. `100px`).
@@ -238,8 +239,6 @@ Props:
- `height: number` - Box height. - `height: number` - Box height.
- `minHeight: number` - Box minimum height. - `minHeight: number` - Box minimum height.
- `maxHeight: number` - Box maximum height. - `maxHeight: number` - Box maximum height.
- `fontSize: number` - Font size.
- `fontFamily: string` - Font family.
- `lineHeight: number` - Directly affects the height of text lines. - `lineHeight: number` - Directly affects the height of text lines.
Useful for adjusting button height. Useful for adjusting button height.
- `inline: boolean` - Forces the `Box` to appear as an `inline-block`, - `inline: boolean` - Forces the `Box` to appear as an `inline-block`,
@@ -255,7 +254,6 @@ all available horizontal space.
- `opacity: number` - Opacity, from 0 to 1. - `opacity: number` - Opacity, from 0 to 1.
- `bold: boolean` - Make text bold. - `bold: boolean` - Make text bold.
- `italic: boolean` - Make text italic. - `italic: boolean` - Make text italic.
- `nowrap: boolean` - Stops text from wrapping.
- `textAlign: string` - Align text inside the box. - `textAlign: string` - Align text inside the box.
- `left` (default) - `left` (default)
- `center` - `center`
@@ -295,34 +293,11 @@ over the button.
- `bottom` (default) - Show tooltip below the button. - `bottom` (default) - Show tooltip below the button.
- `left` - Show tooltip on the left of the button. - `left` - Show tooltip on the left of the button.
- `right` - Show tooltip on the right of the button. - `right` - Show tooltip on the right of the button.
- `ellipsis: boolean` - If button width is constrained, button text will
be truncated with an ellipsis. Be careful however, because this prop breaks
the baseline alignment.
- `title: string` - A native browser tooltip, which appears when hovering - `title: string` - A native browser tooltip, which appears when hovering
over the button. over the button.
- `content/children: any` - Content to render inside the button. - `content/children: any` - Content to render inside the button.
- `onClick: function` - Called when element is clicked. - `onClick: function` - Called when element is clicked.
### `Button.Checkbox`
A ghetto checkbox, made entirely using existing Button API.
Props:
- See inherited props: [Button](#button)
- `checked: boolean` - Boolean value, which marks the checkbox as checked.
### `Collapsible`
Displays contents when open, acts as a fluid button when closed. Click to toggle, closed by default.
Props:
- See inherited props: [Box](#box)
- `children: any` - What is collapsed when closed
- `title: string` - Text to display on the button for collapsing
- `color: string` - Color of the button; see [Button](#button)
- `buttons: any` - Buttons or other content to render inline with the button
### `ColorBox` ### `ColorBox`
Displays a 1-character wide colored square. Can be used as a status indicator, Displays a 1-character wide colored square. Can be used as a status indicator,
@@ -344,21 +319,6 @@ Props:
- See inherited props: [Box](#box) - See inherited props: [Box](#box)
### `Dropdown`
A simple dropdown box component. Lets the user select from a list of options and displays selected entry.
Props:
- See inherited props: [Box](#box)
- `options: string[]` - An array of strings which will be displayed in the dropdown when open
- `selected: string` - Currently selected entry
- `width: number` - Width of dropdown button and resulting menu
- `over: boolean` - dropdown renders over instead of below
- `color: string` - color of dropdown button
- `onClick: (e) => void` - Called when dropdown button is clicked
- `onSet: (e, value) => void` - Called when a value is picked from the list, `value` is the value that was picked
### `Flex` ### `Flex`
Quickly manage the layout, alignment, and sizing of grid columns, navigation, components, and more with a full suite of responsive flexbox utilities. Quickly manage the layout, alignment, and sizing of grid columns, navigation, components, and more with a full suite of responsive flexbox utilities.
@@ -390,10 +350,6 @@ two flex items as far as possible from each other.
Props: Props:
- See inherited props: [Box](#box) - See inherited props: [Box](#box)
- `spacing: number` - Spacing between flex items, in integer units
(1 unit - 0.5em). Does not directly relate to a flex css property
(adds a modifier class under the hood), and only integer numbers are
supported.
- `direction: string` - This establishes the main-axis, thus defining the - `direction: string` - This establishes the main-axis, thus defining the
direction flex items are placed in the flex container. direction flex items are placed in the flex container.
- `row` (default) - left to right. - `row` (default) - left to right.
@@ -450,7 +406,6 @@ remaining space is distributed. It can be a length (e.g. `20%`, `5rem`, etc.),
an `auto` or `content` keyword. an `auto` or `content` keyword.
- `align: string` - This allows the default alignment (or the one specified by align-items) to be overridden for individual flex items. See: [Flex](#flex). - `align: string` - This allows the default alignment (or the one specified by align-items) to be overridden for individual flex items. See: [Flex](#flex).
### `Grid` ### `Grid`
Helps you to divide horizontal space into two or more equal sections. Helps you to divide horizontal space into two or more equal sections.
@@ -477,7 +432,7 @@ Props:
Props: Props:
- See inherited props: [Table.Cell](#tablecell) - See inherited props: [Table.Cell](#table-cell)
- `size: number` (default: 1) - Size of the column relative to other columns. - `size: number` (default: 1) - Size of the column relative to other columns.
### `Icon` ### `Icon`
@@ -490,6 +445,7 @@ Renders one of the FontAwesome icons of your choice.
To smoothen the transition from v4 to v5, we have added a v4 semantic to To smoothen the transition from v4 to v5, we have added a v4 semantic to
transform names with `-o` suffixes to FA Regular icons. For example: transform names with `-o` suffixes to FA Regular icons. For example:
- `square` will get transformed to `fas square` - `square` will get transformed to `fas square`
- `square-o` will get transformed to `far square` - `square-o` will get transformed to `far square`
@@ -514,7 +470,6 @@ Props:
- See inherited props: [Box](#box) - See inherited props: [Box](#box)
- `value: string` - Value of an input. - `value: string` - Value of an input.
- `placeholder: string` - Text placed into Input box when value is otherwise nothing. Clears automatically when focused.
- `fluid: boolean` - Fill all available horizontal space. - `fluid: boolean` - Fill all available horizontal space.
- `onChange: (e, value) => void` - An event, which fires when you commit - `onChange: (e, value) => void` - An event, which fires when you commit
the text by either unfocusing the input box, or by pressing the Enter key. the text by either unfocusing the input box, or by pressing the Enter key.

View File

@@ -10,27 +10,6 @@ export const Cargo = props => {
const { ref } = config; const { ref } = config;
const supplies = data.supplies || {}; const supplies = data.supplies || {};
const requests = data.requests || []; const requests = data.requests || [];
const cart = data.cart || [];
const cartTotalAmount = cart
.reduce((total, entry) => total + entry.cost, 0);
const cartButtons = !data.requestonly && (
<Fragment>
<Box inline mx={1}>
{cart.length === 0 && 'Cart is empty'}
{cart.length === 1 && '1 item'}
{cart.length >= 2 && cart.length + ' items'}
{' '}
{cartTotalAmount > 0 && `(${cartTotalAmount} cr)`}
</Box>
<Button
icon="times"
color="transparent"
content="Clear"
onClick={() => act(ref, 'clear')} />
</Fragment>
);
return ( return (
<Fragment> <Fragment>
@@ -243,61 +222,6 @@ const Requests = props => {
); );
}; };
const Cart = props => {
const { state, cart } = props;
const { config, data } = state;
const { ref } = config;
return (
<Fragment>
{cart.length === 0 && 'Nothing in cart'}
{cart.length > 0 && (
<LabeledList>
{cart.map(entry => (
<LabeledList.Item
key={entry.id}
className="candystripe"
label={'#' + entry.id}
buttons={(
<Fragment>
<Box inline mx={2}>
{!!entry.paid && (<b>[Paid Privately]</b>)}
{' '}
{entry.cost} credits
</Box>
<Button
icon="minus"
onClick={() => act(ref, 'remove', {
id: entry.id,
})} />
</Fragment>
)}>
{entry.object}
</LabeledList.Item>
))}
</LabeledList>
)}
{cart.length > 0 && !data.requestonly && (
<Box mt={2}>
{data.away === 1 && data.docked === 1 && (
<Button
color="green"
style={{
'line-height': '28px',
'padding': '0 12px',
}}
content="Confirm the order"
onClick={() => act(ref, 'send')} />
) || (
<Box opacity={0.5}>
Shuttle in {data.location}.
</Box>
)}
</Box>
)}
</Fragment>
);
};
export const CargoExpress = props => { export const CargoExpress = props => {
const { state } = props; const { state } = props;
const { config, data } = state; const { config, data } = state;

File diff suppressed because one or more lines are too long

View File

@@ -32,19 +32,28 @@ import { Cryo } from './interfaces/Cryo';
import { DecalPainter } from './interfaces/DecalPainter'; import { DecalPainter } from './interfaces/DecalPainter';
import { DisposalUnit } from './interfaces/DisposalUnit'; import { DisposalUnit } from './interfaces/DisposalUnit';
import { DnaVault } from './interfaces/DnaVault'; import { DnaVault } from './interfaces/DnaVault';
import { EightBallVote } from './interfaces/EightBallVote';
import { EmergencyShuttleConsole } from './interfaces/EmergencyShuttleConsole';
import { EngravedMessage } from './interfaces/EngravedMessage'; import { EngravedMessage } from './interfaces/EngravedMessage';
import { Gps } from './interfaces/Gps'; import { Gps } from './interfaces/Gps';
import { GravityGenerator } from './interfaces/GravityGenerator'; import { GravityGenerator } from './interfaces/GravityGenerator';
import { GulagTeleporterConsole } from './interfaces/GulagTeleporterConsole';
import { GulagItemReclaimer } from './interfaces/GulagItemReclaimer'; import { GulagItemReclaimer } from './interfaces/GulagItemReclaimer';
import { Holodeck } from './interfaces/Holodeck'; import { Holodeck } from './interfaces/Holodeck';
import { ImplantChair } from './interfaces/ImplantChair'; import { ImplantChair } from './interfaces/ImplantChair';
import { Intellicard } from './interfaces/Intellicard';
import { KeycardAuth } from './interfaces/KeycardAuth'; import { KeycardAuth } from './interfaces/KeycardAuth';
import { LaborClaimConsole } from './interfaces/LaborClaimConsole'; import { LaborClaimConsole } from './interfaces/LaborClaimConsole';
import { LanguageMenu } from './interfaces/LanguageMenu'; import { LanguageMenu } from './interfaces/LanguageMenu';
import { LaunchpadConsole, LaunchpadRemote } from './interfaces/Launchpad';
import { MechBayPowerConsole } from './interfaces/MechBayPowerConsole'; import { MechBayPowerConsole } from './interfaces/MechBayPowerConsole';
import { MedicalKiosk } from './interfaces/MedicalKiosk'; import { Mule } from './interfaces/Mule';
import { NotificationPreferences } from './interfaces/NotificationPreferences';
import { NtnetRelay } from './interfaces/NtnetRelay';
import { NtosArcade } from './interfaces/NtosArcade'; import { NtosArcade } from './interfaces/NtosArcade';
import { NtosConfiguration } from './interfaces/NtosConfiguration';
import { NtosMain } from './interfaces/NtosMain'; import { NtosMain } from './interfaces/NtosMain';
import { NtosNetChat } from './interfaces/NtosNetChat';
import { NtosNetDownloader } from './interfaces/NtosNetDownloader'; import { NtosNetDownloader } from './interfaces/NtosNetDownloader';
import { NtosSupermatterMonitor } from './interfaces/NtosSupermatterMonitor'; import { NtosSupermatterMonitor } from './interfaces/NtosSupermatterMonitor';
import { NtosWrapper } from './interfaces/NtosWrapper'; import { NtosWrapper } from './interfaces/NtosWrapper';
@@ -61,6 +70,8 @@ import { RapidPipeDispenser } from './interfaces/RapidPipeDispenser';
import { SatelliteControl } from './interfaces/SatelliteControl'; import { SatelliteControl } from './interfaces/SatelliteControl';
import { ScannerGate } from './interfaces/ScannerGate'; import { ScannerGate } from './interfaces/ScannerGate';
import { ShuttleManipulator } from './interfaces/ShuttleManipulator'; import { ShuttleManipulator } from './interfaces/ShuttleManipulator';
import { SlimeBodySwapper } from './interfaces/SlimeBodySwapper';
import { Signaler } from './interfaces/Signaler';
import { SmartVend } from './interfaces/SmartVend'; import { SmartVend } from './interfaces/SmartVend';
import { Smes } from './interfaces/Smes'; import { Smes } from './interfaces/Smes';
import { SmokeMachine } from './interfaces/SmokeMachine'; import { SmokeMachine } from './interfaces/SmokeMachine';
@@ -71,10 +82,10 @@ import { StationAlertConsole } from './interfaces/StationAlertConsole';
import { SuitStorageUnit } from './interfaces/SuitStorageUnit'; import { SuitStorageUnit } from './interfaces/SuitStorageUnit';
import { Tank } from './interfaces/Tank'; import { Tank } from './interfaces/Tank';
import { TankDispenser } from './interfaces/TankDispenser'; import { TankDispenser } from './interfaces/TankDispenser';
import { Teleporter } from './interfaces/Teleporter';
import { ThermoMachine } from './interfaces/ThermoMachine'; import { ThermoMachine } from './interfaces/ThermoMachine';
import { TurbineComputer } from './interfaces/TurbineComputer'; import { TurbineComputer } from './interfaces/TurbineComputer';
import { VaultController } from './interfaces/VaultController'; import { VaultController } from './interfaces/VaultController';
import { Vending } from './interfaces/Vending';
import { Wires } from './interfaces/Wires'; import { Wires } from './interfaces/Wires';
const ROUTES = { const ROUTES = {
@@ -218,6 +229,14 @@ const ROUTES = {
component: () => DnaVault, component: () => DnaVault,
scrollable: false, scrollable: false,
}, },
eightball: {
component: () => EightBallVote,
scrollable: false,
},
emergency_shuttle_console: {
component: () => EmergencyShuttleConsole,
scrollable: false,
},
engraved_message: { engraved_message: {
component: () => EngravedMessage, component: () => EngravedMessage,
scrollable: false, scrollable: false,
@@ -230,6 +249,10 @@ const ROUTES = {
component: () => GravityGenerator, component: () => GravityGenerator,
scrollable: false, scrollable: false,
}, },
gulag_console: {
component: () => GulagTeleporterConsole,
scrollable: false,
},
gulag_item_reclaimer: { gulag_item_reclaimer: {
component: () => GulagItemReclaimer, component: () => GulagItemReclaimer,
scrollable: true, scrollable: true,
@@ -242,6 +265,10 @@ const ROUTES = {
component: () => ImplantChair, component: () => ImplantChair,
scrollable: false, scrollable: false,
}, },
intellicard: {
component: () => Intellicard,
scrollable: true,
},
keycard_auth: { keycard_auth: {
component: () => KeycardAuth, component: () => KeycardAuth,
scrollable: false, scrollable: false,
@@ -254,32 +281,61 @@ const ROUTES = {
component: () => LanguageMenu, component: () => LanguageMenu,
scrollable: true, scrollable: true,
}, },
launchpad_console: {
component: () => LaunchpadConsole,
scrollable: true,
},
launchpad_remote: {
component: () => LaunchpadRemote,
scrollable: false,
theme: 'syndicate',
},
mech_bay_power_console: { mech_bay_power_console: {
component: () => MechBayPowerConsole, component: () => MechBayPowerConsole,
scrollable: false, scrollable: false,
}, },
medical_kiosk: { mulebot: {
component: () => MedicalKiosk, component: () => Mule,
scrollable: false, scrollable: false,
}, },
notificationpanel: {
component: () => NotificationPreferences,
scrollable: true,
},
ntnet_relay: {
component: () => NtnetRelay,
scrollable: false,
},
ntos_arcade: {
component: () => NtosArcade,
wrapper: () => NtosWrapper,
scrollable: false,
theme: 'ntos',
},
ntos_configuration: {
component: () => NtosConfiguration,
wrapper: () => NtosWrapper,
scrollable: true,
theme: 'ntos',
},
ntos_main: { ntos_main: {
component: () => NtosMain, component: () => NtosMain,
wrapper: () => NtosWrapper, wrapper: () => NtosWrapper,
scrollable: true, scrollable: true,
theme: 'ntos', theme: 'ntos',
}, },
ntos_net_chat: {
component: () => NtosNetChat,
wrapper: () => NtosWrapper,
scrollable: false,
theme: 'ntos',
},
ntos_net_downloader: { ntos_net_downloader: {
component: () => NtosNetDownloader, component: () => NtosNetDownloader,
wrapper: () => NtosWrapper, wrapper: () => NtosWrapper,
scrollable: true, scrollable: true,
theme: 'ntos', theme: 'ntos',
}, },
ntos_arcade: {
component: () => NtosArcade,
wrapper: () => NtosWrapper,
scrollable: false,
theme: 'ntos',
},
ntos_power_monitor: { ntos_power_monitor: {
component: () => PowerMonitor, component: () => PowerMonitor,
wrapper: () => NtosWrapper, wrapper: () => NtosWrapper,
@@ -349,6 +405,14 @@ const ROUTES = {
component: () => ShuttleManipulator, component: () => ShuttleManipulator,
scrollable: true, scrollable: true,
}, },
slime_swap_body: {
component: () => SlimeBodySwapper,
scrollable: true,
},
signaler: {
component: () => Signaler,
scrollable: false,
},
smartvend: { smartvend: {
component: () => SmartVend, component: () => SmartVend,
scrollable: true, scrollable: true,
@@ -389,6 +453,10 @@ const ROUTES = {
component: () => TankDispenser, component: () => TankDispenser,
scrollable: false, scrollable: false,
}, },
teleporter: {
component: () => Teleporter,
scrollable: false,
},
thermomachine: { thermomachine: {
component: () => ThermoMachine, component: () => ThermoMachine,
scrollable: false, scrollable: false,
@@ -401,10 +469,6 @@ const ROUTES = {
component: () => VaultController, component: () => VaultController,
scrollable: false, scrollable: false,
}, },
vending: {
component: () => Vending,
scrollable: true,
},
wires: { wires: {
component: () => Wires, component: () => Wires,
scrollable: false, scrollable: false,

File diff suppressed because one or more lines are too long

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>dmitool</name>
<comment>Project dmitool created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>